Mercurial > hg > graal-compiler
changeset 15396:824b41170df9
Merge.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Mon, 28 Apr 2014 10:31:17 +0200 |
parents | 2a8628bc6c10 (current diff) 684fcfc314a8 (diff) |
children | d030e31fe082 |
files | graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRLoop.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/LIRTypeTool.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResultBase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/nodes/AtomicGetAndAddNode.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/nodes/LoweredAtomicGetAndAddNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryLogicNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampProvider.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/VoidStamp.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalLongUnitTest.java graal/com.oracle.graal.test/src/com/oracle/graal/test/LongTest.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ASTPrinter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugContext.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugManager.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DefaultDebugManager.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/DefaultNodeInstrumenter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeEvents.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProxyNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodeInstrumenter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodePhylum.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/PhylumMarked.java test/baseline_whitelist.txt |
diffstat | 703 files changed, 18807 insertions(+), 8251 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGELOG.md Fri Apr 18 15:41:13 2014 +0200 +++ b/CHANGELOG.md Mon Apr 28 10:31:17 2014 +0200 @@ -8,6 +8,7 @@ * Added graal.version system property to Graal enabled VM builds. * Transitioned to JDK 8 as minimum JDK level for Graal. * Added support for stack introspection. +* New MatchRule facility to convert multiple HIR nodes into specialized LIR * ... ### Truffle
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Mon Apr 28 10:31:17 2014 +0200 @@ -94,6 +94,43 @@ public final boolean duringCall; /** + * This BCI should be used for frame states that are built for code with no meaningful BCI. + */ + public static final int UNKNOWN_BCI = -5; + + /** + * The BCI for exception unwind. This is synthetic code and has no representation in bytecode. + * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized, + * the monitor is still held. + */ + public static final int UNWIND_BCI = -1; + + /** + * The BCI for the state before starting to execute a method. Note that if the method is + * synchronized, the monitor is not yet held. + */ + public static final int BEFORE_BCI = -2; + + /** + * The BCI for the state after finishing the execution of a method and returning normally. Note + * that if the method was synchronized the monitor is already released. + */ + public static final int AFTER_BCI = -3; + + /** + * The BCI for exception unwind. This is synthetic code and has no representation in bytecode. + * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the + * monitor is already released. + */ + public static final int AFTER_EXCEPTION_BCI = -4; + + /** + * This BCI should be used for states that cannot be the target of a deoptimization, like + * snippet frame states. + */ + public static final int INVALID_FRAMESTATE_BCI = -6; + + /** * Creates a new frame object. * * @param caller the caller frame (which may be {@code null})
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, 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 @@ -93,4 +93,9 @@ * Gets a description of the target architecture. */ TargetDescription getTarget(); + + /** + * Create a new speculation log for the target runtime. + */ + SpeculationLog createSpeculationLog(); }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.api.code; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; @@ -342,7 +341,7 @@ int sigCount = sig.getParameterCount(false); JavaType[] argTypes; int argIndex = 0; - if (!Modifier.isStatic(method.getModifiers())) { + if (!method.isStatic()) { argTypes = new JavaType[sigCount + 1]; argTypes[argIndex++] = method.getDeclaringClass(); } else {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Mon Apr 28 10:31:17 2014 +0200 @@ -432,22 +432,20 @@ private static final long serialVersionUID = 3612943150662354844L; public final Object id; - public final Mark[] references; - public Mark(int pcOffset, Object id, Mark[] references) { + public Mark(int pcOffset, Object id) { super(pcOffset); this.id = id; - this.references = references; } @Override public String toString() { if (id == null) { - return String.format("%d[<mark with %d references>]", pcOffset, references.length); + return String.format("%d[<mar>]", pcOffset); } else if (id instanceof Integer) { - return String.format("%d[<mark with %d references and id %s>]", pcOffset, references.length, Integer.toHexString((Integer) id)); + return String.format("%d[<mark with id %s>]", pcOffset, Integer.toHexString((Integer) id)); } else { - return String.format("%d[<mark with %d references and id %s>]", pcOffset, references.length, id.toString()); + return String.format("%d[<mark with id %s>]", pcOffset, id.toString()); } } } @@ -635,10 +633,9 @@ * * @param codePos the position in the code that is covered by the handler * @param markId the identifier for this mark - * @param references an array of other marks that this mark references */ - public Mark recordMark(int codePos, Object markId, Mark[] references) { - Mark mark = new Mark(codePos, markId, references); + public Mark recordMark(int codePos, Object markId) { + Mark mark = new Mark(codePos, markId); marks.add(mark); return mark; }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.api.code; import static com.oracle.graal.api.meta.MetaUtil.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.meta.*; @@ -83,7 +81,7 @@ /** * Derives hint information for use when generating the code for a type check instruction. - * + * * @param targetType the target type of the type check * @param profile the profiling information available for the instruction (if any) * @param assumptions the object in which speculations are recorded. This is null if @@ -151,10 +149,10 @@ /** * Determines if a given type can have subtypes other than itself. This analysis is purely * static; no assumptions are made. - * + * * @return true if {@code type} can have subtypes */ public static boolean canHaveSubtype(ResolvedJavaType type) { - return !isFinal(getElementalType(type).getModifiers()); + return !getElementalType(type).isFinal(); } }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.api.meta.test; -import static java.lang.reflect.Modifier.*; import static org.junit.Assert.*; import java.lang.annotation.*; @@ -52,9 +51,9 @@ if (code == null) { assertTrue(m.getCodeSize() == 0); } else { - if (isAbstract(m.getModifiers())) { + if (m.isAbstract()) { assertTrue(code.length == 0); - } else if (!isNative(m.getModifiers())) { + } else if (!m.isNative()) { assertTrue(code.length > 0); } } @@ -69,9 +68,9 @@ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); int codeSize = m.getCodeSize(); - if (isAbstract(m.getModifiers())) { + if (m.isAbstract()) { assertTrue(codeSize == 0); - } else if (!isNative(m.getModifiers())) { + } else if (!m.isNative()) { assertTrue(codeSize > 0); } } @@ -128,6 +127,18 @@ } @Test + public void isSynchronizedTest() { + for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized()); + } + for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized()); + } + } + + @Test public void canBeStaticallyBoundTest() { for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue();
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.api.meta; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; @@ -146,7 +144,7 @@ public ProfiledType(ResolvedJavaType type, double probability) { super(type, probability); - assert type.isArray() || !isAbstract(type.getModifiers()) : type; + assert type.isArray() || !type.isAbstract() : type; } /**
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.api.meta; -import static java.lang.reflect.Modifier.*; - import java.io.*; import java.lang.annotation.*; import java.lang.reflect.*; @@ -378,7 +376,7 @@ break; } case 'f': { - sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : isStatic(((ResolvedJavaMethod) method).getModifiers()) ? "static" : "virtual"); + sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : ((ResolvedJavaMethod) method).isStatic() ? "static" : "virtual"); break; } case '%': { @@ -452,7 +450,7 @@ break; } case 'f': { - sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : isStatic(((ResolvedJavaField) field).getModifiers()) ? "static" : "instance"); + sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) field).isStatic() ? "static" : "instance"); break; } case '%': { @@ -561,7 +559,7 @@ } public static JavaType[] signatureToTypes(ResolvedJavaMethod method) { - JavaType receiver = isStatic(method.getModifiers()) ? null : method.getDeclaringClass(); + JavaType receiver = method.isStatic() ? null : method.getDeclaringClass(); return signatureToTypes(method.getSignature(), receiver); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ModifiersProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,131 @@ +/* + * 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.api.meta; + +import static java.lang.reflect.Modifier.*; + +import java.lang.reflect.*; + +/** + * A Java element (i.e., a class, interface, field or method) that is described by a set of Java + * language {@linkplain #getModifiers() modifiers}. + */ +public interface ModifiersProvider { + + /** + * Returns the Java language modifiers for this element. + */ + int getModifiers(); + + /** + * see {@link Modifier#isInterface(int)} + */ + default boolean isInterface() { + return Modifier.isInterface(getModifiers()); + } + + /** + * see {@link Modifier#isSynchronized(int)} + */ + default boolean isSynchronized() { + return Modifier.isSynchronized(getModifiers()); + } + + /** + * see {@link Modifier#isStatic(int)} + */ + default boolean isStatic() { + return Modifier.isStatic(getModifiers()); + } + + /** + * see {@link Modifier#isFinal(int)} + */ + default boolean isFinal() { + return Modifier.isFinal(getModifiers()); + } + + /** + * see {@link Modifier#isPublic(int)} + */ + default boolean isPublic() { + return Modifier.isPublic(getModifiers()); + } + + /** + * Determines if this element is neither {@linkplain #isPublic() public}, + * {@linkplain #isProtected() protected} nor {@linkplain #isPrivate() private}. + */ + default boolean isPackagePrivate() { + return ((PUBLIC | PROTECTED | PRIVATE) & getModifiers()) == 0; + } + + /** + * see {@link Modifier#isPrivate(int)} + */ + default boolean isPrivate() { + return Modifier.isPrivate(getModifiers()); + } + + /** + * see {@link Modifier#isProtected(int)} + */ + default boolean isProtected() { + return Modifier.isProtected(getModifiers()); + } + + /** + * see {@link Modifier#isTransient(int)} + */ + default boolean isTransient() { + return Modifier.isTransient(getModifiers()); + } + + /** + * see {@link Modifier#isStrict(int)} + */ + default boolean isStrict() { + return Modifier.isStrict(getModifiers()); + } + + /** + * see {@link Modifier#isVolatile(int)} + */ + default boolean isVolatile() { + return Modifier.isVolatile(getModifiers()); + } + + /** + * see {@link Modifier#isNative(int)} + */ + default boolean isNative() { + return Modifier.isNative(getModifiers()); + } + + /** + * see {@link Modifier#isAbstract(int)} + */ + default boolean isAbstract() { + return Modifier.isAbstract(getModifiers()); + } +}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,12 +29,13 @@ * Represents a reference to a resolved Java field. Fields, like methods and types, are resolved * through {@link ConstantPool constant pools}. */ -public interface ResolvedJavaField extends JavaField, LocationIdentity { +public interface ResolvedJavaField extends JavaField, LocationIdentity, ModifiersProvider { /** - * Returns the Java language modifiers for this field, as an integer. The {@link Modifier} class - * should be used to decode the modifiers. Only the {@linkplain Modifier#fieldModifiers() field - * flags} specified in the JVM specification will be included in the returned mask. + * {@inheritDoc} + * <p> + * Only the {@linkplain Modifier#fieldModifiers() field flags} specified in the JVM + * specification will be included in the returned mask. */ int getModifiers(); @@ -53,7 +54,7 @@ * Gets the constant value of this field. Note that a {@code static final} field may not be * considered constant if its declaring class is not yet initialized or if it is a well known * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}). - * + * * @param receiver object from which this field's value is to be read. This value is ignored if * this field is static. * @return the constant value of this field or {@code null} if this field is not considered @@ -65,7 +66,7 @@ * Gets the current value of this field for a given object, if available. There is no guarantee * that the same value will be returned by this method for a field unless the field is * considered to be {@linkplain #readConstantValue(Constant) constant} by the runtime. - * + * * @param receiver object from which this field's value is to be read. This value is ignored if * this field is static. * @return the value of this field or {@code null} if the value is not available (e.g., because @@ -82,7 +83,7 @@ /** * Returns the annotation for the specified type of this field, if such an annotation is * present. - * + * * @param annotationClass the Class object corresponding to the annotation type * @return this element's annotation for the specified annotation type if present on this field, * else {@code null}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,7 +29,7 @@ * Represents a resolved Java method. Methods, like fields and types, are resolved through * {@link ConstantPool constant pools}. */ -public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget { +public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersProvider { /** * Returns the bytecode of this method, if the method has code. The returned byte array does not @@ -69,10 +69,10 @@ int getMaxStackSize(); /** - * Returns the Java language modifiers for this method, as an integer. The {@link Modifier} - * class should be used to decode the modifiers. Only the - * {@linkplain Modifier#methodModifiers() method flags} specified in the JVM specification will - * be included in the returned mask. + * {@inheritDoc} + * <p> + * Only the {@linkplain Modifier#methodModifiers() method flags} specified in the JVM + * specification will be included in the returned mask. */ int getModifiers();
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Mon Apr 28 10:31:17 2014 +0200 @@ -31,7 +31,7 @@ * thereof. Types, like fields and methods, are resolved through {@link ConstantPool constant pools} * . */ -public interface ResolvedJavaType extends JavaType { +public interface ResolvedJavaType extends JavaType, ModifiersProvider { /** * Represents each of the several different parts of the runtime representation of a type which @@ -54,7 +54,7 @@ /** * Gets the encoding of (that is, a constant representing the value of) the specified part of * this type. - * + * * @param r the part of this type * @return a constant representing a reference to the specified part of this type */ @@ -62,7 +62,7 @@ /** * Checks whether this type has a finalizer method. - * + * * @return {@code true} if this class has a finalizer */ boolean hasFinalizer(); @@ -70,51 +70,52 @@ /** * Checks whether this type has any finalizable subclasses so far. Any decisions based on this * information require the registration of a dependency, since this information may change. - * + * * @return {@code true} if this class has any subclasses with finalizers */ boolean hasFinalizableSubclass(); /** * Checks whether this type is an interface. - * + * * @return {@code true} if this type is an interface */ boolean isInterface(); /** * Checks whether this type is an instance class. - * + * * @return {@code true} if this type is an instance class */ boolean isInstanceClass(); /** * Checks whether this type is an array class. - * + * * @return {@code true} if this type is an array class */ boolean isArray(); /** * Checks whether this type is primitive. - * + * * @return {@code true} if this type is primitive */ boolean isPrimitive(); /** - * Returns the Java language modifiers for this type, as an integer. The {@link Modifier} class - * should be used to decode the modifiers. Only the flags specified in the JVM specification - * will be included in the returned mask. This method is identical to - * {@link Class#getModifiers()} in terms of the value return for this type. + * {@inheritDoc} + * <p> + * Only the flags specified in the JVM specification will be included in the returned mask. This + * method is identical to {@link Class#getModifiers()} in terms of the value return for this + * type. */ int getModifiers(); /** * Checks whether this type is initialized. If a type is initialized it implies that it was * {@link #isLinked() linked} and that the static initializer has run. - * + * * @return {@code true} if this type is initialized */ boolean isInitialized(); @@ -127,7 +128,7 @@ /** * Checks whether this type is linked and verified. When a type is linked the static initializer * has not necessarily run. An {@link #isInitialized() initialized} type is always linked. - * + * * @return {@code true} if this type is linked */ boolean isLinked(); @@ -141,7 +142,7 @@ /** * Checks whether the specified object is an instance of this type. - * + * * @param obj the object to test * @return {@code true} if the object is an instance of this type */ @@ -150,7 +151,7 @@ /** * Returns this type if it is an exact type otherwise returns null. This type is exact if it is * void, primitive, final, or an array of a final or primitive type. - * + * * @return this type if it is exact; {@code null} otherwise */ ResolvedJavaType asExactType(); @@ -172,7 +173,7 @@ /** * Walks the class hierarchy upwards and returns the least common class that is a superclass of * both the current and the given type. - * + * * @return the least common type that is a super type of both the current and the given type, or * {@code null} if primitive types are involved. */ @@ -194,7 +195,7 @@ * <p> * If the compiler uses the result of this method for its compilation, it must register an * assumption because dynamic class loading can invalidate the result of this method. - * + * * @return the unique concrete subclass for this type as described above */ ResolvedJavaType findUniqueConcreteSubtype(); @@ -208,7 +209,7 @@ * This resolution process only searches "up" the class hierarchy of this type. A broader search * that also walks "down" the hierarchy is implemented by * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}. - * + * * @param method the method to select the implementation of * @return the concrete method that would be selected at runtime, or {@code null} if there is no * concrete implementation of {@code method} in this type or any of its superclasses @@ -223,7 +224,7 @@ * <p> * If the compiler uses the result of this method for its compilation, it must register an * assumption because dynamic class loading can invalidate the result of this method. - * + * * @param method the method A for which a unique concrete target is searched * @return the unique concrete target or {@code null} if no such target exists or assumptions * are not supported by this runtime @@ -237,7 +238,7 @@ * is, for a single JVM execution the same order is returned each time this method is called. It * is also the "natural" order, which means that the JVM would expect the fields in this order * if no specific order is given. - * + * * @param includeSuperclasses if true, then instance fields for the complete hierarchy of this * type are included in the result * @return an array of instance fields @@ -247,7 +248,7 @@ /** * Returns the annotation for the specified type of this class, if such an annotation is * present. - * + * * @param annotationClass the Class object corresponding to the annotation type * @return this element's annotation for the specified annotation type if present on this class, * else {@code null} @@ -257,7 +258,7 @@ /** * Returns the instance field of this class (or one of its super classes) at the given offset, * or {@code null} if there is no such field. - * + * * @param offset the offset of the field to look for * @return the field with the given offset, or {@code null} if there is no such field. */
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Mon Apr 28 10:31:17 2014 +0200 @@ -40,12 +40,30 @@ } }; + /** + * 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(Kind.Illegal) { + + @Override + public String toString() { + return "INTERIOR_MATCH"; + } + + @Override + public boolean equals(Object other) { + // This class is a singleton + return other != null && getClass() == other.getClass(); + } + }; + private final Kind kind; private final PlatformKind platformKind; /** * Initializes a new value of the specified kind. - * + * * @param platformKind the kind */ protected Value(PlatformKind platformKind) {
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Apr 28 10:31:17 2014 +0200 @@ -1647,9 +1647,14 @@ public final void shrl(Register dst, int imm8) { assert isShiftCount(imm8) : "illegal shift count"; int encode = prefixAndEncode(dst.encoding); - emitByte(0xC1); - emitByte(0xE8 | encode); - emitByte(imm8); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xE8 | encode); + } else { + emitByte(0xC1); + emitByte(0xE8 | encode); + emitByte(imm8); + } } public final void shrl(Register dst) { @@ -1658,6 +1663,82 @@ emitByte(0xE8 | encode); } + public final void roll(Register dst, int imm8) { + assert isShiftCount(imm8) : "illegal shift count"; + int encode = prefixAndEncode(dst.encoding); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xC0 | encode); + } else { + emitByte(0xC1); + emitByte(0xC0 | encode); + emitByte(imm8); + } + } + + public final void roll(Register dst) { + int encode = prefixAndEncode(dst.encoding); + emitByte(0xD3); + emitByte(0xC0 | encode); + } + + public final void rorl(Register dst, int imm8) { + assert isShiftCount(imm8) : "illegal shift count"; + int encode = prefixAndEncode(dst.encoding); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xC8 | encode); + } else { + emitByte(0xC1); + emitByte(0xC8 | encode); + emitByte(imm8); + } + } + + public final void rorl(Register dst) { + int encode = prefixAndEncode(dst.encoding); + emitByte(0xD3); + emitByte(0xC8 | encode); + } + + public final void rolq(Register dst, int imm8) { + assert isShiftCount(imm8) : "illegal shift count"; + int encode = prefixqAndEncode(dst.encoding); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xC0 | encode); + } else { + emitByte(0xC1); + emitByte(0xC0 | encode); + emitByte(imm8); + } + } + + public final void rolq(Register dst) { + int encode = prefixqAndEncode(dst.encoding); + emitByte(0xD3); + emitByte(0xC0 | encode); + } + + public final void rorq(Register dst, int imm8) { + assert isShiftCount(imm8) : "illegal shift count"; + int encode = prefixqAndEncode(dst.encoding); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xC8 | encode); + } else { + emitByte(0xC1); + emitByte(0xC8 | encode); + emitByte(imm8); + } + } + + public final void rorq(Register dst) { + int encode = prefixqAndEncode(dst.encoding); + emitByte(0xD3); + emitByte(0xC8 | encode); + } + public final void sqrtsd(Register dst, AMD64Address src) { assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); @@ -2442,9 +2523,14 @@ public final void shrq(Register dst, int imm8) { assert isShiftCount(imm8 >> 1) : "illegal shift count"; int encode = prefixqAndEncode(dst.encoding); - emitByte(0xC1); - emitByte(0xE8 | encode); - emitByte(imm8); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xE8 | encode); + } else { + emitByte(0xC1); + emitByte(0xE8 | encode); + emitByte(imm8); + } } public final void shrq(Register dst) { @@ -2512,6 +2598,32 @@ emitInt(imm32); } + public final void xaddl(AMD64Address dst, Register src) { + prefix(dst, src); + emitByte(0x0F); + emitByte(0xC1); + emitOperandHelper(src, dst); + } + + public final void xaddq(AMD64Address dst, Register src) { + prefixq(dst, src); + emitByte(0x0F); + emitByte(0xC1); + emitOperandHelper(src, dst); + } + + public final void xchgl(Register dst, AMD64Address src) { + prefix(src, dst); + emitByte(0x87); + emitOperandHelper(dst, src); + } + + public final void xchgq(Register dst, AMD64Address src) { + prefixq(src, dst); + emitByte(0x87); + emitOperandHelper(dst, src); + } + public final void xorq(Register dst, int imm32) { emitArithImm32q(6, dst, imm32); }
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Mon Apr 28 10:31:17 2014 +0200 @@ -548,6 +548,17 @@ } /** + * Emits an atomic_exch_global instruction. + * + * @param result result operand that gets the original contents of the memory location + * @param address the memory location + * @param newValue the new value to write to the memory location + */ + public void emitAtomicExch(Kind accessKind, AllocatableValue result, HSAILAddress address, Value newValue) { + emitString(String.format("atomic_exch_global_b%d %s, %s, %s;", getArgSizeFromKind(accessKind), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(newValue))); + } + + /** * Emits a comment. Useful for debugging purposes. * * @param comment
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java Mon Apr 28 10:31:17 2014 +0200 @@ -30,11 +30,6 @@ public class SPARCAddress extends AbstractAddress { - /** - * Stack bias for stack and frame pointer loads. - */ - private static final int STACK_BIAS = 0x7ff; - private final Register base; private final Register index; private final int displacement; @@ -42,7 +37,7 @@ /** * Creates an {@link SPARCAddress} with given base register, no scaling and a given * displacement. - * + * * @param base the base register * @param displacement the displacement */ @@ -54,7 +49,7 @@ /** * Creates an {@link SPARCAddress} with given base register, no scaling and a given index. - * + * * @param base the base register * @param index the index register */ @@ -113,7 +108,7 @@ /** * This method adds the stack-bias to the displacement if the base register is either * {@link SPARC#sp} or {@link SPARC#fp}. - * + * * @return Optional additive displacement. */ public int getDisplacement() {
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Apr 28 10:31:17 2014 +0200 @@ -37,7 +37,7 @@ /** * Constructs an assembler for the SPARC architecture. - * + * * @param registerConfig the register configuration used to bind {@link Register#Frame} and * {@link Register#CallerFrame} to physical registers. This value can be null if this * assembler instance will not be used to assemble instructions using these logical @@ -50,7 +50,7 @@ // @formatter:off /** * Instruction format for sethi. - * + * * | 00 | rd | op2 | imm22 | * |31 30|29 25|24 22|21 0| */ @@ -123,7 +123,7 @@ // @formatter:off /** * Instruction format for branches. - * + * * | 00 |a | cond | op2 | disp22 | * |31 30|29|28 25|24 22|21 0| */ @@ -142,7 +142,7 @@ // @formatter:off /** * Instruction format for conditional branches. - * + * * | 00 |a | cond | op2 |cc1|cc0|p | disp19 | * |31 30|29|28 25|24 22|21 |20 |19| 0| */ @@ -330,7 +330,7 @@ // @formatter:off /** * Instruction format for calls. - * + * * | 01 | disp30 | * |31 30|29 0| */ @@ -457,7 +457,7 @@ // @formatter:off /** * Instruction format for Arithmetic, Logical, Moves, Tcc, Prefetch, and Misc. - * + * * | 10 | rd | op3 | rs1 | i| imm_asi | rs2 | * | 10 | rd | op3 | rs1 | i| simm13 | * | 10 | rd | op3 | rs1 | i| x| | rs2 | @@ -594,7 +594,7 @@ // @formatter:off /** * Instruction format for Loads, Stores and Misc. - * + * * | 11 | rd | op3 | rs1 | i| imm_asi | rs2 | * | 11 | rd | op3 | rs1 | i| simm13 | * |31 30|29 25|24 19|18 14|13|12 5|4 0| @@ -749,7 +749,7 @@ // @formatter:off /** * Instruction format for Movcc. - * + * * | 10 | rd | op3 |cc2| cond | i|cc1|cc0| - | rs2 | * | 10 | rd | op3 |cc2| cond | i|cc1|cc0| simm11 | * |31 30|29 25|24 19| 18|17 14|13| 12| 11|10 5|4 0| @@ -1007,7 +1007,7 @@ Wrreg(0x30, "wrreg"), Saved(0x31, "saved"), - Fpop1(0x34, "fpop1"), + Fpop1(0b11_0100, "fpop1"), Fpop2(0x35, "fpop2"), Impdep1(0x36, "impdep1"), Impdep2(0x37, "impdep2"), @@ -1036,14 +1036,14 @@ Ldx(0b001011, "ldx"), Stx(0b001110, "stx"), - Ldf(0x20, "ldf"), + Ldf(0b100000, "ldf"), Ldfsr(0x21, "ldfsr"), Ldaf(0x22, "ldaf"), - Lddf(0x23, "lddf"), - Stf(0x24, "stf"), + Lddf(0b100011, "lddf"), + Stf(0b100100, "stf"), Stfsr(0x25, "stfsr"), Staf(0x26, "staf"), - Stdf(0x27, "stdf"); + Stdf(0b100111, "stdf"); // @formatter:on @@ -1092,9 +1092,9 @@ public enum Opfs { // @formatter:off - Fmovs(0x01, "fmovs"), - Fmovd(0x02, "fmovd"), - Fmovq(0x03, "fmovq"), + Fmovs(0b0_0000_0001, "fmovs"), + Fmovd(0b0_0000_0010, "fmovd"), + Fmovq(0b0_0000_0011, "fmovq"), Fnegs(0x05, "fnegs"), Fnegd(0x06, "fnegd"), Fnegq(0x07, "fnegq"), @@ -2376,6 +2376,20 @@ } } + public static class Fmovs extends Fmt3p { + + public Fmovs(Register src, Register dst) { + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovs, g0, src, dst); + } + } + + public static class Fmovd extends Fmt3p { + + public Fmovd(Register src, Register dst) { + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovd, g0, src, dst); + } + } + public static class Fmuls extends Fmt3p { public Fmuls(Register src1, Register src2, Register dst) { @@ -3174,6 +3188,20 @@ } } + public static class Stdf extends Fmt11 { + + public Stdf(Register dst, SPARCAddress src) { + super(Op3s.Stdf, src, dst); + } + } + + public static class Stf extends Fmt11 { + + public Stf(Register dst, SPARCAddress src) { + super(Op3s.Stf, src, dst); + } + } + public static class Sth extends Fmt11 { public Sth(Register dst, SPARCAddress addr) {
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,7 @@ */ package com.oracle.graal.baseline; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -45,13 +44,13 @@ import com.oracle.graal.java.BciBlockMapping.LocalLiveness; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.BlockEndOp; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.*; -public class BaselineBytecodeParser extends AbstractBytecodeParser<Value, LIRFrameStateBuilder> implements BytecodeParserTool { +public class BaselineBytecodeParser extends AbstractBytecodeParser<Value, BaselineFrameStateBuilder> implements BytecodeParserTool { private Backend backend; - protected LIRGenerator gen; + protected LIRGeneratorTool gen; private LIRGenerationResult lirGenRes; private BytecodeLIRBuilder lirBuilder; @SuppressWarnings("unused") private BciBlock[] loopHeaders; @@ -75,7 +74,7 @@ } public BaselineBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, - LIRFrameStateBuilder frameState, BytecodeStream stream, ProfilingInfo profilingInfo, ConstantPool constantPool, int entryBCI, Backend backend) { + BaselineFrameStateBuilder frameState, BytecodeStream stream, ProfilingInfo profilingInfo, ConstantPool constantPool, int entryBCI, Backend backend) { super(metaAccess, method, graphBuilderConfig, optimisticOpts, frameState, stream, profilingInfo, constantPool, entryBCI); this.backend = backend; @@ -106,11 +105,11 @@ } } - if (isSynchronized(method.getModifiers())) { + if (method.isSynchronized()) { throw GraalInternalError.unimplemented("Handle synchronized methods"); } - frameState = new LIRFrameStateBuilder(method); + frameState = new BaselineFrameStateBuilder(method); frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true); currentBlock = blockMap.startBlock; @@ -122,7 +121,7 @@ // add loops ? how do we add looks when we haven't parsed the bytecode? // create the control flow graph - LIRControlFlowGraph cfg = new LIRControlFlowGraph(blockMap); + BaselineControlFlowGraph cfg = new BaselineControlFlowGraph(blockMap); BlocksToDoubles blockProbabilities = new BlocksToDoubles(blockMap.blocks.size()); for (BciBlock b : blockMap.blocks) { @@ -609,7 +608,7 @@ } // We already saw this block before, so we have to merge states. - if (!((LIRFrameStateBuilder) block.entryState).isCompatibleWith(frameState)) { + if (!((BaselineFrameStateBuilder) block.entryState).isCompatibleWith(frameState)) { throw new BailoutException("stacks do not match; bytecodes would not verify"); } @@ -617,7 +616,7 @@ assert currentBlock == null || currentBlock.getId() >= block.getId() : "must be backward branch"; if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) { // this is the only successor of the current block so we can adjust - adaptFramestate((LIRFrameStateBuilder) block.entryState); + adaptFramestate((BaselineFrameStateBuilder) block.entryState); return; } GraalInternalError.unimplemented("Loops not yet supported"); @@ -631,7 +630,7 @@ */ if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) { // this is the only successor of the current block so we can adjust - adaptFramestate((LIRFrameStateBuilder) block.entryState); + adaptFramestate((BaselineFrameStateBuilder) block.entryState); return; } GraalInternalError.unimplemented("second block visit not yet implemented"); @@ -675,7 +674,7 @@ } } - private void adaptFramestate(LIRFrameStateBuilder other) { + private void adaptFramestate(BaselineFrameStateBuilder other) { assert frameState.isCompatibleWith(other) : "framestates not compatible!"; PhiResolver resolver = new PhiResolver(gen); for (int i = 0; i < frameState.stackSize(); i++) { @@ -693,7 +692,7 @@ @Override protected void processBlock(BciBlock block) { - frameState = (LIRFrameStateBuilder) block.entryState; + frameState = (BaselineFrameStateBuilder) block.entryState; setCurrentFrameState(frameState); currentBlock = block; iterateBytecodesForBlock(block);
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.baseline; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -57,7 +57,7 @@ ConstantPool constantPool = method.getConstantPool(); TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); - LIRFrameStateBuilder frameState = new LIRFrameStateBuilder(method); + BaselineFrameStateBuilder frameState = new BaselineFrameStateBuilder(method); BaselineBytecodeParser parser = new BaselineBytecodeParser(metaAccess, method, graphBuilderConfig, optimisticOpts, frameState, stream, profilingInfo, constantPool, entryBCI, backend);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,99 @@ +/* + * 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.baseline; + +import java.util.*; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.BciBlockMapping.BciBlock; + +public class BaselineControlFlowGraph implements AbstractControlFlowGraph<BciBlock> { + + private BciBlock[] blocks; + private Collection<Loop<BciBlock>> loops; + private BitSet visited; + + public BaselineControlFlowGraph(BciBlockMapping blockMap) { + blocks = blockMap.blocks.toArray(new BciBlock[0]); + loops = new ArrayList<>(); + computeLoopInformation(); + } + + public BciBlock[] getBlocks() { + return blocks; + } + + public Collection<Loop<BciBlock>> getLoops() { + return loops; + } + + public BciBlock getStartBlock() { + if (blocks.length > 0) { + return blocks[0]; + } + return null; + } + + private void computeLoopInformation() { + visited = new BitSet(blocks.length); + Deque<BaselineLoop> stack = new ArrayDeque<>(); + for (int i = blocks.length - 1; i >= 0; i--) { + BciBlock block = blocks[i]; + calcLoop(block, stack); + } + } + + private void calcLoop(BciBlock block, Deque<BaselineLoop> stack) { + if (visited.get(block.getId())) { + return; + } + visited.set(block.getId()); + if (block.isLoopEnd()) { + BciBlock loopHeader = getLoopHeader(block); + BaselineLoop l = new BaselineLoop(stack.peek(), loops.size(), loopHeader); + loops.add(l); + stack.push(l); + } + block.loop = stack.peek(); + if (block.isLoopHeader()) { + assert block.loop.header.equals(block); + stack.pop(); + } + for (BciBlock pred : block.getPredecessors()) { + calcLoop(pred, stack); + } + } + + private static BciBlock getLoopHeader(BciBlock block) { + assert block.isLoopEnd(); + for (BciBlock sux : block.getSuccessors()) { + if (sux.isLoopHeader() && sux.getId() <= block.getId() && block.loops == sux.loops) { + return sux; + } + } + throw GraalInternalError.shouldNotReachHere("No loop header found for " + block); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineFrameStateBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,103 @@ +/* + * 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.baseline; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.java.*; + +public class BaselineFrameStateBuilder extends AbstractFrameStateBuilder<Value, BaselineFrameStateBuilder> { + + private static final Value[] EMPTY_ARRAY = new Value[0]; + + public BaselineFrameStateBuilder(ResolvedJavaMethod method) { + // we always need at least one stack slot (for exceptions) + super(method, new Value[method.getMaxLocals()], new Value[Math.max(1, method.getMaxStackSize())], EMPTY_ARRAY); + } + + protected BaselineFrameStateBuilder(BaselineFrameStateBuilder other) { + super(other); + } + + @Override + protected Value[] getEmtpyArray() { + return EMPTY_ARRAY; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[locals: ["); + for (int i = 0; i < locals.length; i++) { + sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString()); + } + sb.append("] stack: ["); + for (int i = 0; i < stackSize; i++) { + sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString()); + } + sb.append("] locks: ["); + for (int i = 0; i < lockedObjects.length; i++) { + sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString()); + } + sb.append("]"); + if (rethrowException) { + sb.append(" rethrowException"); + } + sb.append("]"); + return sb.toString(); + } + + @Override + public BaselineFrameStateBuilder copy() { + return new BaselineFrameStateBuilder(this); + } + + private static boolean isCompatible(Value x, Value y) { + if (x == null && y == null) { + return true; + } + if ((x == null || y == null) || (x.getKind() != y.getKind())) { + return false; + } + return true; + + } + + @Override + public boolean isCompatibleWith(BaselineFrameStateBuilder other) { + assert method.equals(other.method) && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; + + if (stackSize() != other.stackSize()) { + return false; + } + for (int i = 0; i < stackSize(); i++) { + if (!isCompatible(stackAt(i), other.stackAt(i))) { + return false; + } + } + if (lockedObjects.length != other.lockedObjects.length) { + return false; + } + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineLoop.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,41 @@ +/* + * 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.baseline; + +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.java.BciBlockMapping.BciBlock; + +public class BaselineLoop extends Loop<BciBlock> { + + protected BaselineLoop(Loop<BciBlock> parent, int index, BciBlock header) { + super(parent, index, header); + } + + @Override + public long numBackedges() { + // currently only loops with one backedge are supported + return 1; + } + +}
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * 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.baseline; - -import java.util.*; - -import com.oracle.graal.compiler.common.cfg.*; - -public class LIRBlock extends AbstractBlockBase<LIRBlock> { - - public LIRBlock(int id) { - this.id = id; - predecessors = Collections.emptyList(); - successors = Collections.emptyList(); - } - - public Loop<LIRBlock> getLoop() { - // TODO Auto-generated method stub - return null; - } - - public int getLoopDepth() { - // TODO Auto-generated method stub - return 0; - } - - public boolean isLoopEnd() { - // TODO Auto-generated method stub - return false; - } - - public boolean isLoopHeader() { - // TODO Auto-generated method stub - return false; - } - - public boolean isExceptionEntry() { - // TODO Auto-generated method stub - return false; - } - -}
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * 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.baseline; - -import java.util.*; - -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.java.*; -import com.oracle.graal.java.BciBlockMapping.BciBlock; - -public class LIRControlFlowGraph implements AbstractControlFlowGraph<BciBlock> { - - private BciBlock[] blocks; - private Collection<Loop<BciBlock>> loops; - private BitSet visited; - - public LIRControlFlowGraph(BciBlockMapping blockMap) { - blocks = blockMap.blocks.toArray(new BciBlock[0]); - loops = new ArrayList<>(); - computeLoopInformation(); - } - - public BciBlock[] getBlocks() { - return blocks; - } - - public Collection<Loop<BciBlock>> getLoops() { - return loops; - } - - public BciBlock getStartBlock() { - if (blocks.length > 0) { - return blocks[0]; - } - return null; - } - - private void computeLoopInformation() { - visited = new BitSet(blocks.length); - Deque<LIRLoop> stack = new ArrayDeque<>(); - for (int i = blocks.length - 1; i >= 0; i--) { - BciBlock block = blocks[i]; - calcLoop(block, stack); - } - } - - private void calcLoop(BciBlock block, Deque<LIRLoop> stack) { - if (visited.get(block.getId())) { - return; - } - visited.set(block.getId()); - if (block.isLoopEnd()) { - BciBlock loopHeader = getLoopHeader(block); - LIRLoop l = new LIRLoop(stack.peek(), loops.size(), loopHeader); - loops.add(l); - stack.push(l); - } - block.loop = stack.peek(); - if (block.isLoopHeader()) { - assert block.loop.header.equals(block); - stack.pop(); - } - for (BciBlock pred : block.getPredecessors()) { - calcLoop(pred, stack); - } - } - - private static BciBlock getLoopHeader(BciBlock block) { - assert block.isLoopEnd(); - for (BciBlock sux : block.getSuccessors()) { - if (sux.isLoopHeader() && sux.getId() <= block.getId() && block.loops == sux.loops) { - return sux; - } - } - throw GraalInternalError.shouldNotReachHere("No loop header found for " + block); - } - -}
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * 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.baseline; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.java.*; - -public class LIRFrameStateBuilder extends AbstractFrameStateBuilder<Value, LIRFrameStateBuilder> { - - private static final Value[] EMPTY_ARRAY = new Value[0]; - - public LIRFrameStateBuilder(ResolvedJavaMethod method) { - // we always need at least one stack slot (for exceptions) - super(method, new Value[method.getMaxLocals()], new Value[Math.max(1, method.getMaxStackSize())], EMPTY_ARRAY); - } - - protected LIRFrameStateBuilder(LIRFrameStateBuilder other) { - super(other); - } - - @Override - protected Value[] getEmtpyArray() { - return EMPTY_ARRAY; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[locals: ["); - for (int i = 0; i < locals.length; i++) { - sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString()); - } - sb.append("] stack: ["); - for (int i = 0; i < stackSize; i++) { - sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString()); - } - sb.append("] locks: ["); - for (int i = 0; i < lockedObjects.length; i++) { - sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString()); - } - sb.append("]"); - if (rethrowException) { - sb.append(" rethrowException"); - } - sb.append("]"); - return sb.toString(); - } - - @Override - public LIRFrameStateBuilder copy() { - return new LIRFrameStateBuilder(this); - } - - private static boolean isCompatible(Value x, Value y) { - if (x == null && y == null) { - return true; - } - if ((x == null || y == null) || (x.getKind() != y.getKind())) { - return false; - } - return true; - - } - - @Override - public boolean isCompatibleWith(LIRFrameStateBuilder other) { - assert method.equals(other.method) && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; - - if (stackSize() != other.stackSize()) { - return false; - } - for (int i = 0; i < stackSize(); i++) { - if (!isCompatible(stackAt(i), other.stackAt(i))) { - return false; - } - } - if (lockedObjects.length != other.lockedObjects.length) { - return false; - } - return true; - } -}
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRLoop.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * 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.baseline; - -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.java.BciBlockMapping.BciBlock; - -public class LIRLoop extends Loop<BciBlock> { - - protected LIRLoop(Loop<BciBlock> parent, int index, BciBlock header) { - super(parent, index, header); - } - - @Override - public long numBackedges() { - // currently only loops with one backedge are supported - return 1; - } - -}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -37,7 +37,7 @@ import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.amd64.*; @@ -52,6 +52,7 @@ import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary1Op; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2MemoryOp; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2Op; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2RegOp; import com.oracle.graal.lir.amd64.AMD64Compare.CompareMemoryOp; import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; @@ -68,9 +69,7 @@ import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp; import com.oracle.graal.lir.amd64.AMD64Move.ZeroExtendLoadOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.phases.util.*; /** @@ -264,6 +263,25 @@ } } + public void emitCompareBranchMemory(Kind cmpKind, Value left, AMD64AddressValue right, LIRFrameState state, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel, + double trueLabelProbability) { + boolean mirrored = emitCompareMemory(cmpKind, left, right, state); + Condition finalCondition = mirrored ? cond.mirror() : cond; + switch (left.getKind().getStackKind()) { + case Int: + case Long: + case Object: + append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); + break; + case Float: + case Double: + append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability)); + break; + default: + throw GraalInternalError.shouldNotReachHere("" + left.getKind()); + } + } + @Override public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) { append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow, overflowProbability)); @@ -344,6 +362,26 @@ } } + /** + * This method emits the compare against memory instruction, and may reorder the operands. It + * returns true if it did so. + * + * @param b the right operand of the comparison + * @return true if the left and right operands were switched, false otherwise + */ + private boolean emitCompareMemory(Kind cmpKind, Value a, AMD64AddressValue b, LIRFrameState state) { + boolean mirrored; + if (LIRValueUtil.isVariable(a)) { + Variable left = load(a); + emitCompareRegMemoryOp(cmpKind, left, b, state); + mirrored = false; + } else { + emitCompareMemoryConOp(cmpKind, b, a, state); + mirrored = true; + } + return mirrored; + } + protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Value value, LIRFrameState state) { assert kind.getStackKind() == value.getKind().getStackKind(); switch (kind) { @@ -589,8 +627,7 @@ append(new DivRemOp(op, rax, asAllocatable(b), state)); } - public Value[] emitIntegerDivRem(Value a, Value b, DeoptimizingNode deopting) { - LIRFrameState state = state(deopting); + public Value[] emitIntegerDivRem(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: emitDivRem(IDIVREM, a, b, state); @@ -604,13 +641,13 @@ } @Override - public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitDiv(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: - emitDivRem(IDIV, a, b, state(deopting)); + emitDivRem(IDIV, a, b, state); return emitMove(RAX_I); case Long: - emitDivRem(LDIV, a, b, state(deopting)); + emitDivRem(LDIV, a, b, state); return emitMove(RAX_L); case Float: { Variable result = newVariable(a.getPlatformKind()); @@ -628,13 +665,13 @@ } @Override - public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { + public Value emitRem(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: - emitDivRem(IREM, a, b, state(deopting)); + emitDivRem(IREM, a, b, state); return emitMove(RDX_I); case Long: - emitDivRem(LREM, a, b, state(deopting)); + emitDivRem(LREM, a, b, state); return emitMove(RDX_L); case Float: { Variable result = newVariable(a.getPlatformKind()); @@ -652,8 +689,7 @@ } @Override - public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { - LIRFrameState state = state(deopting); + public Variable emitUDiv(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: emitDivRem(IUDIV, a, b, state); @@ -667,8 +703,7 @@ } @Override - public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { - LIRFrameState state = state(deopting); + public Variable emitURem(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: emitDivRem(IUREM, a, b, state); @@ -765,9 +800,31 @@ } } - private AllocatableValue emitConvert1Op(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) { + public Variable emitRol(Value a, Value b) { + switch (a.getKind().getStackKind()) { + case Int: + return emitShift(IROL, a, b); + case Long: + return emitShift(LROL, a, b); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + public Variable emitRor(Value a, Value b) { + switch (a.getKind().getStackKind()) { + case Int: + return emitShift(IROR, a, b); + case Long: + return emitShift(LROR, a, b); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private AllocatableValue emitConvert2RegOp(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) { Variable result = newVariable(kind); - append(new Unary1Op(op, result, input)); + append(new Unary2RegOp(op, result, input)); return result; } @@ -850,7 +907,7 @@ public Value emitNarrow(Value inputVal, int bits) { if (inputVal.getKind() == Kind.Long && bits <= 32) { // TODO make it possible to reinterpret Long as Int in LIR without move - return emitConvert1Op(Kind.Int, L2I, asAllocatable(inputVal)); + return emitConvert2RegOp(Kind.Int, L2I, asAllocatable(inputVal)); } else { return inputVal; } @@ -1020,7 +1077,7 @@ } @Override - protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { + public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { // a temp is needed for loading object constants boolean needsTemp = key.getKind() == Kind.Object; append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL));
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.compiler.amd64; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; import static com.oracle.graal.nodes.ConstantNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; @@ -41,10 +41,8 @@ import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class AMD64MemoryPeephole implements MemoryArithmeticLIRLowerer { protected final AMD64NodeLIRBuilder gen; @@ -73,13 +71,13 @@ protected LIRFrameState getState(Access access) { if (access instanceof DeoptimizingNode) { - return gen.getLIRGenerator().state((DeoptimizingNode) access); + return gen.state((DeoptimizingNode) access); } return null; } protected Kind getMemoryKind(Access access) { - return (Kind) gen.getLIRGenerator().getPlatformKind(access.asNode().stamp()); + return (Kind) gen.getLIRGeneratorTool().getPlatformKind(access.asNode().stamp()); } protected AMD64AddressValue makeAddress(Access access) { @@ -96,7 +94,7 @@ } } ensureEvaluated(other); - return gen.getLIRGenerator().emitBinaryMemory(op, getMemoryKind(access), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access)); + return gen.getLIRGeneratorTool().emitBinaryMemory(op, getMemoryKind(access), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access)); } /** @@ -130,7 +128,7 @@ AMD64AddressValue address = makeAddress(access); LIRFrameState state = getState(access); evaluateDeferred(); - return gen.getLIRGenerator().emitConvert2MemoryOp(kind, op, address, state); + return gen.getLIRGeneratorTool().emitConvert2MemoryOp(kind, op, address, state); } @Override @@ -254,7 +252,7 @@ @Override public Value emitReinterpretMemory(Stamp stamp, Access access) { - PlatformKind to = gen.getLIRGenerator().getPlatformKind(stamp); + PlatformKind to = gen.getLIRGeneratorTool().getPlatformKind(stamp); Kind from = getMemoryKind(access); assert to != from : "should have been eliminated"; @@ -372,7 +370,7 @@ memoryKind = Kind.Char; } evaluateDeferred(); - return gen.getLIRGenerator().emitZeroExtendMemory(memoryKind, toBits, makeAddress(access), getState(access)); + return gen.getLIRGeneratorTool().emitZeroExtendMemory(memoryKind, toBits, makeAddress(access), getState(access)); } public boolean emitIfMemory(IfNode x, Access access) { @@ -465,7 +463,7 @@ } } ensureEvaluated(other); - gen.getLIRGenerator().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access)); + gen.getLIRGeneratorTool().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access)); mirrored = uncast(right) == access; } else { if (kind == Kind.Object) { @@ -475,7 +473,7 @@ } evaluateDeferred(); - gen.getLIRGenerator().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access)); + gen.getLIRGeneratorTool().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access)); mirrored = uncast(left) == access; }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,19 +23,29 @@ package com.oracle.graal.compiler.amd64; +import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; + import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.match.*; +import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder { - public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) { + public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen) { super(graph, gen); } @@ -60,7 +70,7 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) { assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt; - append(new AMD64Move.NullCheckOp(gen.load(operand(v)), gen.state(deopt))); + append(new AMD64Move.NullCheckOp(gen.load(operand(v)), state(deopt))); } @Override @@ -73,7 +83,7 @@ if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) { FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode; if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && !hasOperand(otherDivRem)) { - Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode); + Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), state((DeoptimizingNode) valueNode)); if (divRem instanceof IntegerDivNode) { setResult(divRem, results[0]); setResult(otherDivRem, results[1]); @@ -90,6 +100,525 @@ return false; } + protected LIRFrameState getState(Access access) { + if (access instanceof DeoptimizingNode) { + return state((DeoptimizingNode) access); + } + return null; + } + + protected Kind getMemoryKind(Access access) { + return (Kind) gen.getPlatformKind(access.asNode().stamp()); + } + + protected AMD64AddressValue makeAddress(Access access) { + return (AMD64AddressValue) access.accessLocation().generateAddress(this, gen, operand(access.object())); + } + + protected ValueNode uncast(ValueNode value) { + if (value instanceof UnsafeCastNode) { + UnsafeCastNode cast = (UnsafeCastNode) value; + return cast.getOriginalNode(); + } + return value; + } + + protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, Access access) { + Condition cond = compare.condition(); + Kind kind = getMemoryKind(access); + + if (value.isConstant()) { + Constant constant = value.asConstant(); + if (kind == Kind.Long && !NumUtil.isInt(constant.asLong())) { + // Only imm32 as long + return null; + } + if (kind.isNumericFloat()) { + Debug.log("Skipping constant compares for float kinds"); + return null; + } + if (kind == Kind.Object) { + if (!constant.isNull()) { + Debug.log("Skipping constant compares for Object kinds"); + return null; + } + } + } else { + if (kind == Kind.Object) { + // Can't compare against objects since they require encode/decode + Debug.log("Skipping compares for Object kinds"); + return null; + } + } + + PlatformKind cmpKind = gen.getPlatformKind(compare.x().stamp()); + if (cmpKind instanceof Kind) { + // emitCompareBranchMemory expects the memory on the right, so mirror the condition if + // that's not true. It might be mirrored again the actual compare is emitted but that's + // ok. + Condition finalCondition = uncast(compare.x()) == access ? cond.mirror() : cond; + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor()); + boolean unorderedIsTrue = compare.unorderedIsTrue(); + double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); + Value other; + if (value.isConstant()) { + other = value.asConstant(); + } else { + other = operand(value); + } + + getLIRGeneratorTool().emitCompareBranchMemory((Kind) cmpKind, other, makeAddress(access), getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, + trueLabelProbability); + return null; + } + }; + } + return null; + + } + + private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, Access access) { + LabelRef trueLabel = getLIRBlock(x.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(x.falseSuccessor()); + double trueLabelProbability = x.probability(x.trueSuccessor()); + Kind kind = getMemoryKind(access); + if (value.isConstant()) { + if (kind != kind.getStackKind()) { + return null; + } + Constant constant = value.asConstant(); + if (kind == Kind.Long && !NumUtil.isInt(constant.asLong())) { + // Only imm32 as long + return null; + } + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + gen.append(new AMD64TestMemoryOp(kind, makeAddress(access), constant, getState(access))); + gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability)); + return null; + } + }; + } else { + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + gen.append(new AMD64TestMemoryOp(kind, makeAddress(access), operand(value), getState(access))); + gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability)); + return null; + } + }; + } + } + + protected Value emitConvert2MemoryOp(PlatformKind kind, AMD64Arithmetic op, Access access) { + AMD64AddressValue address = makeAddress(access); + LIRFrameState state = getState(access); + return getLIRGeneratorTool().emitConvert2MemoryOp(kind, op, address, state); + } + + private Value emitFloatConvertMemory(FloatConvertNode op, Access access) { + switch (op.getOp()) { + case D2F: + return emitConvert2MemoryOp(Kind.Float, D2F, access); + case D2I: + return emitConvert2MemoryOp(Kind.Int, D2I, access); + case D2L: + return emitConvert2MemoryOp(Kind.Long, D2L, access); + case F2D: + return emitConvert2MemoryOp(Kind.Double, F2D, access); + case F2I: + return emitConvert2MemoryOp(Kind.Int, F2I, access); + case F2L: + return emitConvert2MemoryOp(Kind.Long, F2L, access); + case I2D: + return emitConvert2MemoryOp(Kind.Double, I2D, access); + case I2F: + return emitConvert2MemoryOp(Kind.Float, I2F, access); + case L2D: + return emitConvert2MemoryOp(Kind.Double, L2D, access); + case L2F: + return emitConvert2MemoryOp(Kind.Float, L2F, access); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) { + assert fromBits <= toBits && toBits <= 64; + Kind kind = null; + AMD64Arithmetic op = null; + if (fromBits == toBits) { + return null; + } else if (toBits > 32) { + kind = Kind.Long; + // sign extend to 64 bits + switch (fromBits) { + case 8: + op = B2L; + break; + case 16: + op = S2L; + break; + case 32: + op = I2L; + break; + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } else { + kind = Kind.Int; + // sign extend to 32 bits (smaller values are internally represented as 32 bit values) + switch (fromBits) { + case 8: + op = B2I; + break; + case 16: + op = S2I; + break; + case 32: + return null; + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } + if (kind != null && op != null) { + Kind localKind = kind; + AMD64Arithmetic localOp = op; + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + return emitConvert2MemoryOp(localKind, localOp, access); + } + }; + } + return null; + } + + private Value emitReinterpretMemory(PlatformKind to, Access access) { + Kind from = getMemoryKind(access); + assert to != from : "should have been eliminated"; + + /* + * Conversions between integer to floating point types require moves between CPU and FPU + * registers. + */ + switch ((Kind) to) { + case Int: + switch (from) { + case Float: + return emitConvert2MemoryOp(to, MOV_F2I, access); + } + break; + case Long: + switch (from) { + case Double: + return emitConvert2MemoryOp(to, MOV_D2L, access); + } + break; + case Float: + switch (from) { + case Int: + return emitConvert2MemoryOp(to, MOV_I2F, access); + } + break; + case Double: + switch (from) { + case Long: + return emitConvert2MemoryOp(to, MOV_L2D, access); + } + break; + } + throw GraalInternalError.shouldNotReachHere(); + } + + static Object lock = new Object(); + + private AMD64Arithmetic getOp(ValueNode operation, Access access) { + Kind memoryKind = getMemoryKind(access); + if (operation.getClass() == IntegerAddNode.class) { + switch (memoryKind) { + case Int: + return IADD; + case Long: + return LADD; + } + } else if (operation.getClass() == FloatAddNode.class) { + switch (memoryKind) { + case Float: + return FADD; + case Double: + return DADD; + } + } else if (operation.getClass() == AndNode.class) { + switch (memoryKind) { + case Int: + return IAND; + case Long: + return LAND; + } + } else if (operation.getClass() == OrNode.class) { + switch (memoryKind) { + case Int: + return IOR; + case Long: + return LOR; + } + } else if (operation.getClass() == XorNode.class) { + switch (memoryKind) { + case Int: + return IXOR; + case Long: + return LXOR; + } + } else if (operation.getClass() == IntegerSubNode.class) { + switch (memoryKind) { + case Int: + return ISUB; + case Long: + return LSUB; + } + } else if (operation.getClass() == FloatSubNode.class) { + switch (memoryKind) { + case Float: + return FSUB; + case Double: + return DSUB; + } + } else if (operation.getClass() == IntegerMulNode.class) { + switch (memoryKind) { + case Int: + return IMUL; + case Long: + return LMUL; + } + } else if (operation.getClass() == FloatMulNode.class) { + switch (memoryKind) { + case Float: + return FMUL; + case Double: + return DMUL; + } + } + return null; + } + + @MatchRule("(If (IntegerTest=compare Read=access value))") + @MatchRule("(If (IntegerTest=compare FloatingRead=access value))") + public static class IfIntegerTest extends AMD64MatchGenerator { + IfNode root; + Access access; + ValueNode value; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return gen.emitIntegerTestBranchMemory(root, value, access); + } + } + + @MatchRule("(If (IntegerEquals=compare value Read=access))") + @MatchRule("(If (IntegerLessThan=compare value Read=access))") + @MatchRule("(If (IntegerBelowThan=compare value Read=access))") + @MatchRule("(If (IntegerEquals=compare value FloatingRead=access))") + @MatchRule("(If (IntegerLessThan=compare value FloatingRead=access))") + @MatchRule("(If (IntegerBelowThan=compare value FloatingRead=access))") + @MatchRule("(If (FloatEquals=compare value Read=access))") + @MatchRule("(If (FloatEquals=compare value FloatingRead=access))") + @MatchRule("(If (FloatLessThan=compare value Read=access))") + @MatchRule("(If (FloatLessThan=compare value FloatingRead=access))") + public static class IfCompareMemory extends AMD64MatchGenerator { + IfNode root; + Access access; + ValueNode value; + CompareNode compare; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return gen.emitCompareBranchMemory(root, compare, value, access); + } + } + + @MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))") + public static class RotateLeftConstant extends AMD64MatchGenerator { + LeftShiftNode lshift; + UnsignedRightShiftNode rshift; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + if ((lshift.getShiftAmountMask() & (lshift.y().asConstant().asInt() + rshift.y().asConstant().asInt())) == 0) { + return builder -> gen.getLIRGeneratorTool().emitRol(gen.operand(lshift.x()), gen.operand(lshift.y())); + } + return null; + } + + } + + @MatchRule("(Or (LeftShift=lshift value (IntegerSub Constant=delta shiftAmount)) (UnsignedRightShift value shiftAmount))") + public static class RotateRightVariable extends AMD64MatchGenerator { + ValueNode value; + ValueNode shiftAmount; + ConstantNode delta; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + if (delta.asConstant().asLong() == 0 || delta.asConstant().asLong() == 32) { + return builder -> gen.getLIRGeneratorTool().emitRor(gen.operand(value), gen.operand(shiftAmount)); + } + return null; + } + + } + + @MatchRule("(Or (LeftShift value shiftAmount) (UnsignedRightShift value (IntegerSub Constant=delta shiftAmount)))") + public static class RotateLeftVariable extends AMD64MatchGenerator { + ValueNode value; + ValueNode shiftAmount; + ConstantNode delta; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + if (delta.asConstant().asLong() == 0 || delta.asConstant().asLong() == 32) { + return builder -> gen.getLIRGeneratorTool().emitRol(gen.operand(value), gen.operand(shiftAmount)); + } + return null; + } + } + + @MatchRule("(IntegerAdd value Read=access)") + @MatchRule("(IntegerSub value Read=access)") + @MatchRule("(IntegerMul value Read=access)") + @MatchRule("(FloatAdd value Read=access)") + @MatchRule("(FloatSub value Read=access)") + @MatchRule("(FloatMul value Read=access)") + @MatchRule("(Or value Read=access)") + @MatchRule("(Xor value Read=access)") + @MatchRule("(And value Read=access)") + @MatchRule("(IntegerAdd value FloatingRead=access)") + @MatchRule("(IntegerSub value FloatingRead=access)") + @MatchRule("(IntegerMul value FloatingRead=access)") + @MatchRule("(FloatAdd value FloatingRead=access)") + @MatchRule("(FloatSub value FloatingRead=access)") + @MatchRule("(FloatMul value FloatingRead=access)") + @MatchRule("(Or value FloatingRead=access)") + @MatchRule("(Xor value FloatingRead=access)") + @MatchRule("(And value FloatingRead=access)") + public static class BinaryRead extends AMD64MatchGenerator { + BinaryNode root; + Access access; + ValueNode value; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + AMD64Arithmetic op = gen.getOp(root, access); + if (op != null) { + return builder -> gen.getLIRGeneratorTool().emitBinaryMemory(op, gen.getMemoryKind(access), gen.getLIRGeneratorTool().asAllocatable(gen.operand(value)), gen.makeAddress(access), + gen.getState(access)); + } + return null; + } + } + + @MatchRule("(Write Narrow=narrow value)") + public static class WriteNarrow extends AMD64MatchGenerator { + WriteNode root; + NarrowNode narrow; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return new ComplexMatchResult() { + @Override + public Value evaluate(NodeLIRBuilder builder) { + PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(root.value().stamp()); + Value address = root.location().generateAddress(builder, gen.getLIRGeneratorTool(), gen.operand(root.object())); + Value v = gen.operand(narrow.getInput()); + gen.getLIRGeneratorTool().emitStore(writeKind, address, v, gen.state(root)); + return null; + } + }; + } + } + + @MatchRule("(SignExtend Read=access)") + @MatchRule("(SignExtend FloatingRead=access)") + public static class SignExtend extends AMD64MatchGenerator { + Access access; + SignExtendNode root; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return gen.emitSignExtendMemory(access, root.getInputBits(), root.getResultBits()); + } + } + + static abstract class AMD64MatchGenerator implements MatchGenerator { + public AMD64MatchGenerator() { + } + + public ComplexMatchResult match(NodeLIRBuilder gen) { + return match((AMD64NodeLIRBuilder) gen); + } + + abstract public ComplexMatchResult match(AMD64NodeLIRBuilder gen); + } + + @MatchRule("(ZeroExtend Read=access)") + @MatchRule("(ZeroExtend FloatingRead=access)") + public static class ZeroExtend extends AMD64MatchGenerator { + Access access; + ZeroExtendNode root; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + Kind memoryKind = gen.getMemoryKind(access); + if (memoryKind.getBitCount() != root.getInputBits() && !memoryKind.isUnsigned()) { + /* + * The memory being read from is signed and smaller than the result size so this is + * a sign extension to inputBits followed by a zero extension to resultBits which + * can't be expressed in a memory operation. + */ + return null; + } + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder unused) { + return gen.getLIRGeneratorTool().emitZeroExtendMemory(memoryKind == Kind.Short ? Kind.Char : memoryKind, root.getResultBits(), gen.makeAddress(access), gen.getState(access)); + } + }; + } + } + + @MatchRule("(FloatConvert Read=access)") + @MatchRule("(FloatConvert FloatingRead=access)") + public static class FloatConvert extends AMD64MatchGenerator { + Access access; + FloatConvertNode root; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + return gen.emitFloatConvertMemory(root, access); + } + }; + } + } + + @MatchRule("(Reinterpret Read=access)") + @MatchRule("(Reinterpret FloatingRead=access)") + public static class Reinterpret extends AMD64MatchGenerator { + Access access; + ReinterpretNode root; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(root.stamp()); + return gen.emitReinterpretMemory(kind, access); + } + }; + } + } + @Override public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; @@ -103,11 +632,11 @@ @Override public void visitInfopointNode(InfopointNode i) { - append(new InfopointOp(gen.stateFor(i.getState()), i.reason)); + append(new InfopointOp(stateFor(i.getState()), i.reason)); } @Override - public AMD64LIRGenerator getLIRGenerator() { + public AMD64LIRGenerator getLIRGeneratorTool() { return (AMD64LIRGenerator) gen; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012, 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.compiler.common; + +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; + +public abstract class FieldIntrospection extends UnsafeAccess { + + /** + * Interface used by {@link #rescanAllFieldOffsets(CalcOffset)} to determine the offset (in + * bytes) of a field. + */ + public interface CalcOffset { + + long getOffset(Field field); + } + + public static class DefaultCalcOffset implements CalcOffset { + + @Override + public long getOffset(Field field) { + return unsafe.objectFieldOffset(field); + } + } + + protected static final ConcurrentHashMap<Class<?>, FieldIntrospection> allClasses = new ConcurrentHashMap<>(); + + private final Class<?> clazz; + protected long[] dataOffsets; + protected Map<Long, String> fieldNames; + protected Map<Long, Class<?>> fieldTypes; + + public FieldIntrospection(Class<?> clazz) { + this.clazz = clazz; + } + + public Class<?> getClazz() { + return clazz; + } + + public static void rescanAllFieldOffsets(CalcOffset calc) { + for (FieldIntrospection nodeClass : allClasses.values()) { + nodeClass.rescanFieldOffsets(calc); + } + } + + protected abstract void rescanFieldOffsets(CalcOffset calc); + + public abstract static class BaseFieldScanner { + + private final CalcOffset calc; + + /** The offsets of fields that are not specially handled by subclasses. */ + public final ArrayList<Long> dataOffsets = new ArrayList<>(); + + public final Map<Long, String> fieldNames = new HashMap<>(); + public final Map<Long, Class<?>> fieldTypes = new HashMap<>(); + + protected BaseFieldScanner(CalcOffset calc) { + this.calc = calc; + } + + public void scan(Class<?> clazz) { + Class<?> currentClazz = clazz; + do { + for (Field field : currentClazz.getDeclaredFields()) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + Class<?> type = field.getType(); + long offset = calc.getOffset(field); + + // scanField() may overwrite the name with a customized name. + fieldNames.put(offset, field.getName()); + fieldTypes.put(offset, type); + + scanField(field, type, offset); + } + currentClazz = currentClazz.getSuperclass(); + } while (currentClazz.getSuperclass() != Object.class); + } + + protected abstract void scanField(Field field, Class<?> type, long offset); + } + + protected static void copyInto(long[] dest, long[] src) { + assert dest.length == src.length; + for (int i = 0; i < dest.length; i++) { + dest[i] = src[i]; + } + } + + protected static <T> void copyInto(T[] dest, T[] src) { + assert dest.length == src.length; + for (int i = 0; i < dest.length; i++) { + dest[i] = src[i]; + } + } + + protected static <T> void copyInto(T[] dest, List<T> src) { + assert dest.length == src.size(); + for (int i = 0; i < dest.length; i++) { + dest[i] = src.get(i); + } + } + + protected static <T> T[] arrayUsingSortedOffsets(Map<Long, T> map, long[] sortedOffsets, T[] result) { + for (int i = 0; i < sortedOffsets.length; i++) { + result[i] = map.get(sortedOffsets[i]); + } + return result; + } + + protected static long[] sortedLongCopy(ArrayList<Long> list1) { + Collections.sort(list1); + long[] result = new long[list1.size()]; + for (int i = 0; i < list1.size(); i++) { + result[i] = list1.get(i); + } + return result; + } + + protected static long[] sortedLongCopy(ArrayList<Long> list1, ArrayList<Long> list2) { + Collections.sort(list1); + Collections.sort(list2); + long[] result = new long[list1.size() + list2.size()]; + for (int i = 0; i < list1.size(); i++) { + result[i] = list1.get(i); + } + for (int i = 0; i < list2.size(); i++) { + result[list1.size() + i] = list2.get(i); + } + return result; + } +}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalInternalError.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalInternalError.java Mon Apr 28 10:31:17 2014 +0200 @@ -94,7 +94,7 @@ * @param e the original GraalInternalError */ public GraalInternalError(GraalInternalError e) { - super(e.getCause()); + super(e); context.addAll(e.context); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,287 @@ +/* + * 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 + * 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.common; + +import com.oracle.graal.options.*; + +/** + * This class encapsulates options that control the behavior of the Graal compiler. + */ +// @formatter:off +public final class GraalOptions { + + @Option(help = "Use baseline compiler configuration") + public static final OptionValue<Boolean> UseBaselineCompiler = new OptionValue<>(false); + @Option(help = "Enable use of compiler intrinsics") + public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true); + @Option(help = "Enable inlining of monomorphic calls") + public static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true); + @Option(help = "Enable inlining of polymorphic calls") + public static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true); + @Option(help = "Enable inlining of megamorphic calls") + public static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D); + @Option(help = "") + public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(20000); + @Option(help = "") + public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(5); + + // inlining settings + @Option(help = "") + public static final OptionValue<Float> BoostInliningForEscapeAnalysis = new OptionValue<>(2f); + @Option(help = "") + public static final OptionValue<Float> RelevanceCapForInlining = new OptionValue<>(1f); + @Option(help = "") + public static final OptionValue<Float> CapInheritedRelevance = new OptionValue<>(1f); + @Option(help = "") + public static final OptionValue<Boolean> IterativeInlining = new OptionValue<>(false); + + @Option(help = "") + public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10); + @Option(help = "") + public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300); + @Option(help = "") + public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300); + @Option(help = "") + public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0); + @Option(help = "") + public static final OptionValue<Boolean> InlineEverything = new OptionValue<>(false); + + // escape analysis settings + @Option(help = "") + public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2); + @Option(help = "") + public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null); + @Option(help = "") + public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32); + @Option(help = "") + public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false); + + @Option(help = "") + public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5); + @Option(help = "") + public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1); + + // profiling information + @Option(help = "") + public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); + + // graph caching + @Option(help = "") + public static final OptionValue<Boolean> CacheGraphs = new OptionValue<>(true); + + //loop transform settings TODO (gd) tune + @Option(help = "") + public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Integer> FullUnrollMaxNodes = new OptionValue<>(300); + @Option(help = "") + public static final OptionValue<Integer> ExactFullUnrollMaxNodes = new OptionValue<>(1200); + @Option(help = "") + public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f); + @Option(help = "") + public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3); + @Option(help = "") + public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(50); + @Option(help = "") + public static final OptionValue<Integer> LoopUnswitchUncertaintyBoost = new OptionValue<>(5); + @Option(help = "") + public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true); + + // debugging settings + @Option(help = "") + public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false); + + @Option(help = "") + public static final OptionValue<String> PrintFilter = new OptionValue<>(null); + + // Debug settings: + @Option(help = "") + public static final OptionValue<Boolean> BootstrapReplacements = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Integer> GCDebugStartCycle = new OptionValue<>(-1); + // Ideal graph visualizer output settings + @Option(help = "Dump IdealGraphVisualizer output in binary format") + public static final OptionValue<Boolean> PrintBinaryGraphs = new OptionValue<>(true); + @Option(help = "Output probabilities for fixed nodes during binary graph dumping") + public static final OptionValue<Boolean> PrintGraphProbabilities = new OptionValue<>(false); + @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.") + public static final OptionValue<Boolean> PrintCFG = new OptionValue<>(false); + @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.") + public static final OptionValue<Boolean> PrintBackendCFG = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> PrintIdealGraphFile = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<String> PrintIdealGraphAddress = new OptionValue<>("127.0.0.1"); + @Option(help = "") + public static final OptionValue<Integer> PrintIdealGraphPort = new OptionValue<>(4444); + @Option(help = "") + public static final OptionValue<Integer> PrintBinaryGraphPort = new OptionValue<>(4445); + + // Other printing settings + @Option(help = "") + public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false); + @Option(help = "Print profiling information when parsing a method's bytecode") + public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> PrintCodeBytes = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> PrintBailout = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> TraceEscapeAnalysis = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false); + @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required") + public static final OptionValue<String> DecompileAfterPhase = new OptionValue<>(null); + + // HotSpot command line options + @Option(help = "") + public static final OptionValue<Boolean> HotSpotPrintCompilation = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> HotSpotCIPrintCompilerName = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false); + + // Register allocator debugging + @Option(help = "") + public static final OptionValue<String> RegisterPressure = new OptionValue<>(null); + + // Code generator settings + @Option(help = "") + public static final OptionValue<Boolean> FlowSensitiveReduction = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> GenAssertionCode = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> AlignCallsForPatching = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true); + + @Option(help = "") + public static final OptionValue<Boolean> MemoryAwareScheduling = new OptionValue<>(true); + + // Translating tableswitch instructions + @Option(help = "") + public static final OptionValue<Integer> MinimumJumpTableSize = new OptionValue<>(5); + @Option(help = "") + public static final OptionValue<Integer> RangeTestsSwitchDensity = new OptionValue<>(5); + @Option(help = "") + public static final OptionValue<Double> MinTableSwitchDensity = new OptionValue<>(0.5); + + // Ahead of time compilation + @Option(help = "Try to avoid emitting code where patching is required") + public static final OptionValue<Boolean> ImmutableCode = new OptionValue<>(false); + + @Option(help = "") + public static final OptionValue<Boolean> CallArrayCopy = new OptionValue<>(true); + + // Runtime settings + @Option(help = "") + public static final OptionValue<Boolean> SupportJsrBytecodes = new OptionValue<>(true); + + @Option(help = "") + public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptDeoptimizationGrouping = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true); + @Option(help = "Allow backend to emit arithmetic and compares directly against memory.") + public static final OptionValue<Boolean> OptFoldMemory = new OptionValue<>(false); + @Option(help = "Allow backend to match complex expressions.") + public static final OptionValue<Boolean> MatchExpressions = new OptionValue<>(true); + + + /** + * Counts the various paths taken through snippets. + */ + @Option(help = "") + public static final OptionValue<Boolean> SnippetCounters = new OptionValue<>(false); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2012, 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.compiler.common; + +import java.lang.reflect.*; + +import sun.misc.*; + +public class UnsafeAccess { + + /** + * An instance of {@link Unsafe} for use within Graal. + */ + public static final Unsafe unsafe = getUnsafe(); + + private static Unsafe getUnsafe() { + try { + // this will fail if Graal is not part of the boot class path + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + // nothing to do + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + // currently we rely on being able to use Unsafe... + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } + + /** + * Copies the contents of a {@link String} to a native memory buffer as a {@code '\0'} + * terminated C string. The native memory buffer is allocated via + * {@link Unsafe#allocateMemory(long)}. The caller is responsible for releasing the buffer when + * it is no longer needed via {@link Unsafe#freeMemory(long)}. + * + * @return the native memory pointer of the C string created from {@code s} + */ + public static long createCString(String s) { + return writeCString(s, unsafe.allocateMemory(s.length() + 1)); + } + + /** + * Reads a {@code '\0'} terminated C string from native memory and converts it to a + * {@link String}. + * + * @return a Java string + */ + public static String readCString(long address) { + if (address == 0) { + return null; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0;; i++) { + char c = (char) unsafe.getByte(address + i); + if (c == 0) { + break; + } + sb.append(c); + } + return sb.toString(); + } + + /** + * Writes the contents of a {@link String} to a native memory buffer as a {@code '\0'} + * terminated C string. The caller is responsible for ensuring the buffer is at least + * {@code s.length() + 1} bytes long. The caller is also responsible for releasing the buffer + * when it is no longer. + * + * @return the value of {@code buf} + */ + public static long writeCString(String s, long buf) { + int size = s.length(); + for (int i = 0; i < size; i++) { + unsafe.putByte(buf + i, (byte) s.charAt(i)); + } + unsafe.putByte(buf + size, (byte) '\0'); + return buf; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/FloatConvert.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,65 @@ +/* + * 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.compiler.common.calc; + +import com.oracle.graal.compiler.common.*; + +public enum FloatConvert { + F2I, + D2I, + F2L, + D2L, + I2F, + L2F, + D2F, + I2D, + L2D, + F2D; + + public FloatConvert reverse() { + switch (this) { + case D2F: + return F2D; + case D2I: + return I2D; + case D2L: + return L2D; + case F2D: + return D2F; + case F2I: + return I2F; + case F2L: + return L2F; + case I2D: + return D2I; + case I2F: + return F2I; + case L2D: + return D2L; + case L2F: + return F2L; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/CodeGenProviders.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 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.common.spi; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +/** + * A set of providers which are required for LIR and/or code generation. Some may not be present + * (i.e., null). + */ +public interface CodeGenProviders { + + MetaAccessProvider getMetaAccess(); + + CodeCacheProvider getCodeCache(); + + ForeignCallsProvider getForeignCalls(); + + ConstantReflectionProvider getConstantReflection(); + +}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/LIRTypeTool.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * 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.common.spi; - -import com.oracle.graal.api.meta.*; - -/** - * This interface can be used to access platform and VM specific kinds. - */ -public interface LIRTypeTool { - - PlatformKind getIntegerKind(int bits); - - PlatformKind getFloatingKind(int bits); - - PlatformKind getObjectKind(); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/PlatformKindTool.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,37 @@ +/* + * 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.common.spi; + +import com.oracle.graal.api.meta.*; + +/** + * This interface can be used to access platform and VM specific kinds. + */ +public interface PlatformKindTool { + + PlatformKind getIntegerKind(int bits); + + PlatformKind getFloatingKind(int bits); + + PlatformKind getObjectKind(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,234 @@ +/* + * 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 + * 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.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.spi.*; + +public class FloatStamp extends PrimitiveStamp { + + private final double lowerBound; + private final double upperBound; + private final boolean nonNaN; + + protected FloatStamp(int bits) { + this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false); + } + + public FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) { + super(bits); + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.nonNaN = nonNaN; + } + + @Override + public Stamp unrestricted() { + return new FloatStamp(getBits()); + } + + @Override + public Stamp illegal() { + return new FloatStamp(getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, true); + } + + @Override + public boolean isLegal() { + return lowerBound <= upperBound || !nonNaN; + } + + @Override + public Kind getStackKind() { + if (getBits() > 32) { + return Kind.Double; + } else { + return Kind.Float; + } + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + return tool.getFloatingKind(getBits()); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + switch (getBits()) { + case 32: + return metaAccess.lookupJavaType(Float.TYPE); + case 64: + return metaAccess.lookupJavaType(Double.TYPE); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + /** + * The (inclusive) lower bound on the value described by this stamp. + */ + public double lowerBound() { + return lowerBound; + } + + /** + * The (inclusive) upper bound on the value described by this stamp. + */ + public double upperBound() { + return upperBound; + } + + public boolean isNonNaN() { + return nonNaN; + } + + public boolean isUnrestricted() { + return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; + } + + public boolean contains(double value) { + if (Double.isNaN(value)) { + return !nonNaN; + } else { + return value >= lowerBound && value <= upperBound; + } + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append('f'); + str.append(getBits()); + str.append(nonNaN ? "!" : ""); + if (lowerBound == upperBound) { + str.append(" [").append(lowerBound).append(']'); + } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) { + str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); + } + return str.toString(); + } + + @Override + public Stamp meet(Stamp otherStamp) { + if (otherStamp == this) { + return this; + } + if (!(otherStamp instanceof FloatStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + FloatStamp other = (FloatStamp) otherStamp; + assert getBits() == other.getBits(); + double meetUpperBound = Math.max(upperBound, other.upperBound); + double meetLowerBound = Math.min(lowerBound, other.lowerBound); + boolean meetNonNaN = nonNaN && other.nonNaN; + if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) { + return this; + } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) { + return other; + } else { + return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN); + } + } + + @Override + public Stamp join(Stamp otherStamp) { + if (otherStamp == this) { + return this; + } + if (!(otherStamp instanceof FloatStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + FloatStamp other = (FloatStamp) otherStamp; + assert getBits() == other.getBits(); + double joinUpperBound = Math.min(upperBound, other.upperBound); + double joinLowerBound = Math.max(lowerBound, other.lowerBound); + boolean joinNonNaN = nonNaN || other.nonNaN; + if (joinLowerBound == lowerBound && joinUpperBound == upperBound && joinNonNaN == nonNaN) { + return this; + } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) { + return other; + } else { + return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + result = prime * result + super.hashCode(); + temp = Double.doubleToLongBits(lowerBound); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + (nonNaN ? 1231 : 1237); + temp = Double.doubleToLongBits(upperBound); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean isCompatible(Stamp stamp) { + if (this == stamp) { + return true; + } + if (stamp instanceof FloatStamp) { + FloatStamp other = (FloatStamp) stamp; + return getBits() == other.getBits(); + } + return false; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { + return false; + } + FloatStamp other = (FloatStamp) obj; + if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) { + return false; + } + if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) { + return false; + } + if (nonNaN != other.nonNaN) { + return false; + } + return true; + } + + @Override + public Constant asConstant() { + if (nonNaN && lowerBound == upperBound) { + switch (getBits()) { + case 32: + return Constant.forFloat((float) lowerBound); + case 64: + return Constant.forDouble(lowerBound); + } + } + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,92 @@ +/* + * 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 + * 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.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.spi.*; + +/** + * This stamp represents the illegal type. Values with this type can not exist at run time. + */ +public final class IllegalStamp extends Stamp { + + private IllegalStamp() { + } + + @Override + public Kind getStackKind() { + return Kind.Illegal; + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + throw GraalInternalError.shouldNotReachHere("illegal stamp should not reach backend"); + } + + @Override + public Stamp unrestricted() { + return this; + } + + @Override + public Stamp illegal() { + return this; + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + throw GraalInternalError.shouldNotReachHere("illegal stamp has no Java type"); + } + + @Override + public Stamp meet(Stamp other) { + return this; + } + + @Override + public Stamp join(Stamp other) { + return this; + } + + @Override + public boolean isCompatible(Stamp stamp) { + return false; + } + + @Override + public String toString() { + return "ILLEGAL"; + } + + @Override + public boolean isLegal() { + return false; + } + + private static IllegalStamp instance = new IllegalStamp(); + + static IllegalStamp getInstance() { + return instance; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,318 @@ +/* + * 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 + * 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.common.type; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.spi.*; + +/** + * Describes the possible values of a {@link ValueNode} that produces an int or long result. + * + * The description consists of (inclusive) lower and upper bounds and up (may be set) and down + * (always set) bit-masks. + */ +@SuppressWarnings("javadoc") +public class IntegerStamp extends PrimitiveStamp { + + private final long lowerBound; + private final long upperBound; + private final long downMask; + private final long upMask; + + public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { + super(bits); + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.downMask = downMask; + this.upMask = upMask; + assert lowerBound >= defaultMinValue(bits) : this; + assert upperBound <= defaultMaxValue(bits) : this; + assert (downMask & defaultMask(bits)) == downMask : this; + assert (upMask & defaultMask(bits)) == upMask : this; + } + + @Override + public Stamp unrestricted() { + return new IntegerStamp(getBits(), defaultMinValue(getBits()), defaultMaxValue(getBits()), 0, defaultMask(getBits())); + } + + @Override + public Stamp illegal() { + return new IntegerStamp(getBits(), defaultMaxValue(getBits()), defaultMinValue(getBits()), defaultMask(getBits()), 0); + } + + @Override + public boolean isLegal() { + return lowerBound <= upperBound; + } + + @Override + public Kind getStackKind() { + if (getBits() > 32) { + return Kind.Long; + } else { + return Kind.Int; + } + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + return tool.getIntegerKind(getBits()); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + switch (getBits()) { + case 1: + return metaAccess.lookupJavaType(Boolean.TYPE); + case 8: + return metaAccess.lookupJavaType(Byte.TYPE); + case 16: + return metaAccess.lookupJavaType(Short.TYPE); + case 32: + return metaAccess.lookupJavaType(Integer.TYPE); + case 64: + return metaAccess.lookupJavaType(Long.TYPE); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + /** + * The signed inclusive lower bound on the value described by this stamp. + */ + public long lowerBound() { + return lowerBound; + } + + /** + * The signed inclusive upper bound on the value described by this stamp. + */ + public long upperBound() { + return upperBound; + } + + /** + * This bit-mask describes the bits that are always set in the value described by this stamp. + */ + public long downMask() { + return downMask; + } + + /** + * This bit-mask describes the bits that can be set in the value described by this stamp. + */ + public long upMask() { + return upMask; + } + + public boolean isUnrestricted() { + return lowerBound == defaultMinValue(getBits()) && upperBound == defaultMaxValue(getBits()) && downMask == 0 && upMask == defaultMask(getBits()); + } + + public boolean contains(long value) { + return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & defaultMask(getBits())); + } + + public boolean isPositive() { + return lowerBound() >= 0; + } + + public boolean isNegative() { + return upperBound() <= 0; + } + + public boolean isStrictlyPositive() { + return lowerBound() > 0; + } + + public boolean isStrictlyNegative() { + return upperBound() < 0; + } + + public boolean canBePositive() { + return upperBound() > 0; + } + + public boolean canBeNegative() { + return lowerBound() < 0; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append('i'); + str.append(getBits()); + if (lowerBound == upperBound) { + str.append(" [").append(lowerBound).append(']'); + } else if (lowerBound != defaultMinValue(getBits()) || upperBound != defaultMaxValue(getBits())) { + str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); + } + if (downMask != 0) { + str.append(" \u21ca"); + new Formatter(str).format("%016x", downMask); + } + if (upMask != defaultMask(getBits())) { + str.append(" \u21c8"); + new Formatter(str).format("%016x", upMask); + } + return str.toString(); + } + + private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { + assert getBits() == other.getBits(); + if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0) { + return illegal(); + } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) { + return this; + } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) { + return other; + } else { + return new IntegerStamp(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); + } + } + + @Override + public Stamp meet(Stamp otherStamp) { + if (otherStamp == this) { + return this; + } + if (!(otherStamp instanceof IntegerStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + IntegerStamp other = (IntegerStamp) otherStamp; + return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask); + } + + @Override + public Stamp join(Stamp otherStamp) { + if (otherStamp == this) { + return this; + } + if (!(otherStamp instanceof IntegerStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + IntegerStamp other = (IntegerStamp) otherStamp; + long newDownMask = downMask | other.downMask; + long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; + return createStamp(other, Math.min(upperBound, other.upperBound), newLowerBound, newDownMask, upMask & other.upMask); + } + + @Override + public boolean isCompatible(Stamp stamp) { + if (this == stamp) { + return true; + } + if (stamp instanceof IntegerStamp) { + IntegerStamp other = (IntegerStamp) stamp; + return getBits() == other.getBits(); + } + return false; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + super.hashCode(); + result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32)); + result = prime * result + (int) (upperBound ^ (upperBound >>> 32)); + result = prime * result + (int) (downMask ^ (downMask >>> 32)); + result = prime * result + (int) (upMask ^ (upMask >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { + return false; + } + IntegerStamp other = (IntegerStamp) obj; + if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) { + return false; + } + return true; + } + + public static long defaultMask(int bits) { + assert 0 <= bits && bits <= 64; + if (bits == 64) { + return 0xffffffffffffffffL; + } else { + return (1L << bits) - 1; + } + } + + public static long defaultMinValue(int bits) { + return -1L << (bits - 1); + } + + public static long defaultMaxValue(int bits) { + return defaultMask(bits - 1); + } + + public static long upMaskFor(int bits, long lowerBound, long upperBound) { + long mask = lowerBound | upperBound; + if (mask == 0) { + return 0; + } else { + return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & defaultMask(bits); + } + } + + /** + * Checks if the 2 stamps represent values of the same sign. Returns true if the two stamps are + * both positive of null or if they are both strictly negative + * + * @return true if the two stamps are both positive of null or if they are both strictly + * negative + */ + public static boolean sameSign(IntegerStamp s1, IntegerStamp s2) { + return s1.isPositive() && s2.isPositive() || s1.isStrictlyNegative() && s2.isStrictlyNegative(); + } + + @Override + public Constant asConstant() { + if (lowerBound == upperBound) { + switch (getBits()) { + case 1: + return Constant.forBoolean(lowerBound != 0); + case 8: + return Constant.forByte((byte) lowerBound); + case 16: + return Constant.forShort((short) lowerBound); + case 32: + return Constant.forInt((int) lowerBound); + case 64: + return Constant.forLong(lowerBound); + } + } + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,297 @@ +/* + * 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 + * 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.common.type; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.spi.*; + +public class ObjectStamp extends Stamp { + + private final ResolvedJavaType type; + private final boolean exactType; + private final boolean nonNull; + private final boolean alwaysNull; + + public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { + this.type = type; + this.exactType = exactType; + this.nonNull = nonNull; + this.alwaysNull = alwaysNull; + } + + @Override + public Stamp unrestricted() { + return StampFactory.object(); + } + + @Override + public Stamp illegal() { + return new ObjectStamp(null, true, true, false); + } + + @Override + public boolean isLegal() { + return !exactType || (type != null && (isConcreteType(type))); + } + + @Override + public Kind getStackKind() { + return Kind.Object; + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + return tool.getObjectKind(); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + if (type != null) { + return type; + } + return metaAccess.lookupJavaType(Object.class); + } + + public boolean nonNull() { + return nonNull; + } + + public boolean alwaysNull() { + return alwaysNull; + } + + public ResolvedJavaType type() { + return type; + } + + public boolean isExactType() { + return exactType; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append('a'); + str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.getName()).append(alwaysNull ? " NULL" : ""); + return str.toString(); + } + + @Override + public Stamp meet(Stamp otherStamp) { + if (this == otherStamp) { + return this; + } + if (!(otherStamp instanceof ObjectStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + ObjectStamp other = (ObjectStamp) otherStamp; + ResolvedJavaType meetType; + boolean meetExactType; + boolean meetNonNull; + boolean meetAlwaysNull; + if (other.alwaysNull) { + meetType = type(); + meetExactType = exactType; + meetNonNull = false; + meetAlwaysNull = alwaysNull; + } else if (alwaysNull) { + meetType = other.type(); + meetExactType = other.exactType; + meetNonNull = false; + meetAlwaysNull = other.alwaysNull; + } else { + meetType = meetTypes(type(), other.type()); + meetExactType = exactType && other.exactType; + if (meetExactType && type != null && other.type != null) { + // meeting two valid exact types may result in a non-exact type + meetExactType = Objects.equals(meetType, type) && Objects.equals(meetType, other.type); + } + meetNonNull = nonNull && other.nonNull; + meetAlwaysNull = false; + } + + if (Objects.equals(meetType, type) && meetExactType == exactType && meetNonNull == nonNull && meetAlwaysNull == alwaysNull) { + return this; + } else if (Objects.equals(meetType, other.type) && meetExactType == other.exactType && meetNonNull == other.nonNull && meetAlwaysNull == other.alwaysNull) { + return other; + } else { + return new ObjectStamp(meetType, meetExactType, meetNonNull, meetAlwaysNull); + } + } + + @Override + public Stamp join(Stamp otherStamp) { + return join0(otherStamp, false); + } + + @Override + public boolean isCompatible(Stamp other) { + if (this == other) { + return true; + } + if (other instanceof ObjectStamp) { + return true; + } + return false; + } + + /** + * Returns the stamp representing the type of this stamp after a cast to the type represented by + * the {@code to} stamp. While this is very similar to a {@link #join} operation, in the case + * where both types are not obviously related, the cast operation will prefer the type of the + * {@code to} stamp. This is necessary as long as ObjectStamps are not able to accurately + * represent intersection types. + * + * For example when joining the {@link RandomAccess} type with the {@link AbstractList} type, + * without intersection types, this would result in the most generic type ({@link Object} ). For + * this reason, in some cases a {@code castTo} operation is preferable in order to keep at least + * the {@link AbstractList} type. + * + * @param to the stamp this stamp should be casted to + * @return This stamp casted to the {@code to} stamp + */ + public Stamp castTo(ObjectStamp to) { + return join0(to, true); + } + + private Stamp join0(Stamp otherStamp, boolean castToOther) { + if (this == otherStamp) { + return this; + } + if (!(otherStamp instanceof ObjectStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + ObjectStamp other = (ObjectStamp) otherStamp; + if (!isLegal()) { + return this; + } else if (!other.isLegal()) { + return other; + } + + ResolvedJavaType joinType; + boolean joinAlwaysNull = alwaysNull || other.alwaysNull; + boolean joinNonNull = nonNull || other.nonNull; + boolean joinExactType = exactType || other.exactType; + if (Objects.equals(type, other.type)) { + joinType = type; + } else if (type == null && other.type == null) { + joinType = null; + } else if (type == null) { + joinType = other.type; + } else if (other.type == null) { + joinType = type; + } else { + // both types are != null and different + if (type.isAssignableFrom(other.type)) { + joinType = other.type; + if (exactType) { + joinAlwaysNull = true; + } + } else if (other.type.isAssignableFrom(type)) { + joinType = type; + if (other.exactType) { + joinAlwaysNull = true; + } + } else { + if (castToOther) { + joinType = other.type; + joinExactType = other.exactType; + } else { + joinType = null; + } + if (joinExactType || (!type.isInterface() && !other.type.isInterface())) { + joinAlwaysNull = true; + } + } + } + if (joinAlwaysNull) { + joinType = null; + joinExactType = false; + } + if (joinExactType && joinType == null) { + return StampFactory.illegal(Kind.Object); + } + if (joinAlwaysNull && joinNonNull) { + return StampFactory.illegal(Kind.Object); + } else if (joinExactType && !isConcreteType(joinType)) { + return StampFactory.illegal(Kind.Object); + } + if (Objects.equals(joinType, type) && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) { + return this; + } else if (Objects.equals(joinType, other.type) && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) { + return other; + } else { + return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull); + } + } + + public static boolean isConcreteType(ResolvedJavaType type) { + return !(type.isAbstract() && !type.isArray()); + } + + private static ResolvedJavaType meetTypes(ResolvedJavaType a, ResolvedJavaType b) { + if (Objects.equals(a, b)) { + return a; + } else if (a == null || b == null) { + return null; + } else { + return a.findLeastCommonAncestor(b); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (exactType ? 1231 : 1237); + result = prime * result + (nonNull ? 1231 : 1237); + result = prime * result + (alwaysNull ? 1231 : 1237); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + ObjectStamp other = (ObjectStamp) obj; + if (exactType != other.exactType || nonNull != other.nonNull || alwaysNull != other.alwaysNull) { + return false; + } + if (type == null) { + if (other.type != null) { + return false; + } + } else if (!type.equals(other.type)) { + return false; + } + return true; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,71 @@ +/* + * 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.common.type; + +/** + * Describes the possible values of a {@link ValueNode} that produces a primitive value as result. + */ +@SuppressWarnings("javadoc") +public abstract class PrimitiveStamp extends Stamp { + + private final int bits; + + protected PrimitiveStamp(int bits) { + this.bits = bits; + } + + /** + * The width in bits of the value described by this stamp. + */ + public int getBits() { + return bits; + } + + public static int getBits(Stamp stamp) { + if (stamp instanceof PrimitiveStamp) { + return ((PrimitiveStamp) stamp).getBits(); + } else { + return 0; + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + bits; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof PrimitiveStamp) { + PrimitiveStamp other = (PrimitiveStamp) obj; + return bits == other.bits; + } + return false; + } +}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java Mon Apr 28 10:31:17 2014 +0200 @@ -54,7 +54,7 @@ * Gets a platform dependent {@link PlatformKind} that can be used to store a value of this * stamp. */ - public abstract PlatformKind getPlatformKind(LIRTypeTool tool); + public abstract PlatformKind getPlatformKind(PlatformKindTool tool); /** * Returns the union of this stamp and the given stamp. Typically used to create stamps for
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2011, 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.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; + +public class StampFactory { + + // JaCoCo Exclude + + private static final Stamp[] stampCache = new Stamp[Kind.values().length]; + private static final Stamp[] illegalStampCache = new Stamp[Kind.values().length]; + private static final Stamp objectStamp = new ObjectStamp(null, false, false, false); + private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false); + private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true); + private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false); + private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); + + private static void setCache(Kind kind, Stamp stamp) { + stampCache[kind.ordinal()] = stamp; + } + + private static void setIntCache(Kind kind) { + int bits = kind.getStackKind().getBitCount(); + long mask; + if (kind.isUnsigned()) { + mask = IntegerStamp.defaultMask(kind.getBitCount()); + } else { + mask = IntegerStamp.defaultMask(bits); + } + setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); + } + + private static void setFloatCache(Kind kind) { + setCache(kind, new FloatStamp(kind.getBitCount())); + } + + static { + setIntCache(Kind.Boolean); + setIntCache(Kind.Byte); + setIntCache(Kind.Short); + setIntCache(Kind.Char); + setIntCache(Kind.Int); + setIntCache(Kind.Long); + + setFloatCache(Kind.Float); + setFloatCache(Kind.Double); + + setCache(Kind.Object, objectStamp); + setCache(Kind.Void, VoidStamp.getInstance()); + + for (Kind k : Kind.values()) { + if (stampCache[k.ordinal()] != null) { + illegalStampCache[k.ordinal()] = stampCache[k.ordinal()].illegal(); + } else { + illegalStampCache[k.ordinal()] = IllegalStamp.getInstance(); + } + } + } + + /** + * Return a stamp for a Java kind, as it would be represented on the bytecode stack. + */ + public static Stamp forKind(Kind kind) { + assert stampCache[kind.ordinal()] != null : "unexpected forKind(" + kind + ")"; + return stampCache[kind.ordinal()]; + } + + /** + * Return the stamp for the {@code void} type. This will return a singleton instance than can be + * compared using {@code ==}. + */ + public static Stamp forVoid() { + return VoidStamp.getInstance(); + } + + /** + * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an + * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated. + */ + public static Stamp forNodeIntrinsic() { + return nodeIntrinsicStamp; + } + + public static Stamp intValue() { + return forKind(Kind.Int); + } + + public static Stamp positiveInt() { + return positiveInt; + } + + public static Stamp illegal() { + return illegal(Kind.Illegal); + } + + public static Stamp illegal(Kind kind) { + return illegalStampCache[kind.ordinal()]; + } + + public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) { + return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); + } + + public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound) { + return forInteger(kind.getBitCount(), lowerBound, upperBound); + } + + public static IntegerStamp forInteger(int bits) { + return new IntegerStamp(bits, IntegerStamp.defaultMinValue(bits), IntegerStamp.defaultMaxValue(bits), 0, IntegerStamp.defaultMask(bits)); + } + + public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) { + long defaultMask = IntegerStamp.defaultMask(bits); + if (lowerBound == upperBound) { + return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask); + } + final long downMask; + final long upMask; + if (lowerBound >= 0) { + int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound); + long differentBits = lowerBound ^ upperBound; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); + + upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount); + downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); + } else { + if (upperBound >= 0) { + upMask = defaultMask; + downMask = 0; + } else { + int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound); + long differentBits = lowerBound ^ upperBound; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); + + upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); + downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); + } + } + return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask); + } + + public static FloatStamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) { + assert kind.isNumericFloat(); + return new FloatStamp(kind.getBitCount(), lowerBound, upperBound, nonNaN); + } + + public static Stamp forConstant(Constant value) { + Kind kind = value.getKind(); + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + case Long: + long mask = value.asLong() & IntegerStamp.defaultMask(kind.getBitCount()); + return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), mask, mask); + case Float: + return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat())); + case Double: + return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble())); + case Illegal: + return illegal(Kind.Illegal); + case Object: + if (value.isNull()) { + return alwaysNull(); + } else { + return objectNonNull(); + } + default: + throw new GraalInternalError("unexpected kind: %s", kind); + } + } + + public static Stamp forConstant(Constant value, MetaAccessProvider metaAccess) { + assert value.getKind() == Kind.Object; + if (value.getKind() == Kind.Object) { + ResolvedJavaType type = value.isNull() ? null : metaAccess.lookupJavaType(value); + return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull()); + } else { + throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.getKind()); + } + } + + public static Stamp object() { + return objectStamp; + } + + public static Stamp objectNonNull() { + return objectNonNullStamp; + } + + public static Stamp alwaysNull() { + return objectAlwaysNullStamp; + } + + public static Stamp declared(ResolvedJavaType type) { + return declared(type, false); + } + + public static Stamp declaredNonNull(ResolvedJavaType type) { + return declared(type, true); + } + + public static Stamp declared(ResolvedJavaType type, boolean nonNull) { + return object(type, false, nonNull); + } + + public static Stamp object(ResolvedJavaType type, boolean exactType, boolean nonNull) { + assert type != null; + assert type.getKind() == Kind.Object; + ResolvedJavaType exact = type.asExactType(); + if (exact != null) { + assert !exactType || type.equals(exact); + return new ObjectStamp(exact, true, nonNull, false); + } else { + return new ObjectStamp(type, exactType, nonNull, false); + } + } + + public static Stamp exactNonNull(ResolvedJavaType type) { + if (ObjectStamp.isConcreteType(type)) { + return new ObjectStamp(type, true, true, false); + } else { + return illegal(Kind.Object); + } + } + + public static Stamp exact(ResolvedJavaType type) { + return new ObjectStamp(type, true, false, false); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011, 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.common.type; + +public interface StampProvider { + + Stamp stamp(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,110 @@ +/* + * 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.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.spi.*; + +/** + * Singleton stamp representing the value of type {@code void}. + */ +public final class VoidStamp extends Stamp { + + private VoidStamp() { + } + + @Override + public Stamp unrestricted() { + return this; + } + + @Override + public Kind getStackKind() { + return Kind.Void; + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + throw GraalInternalError.shouldNotReachHere("void stamp has no value"); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(Void.TYPE); + } + + @Override + public String toString() { + return "void"; + } + + @Override + public boolean alwaysDistinct(Stamp other) { + return this != other; + } + + @Override + public Stamp meet(Stamp other) { + if (other instanceof IllegalStamp) { + return other.join(this); + } + if (this == other) { + return this; + } + return StampFactory.illegal(Kind.Illegal); + } + + @Override + public Stamp join(Stamp other) { + if (other instanceof IllegalStamp) { + return other.join(this); + } + if (this == other) { + return this; + } + return StampFactory.illegal(Kind.Illegal); + } + + @Override + public boolean isCompatible(Stamp stamp) { + return this == stamp; + } + + @Override + public Stamp illegal() { + // there is no illegal void stamp + return this; + } + + @Override + public boolean isLegal() { + return true; + } + + private static VoidStamp instance = new VoidStamp(); + + static VoidStamp getInstance() { + return instance; + } +}
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,8 +27,8 @@ * This class extends KernelTester and provides a base class * for which the HSAIL code comes from the Graal compiler. */ +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.phases.GraalOptions.*; import static org.junit.Assume.*; import java.io.*; @@ -47,7 +47,6 @@ import com.oracle.graal.hsail.*; import com.oracle.graal.options.*; import com.oracle.graal.options.OptionValue.OverrideScope; -import com.oracle.graal.phases.*; public abstract class GraalKernelTester extends KernelTester {
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,13 +27,10 @@ import org.junit.*; -import sun.misc.*; - import com.oracle.graal.compiler.hsail.test.infra.*; /** - * Tests {@link AtomicInteger#getAndAdd(int)} which indirectly tests - * {@link Unsafe#compareAndSwapInt(Object, long, int, int)}. + * Tests {@link AtomicInteger#getAndAdd(int)} which tests HSAIL atomic_add codegen. */ public class AtomicIntGetAndAddTest extends GraalKernelTester {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import java.util.*; +import java.util.concurrent.atomic.*; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.*; + +/** + * Tests {@link AtomicInteger#getAndSet(int)} which tests HSAIL atomic_exch codegen. + */ +public class AtomicIntGetAndSetTest extends GraalKernelTester { + + static final int NUM = 1000; + @Result public int[] outArray = new int[NUM]; + AtomicInteger atomicInt = new AtomicInteger(Integer.MAX_VALUE); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchMethodKernel(NUM); + // to complete the circle, replace the initial get value with that of the last executor + for (int i = 0; i < NUM; i++) { + if (outArray[i] == Integer.MAX_VALUE) { + outArray[i] = atomicInt.get(); + } + } + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + public void run(int gid) { + outArray[gid] = atomicInt.getAndSet(gid); + } + + @Test + public void test() { + testGeneratedHsail(); + } +}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,13 +27,10 @@ import org.junit.*; -import sun.misc.*; - import com.oracle.graal.compiler.hsail.test.infra.*; /** - * Tests {@link AtomicLong#getAndAdd(long)} which indirectly tests - * {@link Unsafe#compareAndSwapLong(Object, long, long, long)}. + * Tests {@link AtomicLong#getAndAdd(long)} which tests HSAIL atomic_add codegen. */ public class AtomicLongGetAndAddTest extends GraalKernelTester {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import java.util.*; +import java.util.concurrent.atomic.*; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.*; + +/** + * Tests {@link AtomicLong#getAndSet(long)} which tests HSAIL atomic_exch codegen. + */ +public class AtomicLongGetAndSetTest extends GraalKernelTester { + + static final int NUM = 1000; + @Result public long[] outArray = new long[NUM]; + AtomicLong atomicLong = new AtomicLong(Long.MAX_VALUE); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchMethodKernel(NUM); + // to complete the circle, replace the initial get value with that of the last executor + for (int i = 0; i < NUM; i++) { + if (outArray[i] == Long.MAX_VALUE) { + outArray[i] = atomicLong.get(); + } + } + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + public void run(int gid) { + outArray[gid] = atomicLong.getAndSet(gid); + } + + @Test + public void test() { + testGeneratedHsail(); + } +}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewFloatStringTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewFloatStringTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.compiler.hsail.test; +import org.junit.*; + /** * Tests creating a new String from a float. */ @@ -35,8 +37,8 @@ myOutArray[gid] = Float.toString(gid * 2.22f); } - // problems runs out of memory space while inlining - // @Test + @Ignore("problems runs out of memory space while inlining") + @Test public void test() { testGeneratedHsail(); }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -118,9 +118,8 @@ dispatchMethodKernel(size, out, in); } - // Marked to only run on hardware until simulator spill bug is fixed. - @Ignore @Test + @Ignore("until stack slots are supported in deopt") public void test() { testGeneratedHsail(); }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -87,9 +87,8 @@ dispatchMethodKernel(size, out, in); } - // Marked to only run on hardware until simulator spill bug is fixed. - @Ignore @Test + @Ignore("until stack slots are supported in deopt") public void test() { testGeneratedHsail(); }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectArrayInstanceDerivedTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectArrayInstanceDerivedTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.compiler.hsail.test.lambda; +import org.junit.*; + import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; /** @@ -69,12 +71,14 @@ }); } - // @Test + @Ignore + @Test public void test() { testGeneratedHsail(); } - // @Test + @Ignore + @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod(); }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectArrayInstanceTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectArrayInstanceTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,7 +24,8 @@ package com.oracle.graal.compiler.hsail.test.lambda; import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; -import org.junit.Test; + +import org.junit.*; /** * Tests calling a method on an object when there are no derived types of that object. @@ -53,11 +54,13 @@ }); } + @Ignore @Test public void test() { testGeneratedHsail(); } + @Ignore @Test public void testUsingLambdaMethod() { testGeneratedHsailUsingLambdaMethod();
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -33,9 +33,9 @@ import com.oracle.graal.asm.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILArithmetic.ConvertOp; import com.oracle.graal.lir.hsail.HSAILArithmetic.Op1Stack; @@ -51,8 +51,6 @@ import com.oracle.graal.lir.hsail.HSAILMove.MembarOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.phases.util.*; /** @@ -148,8 +146,7 @@ finalDisp += asConstant(index).asLong() * scale; } else { Value indexRegister; - Value convertedIndex; - convertedIndex = this.emitSignExtend(index, 32, 64); + Value convertedIndex = index.getKind() == Kind.Long ? index : this.emitSignExtend(index, 32, 64); if (scale != 1) { indexRegister = emitUMul(convertedIndex, Constant.forInt(scale)); } else { @@ -417,7 +414,7 @@ } @Override - public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitDiv(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: @@ -440,7 +437,7 @@ } @Override - public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { + public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: @@ -462,12 +459,12 @@ } @Override - public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { + public Variable emitUDiv(Value a, Value b, LIRFrameState state) { throw GraalInternalError.unimplemented(); } @Override - public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { + public Variable emitURem(Value a, Value b, LIRFrameState state) { throw GraalInternalError.unimplemented(); } @@ -685,7 +682,7 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { append(new ReturnOp(Value.ILLEGAL)); } @@ -832,7 +829,7 @@ * Graal generates for any switch construct appearing in Java bytecode. */ @Override - protected void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) { + public void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) { emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget); } @@ -857,7 +854,7 @@ * @param key the key that is compared against the key constants in the case statements. */ @Override - protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { + public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { if ((key.getKind() == Kind.Int) || (key.getKind() == Kind.Long)) { // Append the LIR instruction for generating compare and branch instructions. append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key));
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,18 +25,19 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; /** * This class implements the HSAIL specific portion of the LIR generator. */ public abstract class HSAILNodeLIRBuilder extends NodeLIRBuilder { - public HSAILNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public HSAILNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } @@ -66,11 +67,12 @@ assert v.stamp() instanceof ObjectStamp; Variable obj = newVariable(Kind.Object); gen.emitMove(obj, operand(v)); - append(new HSAILMove.NullCheckOp(obj, gen.state(deopting))); + append(new HSAILMove.NullCheckOp(obj, state(deopting))); } @Override public void visitInfopointNode(InfopointNode i) { + // TODO Auto-generated method stub throw GraalInternalError.unimplemented(); } }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -34,9 +34,10 @@ import com.oracle.graal.asm.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.ptx.*; import com.oracle.graal.lir.ptx.PTXArithmetic.ConvertOp; import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; @@ -58,10 +59,6 @@ import com.oracle.graal.lir.ptx.PTXMemOp.StoreReturnValOp; import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp; import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; /** @@ -232,25 +229,17 @@ } @Override - public Variable emitLoad(PlatformKind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { PTXAddressValue loadAddress = asAddress(address); Variable result = newVariable(kind); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } append(new LoadOp((Kind) kind, result, loadAddress, state)); return result; } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { PTXAddressValue storeAddress = asAddress(address); Variable input = load(inputVal); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } append(new StoreOp((Kind) kind, storeAddress, input, state)); } @@ -376,7 +365,6 @@ @Override public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { - emitIntegerTest(left, right); Variable result = newVariable(trueValue.getKind()); append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue), nextPredRegNum)); @@ -386,7 +374,6 @@ } private void emitIntegerTest(Value a, Value b) { - assert a.getKind().isNumericInteger(); if (LIRValueUtil.isVariable(b)) { @@ -498,7 +485,7 @@ } @Override - public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitDiv(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: @@ -520,7 +507,7 @@ } @Override - public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { + public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: @@ -536,12 +523,12 @@ } @Override - public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { + public Variable emitUDiv(Value a, Value b, LIRFrameState state) { throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUDiv()"); } @Override - public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { + public Variable emitURem(Value a, Value b, LIRFrameState state) { throw GraalInternalError.unimplemented("PTXLIRGenerator.emitURem()"); } @@ -555,7 +542,6 @@ case Long: append(new Op2Stack(LAND, result, a, loadNonConst(b))); break; - default: throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); } @@ -754,7 +740,7 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { append(new ReturnOp(Value.ILLEGAL)); } @@ -845,7 +831,7 @@ } @Override - protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { + public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { boolean needsTemp = key.getKind() == Kind.Object; append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL, nextPredRegNum++)); } @@ -863,17 +849,16 @@ throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUnwind()"); } - public Variable emitLoadParam(Kind kind, Value address, DeoptimizingNode deopting) { + public Variable emitLoadParam(Kind kind, Value address, LIRFrameState state) { PTXAddressValue loadAddress = asAddress(address); Variable result = newVariable(kind); - append(new LoadParamOp(kind, result, loadAddress, deopting != null ? state(deopting) : null)); + append(new LoadParamOp(kind, result, loadAddress, state)); return result; } - public Variable emitLoadReturnAddress(Kind kind, Value address, DeoptimizingNode deopting) { - + public Variable emitLoadReturnAddress(Kind kind, Value address, LIRFrameState state) { PTXAddressValue loadAddress = asAddress(address); Variable result; switch (kind) { @@ -885,18 +870,16 @@ break; default: result = newVariable(kind); - } - append(new LoadReturnAddrOp(kind, result, loadAddress, deopting != null ? state(deopting) : null)); + append(new LoadReturnAddrOp(kind, result, loadAddress, state)); return result; } - public void emitStoreReturnValue(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) { - + public void emitStoreReturnValue(Kind kind, Value address, Value inputVal, LIRFrameState state) { PTXAddressValue storeAddress = asAddress(address); Variable input = load(inputVal); - append(new StoreReturnValOp(kind, storeAddress, input, deopting != null ? state(deopting) : null)); + append(new StoreReturnValOp(kind, storeAddress, input, state)); } @Override @@ -908,6 +891,7 @@ } public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.emitCompareAndSwap()"); + throw GraalInternalError.unimplemented(); } + }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.ptx.*; import com.oracle.graal.nodes.*; @@ -55,7 +56,7 @@ } } - public PTXNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public PTXNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } @@ -135,7 +136,7 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { assert v.getKind() == Kind.Object; - append(new PTXMove.NullCheckOp(gen.load(operand(v)), gen.state(deopting))); + append(new PTXMove.NullCheckOp(gen.load(operand(v)), state(deopting))); } @Override
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,7 +27,9 @@ import static com.oracle.graal.lir.sparc.SPARCArithmetic.*; import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.sparc.SPARCCompare.*; +import static com.oracle.graal.lir.sparc.SPARCControlFlow.*; import static com.oracle.graal.lir.sparc.SPARCMathIntrinsicOp.IntrinsicOpcode.*; +import static com.oracle.graal.lir.sparc.SPARCMove.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -35,32 +37,11 @@ import com.oracle.graal.asm.sparc.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryCommutative; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegConst; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegReg; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Op1Stack; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Stack; -import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary2Op; -import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.CondMoveOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.FloatCondMoveOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.StrategySwitchOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp; -import com.oracle.graal.lir.sparc.SPARCMove.LoadAddressOp; -import com.oracle.graal.lir.sparc.SPARCMove.MembarOp; -import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp; -import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp; -import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; /** @@ -131,7 +112,7 @@ @Override public void emitData(AllocatableValue dst, byte[] data) { - throw GraalInternalError.unimplemented(); + append(new LoadDataAddressOp(dst, data)); } @Override @@ -158,7 +139,7 @@ indexRegister = Value.ILLEGAL; } else { if (scale != 1) { - Value longIndex = emitSignExtend(index, 32, 64); + Value longIndex = index.getKind() == Kind.Long ? index : emitSignExtend(index, 32, 64); if (CodeUtil.isPowerOf2(scale)) { indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale))); } else { @@ -186,16 +167,20 @@ // If we don't have an index register we can use a displacement, otherwise load the // displacement into a register and add it to the base. if (indexRegister.equals(Value.ILLEGAL)) { - // TODO What if displacement if too big? displacementInt = (int) finalDisp; + assert SPARCAssembler.isSimm13(displacementInt) : displacementInt; } else { displacementInt = 0; if (baseRegister.equals(Value.ILLEGAL)) { baseRegister = load(Constant.forLong(finalDisp)); } else { - Variable longBaseRegister = newVariable(Kind.Long); - emitMove(longBaseRegister, baseRegister); // FIXME get rid of this move - baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp)); + if (finalDisp == 0) { + // Nothing to do. Just use the base register. + } else { + Variable longBaseRegister = newVariable(Kind.Long); + emitMove(longBaseRegister, baseRegister); + baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp)); + } } } @@ -284,15 +269,16 @@ Condition finalCondition = mirrored ? cond.mirror() : cond; Variable result = newVariable(trueValue.getKind()); - switch (left.getKind().getStackKind()) { + Kind kind = left.getKind().getStackKind(); + switch (kind) { case Int: case Long: case Object: - append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); + append(new CondMoveOp(kind, result, finalCondition, load(trueValue), loadNonConst(falseValue))); break; case Float: case Double: - append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); + append(new FloatCondMoveOp(kind, result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); break; default: throw GraalInternalError.shouldNotReachHere("" + left.getKind()); @@ -347,7 +333,8 @@ public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { emitIntegerTest(left, right); Variable result = newVariable(trueValue.getKind()); - append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue))); + Kind kind = left.getKind().getStackKind(); + append(new CondMoveOp(kind, result, Condition.EQ, load(trueValue), loadNonConst(falseValue))); return result; } @@ -362,7 +349,7 @@ } @Override - protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { + public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { // a temp is needed for loading long and object constants boolean needsTemp = key.getKind() == Kind.Long || key.getKind() == Kind.Object; append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL)); @@ -593,7 +580,7 @@ } @Override - public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitDiv(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind().getStackKind()) { case Int: @@ -615,8 +602,7 @@ } @Override - public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { - LIRFrameState state = state(deopting); + public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind().getStackKind()) { case Int: @@ -632,7 +618,7 @@ } @Override - public Value emitUDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitUDiv(Value a, Value b, LIRFrameState state) { // LIRFrameState state = state(deopting); switch (a.getKind().getStackKind()) { case Int: @@ -647,7 +633,7 @@ } @Override - public Value emitURem(Value a, Value b, DeoptimizingNode deopting) { + public Value emitURem(Value a, Value b, LIRFrameState state) { // LIRFrameState state = state(deopting); switch (a.getKind().getStackKind()) { case Int: @@ -814,22 +800,23 @@ return inputVal; } else if (toBits > 32) { // sign extend to 64 bits - if (fromBits == 32) { - return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal)); - } else if (fromBits < 32) { - // TODO implement direct x2L sign extension conversions - Value intVal = emitSignExtend(inputVal, fromBits, 32); - return emitSignExtend(intVal, 32, toBits); - } else { - throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + switch (fromBits) { + case 8: + return emitConvert2Op(Kind.Long, B2L, asAllocatable(inputVal)); + case 16: + return emitConvert2Op(Kind.Long, S2L, asAllocatable(inputVal)); + case 32: + return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal)); + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); } } else { // sign extend to 32 bits (smaller values are internally represented as 32 bit values) switch (fromBits) { case 8: - return emitConvert2Op(Kind.Int, I2B, asAllocatable(inputVal)); + return emitConvert2Op(Kind.Int, B2I, asAllocatable(inputVal)); case 16: - return emitConvert2Op(Kind.Int, I2S, asAllocatable(inputVal)); + return emitConvert2Op(Kind.Int, S2I, asAllocatable(inputVal)); case 32: return inputVal; default: @@ -917,7 +904,7 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { append(new ReturnOp(Value.ILLEGAL)); }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,7 +25,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp; import com.oracle.graal.nodes.*; @@ -35,7 +37,7 @@ */ public abstract class SPARCNodeLIRBuilder extends NodeLIRBuilder { - public SPARCNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public SPARCNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } @@ -59,11 +61,12 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { assert v.getKind() == Kind.Object; - append(new NullCheckOp(gen.load(operand(v)), gen.state(deopting))); + append(new NullCheckOp(gen.load(operand(v)), state(deopting))); } @Override public void visitInfopointNode(InfopointNode i) { - throw new InternalError("NYI"); + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Mon Apr 28 10:31:17 2014 +0200 @@ -43,13 +43,14 @@ import com.oracle.graal.phases.util.*; import com.oracle.graal.phases.verify.*; import com.oracle.graal.runtime.*; +import com.oracle.graal.test.*; /** * Checks that all classes in graal.jar (which must be on the class path) comply with global * invariants such as using {@link Object#equals(Object)} to compare certain types instead of * identity comparisons. */ -public class CheckGraalInvariants { +public class CheckGraalInvariants extends GraalTest { @Test public void test() {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,23 +22,16 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.nodes.ConstantNode.*; -import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static org.junit.Assert.*; - import org.junit.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; /** - * Collection of tests for {@link ConditionalEliminationPhase} including those that triggered bugs - * in this phase. + * Collection of tests for {@link com.oracle.graal.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest extends GraalCompilerTest { @@ -88,174 +81,6 @@ } while (true); } - /** - * This test presents a code pattern that triggered a bug where a (non-eliminated) checkcast - * caused an enclosing instanceof (for the same object and target type) to be incorrectly - * eliminated. - */ - @Test - public void testReanchoringIssue() { - Entry end = new Entry("end"); - EntryWithNext e1 = new EntryWithNext("e1", end); - EntryWithNext e2 = new EntryWithNext("e2", e1); - - test("search", e2, "e3", new Entry("e4")); - } - - @SuppressWarnings("unused") - public static int testNullnessSnippet(Object a, Object b) { - if (a == null) { - if (a == b) { - if (b == null) { - return 1; - } else { - return -2; - } - } else { - if (b == null) { - return -3; - } else { - return 4; - } - } - } else { - if (a == b) { - if (b == null) { - return -5; - } else { - return 6; - } - } else { - if (b == null) { - return 7; - } else { - return 8; - } - } - } - } - - @Test - public void testNullness() { - test("testNullnessSnippet", null, null); - test("testNullnessSnippet", null, new Object()); - test("testNullnessSnippet", new Object(), null); - test("testNullnessSnippet", new Object(), new Object()); - - StructuredGraph graph = parse("testNullnessSnippet"); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - for (ConstantNode constant : getConstantNodes(graph)) { - if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); - } - } - } - - @SuppressWarnings("unused") - public static int testDisjunctionSnippet(Object a) { - try { - if (a instanceof Integer) { - if (a == null) { - return -1; - } else { - return 2; - } - } else { - return 3; - } - } finally { - field = null; - } - } - - @Test - public void testDisjunction() { - StructuredGraph graph = parse("testDisjunctionSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - IfNode ifNode = (IfNode) graph.start().next(); - InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); - IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0))); - InstanceOfNode y = instanceOf; - ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY)); - LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction)); - ifNode.setCondition(negation); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - for (ConstantNode constant : getConstantNodes(graph)) { - if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); - } - } - } - - public static int testInvokeSnippet(Number n) { - if (n instanceof Integer) { - return n.intValue(); - } else { - return 1; - } - } - - @Test - public void testInvoke() { - test("testInvokeSnippet", new Integer(16)); - StructuredGraph graph = parse("testInvokeSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - - InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first(); - assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind()); - } - - public static void testTypeMergingSnippet(Object o, boolean b) { - if (b) { - if (!(o instanceof Double)) { - return; - } - } else { - if (!(o instanceof Integer)) { - return; - } - } - - /* - * For this test the conditional elimination has to correctly merge the type information it - * has about o, so that it can remove the check on Number. - */ - if (!(o instanceof Number)) { - field = o; - } - } - - @Test - public void testTypeMerging() { - StructuredGraph graph = parse("testTypeMergingSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - - assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count()); - } - - public static String testInstanceOfCheckCastSnippet(Object e) { - if (e instanceof Entry) { - return ((Entry) e).name; - } - return null; - } - - @Test - public void testInstanceOfCheckCast() { - StructuredGraph graph = parse("testInstanceOfCheckCastSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - - assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count()); - } - public static int testRedundantComparesSnippet(int[] array) { if (array == null) { return 0; @@ -272,39 +97,17 @@ new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); new FloatingReadPhase().apply(graph); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); + new ConditionalEliminationPhase(getMetaAccess()).apply(graph, context); canonicalizer.apply(graph, context); assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); } - public static int testDuplicateNullChecksSnippet(Object a) { - if (a == null) { - return 2; - } - try { - return ((Integer) a).intValue(); - } catch (ClassCastException e) { - return 0; + public static String testInstanceOfCheckCastSnippet(Object e) { + if (e instanceof Entry) { + return ((Entry) e).name; } - } - - @Test - @Ignore - public void testDuplicateNullChecks() { - // This tests whether explicit null checks properly eliminate later null guards. Currently - // it's failing. - StructuredGraph graph = parse("testDuplicateNullChecksSnippet"); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); - PhaseContext context = new PhaseContext(getProviders(), null); - - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - canonicalizer.apply(graph, context); - new FloatingReadPhase().apply(graph); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - canonicalizer.apply(graph, context); - - assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); + return null; } @Test @@ -317,9 +120,10 @@ new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); + new ConditionalEliminationPhase(getMetaAccess()).apply(graph, context); canonicalizer.apply(graph, context); assertEquals(0, graph.getNodes().filter(GuardNode.class).count()); } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2011, 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 com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugConfig; +import com.oracle.graal.debug.DebugConfigScope; +import com.oracle.graal.debug.internal.DebugScope; +import com.oracle.graal.graph.Node; +import com.oracle.graal.nodes.calc.ObjectEqualsNode; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; +import org.junit.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +import java.util.Iterator; +import java.util.List; + +/** + * Tests whether {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} actually + * performs some graph rewritings that it's supposed to perform. + */ +public class FlowSenReduTest extends GraalCompilerTest { + + /* + * A previous instanceof makes redundant a follow-up checkcast. + */ + public Object redundantCheckCastSnippet(Number o) { + Integer z = null; + if (o instanceof Integer) { + z = (Integer) o; // this CheckCastNode will be removed + } + return z; + } + + static final Integer i7 = new Integer(7); + + @Test + public void redundantCheckCastTest() { + assertEquals(i7, redundantCheckCastSnippet(i7)); + StructuredGraph result = afterFlowSensitiveReduce("redundantCheckCastSnippet"); + nodeCountEquals(result, CheckCastNode.class, 0); + nodeCountEquals(result, InstanceOfNode.class, 1); + } + + @SuppressWarnings("unused") + public boolean redundantInstanceOfSnippet01(Object o) { + if (o != null) { + Integer x = (Integer) o; + return (o instanceof Number); // this InstanceOfNode will be removed + } + return false; + } + + @Test + public void redundantInstanceOfTest01() { + String snippet = "redundantInstanceOfSnippet01"; + assertEquals(true, redundantInstanceOfSnippet01(i7)); + nodeCountEquals(afterFlowSensitiveReduce(snippet), InstanceOfNode.class, 1); + } + + /* + * The combination of (previous) non-null-check and checkcast make redundant an instanceof. + */ + @SuppressWarnings("unused") + public Object redundantInstanceOfSnippet02(Object o) { + Integer x = (Integer) o; + if (o != null) { + if (o instanceof Number) { // this InstanceOfNode will be removed + return o; + } + } + return null; + } + + @Test + public void redundantInstanceOfTest02() { + String snippet = "redundantInstanceOfSnippet02"; + assertEquals(i7, redundantInstanceOfSnippet02(i7)); + int ioAfter = getNodes(afterFlowSensitiveReduce(snippet), InstanceOfNode.class).size(); + assertEquals(ioAfter, 1); + } + + /* + * Once an exact-type has been inferred (due to instanceof final-class) a callsite is + * devirtualized. + */ + public int devirtualizationSnippet(Object x, Object y) { + boolean c = x instanceof Integer; + if (c && x == y) { + Number z = (Number) y; // this CheckCastNode will be removed + return z.intValue(); // devirtualized into InvokeSpecial on Integer.intValue() + } + return 0; + } + + @Test + public void devirtualizationTest() { + String snippet = "devirtualizationSnippet"; + assertEquals(i7, devirtualizationSnippet(i7, i7)); + nodeCountEquals(afterFlowSensitiveReduce(snippet), CheckCastNode.class, 0); + + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count()); + + List<InvokeNode> invokeNodes = getNodes(afterFlowSensitiveReduce(snippet), InvokeNode.class); + assertEquals(1, invokeNodes.size()); + + MethodCallTargetNode target = (MethodCallTargetNode) invokeNodes.get(0).callTarget(); + assertEquals(MethodCallTargetNode.InvokeKind.Special, target.invokeKind()); + assertEquals("HotSpotMethod<Integer.intValue()>", target.targetMethod().toString()); + } + + /* + * At the return statement, the returned value has been inferred to have type j.l.Number. The + * instanceof is deemed to always evaluate to false. The interplay with tail-duplication is also + * taken into account (resulting in two return statements, each with "false" as input). + */ + @SuppressWarnings("unused") + public boolean t5Snippet(Object o, boolean b) { + Number z; + if (b) { + z = (Number) o; // tail duplication of return stmt, which becomes "return false" + } else { + z = (Integer) o; // tail duplication of return stmt, which becomes "return false" + } + return o instanceof String; // unreachable + } + + @Test + public void t5a() { + String snippet = "t5Snippet"; + assertEquals(false, t5Snippet(null, true)); + StructuredGraph resultGraph = canonicalize(afterFlowSensitiveReduce(snippet)); + nodeCountEquals(resultGraph, ReturnNode.class, 2); + + List<ReturnNode> returnNodes = getNodes(resultGraph, ReturnNode.class); + Iterator<ReturnNode> iter = returnNodes.iterator(); + + ConstantNode c1 = (ConstantNode) iter.next().result(); + ConstantNode c2 = (ConstantNode) iter.next().result(); + + assertEquals(c1, c2); + assertEquals(0, c1.getValue().asInt()); + } + + @Test + public void t5b() { + String snippet = "t5Snippet"; + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + canonicalize(graph); + nodeCountEquals(graph, InstanceOfNode.class, 2); + } + + public boolean t6Snippet(Object x, Object y) { + if (!(x instanceof String)) { + return false; + } + if (!(y instanceof Number)) { + return false; + } + return x == y; // two known-not-to-conform reference values can't be == + } + + // TODO: two known-not-to-conform reference values can't be == + // but baseCaseObjectEqualsNode doesn't check that as of now. + public void t6() { + String snippet = "t6Snippet"; + // visualize(snippet); + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + canonicalize(graph); + nodeCountEquals(graph, ObjectEqualsNode.class, 0); + } + + /* + * A previous instanceof check causes a follow-up instanceof to be deemed unsatisfiable, + * resulting in constant-substitution at that usage. + */ + public Object t7Snippet(Object o) { + if (o instanceof Number) { + if (o instanceof String) { // condition amounts to false + return o; // made unreachable + } + } + return null; + } + + @Test + public void t7() { + String snippet = "t7Snippet"; + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + graph = dce(canonicalize(graph)); + // TODO how to simplify IfNode(false) + assertEquals(1, getNodes(graph, InstanceOfNode.class).size()); + + List<ReturnNode> returnNodes = getNodes(graph, ReturnNode.class); + assertEquals(2, returnNodes.size()); + Iterator<ReturnNode> iter = returnNodes.iterator(); + + ConstantNode c1 = (ConstantNode) iter.next().result(); + ConstantNode c2 = (ConstantNode) iter.next().result(); + + assertEquals(c1, c2); + Assert.assertTrue(c1.getValue().isNull()); + } + + /* + * During FlowSensitiveReduction, an unreachable branch doesn't contribute to the merged state. + * The resulting ("non-polluted") more precise inferred type after the merge allows + * devirtualizing a callsite. + */ + public int devirtualizationSnippet02(Number o) { + if (o instanceof Integer) { + Number z = o; + if (o instanceof Long) { + z = o; + } + /* + * devirtualized into InvokeSpecial on Integer.intValue() ie the inferred-type is not + * polluted with values from the unreachable branch. + */ + return z.intValue(); + } + return 0; + } + + @Test + public void devirtualizationTest02() { + String snippet = "devirtualizationSnippet02"; + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + + assertEquals(1, getNodes(graph, InvokeNode.class).size()); + + List<InvokeNode> invokeNodes = getNodes(graph, InvokeNode.class); + assertEquals(1, invokeNodes.size()); + + MethodCallTargetNode target = (MethodCallTargetNode) invokeNodes.get(0).callTarget(); + assertEquals(MethodCallTargetNode.InvokeKind.Special, target.invokeKind()); + assertEquals("HotSpotMethod<Integer.intValue()>", target.targetMethod().toString()); + } + + /* + * TODO ClassCastException known to fail --- either Deopt or throw ObjectGetClassNode The latter + * might lead to direct jump to EH if present. + */ + @SuppressWarnings("unused") + public int t9Snippet(Object o) { + try { + if (o instanceof Number) { + String s = (String) o; + /* + * make a long story short: replace the above with throw new ClassCastException (ok, + * actual type of o unknown). + */ + return 1; + } + } catch (ClassCastException e) { + return 2; + } + return 3; + } + + /* + * "Partial evaluation" via canonicalization of an expression (in the last return statement) one + * of whose leaf sub-expressions was determined to be constant. + */ + @SuppressWarnings("unused") + public Object partialEvalSnippet01(Object o, boolean b) { + if (o == null) { + return o; // turned into "return null;" + } else { + Number z; + if (b) { + z = (Number) o; + } else { + z = (Integer) o; + } + return o instanceof String ? this : null; // turned into "return null;" + } + } + + @Test + public void partialEvalTest01() { + String snippet = "partialEvalSnippet01"; + + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + canonicalize(graph); + dce(graph); + + List<ReturnNode> returnNodes = getNodes(graph, ReturnNode.class); + assertEquals(2, returnNodes.size()); + Iterator<ReturnNode> iter = returnNodes.iterator(); + + ValueNode c1 = GraphUtil.unproxify(iter.next().result()); + ValueNode c2 = GraphUtil.unproxify(iter.next().result()); + assert !iter.hasNext(); + + Assert.assertTrue(c1.isNullConstant()); + Assert.assertTrue(c2.isNullConstant()); + } + + public static class C { + public int f; + } + + /* + * A previous (assumed successful) instanceof check is reused later on to remove a checkcast. + */ + public void deduplicateInstanceOfSnippet(Object o) { + ((C) o).f = ((C) o).f; // boils down to a single instanceof test + } + + @Test + public void deduplicateInstanceOfTest() { + String snippet = "deduplicateInstanceOfSnippet"; + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + List<InstanceOfNode> ioNodes = getNodes(graph, InstanceOfNode.class); + assertEquals(1, ioNodes.size()); + + } + + // --------------------------------------------- + // ----------------- UTILITIES ----------------- + // --------------------------------------------- + + private PhaseContext getPhaseContext() { + return new PhaseContext(getProviders(), null); + } + + private static StructuredGraph dce(StructuredGraph graph) { + new DeadCodeEliminationPhase().apply(graph); + return graph; + } + + private StructuredGraph canonicalize(StructuredGraph graph) { + new CanonicalizerPhase(true).apply(graph, getPhaseContext()); + return graph; + } + + private StructuredGraph flowSensitiveReduce(StructuredGraph graph) { + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, getPhaseContext()); + return graph; + } + + public static <N extends Node> List<N> getNodes(StructuredGraph graph, Class<N> nodeClass) { + return graph.getNodes().filter(nodeClass).snapshot(); + } + + public <N extends Node> void nodeCountEquals(StructuredGraph graph, Class<N> nodeClass, int expected) { + assertEquals(expected, getNodes(graph, nodeClass).size()); + } + + public StructuredGraph afterFlowSensitiveReduce(String snippet) { + StructuredGraph before = canonicalize(parse(snippet)); + // visualize(before, snippet + "-before"); + StructuredGraph result = flowSensitiveReduce(before); + // visualize(result, snippet + "-after"); + return result; + } + + public StructuredGraph visualize(StructuredGraph graph, String title) { + DebugConfig debugConfig = DebugScope.getConfig(); + DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, debugConfig.dumpHandlers(), debugConfig.output()); + try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { + Debug.dump(graph, title); + + return graph; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import static com.oracle.graal.nodes.ConstantNode.*; +import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; +import static org.junit.Assert.*; + +import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; +import org.junit.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +/** + * Collection of tests for {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} + * including those that triggered bugs in this phase. + */ +public class FlowSensitiveReductionTest extends GraalCompilerTest { + + public static Object field; + + static class Entry { + + final String name; + + public Entry(String name) { + this.name = name; + } + } + + static class EntryWithNext extends Entry { + + public EntryWithNext(String name, Entry next) { + super(name); + this.next = next; + } + + final Entry next; + } + + public static Entry search(Entry start, String name, Entry alternative) { + Entry current = start; + do { + while (current instanceof EntryWithNext) { + if (name != null && current.name == name) { + current = null; + } else { + Entry next = ((EntryWithNext) current).next; + current = next; + } + } + + if (current != null) { + if (current.name.equals(name)) { + return current; + } + } + if (current == alternative) { + return null; + } + current = alternative; + + } while (true); + } + + /** + * This test presents a code pattern that triggered a bug where a (non-eliminated) checkcast + * caused an enclosing instanceof (for the same object and target type) to be incorrectly + * eliminated. + */ + @Test + public void testReanchoringIssue() { + Entry end = new Entry("end"); + EntryWithNext e1 = new EntryWithNext("e1", end); + EntryWithNext e2 = new EntryWithNext("e2", e1); + + test("search", e2, "e3", new Entry("e4")); + } + + @SuppressWarnings("unused") + public static int testNullnessSnippet(Object a, Object b) { + if (a == null) { + if (a == b) { + if (b == null) { + return 1; + } else { + return -2; + } + } else { + if (b == null) { + return -3; + } else { + return 4; + } + } + } else { + if (a == b) { + if (b == null) { + return -5; + } else { + return 6; + } + } else { + if (b == null) { + return 7; + } else { + return 8; + } + } + } + } + + @Test + public void testNullness() { + test("testNullnessSnippet", null, null); + test("testNullnessSnippet", null, new Object()); + test("testNullnessSnippet", new Object(), null); + test("testNullnessSnippet", new Object(), new Object()); + + StructuredGraph graph = parse("testNullnessSnippet"); + PhaseContext context = new PhaseContext(getProviders(), null); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, context); + for (ConstantNode constant : getConstantNodes(graph)) { + if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + } + } + } + + @SuppressWarnings("unused") + public static int testDisjunctionSnippet(Object a) { + try { + if (a instanceof Integer) { + if (a == null) { + return -1; + } else { + return 2; + } + } else { + return 3; + } + } finally { + field = null; + } + } + + @Test + public void testDisjunction() { + StructuredGraph graph = parse("testDisjunctionSnippet"); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + IfNode ifNode = (IfNode) graph.start().next(); + InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); + IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0))); + InstanceOfNode y = instanceOf; + ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY)); + LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction)); + ifNode.setCondition(negation); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), null)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + for (ConstantNode constant : getConstantNodes(graph)) { + if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + } + } + } + + public static int testInvokeSnippet(Number n) { + if (n instanceof Integer) { + return n.intValue(); + } else { + return 1; + } + } + + @Test + public void testInvoke() { + test("testInvokeSnippet", new Integer(16)); + StructuredGraph graph = parse("testInvokeSnippet"); + PhaseContext context = new PhaseContext(getProviders(), null); + new CanonicalizerPhase(true).apply(graph, context); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + + InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first(); + assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind()); + } + + public static void testTypeMergingSnippet(Object o, boolean b) { + if (b) { + if (!(o instanceof Double)) { + return; + } + } else { + if (!(o instanceof Integer)) { + return; + } + } + + /* + * For this test the conditional elimination has to correctly merge the type information it + * has about o, so that it can remove the check on Number. + */ + if (!(o instanceof Number)) { + field = o; + } + } + + @Test + public void testTypeMerging() { + StructuredGraph graph = parse("testTypeMergingSnippet"); + PhaseContext context = new PhaseContext(getProviders(), null); + new CanonicalizerPhase(true).apply(graph, context); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + + assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count()); + } + + public static String testInstanceOfCheckCastSnippet(Object e) { + if (e instanceof Entry) { + return ((Entry) e).name; + } + return null; + } + + @Test + public void testInstanceOfCheckCast() { + StructuredGraph graph = parse("testInstanceOfCheckCastSnippet"); + PhaseContext context = new PhaseContext(getProviders(), null); + new CanonicalizerPhase(true).apply(graph, context); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + + assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count()); + } + + public static int testDuplicateNullChecksSnippet(Object a) { + if (a == null) { + return 2; + } + try { + return ((Integer) a).intValue(); + } catch (ClassCastException e) { + return 0; + } + } + + @Test + @Ignore + public void testDuplicateNullChecks() { + // This tests whether explicit null checks properly eliminate later null guards. Currently + // it's failing. + StructuredGraph graph = parse("testDuplicateNullChecksSnippet"); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); + PhaseContext context = new PhaseContext(getProviders(), null); + + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + canonicalizer.apply(graph, context); + new FloatingReadPhase().apply(graph); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + canonicalizer.apply(graph, context); + + assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); + } + +}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,8 @@ import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.nodes.ConstantNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.io.*; import java.lang.reflect.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -39,7 +39,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.test.*; /** * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons. @@ -72,7 +71,7 @@ } } - @LongTest + @Test public void lineInfopoints() { final Method method = getMethod("testMethod"); final StructuredGraph graph = parseDebug(method);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static org.junit.Assert.*; import java.util.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; @@ -71,7 +72,7 @@ for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) { if (rn.location() instanceof ConstantLocationNode && rn.object().stamp() instanceof ObjectStamp) { long disp = ((ConstantLocationNode) rn.location()).getDisplacement(); - ResolvedJavaType receiverType = ObjectStamp.typeOrNull(rn.object()); + ResolvedJavaType receiverType = StampTool.typeOrNull(rn.object()); ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp); assert field != null : "Node " + rn + " tries to access a field which doesn't exists for this type";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, 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.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +public class PushThroughIfTest extends GraalCompilerTest { + + public int field1; + public int field2; + + public int testSnippet(boolean b) { + int i; + if (b) { + i = field1; + } else { + i = field1; + } + return i + field2; + } + + @SuppressWarnings("unused") + public int referenceSnippet(boolean b) { + return field1 + field2; + } + + @Test + public void test1() { + test("testSnippet", "referenceSnippet"); + } + + private void test(String snippet, String reference) { + StructuredGraph graph = parse(snippet); + Debug.dump(graph, "Graph"); + for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) { + fs.replaceAtUsages(null); + GraphUtil.killWithUnusedFloatingInputs(fs); + } + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + + StructuredGraph referenceGraph = parse(reference); + for (FrameState fs : referenceGraph.getNodes(FrameState.class).snapshot()) { + fs.replaceAtUsages(null); + GraphUtil.killWithUnusedFloatingInputs(fs); + } + new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), new Assumptions(false))); + assertEquals(referenceGraph, graph); + } +}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.compiler.test; +import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; import org.junit.*; import com.oracle.graal.api.code.*; @@ -167,8 +168,9 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + PhaseContext context = new PhaseContext(getProviders(), assumptions); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, context); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,8 +25,8 @@ import org.junit.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,6 +24,7 @@ import java.io.*; +import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; import org.junit.*; import com.oracle.graal.api.code.*; @@ -184,7 +185,12 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); + /* + * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase, + * tail-duplication gets activated thus resulting in a graph with more nodes than the + * reference graph. + */ + new ConditionalEliminationPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), assumptions)); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); // a second canonicalizer is needed to process nested MaterializeNodes new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); @@ -239,7 +245,7 @@ StructuredGraph graph = parse(snippet); Assumptions assumptions = new Assumptions(false); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), assumptions)); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); Debug.dump(graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.compiler.test.backend; import static com.oracle.graal.api.code.CodeUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -34,13 +34,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.schedule.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.test.*; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -51,7 +50,7 @@ return f1 + " " + arg1 + " " + arg2 + " " + arg3; } - @LongTest + @Test public void test1() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); @@ -74,7 +73,7 @@ } } - @LongTest + @Test public void test3() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); @@ -88,7 +87,7 @@ } } - @LongTest + @Test public void test4() { Method method = getMethod("testMethodVirtual"); final StructuredGraph graph = parse(method);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,10 +25,10 @@ import org.junit.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -120,6 +120,7 @@ } @Test + @Ignore public void testCache() { testPartialEscapeAnalysis("testCacheSnippet", 0.75, 1); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,7 +27,7 @@ import sun.misc.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -38,7 +38,6 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.test.*; public class InliningTest extends GraalCompilerTest { @@ -73,7 +72,7 @@ assertInlined(getGraph("invokeMethodOnFieldSnippet", false)); } - @LongTest + @Test public void testStaticBindableInliningIP() { assertManyMethodInfopoints(assertInlined(getGraph("invokeConstructorSnippet", true))); assertManyMethodInfopoints(assertInlined(getGraph("invokeFinalMethodSnippet", true))); @@ -82,7 +81,7 @@ } @Ignore("would need read elimination/EA before inlining") - @LongTest + @Test public void testDependentStaticBindableInliningIP() { assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFinalFieldSnippet", true))); assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFieldSnippet", true))); @@ -180,7 +179,7 @@ assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", false)); } - @LongTest + @Test public void testClassHierarchyAnalysisIP() { assertManyMethodInfopoints(assertInlined(getGraph("invokeLeafClassMethodSnippet", true))); assertManyMethodInfopoints(assertInlined(getGraph("invokeConcreteMethodSnippet", true)));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.test.nfi; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static java.io.File.*; import static java.lang.System.*; import static org.junit.Assert.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/META-INF/services/javax.annotation.processing.Processor Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,1 @@ +com.oracle.graal.compiler.match.MatchProcessor
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.compiler.GraalCompiler.Options.*; import static com.oracle.graal.compiler.MethodFilter.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -35,15 +35,16 @@ import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.alloc.*; import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -207,7 +208,7 @@ } } - private static void emitBlock(NodeLIRBuilder nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) { + private static void emitBlock(NodeLIRBuilderTool nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) { if (lirGenRes.getLIR().getLIRforBlock(b) == null) { for (Block pred : b.getPredecessors()) { if (!b.isLoopHeader() || !pred.isLoopEnd()) { @@ -245,8 +246,8 @@ try (Scope ds = Debug.scope("BackEnd", lir)) { FrameMap frameMap = backend.newFrameMap(registerConfig); LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(lir, frameMap, stub); - LIRGenerator lirGen = backend.newLIRGenerator(cc, lirGenRes); - NodeLIRBuilder nodeLirGen = backend.newNodeLIRGenerator(graph, lirGen); + LIRGeneratorTool lirGen = backend.newLIRGenerator(cc, lirGenRes); + NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen); try (Scope s = Debug.scope("LIRGen", lirGen)) { for (Block b : linearScanOrder) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,16 +22,15 @@ */ package com.oracle.graal.compiler.gen; -import java.lang.reflect.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.gen.*; public class BytecodeLIRBuilder { - protected final LIRGenerator gen; + protected final LIRGeneratorTool gen; protected final BytecodeParserTool parser; - public BytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) { + public BytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) { this.gen = gen; this.parser = parser; } @@ -53,7 +52,7 @@ gen.emitIncomingValues(params); Signature sig = method.getSignature(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); for (int i = 0; i < sig.getParameterCount(!isStatic); i++) { Value paramValue = params[i]; assert paramValue.getKind() == sig.getParameterKind(i).getStackKind();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -116,21 +116,33 @@ } protected BytecodeFrame computeFrameForState(FrameState state) { - int numLocals = state.localsSize(); - int numStack = state.stackSize(); - int numLocks = state.locksSize(); + try { + assert state.bci != BytecodeFrame.INVALID_FRAMESTATE_BCI; + assert state.bci != BytecodeFrame.UNKNOWN_BCI; + assert state.bci != BytecodeFrame.BEFORE_BCI || state.locksSize() == 0; + assert state.bci != BytecodeFrame.AFTER_BCI || state.locksSize() == 0; + assert state.bci != BytecodeFrame.AFTER_EXCEPTION_BCI || state.locksSize() == 0; + assert !(state.method().isSynchronized() && state.bci != BytecodeFrame.BEFORE_BCI && state.bci != BytecodeFrame.AFTER_BCI && state.bci != BytecodeFrame.AFTER_EXCEPTION_BCI) || + state.locksSize() > 0; + assert state.verify(); + + int numLocals = state.localsSize(); + int numStack = state.stackSize(); + int numLocks = state.locksSize(); - Value[] values = new Value[numLocals + numStack + numLocks]; - computeLocals(state, numLocals, values); - computeStack(state, numLocals, numStack, values); - computeLocks(state, values); + Value[] values = new Value[numLocals + numStack + numLocks]; + computeLocals(state, numLocals, values); + computeStack(state, numLocals, numStack, values); + computeLocks(state, values); - BytecodeFrame caller = null; - if (state.outerFrameState() != null) { - caller = computeFrameForState(state.outerFrameState()); + BytecodeFrame caller = null; + if (state.outerFrameState() != null) { + caller = computeFrameForState(state.outerFrameState()); + } + return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks); + } catch (GraalInternalError e) { + throw e.addContext("FrameState: ", state); } - assert state.bci >= FrameState.BEFORE_BCI : "bci == " + state.bci; - return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks); } protected void computeLocals(FrameState state, int numLocals, Value[] values) { @@ -169,39 +181,43 @@ private static final DebugMetric STATE_CONSTANTS = Debug.metric("StateConstants"); protected Value toValue(ValueNode value) { - if (value instanceof VirtualObjectNode) { - VirtualObjectNode obj = (VirtualObjectNode) value; - EscapeObjectState state = objectStates.get(obj); - if (state == null && obj.entryCount() > 0) { - // null states occur for objects with 0 fields - throw new GraalInternalError("no mapping found for virtual object %s", obj); - } - if (state instanceof MaterializedObjectState) { - return toValue(((MaterializedObjectState) state).materializedValue()); - } else { - assert obj.entryCount() == 0 || state instanceof VirtualObjectState; - VirtualObject vobject = virtualObjects.get(value); - if (vobject == null) { - vobject = VirtualObject.get(obj.type(), null, virtualObjects.size()); - virtualObjects.put(obj, vobject); + try { + if (value instanceof VirtualObjectNode) { + VirtualObjectNode obj = (VirtualObjectNode) value; + EscapeObjectState state = objectStates.get(obj); + if (state == null && obj.entryCount() > 0) { + // null states occur for objects with 0 fields + throw new GraalInternalError("no mapping found for virtual object %s", obj); } - STATE_VIRTUAL_OBJECTS.increment(); - return vobject; - } - } else if (value instanceof ConstantNode) { - STATE_CONSTANTS.increment(); - return ((ConstantNode) value).getValue(); + if (state instanceof MaterializedObjectState) { + return toValue(((MaterializedObjectState) state).materializedValue()); + } else { + assert obj.entryCount() == 0 || state instanceof VirtualObjectState; + VirtualObject vobject = virtualObjects.get(value); + if (vobject == null) { + vobject = VirtualObject.get(obj.type(), null, virtualObjects.size()); + virtualObjects.put(obj, vobject); + } + STATE_VIRTUAL_OBJECTS.increment(); + return vobject; + } + } else if (value instanceof ConstantNode) { + STATE_CONSTANTS.increment(); + return ((ConstantNode) value).getValue(); - } else if (value != null) { - STATE_VARIABLES.increment(); - Value operand = nodeOperands.get(value); - assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value; - return operand; + } else if (value != null) { + STATE_VARIABLES.increment(); + Value operand = nodeOperands.get(value); + assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value; + return operand; - } else { - // return a dummy value because real value not needed - STATE_ILLEGALS.increment(); - return Value.ILLEGAL; + } else { + // return a dummy value because real value not needed + STATE_ILLEGALS.increment(); + return Value.ILLEGAL; + } + } catch (GraalInternalError e) { + throw e.addContext("toValue: ", value); } } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * 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.compiler.gen; - -import com.oracle.graal.lir.*; - -public interface LIRGenerationResult { - FrameMap getFrameMap(); - - LIR getLIR(); - - boolean hasForeignCall(); - - void setForeignCall(boolean b); -}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResultBase.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * 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.compiler.gen; - -import com.oracle.graal.lir.*; - -public class LIRGenerationResultBase implements LIRGenerationResult { - private final LIR lir; - private final FrameMap frameMap; - /** - * Records whether the code being generated makes at least one foreign call. - */ - private boolean hasForeignCall; - - public LIRGenerationResultBase(LIR lir, FrameMap frameMap) { - this.lir = lir; - this.frameMap = frameMap; - } - - public LIR getLIR() { - return lir; - } - - /** - * Determines whether the code being generated makes at least one foreign call. - */ - public boolean hasForeignCall() { - return hasForeignCall; - } - - public final void setForeignCall(boolean hasForeignCall) { - this.hasForeignCall = hasForeignCall; - } - - public final FrameMap getFrameMap() { - return frameMap; - } - -}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,628 +0,0 @@ -/* - * Copyright (c) 2009, 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.compiler.gen; - -import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.api.meta.Value.*; -import static com.oracle.graal.lir.LIR.*; -import static com.oracle.graal.lir.LIRValueUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.compiler.common.spi.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.BlockEndOp; -import com.oracle.graal.lir.StandardOp.LabelOp; -import com.oracle.graal.lir.StandardOp.NoOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.options.*; -import com.oracle.graal.phases.util.*; - -/** - * This class traverses the HIR instructions and generates LIR instructions from them. - */ -public abstract class LIRGenerator implements ArithmeticLIRGenerator, LIRGeneratorTool, LIRTypeTool { - - public static class Options { - // @formatter:off - @Option(help = "Print HIR along side LIR as the latter is generated") - public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false); - @Option(help = "The trace level for the LIR generator") - public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0); - // @formatter:on - } - - private final Providers providers; - private final CallingConvention cc; - - private DebugInfoBuilder debugInfoBuilder; - - protected AbstractBlock<?> currentBlock; - public final int traceLevel; - public final boolean printIRWithLIR; - - /** - * Handle for an operation that loads a constant into a variable. The operation starts in the - * first block where the constant is used but will eventually be - * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the - * constant. - */ - public static class LoadConstant implements Comparable<LoadConstant> { - /** - * The index of {@link #op} within {@link #block}'s instruction list or -1 if {@code op} is - * to be moved to a dominator block. - */ - int index; - - /** - * The operation that loads the constant. - */ - private final LIRInstruction op; - - /** - * The block that does or will contain {@link #op}. This is initially the block where the - * first usage of the constant is seen during LIR generation. - */ - AbstractBlock<?> block; - - /** - * The variable into which the constant is loaded. - */ - final Variable variable; - - public LoadConstant(Variable variable, AbstractBlock<?> block, int index, LIRInstruction op) { - this.variable = variable; - this.block = block; - this.index = index; - this.op = op; - } - - /** - * Sorts {@link LoadConstant} objects according to their enclosing blocks. This is used to - * group loads per block in {@link LIRGenerator#insertConstantLoads()}. - */ - public int compareTo(LoadConstant o) { - if (block.getId() < o.block.getId()) { - return -1; - } - if (block.getId() > o.block.getId()) { - return 1; - } - return 0; - } - - @Override - public String toString() { - return block + "#" + op; - } - - /** - * Removes the {@link #op} from its original location if it is still at that location. - */ - public void unpin(LIR lir) { - if (index >= 0) { - // Replace the move with a filler op so that the operation - // list does not need to be adjusted. - List<LIRInstruction> instructions = lir.getLIRforBlock(block); - instructions.set(index, new NoOp(null, -1)); - index = -1; - } - } - } - - Map<Constant, LoadConstant> constantLoads; - - private LIRGenerationResult res; - - /** - * Set this before using the LIRGenerator. - * - * TODO this should be removed - */ - void setDebugInfoBuilder(DebugInfoBuilder builder) { - debugInfoBuilder = builder; - } - - /** - * Checks whether the supplied constant can be used without loading it into a register for store - * operations, i.e., on the right hand side of a memory access. - * - * @param c The constant to check. - * @return True if the constant can be used directly, false if the constant needs to be in a - * register. - */ - public abstract boolean canStoreConstant(Constant c, boolean isCompressed); - - public LIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult res) { - this.res = res; - this.providers = providers; - this.cc = cc; - this.traceLevel = Options.TraceLIRGeneratorLevel.getValue(); - this.printIRWithLIR = Options.PrintIRWithLIR.getValue(); - } - - /** - * Returns true if the redundant move elimination optimization should be done after register - * allocation. - */ - public boolean canEliminateRedundantMoves() { - return true; - } - - @Override - public TargetDescription target() { - return getCodeCache().getTarget(); - } - - public Providers getProviders() { - return providers; - } - - @Override - public MetaAccessProvider getMetaAccess() { - return providers.getMetaAccess(); - } - - @Override - public CodeCacheProvider getCodeCache() { - return providers.getCodeCache(); - } - - @Override - public ForeignCallsProvider getForeignCalls() { - return providers.getForeignCalls(); - } - - /** - * Creates a new {@linkplain Variable variable}. - * - * @param platformKind The kind of the new variable. - * @return a new variable - */ - @Override - public Variable newVariable(PlatformKind platformKind) { - return new Variable(platformKind, res.getLIR().nextVariable()); - } - - @Override - public RegisterAttributes attributes(Register register) { - return res.getFrameMap().registerConfig.getAttributesMap()[register.number]; - } - - @Override - public abstract Variable emitMove(Value input); - - public AllocatableValue asAllocatable(Value value) { - if (isAllocatableValue(value)) { - return asAllocatableValue(value); - } else { - return emitMove(value); - } - } - - public Variable load(Value value) { - if (!isVariable(value)) { - return emitMove(value); - } - return (Variable) value; - } - - public Value loadNonConst(Value value) { - if (isConstant(value) && !canInlineConstant((Constant) value)) { - return emitMove(value); - } - return value; - } - - /** - * Determines if only oop maps are required for the code generated from the LIR. - */ - protected boolean needOnlyOopMaps() { - return false; - } - - private static FrameState getFrameState(DeoptimizingNode deopt) { - if (deopt instanceof DeoptimizingNode.DeoptBefore) { - assert !(deopt instanceof DeoptimizingNode.DeoptDuring || deopt instanceof DeoptimizingNode.DeoptAfter); - return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore(); - } else if (deopt instanceof DeoptimizingNode.DeoptDuring) { - assert !(deopt instanceof DeoptimizingNode.DeoptAfter); - return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring(); - } else { - assert deopt instanceof DeoptimizingNode.DeoptAfter; - return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter(); - } - } - - public LIRFrameState state(DeoptimizingNode deopt) { - if (!deopt.canDeoptimize()) { - return null; - } - return stateFor(getFrameState(deopt)); - } - - public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) { - if (!deopt.canDeoptimize()) { - return null; - } - return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge); - } - - public LIRFrameState stateFor(FrameState state) { - return stateForWithExceptionEdge(state, null); - } - - public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) { - if (needOnlyOopMaps()) { - return new LIRFrameState(null, null, null); - } - assert state != null; - return getDebugInfoBuilder().build(state, exceptionEdge); - } - - /** - * Gets the ABI specific operand used to return a value of a given kind from a method. - * - * @param kind the kind of value being returned - * @return the operand representing the ABI defined location used return a value of kind - * {@code kind} - */ - public AllocatableValue resultOperandFor(Kind kind) { - if (kind == Kind.Void) { - return ILLEGAL; - } - return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind); - } - - public void append(LIRInstruction op) { - if (printIRWithLIR && !TTY.isSuppressed()) { - TTY.println(op.toStringWithIdPrefix()); - TTY.println(); - } - assert LIRVerifier.verify(op); - res.getLIR().getLIRforBlock(currentBlock).add(op); - } - - public boolean hasBlockEnd(AbstractBlock<?> block) { - List<LIRInstruction> ops = getResult().getLIR().getLIRforBlock(block); - if (ops.size() == 0) { - return false; - } - return ops.get(ops.size() - 1) instanceof BlockEndOp; - } - - public final void doBlockStart(AbstractBlock<?> block) { - if (printIRWithLIR) { - TTY.print(block.toString()); - } - - currentBlock = block; - - // set up the list of LIR instructions - assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block"; - res.getLIR().setLIRforBlock(block, new ArrayList<LIRInstruction>()); - - append(new LabelOp(new Label(block.getId()), block.isAligned())); - - if (traceLevel >= 1) { - TTY.println("BEGIN Generating LIR for block B" + block.getId()); - } - } - - public final void doBlockEnd(AbstractBlock<?> block) { - - if (traceLevel >= 1) { - TTY.println("END Generating LIR for block B" + block.getId()); - } - - currentBlock = null; - - if (printIRWithLIR) { - TTY.println(); - } - } - - public void emitIncomingValues(Value[] params) { - ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params); - } - - public abstract void emitJump(LabelRef label); - - public abstract void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, - double trueDestinationProbability); - - public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability); - - public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability); - - public abstract Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); - - public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue); - - protected abstract void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info); - - public static AllocatableValue toStackKind(AllocatableValue value) { - if (value.getKind().getStackKind() != value.getKind()) { - // We only have stack-kinds in the LIR, so convert the operand kind for values from the - // calling convention. - if (isRegister(value)) { - return asRegister(value).asValue(value.getKind().getStackKind()); - } else if (isStackSlot(value)) { - return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize()); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - } - return value; - } - - @Override - public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { - LIRFrameState state = null; - if (linkage.canDeoptimize()) { - if (info != null) { - state = stateFor(getFrameState(info)); - } else { - assert needOnlyOopMaps(); - state = new LIRFrameState(null, null, null); - } - } - - // move the arguments into the correct location - CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); - res.getFrameMap().callsMethod(linkageCc); - assert linkageCc.getArgumentCount() == args.length : "argument count mismatch"; - Value[] argLocations = new Value[args.length]; - for (int i = 0; i < args.length; i++) { - Value arg = args[i]; - AllocatableValue loc = linkageCc.getArgument(i); - emitMove(loc, arg); - argLocations[i] = loc; - } - res.setForeignCall(true); - emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state); - - if (isLegal(linkageCc.getReturn())) { - return emitMove(linkageCc.getReturn()); - } else { - return null; - } - } - - protected void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) { - int keyCount = keyConstants.length; - SwitchStrategy strategy = SwitchStrategy.getBestStrategy(keyProbabilities, keyConstants, keyTargets); - long valueRange = keyConstants[keyCount - 1].asLong() - keyConstants[0].asLong() + 1; - double tableSwitchDensity = keyCount / (double) valueRange; - /* - * This heuristic tries to find a compromise between the effort for the best switch strategy - * and the density of a tableswitch. If the effort for the strategy is at least 4, then a - * tableswitch is preferred if better than a certain value that starts at 0.5 and lowers - * gradually with additional effort. - */ - if (strategy.getAverageEffort() < 4 || tableSwitchDensity < (1 / Math.sqrt(strategy.getAverageEffort()))) { - emitStrategySwitch(strategy, value, keyTargets, defaultTarget); - } else { - int minValue = keyConstants[0].asInt(); - assert valueRange < Integer.MAX_VALUE; - LabelRef[] targets = new LabelRef[(int) valueRange]; - for (int i = 0; i < valueRange; i++) { - targets[i] = defaultTarget; - } - for (int i = 0; i < keyCount; i++) { - targets[keyConstants[i].asInt() - minValue] = keyTargets[i]; - } - emitTableSwitch(minValue, defaultTarget, targets, value); - } - } - - protected abstract void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget); - - protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key); - - public CallingConvention getCallingConvention() { - return cc; - } - - public DebugInfoBuilder getDebugInfoBuilder() { - assert debugInfoBuilder != null; - return debugInfoBuilder; - } - - @Override - public void beforeRegisterAllocation() { - insertConstantLoads(); - } - - /** - * Moves deferred {@linkplain LoadConstant loads} of constants into blocks dominating all usages - * of the constant. Any operations inserted into a block are guaranteed to be immediately prior - * to the first control flow instruction near the end of the block. - */ - private void insertConstantLoads() { - if (constantLoads != null) { - // Remove loads where all usages are in the same block. - for (Iterator<Map.Entry<Constant, LoadConstant>> iter = constantLoads.entrySet().iterator(); iter.hasNext();) { - LoadConstant lc = iter.next().getValue(); - - // Move loads of constant outside of loops - if (OptScheduleOutOfLoops.getValue()) { - AbstractBlock<?> outOfLoopDominator = lc.block; - while (outOfLoopDominator.getLoop() != null) { - outOfLoopDominator = outOfLoopDominator.getDominator(); - } - if (outOfLoopDominator != lc.block) { - lc.unpin(res.getLIR()); - lc.block = outOfLoopDominator; - } - } - - if (lc.index != -1) { - assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op; - iter.remove(); - } - } - if (constantLoads.isEmpty()) { - return; - } - - // Sorting groups the loads per block. - LoadConstant[] groupedByBlock = constantLoads.values().toArray(new LoadConstant[constantLoads.size()]); - Arrays.sort(groupedByBlock); - - int groupBegin = 0; - while (true) { - int groupEnd = groupBegin + 1; - AbstractBlock<?> block = groupedByBlock[groupBegin].block; - while (groupEnd < groupedByBlock.length && groupedByBlock[groupEnd].block == block) { - groupEnd++; - } - int groupSize = groupEnd - groupBegin; - - List<LIRInstruction> ops = res.getLIR().getLIRforBlock(block); - int lastIndex = ops.size() - 1; - assert ops.get(lastIndex) instanceof BlockEndOp; - int insertionIndex = lastIndex; - for (int i = Math.max(0, lastIndex - MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END); i < lastIndex; i++) { - if (getExceptionEdge(ops.get(i)) != null) { - insertionIndex = i; - break; - } - } - - if (groupSize == 1) { - ops.add(insertionIndex, groupedByBlock[groupBegin].op); - } else { - assert groupSize > 1; - List<LIRInstruction> moves = new ArrayList<>(groupSize); - for (int i = groupBegin; i < groupEnd; i++) { - moves.add(groupedByBlock[i].op); - } - ops.addAll(insertionIndex, moves); - } - - if (groupEnd == groupedByBlock.length) { - break; - } - groupBegin = groupEnd; - } - constantLoads = null; - } - } - - /** - * Gets a garbage value for a given kind. - */ - protected Constant zapValueForKind(PlatformKind kind) { - long dead = 0xDEADDEADDEADDEADL; - switch ((Kind) kind) { - case Boolean: - return Constant.FALSE; - case Byte: - return Constant.forByte((byte) dead); - case Char: - return Constant.forChar((char) dead); - case Short: - return Constant.forShort((short) dead); - case Int: - return Constant.forInt((int) dead); - case Double: - return Constant.forDouble(Double.longBitsToDouble(dead)); - case Float: - return Constant.forFloat(Float.intBitsToFloat((int) dead)); - case Long: - return Constant.forLong(dead); - case Object: - return Constant.NULL_OBJECT; - default: - throw new IllegalArgumentException(kind.toString()); - } - } - - /** - * Default implementation: Return the Java stack kind for each stamp. - */ - public PlatformKind getPlatformKind(Stamp stamp) { - return stamp.getPlatformKind(this); - } - - public PlatformKind getIntegerKind(int bits) { - if (bits <= 8) { - return Kind.Byte; - } else if (bits <= 16) { - return Kind.Short; - } else if (bits <= 32) { - return Kind.Int; - } else { - assert bits <= 64; - return Kind.Long; - } - } - - public PlatformKind getFloatingKind(int bits) { - switch (bits) { - case 32: - return Kind.Float; - case 64: - return Kind.Double; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - public PlatformKind getObjectKind() { - return Kind.Object; - } - - public abstract void emitBitCount(Variable result, Value operand); - - public abstract void emitBitScanForward(Variable result, Value operand); - - public abstract void emitBitScanReverse(Variable result, Value operand); - - public abstract void emitByteSwap(Variable result, Value operand); - - public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); - - public AbstractBlock<?> getCurrentBlock() { - return currentBlock; - } - - void setCurrentBlock(AbstractBlock<?> block) { - currentBlock = block; - } - - public LIRGenerationResult getResult() { - return res; - } -}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.gen; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.lir.LIR.*; import static com.oracle.graal.nodes.ConstantNode.*; @@ -34,21 +35,22 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.compiler.gen.LIRGenerator.LoadConstant; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.match.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGenerator.LoadConstant; +import com.oracle.graal.lir.gen.LIRGenerator.Options; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; /** * This class traverses the HIR instructions and generates LIR instructions from them. @@ -58,16 +60,18 @@ private final NodeMap<Value> nodeOperands; private final DebugInfoBuilder debugInfoBuilder; - protected final LIRGenerator gen; + protected final LIRGeneratorTool gen; private ValueNode currentInstruction; private ValueNode lastInstructionPrinted; // Debugging only - public NodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) { + private Map<Class<? extends ValueNode>, List<MatchStatement>> matchRules; + + public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen) { this.gen = gen; this.nodeOperands = graph.createNodeMap(); this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands); - gen.setDebugInfoBuilder(debugInfoBuilder); + matchRules = MatchRuleRegistry.lookup(getClass()); } @SuppressWarnings("hiding") @@ -113,25 +117,25 @@ return setResult(node, value); } else { Variable loadedValue; - if (gen.constantLoads == null) { - gen.constantLoads = new HashMap<>(); + if (gen.getConstantLoads() == null) { + gen.setConstantLoads(new HashMap<>()); } - LoadConstant load = gen.constantLoads.get(value); + LoadConstant load = gen.getConstantLoads().get(value); assert gen.getCurrentBlock() instanceof Block; if (load == null) { int index = gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); loadedValue = gen.emitMove(value); LIRInstruction op = gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).get(index); - gen.constantLoads.put(value, new LoadConstant(loadedValue, gen.getCurrentBlock(), index, op)); + gen.getConstantLoads().put(value, new LoadConstant(loadedValue, gen.getCurrentBlock(), index, op)); } else { - AbstractBlock<?> dominator = ControlFlowGraph.commonDominator((Block) load.block, (Block) gen.getCurrentBlock()); - loadedValue = load.variable; - if (dominator != load.block) { + AbstractBlock<?> dominator = ControlFlowGraph.commonDominator((Block) load.getBlock(), (Block) gen.getCurrentBlock()); + loadedValue = load.getVariable(); + if (dominator != load.getBlock()) { load.unpin(gen.getResult().getLIR()); } else { - assert load.block != gen.getCurrentBlock() || load.index < gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); + assert load.getBlock() != gen.getCurrentBlock() || load.getIndex() < gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); } - load.block = dominator; + load.setBlock(dominator); } return loadedValue; } @@ -154,13 +158,25 @@ @Override public Value setResult(ValueNode x, Value operand) { assert (!isRegister(operand) || !gen.attributes(asRegister(operand)).isAllocatable()); - assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice"; + assert nodeOperands != null && (nodeOperands.get(x) == null || nodeOperands.get(x) instanceof ComplexMatchValue) : "operand cannot be set twice"; assert operand != null && isLegal(operand) : "operand must be legal"; assert !(x instanceof VirtualObjectNode); nodeOperands.set(x, operand); return operand; } + /** + * Used by the {@link MatchStatement} machinery to override the generation LIR for some + * ValueNodes. + */ + public void setMatchResult(ValueNode x, Value operand) { + assert operand.equals(Value.INTERIOR_MATCH) || operand instanceof ComplexMatchValue; + assert operand instanceof ComplexMatchValue || x.usages().count() == 1 : "interior matches must be single user"; + assert nodeOperands != null && nodeOperands.get(x) == null : "operand cannot be set twice"; + assert !(x instanceof VirtualObjectNode); + nodeOperands.set(x, operand); + } + public LabelRef getLIRBlock(FixedNode b) { assert gen.getResult().getLIR().getControlFlowGraph() instanceof ControlFlowGraph; Block result = ((ControlFlowGraph) gen.getResult().getLIR().getControlFlowGraph()).blockFor(b); @@ -172,7 +188,7 @@ } public final void append(LIRInstruction op) { - if (gen.printIRWithLIR && !TTY.isSuppressed()) { + if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { lastInstructionPrinted = currentInstruction; InstructionPrinter ip = new InstructionPrinter(TTY.out()); @@ -193,10 +209,17 @@ } List<ScheduledNode> nodes = blockMap.get(block); + + if (MatchExpressions.getValue()) { + // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups + // of instructions + matchComplexExpressions(nodes); + } + int instructionsFolded = 0; for (int i = 0; i < nodes.size(); i++) { Node instr = nodes.get(i); - if (gen.traceLevel >= 3) { + if (Options.TraceLIRGeneratorLevel.getValue() >= 3) { TTY.println("LIRGen for " + instr); } if (instructionsFolded > 0) { @@ -208,7 +231,8 @@ } else if (instr instanceof ValueNode) { ValueNode valueNode = (ValueNode) instr; - if (!hasOperand(valueNode)) { + Value operand = getOperand(valueNode); + if (operand == null) { if (!peephole(valueNode)) { instructionsFolded = maybeFoldMemory(nodes, i, valueNode); if (instructionsFolded == 0) { @@ -221,6 +245,16 @@ } } } + } else if (Value.INTERIOR_MATCH.equals(operand)) { + // Doesn't need to be evaluated + Debug.log("interior match for %s", valueNode); + } else if (operand instanceof ComplexMatchValue) { + Debug.log("complex match for %s", valueNode); + ComplexMatchValue match = (ComplexMatchValue) operand; + operand = match.evaluate(this); + if (operand != null) { + setResult(valueNode, operand); + } } else { // There can be cases in which the result of an instruction is already set // before by other instructions. @@ -245,6 +279,31 @@ gen.doBlockEnd(block); } + protected void matchComplexExpressions(List<ScheduledNode> nodes) { + if (matchRules != null) { + try (Scope s = Debug.scope("MatchComplexExpressions")) { + // Match the nodes in backwards order to encourage longer matches. + for (int index = nodes.size() - 1; index >= 0; index--) { + ScheduledNode snode = nodes.get(index); + if (!(snode instanceof ValueNode)) { + continue; + } + ValueNode node = (ValueNode) snode; + // See if this node is the root of any MatchStatements + List<MatchStatement> statements = matchRules.get(node.getClass()); + if (statements != null) { + for (MatchStatement statement : statements) { + if (statement.generate(this, node, nodes)) { + // Found a match so skip to the next + break; + } + } + } + } + } + } + } + private static final DebugMetric MemoryFoldSuccess = Debug.metric("MemoryFoldSuccess"); private static final DebugMetric MemoryFoldFailed = Debug.metric("MemoryFoldFailed"); private static final DebugMetric MemoryFoldFailedNonAdjacent = Debug.metric("MemoryFoldedFailedNonAdjacent"); @@ -394,7 +453,7 @@ protected abstract boolean peephole(ValueNode valueNode); private void doRoot(ValueNode instr) { - if (gen.traceLevel >= 2) { + if (Options.TraceLIRGeneratorLevel.getValue() >= 2) { TTY.println("Emitting LIR for instruction " + instr); } currentInstruction = instr; @@ -408,11 +467,7 @@ if (Debug.isLogEnabled() && node.stamp() instanceof IllegalStamp) { Debug.log("This node has invalid type, we are emitting dead code(?): %s", node); } - if (node instanceof LIRGenLowerable) { - ((LIRGenLowerable) node).generate(this); - } else if (node instanceof LIRGenResLowerable) { - ((LIRGenResLowerable) node).generate(this, gen.getResult()); - } else if (node instanceof LIRLowerable) { + if (node instanceof LIRLowerable) { ((LIRLowerable) node).generate(this); } else if (node instanceof ArithmeticLIRLowerable) { ((ArithmeticLIRLowerable) node).generate(this, gen); @@ -461,7 +516,7 @@ } private void moveToPhi(MergeNode merge, AbstractEndNode pred) { - if (gen.traceLevel >= 1) { + if (Options.TraceLIRGeneratorLevel.getValue() >= 1) { TTY.println("MOVE TO PHI from " + pred + " to " + merge); } PhiResolver resolver = new PhiResolver(gen); @@ -569,7 +624,7 @@ if (x instanceof InvokeWithExceptionNode) { exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()); } - LIRFrameState callState = gen.stateWithExceptionEdge(x, exceptionEdge); + LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge); Value result = invokeCc.getReturn(); if (callTarget instanceof DirectCallTargetNode) { @@ -662,6 +717,45 @@ return debugInfoBuilder; } + private static FrameState getFrameState(DeoptimizingNode deopt) { + if (deopt instanceof DeoptimizingNode.DeoptBefore) { + assert !(deopt instanceof DeoptimizingNode.DeoptDuring || deopt instanceof DeoptimizingNode.DeoptAfter); + return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore(); + } else if (deopt instanceof DeoptimizingNode.DeoptDuring) { + assert !(deopt instanceof DeoptimizingNode.DeoptAfter); + return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring(); + } else { + assert deopt instanceof DeoptimizingNode.DeoptAfter; + return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter(); + } + } + + public LIRFrameState state(DeoptimizingNode deopt) { + if (!deopt.canDeoptimize()) { + return null; + } + return stateFor(getFrameState(deopt)); + } + + public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) { + if (!deopt.canDeoptimize()) { + return null; + } + return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge); + } + + public LIRFrameState stateFor(FrameState state) { + return stateForWithExceptionEdge(state, null); + } + + public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) { + if (gen.needOnlyOopMaps()) { + return new LIRFrameState(null, null, null); + } + assert state != null; + return getDebugInfoBuilder().build(state, exceptionEdge); + } + public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability) { gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability); } @@ -687,11 +781,7 @@ } @Override - public LIRGenerator getLIRGeneratorTool() { - return gen; - } - - public LIRGenerator getLIRGenerator() { + public LIRGeneratorTool getLIRGeneratorTool() { return gen; } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,22 +29,23 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; /** * Converts {@link ValuePhiNode} instructions into moves. - * + * * Resolves cycles: - * + * * <pre> - * + * * r1 := r2 becomes temp := r1 * r2 := r1 r1 := r2 * r2 := temp * </pre> - * + * * and orders moves: - * + * * <pre> * r2 := r3 becomes r1 := r2 * r1 := r2 r2 := r3 @@ -103,7 +104,7 @@ } } - private final LIRGenerator gen; + private final LIRGeneratorTool gen; /** * The operand loop header phi for the operand currently being process in {@link #dispose()}. @@ -120,7 +121,7 @@ */ private final HashMap<Value, PhiResolverNode> operandToNodeMap = new HashMap<>(); - public PhiResolver(LIRGenerator gen) { + public PhiResolver(LIRGeneratorTool gen) { this.gen = gen; temp = ILLEGAL; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchResult.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,35 @@ +/* + * 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.match; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; + +/* + * A closure that can be evaluated to produce the LIR for some complex match. Using a closure + * allows normal evaluation in NodeLIRBuilder for all the simple nodes with the complex nodes + * evaluated at the proper time. + */ +public interface ComplexMatchResult { + Value evaluate(NodeLIRBuilder gen); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,49 @@ +/* + * 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.match; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; + +/** + * A wrapper value for the lazy evaluation of a complex match. There's an intermediate class for the + * closure because Value is serializable which is a hassle for the little inner classes which + * usually occur here. + */ +public class ComplexMatchValue extends Value { + /** + * + */ + private static final long serialVersionUID = -4734670273590368770L; + + final ComplexMatchResult result; + + public ComplexMatchValue(ComplexMatchResult result) { + super(Kind.Illegal); + this.result = result; + } + + public Value evaluate(NodeLIRBuilder builder) { + return result.evaluate(builder); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/GraalMatchableNodes.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,131 @@ +/* + * 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.match; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; + +/** + * Helper class to describe the matchable nodes in the core Graal IR. These could possibly live in + * their respective classes but for simplicity in the {@link MatchProcessor} they are grouped here. + */ +@MatchableNode(shortName = "Constant", value = ConstantNode.class, inputs = 0) +@MatchableNode(shortName = "FloatConvert", value = FloatConvertNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class) +@MatchableNode(shortName = "FloatSub", value = FloatSubNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class) +@MatchableNode(shortName = "FloatingRead", value = FloatingReadNode.class, inputs = 1, adapter = GraalMatchableNodes.ReadNodeAdapter.class) +@MatchableNode(shortName = "If", value = IfNode.class, inputs = 1, adapter = GraalMatchableNodes.IfNodeAdapter.class) +@MatchableNode(shortName = "IntegerSub", value = IntegerSubNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class) +@MatchableNode(shortName = "LeftShift", value = LeftShiftNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class) +@MatchableNode(shortName = "Narrow", value = NarrowNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class) +@MatchableNode(shortName = "Read", value = ReadNode.class, inputs = 1, adapter = GraalMatchableNodes.ReadNodeAdapter.class) +@MatchableNode(shortName = "Reinterpret", value = ReinterpretNode.class, inputs = 1, adapter = GraalMatchableNodes.ReinterpretNodeAdapter.class) +@MatchableNode(shortName = "SignExtend", value = SignExtendNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class) +@MatchableNode(shortName = "UnsignedRightShift", value = UnsignedRightShiftNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class) +@MatchableNode(shortName = "Write", value = WriteNode.class, inputs = 2, adapter = GraalMatchableNodes.WriteNodeAdapter.class) +@MatchableNode(shortName = "ZeroExtend", value = ZeroExtendNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class) +@MatchableNode(shortName = "And", value = AndNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "FloatAdd", value = FloatAddNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "FloatEquals", value = FloatEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "FloatLessThan", value = FloatLessThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "FloatMul", value = FloatMulNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "IntegerAdd", value = IntegerAddNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "IntegerBelowThan", value = IntegerBelowThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "IntegerEquals", value = IntegerEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "IntegerLessThan", value = IntegerLessThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "IntegerMul", value = IntegerMulNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "IntegerTest", value = IntegerTestNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "ObjectEquals", value = ObjectEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "Or", value = OrNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true) +@MatchableNode(shortName = "Xor", value = XorNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true) +public class GraalMatchableNodes { + public static class BinaryNodeAdapter extends MatchNodeAdapter { + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((BinaryNode) node).x(); + } + + @Override + protected ValueNode getSecondInput(ValueNode node) { + return ((BinaryNode) node).y(); + } + } + + public static class WriteNodeAdapter extends MatchNodeAdapter { + + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((WriteNode) node).object(); + } + + @Override + protected ValueNode getSecondInput(ValueNode node) { + return ((WriteNode) node).value(); + } + } + + public static class ConvertNodeAdapter extends MatchNodeAdapter { + + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((ConvertNode) node).getInput(); + } + } + + public static class ReinterpretNodeAdapter extends MatchNodeAdapter { + + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((ReinterpretNode) node).value(); + } + } + + public static class IfNodeAdapter extends MatchNodeAdapter { + + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((IfNode) node).condition(); + } + } + + public static class ReadNodeAdapter extends MatchNodeAdapter { + + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((Access) node).object(); + } + } + + public static class BinaryOpLogicNodeAdapter extends MatchNodeAdapter { + + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((BinaryOpLogicNode) node).x(); + } + + @Override + protected ValueNode getSecondInput(ValueNode node) { + return ((BinaryOpLogicNode) node).y(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchContext.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,191 @@ +/* + * 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.match; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.match.MatchPattern.Result; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.virtual.*; + +/** + * Container for state captured during a match. + */ +public class MatchContext { + private final ArrayList<ValueNode> consumed = new ArrayList<>(); + private final List<ScheduledNode> nodes; + private final ValueNode root; + private List<String> names; + private List<Class<? extends ValueNode>> types; + private List<ValueNode> values; + private final MatchStatement rule; + private int startIndex; + private int endIndex; + private final NodeLIRBuilder builder; + + public MatchContext(NodeLIRBuilder builder, MatchStatement rule, ValueNode node, List<ScheduledNode> nodes) { + this.builder = builder; + this.rule = rule; + this.root = node; + this.nodes = nodes; + // The root should be the last index since all the inputs must be scheduled before. + startIndex = endIndex = nodes.indexOf(node); + } + + public ValueNode getRoot() { + return root; + } + + public Result captureNamedValue(String name, Class<? extends ValueNode> type, ValueNode value) { + if (names == null) { + names = new ArrayList<>(2); + values = new ArrayList<>(2); + types = new ArrayList<>(2); + } + int index = names.indexOf(name); + if (index == -1) { + names.add(name); + values.add(value); + types.add(type); + return Result.OK; + } else { + if (values.get(index) != value) { + return Result.NAMED_VALUE_MISMATCH(value, rule.getPattern()); + } + return Result.OK; + } + } + + public Result validate() { + // Ensure that there's no unsafe work in between these operations. + for (int i = startIndex; i <= endIndex; i++) { + ScheduledNode node = getNodes().get(i); + if (node instanceof ConstantNode || node instanceof LocationNode || node instanceof VirtualObjectNode || node instanceof ParameterNode) { + // these can be evaluated lazily so don't worry about them. This should probably be + // captured by some interface that indicates that their generate method is empty. + continue; + } else if (!consumed.contains(node) && node != root) { + // This is too verbose for normal logging. + // Debug.log("unexpected node %s", node); + // for (int j = startIndex; j <= endIndex; j++) { + // ScheduledNode theNode = getNodes().get(j); + // Debug.log("%s(%s) %1s", (consumed.contains(theNode) || theNode == root) ? "*" : + // " ", + // theNode.usages().count(), theNode); + // } + return Result.NOT_SAFE(node, rule.getPattern()); + } + } + return Result.OK; + } + + /** + * Transfers the captured value into the MatchGenerator instance. The reflective information + * should really be generated and checking during construction of the MatchStatement but this is + * ok for now. + */ + public void transferState(MatchGenerator generator) { + try { + for (int i = 0; i < names.size(); i++) { + String name = names.get(i); + try { + Field field = generator.getClass().getDeclaredField(name); + field.setAccessible(true); + field.set(generator, values.get(i)); + } catch (NoSuchFieldException e) { + // Doesn't exist so the generator doesn't care about the value. + } + } + } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) { + throw new GraalInternalError(e); + } + try { + Field field = generator.getClass().getDeclaredField("root"); + field.setAccessible(true); + field.set(generator, getRoot()); + } catch (NoSuchFieldException e) { + // Doesn't exist + } catch (SecurityException | IllegalAccessException | IllegalArgumentException e) { + throw new GraalInternalError(e); + } + } + + public void setResult(ComplexMatchResult result) { + setResult(new ComplexMatchValue(result)); + } + + /** + * Mark the interior nodes with INTERIOR_MATCH and set the Value of the root to be the result. + * During final LIR generation it will be evaluated to produce the actual LIR value. + * + * @param result + */ + public void setResult(ComplexMatchValue result) { + Debug.log("matched %s %s", rule.getName(), rule.getPattern()); + // Debug.log("%s", rule.formatMatch(root)); + for (ValueNode node : consumed) { + // All the interior nodes should be skipped during the normal doRoot calls in + // NodeLIRBuilder so mark them as interior matches. The root of the match will get a + // closure which will be evaluated to produce the final LIR. + getBuilder().setMatchResult(node, Value.INTERIOR_MATCH); + } + getBuilder().setMatchResult(root, result); + } + + /** + * Mark a node as consumed by the match. Consumed nodes will never be evaluated. + * + * @return Result.OK if the node can be safely consumed. + */ + public Result consume(ValueNode node) { + if (node.usages().count() != 1) { + return Result.TOO_MANY_USERS(node, rule.getPattern()); + } + + if (getBuilder().hasOperand(node)) { + return Result.ALREADY_USED(node, rule.getPattern()); + } + + int index = getNodes().indexOf(node); + if (index == -1) { + return Result.NOT_IN_BLOCK(node, rule.getPattern()); + } + startIndex = Math.min(startIndex, index); + consumed.add(node); + return Result.OK; + } + + private NodeLIRBuilder getBuilder() { + return builder; + } + + private List<ScheduledNode> getNodes() { + return nodes; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,35 @@ +/* + * 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.match; + +import com.oracle.graal.compiler.gen.*; + +/** + * Code generator for complex match patterns. + * + * @returns null if the match can't be generated or a {@link ComplexMatchResult} that can be + * evaluated during LIR generation to produce the final LIR value. + */ +public interface MatchGenerator { + ComplexMatchResult match(NodeLIRBuilder gen); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchNodeAdapter.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,42 @@ +/* + * 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.match; + +import com.oracle.graal.nodes.*; + +/** + * Helper class to visit the matchable inputs of a node in a specified order. This may not be needed + * in the end since this could probably be done using the inputs iterator but it simplifies things + * for the moment. + */ +public class MatchNodeAdapter { + @SuppressWarnings("unused") + protected ValueNode getFirstInput(ValueNode node) { + throw new InternalError(); + } + + @SuppressWarnings("unused") + protected ValueNode getSecondInput(ValueNode node) { + throw new InternalError(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,201 @@ +/* + * 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.match; + +import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.nodes.*; + +/** + * A simple recursive pattern matcher for a DAG of nodes. + */ + +public class MatchPattern { + + enum MatchResultCode { + OK, + WRONG_CLASS, + NAMED_VALUE_MISMATCH, + TOO_MANY_USERS, + NOT_IN_BLOCK, + NOT_SAFE, + ALREADY_USED, + } + + /** + * A descriptive result for match failures. This can be helpful for debugging why a match + * doesn't work as expected. + */ + static class Result { + final MatchResultCode code; + final ScheduledNode node; + final MatchPattern matcher; + + Result(MatchResultCode result, ScheduledNode node, MatchPattern matcher) { + this.code = result; + this.node = node; + this.matcher = matcher; + } + + static final Result OK = new Result(MatchResultCode.OK, null, null); + + static Result WRONG_CLASS(ValueNode node, MatchPattern matcher) { + return new Result(MatchResultCode.WRONG_CLASS, node, matcher); + } + + static Result NAMED_VALUE_MISMATCH(ValueNode node, MatchPattern matcher) { + return new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher); + } + + static Result TOO_MANY_USERS(ValueNode node, MatchPattern matcher) { + return new Result(MatchResultCode.TOO_MANY_USERS, node, matcher); + } + + static Result NOT_IN_BLOCK(ScheduledNode node, MatchPattern matcher) { + return new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher); + } + + static Result NOT_SAFE(ScheduledNode node, MatchPattern matcher) { + return new Result(MatchResultCode.NOT_SAFE, node, matcher); + } + + static Result ALREADY_USED(ValueNode node, MatchPattern matcher) { + return new Result(MatchResultCode.ALREADY_USED, node, matcher); + } + + @Override + public String toString() { + if (code == MatchResultCode.OK) { + return "OK"; + } + return code + " " + node.toString(Verbosity.Id) + "|" + node.getClass().getSimpleName() + " " + matcher; + } + } + + /** + * The expected type of the node. It must match exactly. + */ + private final Class<? extends ValueNode> nodeClass; + /** + * An optional name for this node. A name can occur multiple times in a match and that name must + * always refer to the same node of the match will fail. + */ + private final String name; + /** + * An optional pattern for the first input. + */ + private final MatchPattern first; + /** + * An optional pattern for the second input. + */ + private final MatchPattern second; + /** + * Helper class to visit the inputs. + */ + private final MatchNodeAdapter adapter; + /** + * Can there only be one user of the node. Constant nodes can be matched even if there are other + * users. + */ + private final boolean singleUser; + + public MatchPattern(String name, boolean singleUser) { + this(null, name, null, null, null, singleUser); + } + + public MatchPattern(Class<? extends ValueNode> nodeClass, String name, boolean singleUser) { + this(nodeClass, name, null, null, null, singleUser); + } + + public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchNodeAdapter adapter, boolean singleUser) { + this(nodeClass, name, first, null, adapter, singleUser); + } + + public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, MatchNodeAdapter adapter, boolean singleUser) { + this.nodeClass = nodeClass; + this.name = name; + this.singleUser = singleUser; + this.first = first; + this.second = second; + this.adapter = adapter; + } + + Class<? extends ValueNode> nodeClass() { + return nodeClass; + } + + Result match(ValueNode node, MatchContext context) { + return matchTree(node, context, true); + } + + private Result matchTree(ValueNode node, MatchContext context, boolean atRoot) { + Result result = Result.OK; + if (nodeClass != null && node.getClass() != nodeClass) { + return Result.WRONG_CLASS(node, this); + } + if (singleUser && !atRoot) { + result = context.consume(node); + if (result != Result.OK) { + return result; + } + } + + if (name != null) { + result = context.captureNamedValue(name, nodeClass, node); + } + + if (first != null) { + result = first.matchTree(adapter.getFirstInput(node), context, false); + if (result == Result.OK && second != null) { + result = second.matchTree(adapter.getSecondInput(node), context, false); + } + } + + return result; + } + + /** + * For a node starting at root, produce a String showing the inputs that matched against this + * rule. It's assumed that a match has already succeeded against this rule, otherwise the + * printing may produce exceptions. + */ + public String formatMatch(ValueNode root) { + String result = String.format("%s", root); + if (first == null && second == null) { + return result; + } else { + return "(" + result + (first != null ? " " + first.formatMatch(adapter.getFirstInput(root)) : "") + (second != null ? " " + second.formatMatch(adapter.getSecondInput(root)) : "") + ")"; + } + } + + @Override + public String toString() { + if (nodeClass == null) { + return name; + } else { + String pre = first != null || second != null ? "(" : ""; + String post = first != null || second != null ? ")" : ""; + String nodeName = nodeClass.getSimpleName(); + return pre + nodeName + (name != null ? "=\"" + name + "\"" : "") + (first != null ? (" " + first.toString()) : "") + (second != null ? (" " + second.toString()) : "") + post; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,574 @@ +/* + * 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.match; + +import java.io.*; +import java.util.*; +import java.util.regex.*; + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.tools.Diagnostic.Kind; +import javax.tools.*; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.nodes.*; + +/** + * Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is + * generated for each top level class containing at least one such field. These service objects can + * be retrieved as follows: + * + * <pre> + * ServiceLoader<MatchStatementSet> sl = ServiceLoader.loadInstalled(MatchStatementSet.class); + * for (MatchStatementSet rules : sl) { + * ... + * } + * </pre> + */ +@SupportedAnnotationTypes({"com.oracle.graal.compiler.match.MatchRule", "com.oracle.graal.compiler.match.MatchRules", "com.oracle.graal.compiler.match.MatchableNode"}) +public class MatchProcessor extends AbstractProcessor { + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + private final Set<Element> processedMatchRule = new HashSet<>(); + private final Set<Element> processedMatchableNode = new HashSet<>(); + + private static class RuleParseError extends RuntimeException { + private static final long serialVersionUID = 6456128283609257490L; + + RuleParseError(String message) { + super(message); + } + } + + private class RuleParser { + final String[] tokens; + int current; + + RuleParser(String rule) { + Matcher m = tokenizer.matcher(rule); + List<String> list = new ArrayList<>(); + int end = 0; + while (m.lookingAt()) { + list.add(m.group(1)); + end = m.end(); + m.region(m.end(), m.regionEnd()); + } + if (end != m.regionEnd()) { + throw new RuleParseError("unexpected tokens :" + rule.substring(m.end(), m.regionEnd())); + } + tokens = list.toArray(new String[0]); + } + + String next() { + return tokens[current++]; + } + + String peek() { + return tokens[current]; + } + + boolean done() { + return current == tokens.length; + } + + private MatchDescriptor parseSexp() { + if (peek().equals("(")) { + next(); + MatchDescriptor descriptor = parseType(true); + for (int n = 0; n < descriptor.nodeType.inputs; n++) { + if (peek().equals("(")) { + descriptor.inputs[n] = parseSexp(); + } else { + descriptor.inputs[n] = parseType(false); + } + } + for (int n = 0; n < descriptor.nodeType.inputs; n++) { + if (descriptor.inputs[n] == null) { + throw new RuleParseError("not enough inputs for " + descriptor.name); + } + } + if (peek().equals(")")) { + next(); + return descriptor; + } + } + throw new RuleParseError("didn't swallow sexp at: " + peek()); + } + + private MatchDescriptor parseType(boolean sexp) { + TypeDescriptor type = null; + String name = null; + if (Character.isUpperCase(peek().charAt(0))) { + String token = next(); + type = types.get(token); + if (type == null) { + throw new RuleParseError("unknown node type: " + token); + } + if (peek().equals("=")) { + next(); + name = next(); + } + } else { + name = next(); + type = null; + } + return new MatchDescriptor(type, name, sexp); + } + + ArrayList<String> generateVariants() { + MatchDescriptor descriptor = parseSexp(); + if (!done()) { + throw new RuleParseError("didn't consume all tokens"); + } + return descriptor.generateVariants(); + } + } + + static Pattern tokenizer = Pattern.compile("\\s*([()=]|[A-Za-z][A-Za-z0-9]*)\\s*"); + + static class TypeDescriptor { + /** + * The name uses in match expressions to refer to this type. + */ + final String shortName; + /** + * The {@link ValueNode} class represented by this type. + */ + final String nodeClass; + + /** + * The {@link ValueNode} class represented by this type. + */ + final String nodePackage; + + /** + * Expected number of matchable inputs. Should be less <= 2 at the moment. + */ + final int inputs; + + /** + * An adapter class to read the proper matchable inputs of the class. + */ + final String adapter; + + /** + * Should swapped variants of this match be generated. The user of the match is expected to + * compensate for any ordering differences in compare which are commutative but require + * reinterpreting the condition in that case. + */ + final boolean commutative; + + /** + * Can multiple users of this node subsume it. Constants can be swallowed into a match even + * if there are multiple users. + */ + final boolean cloneable; + + TypeDescriptor(String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative) { + this.shortName = shortName; + this.nodeClass = nodeClass; + this.nodePackage = nodePackage; + this.inputs = inputs; + this.adapter = adapter; + this.commutative = commutative; + this.cloneable = (nodePackage + "." + nodeClass).equals(ConstantNode.class.getName()); + assert !commutative || inputs == 2; + } + } + + HashMap<String, TypeDescriptor> types = new HashMap<>(); + ArrayList<String> packages = new ArrayList<>(); + + private void declareType(String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative) { + TypeDescriptor descriptor = new TypeDescriptor(shortName, nodeClass, nodePackage, inputs, adapter, commutative); + types.put(shortName, descriptor); + if (!packages.contains(descriptor.nodePackage)) { + packages.add(descriptor.nodePackage); + } + } + + private static String findPackage(Element type) { + Element enclosing = type.getEnclosingElement(); + while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { + enclosing = enclosing.getEnclosingElement(); + } + if (enclosing != null && enclosing.getKind() == ElementKind.PACKAGE) { + return ((PackageElement) enclosing).getQualifiedName().toString(); + } + throw new GraalInternalError("can't find package for %s", type); + } + + static class MatchDescriptor { + TypeDescriptor nodeType; + String name; + MatchDescriptor[] inputs; + + MatchDescriptor(TypeDescriptor nodeType, String name, boolean sexp) { + this.nodeType = nodeType; + this.name = name; + if (sexp) { + this.inputs = new MatchDescriptor[nodeType.inputs]; + } else { + this.inputs = new MatchDescriptor[0]; + } + } + + ArrayList<String> generateVariants() { + String prefix = formatPrefix(); + String suffix = formatSuffix(); + ArrayList<String> variants = new ArrayList<>(); + if (inputs.length == 2) { + // Generate this version and a swapped version + for (String first : inputs[0].generateVariants()) { + for (String second : inputs[1].generateVariants()) { + variants.add(prefix + ", " + first + ", " + second + suffix); + if (nodeType.commutative) { + variants.add(prefix + ", " + second + ", " + first + suffix); + } + } + } + } else if (inputs.length == 1) { + for (String first : inputs[0].generateVariants()) { + variants.add(prefix + ", " + first + suffix); + } + } else { + variants.add(prefix + suffix); + } + return variants; + } + + private String formatPrefix() { + if (nodeType == null) { + return String.format("new MatchPattern(%s, false", name != null ? ("\"" + name + "\"") : "null"); + } else { + return String.format("new MatchPattern(%s.class, %s", nodeType.nodeClass, name != null ? ("\"" + name + "\"") : "null"); + } + } + + private String formatSuffix() { + if (nodeType != null) { + if (inputs.length != nodeType.inputs) { + return ", true)"; + } else { + if (nodeType.adapter != null) { + return ", " + nodeType.adapter + "," + !nodeType.cloneable + ")"; + } + if (nodeType.cloneable) { + return ", false)"; + } + } + } + return ")"; + } + + } + + private void createFiles(MatchRuleDescriptor info) { + String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString(); + Name topDeclaringClass = info.topDeclaringType.getSimpleName(); + + String optionsClassName = topDeclaringClass + "_" + MatchStatementSet.class.getSimpleName(); + Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]); + + Filer filer = processingEnv.getFiler(); + try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) { + + out.println("// CheckStyle: stop header check"); + out.println("// GENERATED CONTENT - DO NOT EDIT"); + out.println("// Source: " + topDeclaringClass + ".java"); + out.println("package " + pkg + ";"); + out.println(""); + out.println("import java.util.*;"); + out.println("import " + MatchStatementSet.class.getPackage().getName() + ".*;"); + out.println("import " + NodeLIRBuilder.class.getName() + ";"); + for (String p : packages) { + out.println("import " + p + ".*;"); + } + out.println(""); + out.println("public class " + optionsClassName + " implements " + MatchStatementSet.class.getSimpleName() + " {"); + String desc = MatchStatement.class.getSimpleName(); + out.println(" // CheckStyle: stop line length check"); + out.println(" private static final List<" + desc + "> options = Collections.unmodifiableList(Arrays.asList("); + + int i = 0; + for (MatchRuleItem option : info.options) { + String optionValue; + if (option.field.getModifiers().contains(Modifier.PRIVATE)) { + optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")"; + } else { + optionValue = option.declaringClass + "." + option.field.getSimpleName(); + } + String name = option.name; + Name fieldName = option.field.getSimpleName(); + String comma = i == info.options.size() - 1 ? "" : ","; + out.printf(" new MatchStatement(\"%s\", %s, %s.class)%s\n", fieldName, name, optionValue, comma); + i++; + } + out.println(" ));"); + out.println(" // CheckStyle: resume line length check"); + out.println(); + + out.println(" public Class<? extends NodeLIRBuilder> forClass() {"); + out.println(" return " + topDeclaringClass + ".class;"); + out.println(" }"); + out.println(); + out.println(" @Override"); + out.println(" public List<" + desc + "> statements() {"); + out.println(" return options;"); + out.println(" }"); + out.println("}"); + } + + try { + createProviderFile(pkg, optionsClassName, originatingElements); + } catch (IOException e) { + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType); + } + } + + private void createProviderFile(String pkg, String providerClassName, Element... originatingElements) throws IOException { + String filename = "META-INF/providers/" + pkg + "." + providerClassName; + FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); + writer.println(MatchStatementSet.class.getName()); + writer.close(); + } + + protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) { + try { + // Ensure Unix line endings to comply with Graal code style guide checked by Checkstyle + JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, originatingElements); + return new PrintWriter(sourceFile.openWriter()) { + + @Override + public void println() { + print("\n"); + } + }; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + static class MatchRuleItem implements Comparable<MatchRuleItem> { + + final String name; + final String declaringClass; + final TypeElement field; + + public MatchRuleItem(String name, String declaringClass, TypeElement field) { + this.name = name; + this.declaringClass = declaringClass; + this.field = field; + } + + @Override + public int compareTo(MatchRuleItem other) { + return name.compareTo(other.name); + } + + @Override + public String toString() { + return declaringClass + "." + field; + } + } + + static class MatchRuleDescriptor { + + final TypeElement topDeclaringType; + final List<MatchRuleItem> options = new ArrayList<>(); + final Set<Element> originatingElements = new HashSet<>(); + + public MatchRuleDescriptor(TypeElement topDeclaringType) { + this.topDeclaringType = topDeclaringType; + } + } + + private static TypeElement topDeclaringType(Element element) { + Element enclosing = element.getEnclosingElement(); + if (enclosing == null || enclosing.getKind() == ElementKind.PACKAGE) { + assert element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE; + return (TypeElement) element; + } + return topDeclaringType(enclosing); + } + + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + return true; + } + + try { + // Import default definitions + processMatchableNode(processingEnv.getElementUtils().getTypeElement(GraalMatchableNodes.class.getName())); + for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNodeImport.class)) { + // Import any other definitions required by this element + String[] imports = element.getAnnotation(MatchableNodeImport.class).value(); + for (String m : imports) { + TypeElement el = processingEnv.getElementUtils().getTypeElement(m); + processMatchableNode(el); + } + } + + // Process any local MatchableNode declarations + for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNode.class)) { + processMatchableNode(element); + } + + Map<TypeElement, MatchRuleDescriptor> map = new HashMap<>(); + for (Element element : roundEnv.getElementsAnnotatedWith(MatchRule.class)) { + processMatchRule(map, element); + } + for (Element element : roundEnv.getElementsAnnotatedWith(MatchRules.class)) { + processMatchRule(map, element); + } + + for (MatchRuleDescriptor info : map.values()) { + createFiles(info); + } + + } catch (Throwable t) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Exception throw during processing: " + t); + } + + return true; + } + + /** + * Build up the type table to be used during parsing of the MatchRule. + */ + private void processMatchableNode(Element element) { + if (!processedMatchableNode.contains(element)) { + processedMatchableNode.add(element); + TypeElement topDeclaringType = topDeclaringType(element); + MatchableNode[] matchables = element.getAnnotationsByType(MatchableNode.class); + for (MatchableNode matchable : matchables) { + String nodeClass; + String nodePackage; + String shortName = matchable.shortName(); + TypeMirror nodeClassMirror = null; + try { + matchable.value(); + } catch (MirroredTypeException e) { + nodeClassMirror = e.getTypeMirror(); + } + if (nodeClassMirror == null) { + throw new GraalInternalError("Can't get mirror for node class %s", element); + } + if (nodeClassMirror.toString().equals(MatchableNode.class.getName())) { + nodeClass = topDeclaringType.getQualifiedName().toString(); + } else { + nodeClass = nodeClassMirror.toString(); + } + nodePackage = findPackage(processingEnv.getElementUtils().getTypeElement(nodeClass)); + assert nodeClass.startsWith(nodePackage); + nodeClass = nodeClass.substring(nodePackage.length() + 1); + + TypeMirror nodeAdapterMirror = null; + try { + matchable.adapter(); + } catch (MirroredTypeException e) { + nodeAdapterMirror = e.getTypeMirror(); + } + if (nodeAdapterMirror == null) { + throw new GraalInternalError("Can't get mirror for adapter %s", element); + } + String nodeAdapter = null; + if (!nodeAdapterMirror.toString().equals(MatchableNode.class.getName())) { + nodeAdapter = String.format("new %s()", nodeAdapterMirror.toString()); + } + + declareType(shortName, nodeClass, nodePackage, matchable.inputs(), nodeAdapter, matchable.commutative()); + } + } + } + + private void processMatchRule(Map<TypeElement, MatchRuleDescriptor> map, Element element) { + if (!processedMatchRule.contains(element)) { + processedMatchRule.add(element); + TypeElement topDeclaringType = topDeclaringType(element); + MatchRuleDescriptor options = map.get(topDeclaringType); + if (options == null) { + options = new MatchRuleDescriptor(topDeclaringType); + map.put(topDeclaringType, options); + } + MatchRule[] matchRules = element.getAnnotationsByType(MatchRule.class); + for (MatchRule matchRule : matchRules) { + processMatchRule(element, options, matchRule); + } + } + } + + private void processMatchRule(Element element, MatchRuleDescriptor info, MatchRule matchRule) { + assert element instanceof TypeElement; + assert element.getKind() == ElementKind.CLASS; + TypeElement field = (TypeElement) element; + + TypeMirror fieldType = field.asType(); + if (fieldType.getKind() != TypeKind.DECLARED) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + MatchRule.class.getName(), element); + return; + } + + Element enclosing = element.getEnclosingElement(); + String declaringClass = ""; + String separator = ""; + Set<Element> originatingElementsList = info.originatingElements; + originatingElementsList.add(field); + while (enclosing != null) { + if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { + if (enclosing.getModifiers().contains(Modifier.PRIVATE)) { + String msg = String.format("Option field cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing); + processingEnv.getMessager().printMessage(Kind.ERROR, msg, element); + return; + } + originatingElementsList.add(enclosing); + declaringClass = enclosing.getSimpleName() + separator + declaringClass; + separator = "."; + } else { + assert enclosing.getKind() == ElementKind.PACKAGE; + } + enclosing = enclosing.getEnclosingElement(); + } + + String rule = matchRule.value(); + try { + ArrayList<String> matches = new RuleParser(rule).generateVariants(); + for (String match : matches) { + info.options.add(new MatchRuleItem(match, declaringClass, field)); + } + } catch (RuleParseError e) { + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), element); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRule.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,50 @@ +/* + * 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.match; + +import java.lang.annotation.*; + +import com.oracle.graal.nodes.*; + +/** + * This annotation declares a textual pattern for matching an HIR DAG. It's an s-expression with a + * node followed by its inputs. Node types are always uppercase and lowercase words are the names of + * nodes. + * + * <pre> + * NAME := [a-z][a-zA-Z0-9]* + * NODETYPE := [A-Z][a-zA-Z0-9]* + * NODEORNAME := NODE [ = NAME ] | NAME + * EXPRESSION := ( NODEORNAME [ EXPRESSION | NODEORNAME [ EXPRESSION | NODEORNAME ] ) + * </pre> + * + * All matched nodes except the root of the match and {@link ConstantNode}s must have a single user. + * All matched nodes must be in the same block. + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Repeatable(value = MatchRules.class) +public @interface MatchRule { + String value(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,79 @@ +/* + * 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.match; + +import java.util.*; + +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.nodes.*; + +public class MatchRuleRegistry { + + private static final HashMap<Class<? extends NodeLIRBuilder>, Map<Class<? extends ValueNode>, List<MatchStatement>>> registry = new HashMap<>(); + + /** + * Collect all the {@link MatchStatement}s defined by the superclass chain of theClass. + * + * @param theClass + * @return the set of {@link MatchStatement}s applicable to theClass. + */ + public synchronized static Map<Class<? extends ValueNode>, List<MatchStatement>> lookup(Class<? extends NodeLIRBuilder> theClass) { + Map<Class<? extends ValueNode>, List<MatchStatement>> result = registry.get(theClass); + + if (result == null) { + HashMap<Class<? extends NodeLIRBuilder>, List<MatchStatement>> localRules = new HashMap<>(); + ServiceLoader<MatchStatementSet> sl = ServiceLoader.loadInstalled(MatchStatementSet.class); + for (MatchStatementSet rules : sl) { + localRules.put(rules.forClass(), rules.statements()); + } + + // Walk the class hierarchy collecting lists and merge them together. The subclass + // rules are first which gives them preference over earlier rules. + Map<Class<? extends ValueNode>, List<MatchStatement>> rules = new HashMap<>(); + Class<?> currentClass = theClass; + do { + List<MatchStatement> statements = localRules.get(currentClass); + if (statements != null) { + for (MatchStatement statement : statements) { + Class<? extends ValueNode> nodeClass = statement.getPattern().nodeClass(); + List<MatchStatement> current = rules.get(nodeClass); + if (current == null) { + current = new ArrayList<>(); + rules.put(nodeClass, current); + } + current.add(statement); + } + } + currentClass = currentClass.getSuperclass(); + } while (currentClass != NodeLIRBuilder.class); + registry.put(theClass, rules); + assert registry.get(theClass) == rules; + result = rules; + } + + if (result.size() == 0) { + return null; + } + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRules.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,34 @@ +/* + * 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.match; + +import java.lang.annotation.*; + +/** + * The repeatable representation of {@link MatchRule}. Should never be used directly. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MatchRules { + MatchRule[] value(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,106 @@ +/* + * 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.match; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.match.MatchPattern.Result; +import com.oracle.graal.nodes.*; + +/** + * A named {@link MatchPattern} along with a {@link MatchGenerator} that can be evaluated to replace + * one or more {@link ValueNode}s with a single {@link Value}. + */ + +public class MatchStatement { + private final String name; + private final MatchPattern pattern; + private final Class<? extends MatchGenerator> generatorClass; + + public MatchStatement(String name, MatchPattern pattern) { + this.name = name; + this.pattern = pattern; + this.generatorClass = null; + } + + public MatchStatement(String name, MatchPattern pattern, Class<? extends MatchGenerator> generator) { + this.name = name; + this.pattern = pattern; + this.generatorClass = generator; + } + + /** + * Attempt to match the current statement against a Node. + * + * @param builder the current builder instance. + * @param node the node to be matched + * @param nodes the nodes in the current block + * @return true if the statement matched something and set a {@link ComplexMatchResult} to be + * evaluated by the NodeLIRBuilder. + */ + public boolean generate(NodeLIRBuilder builder, ValueNode node, List<ScheduledNode> nodes) { + MatchContext context = new MatchContext(builder, this, node, nodes); + Result result = pattern.match(node, context); + if (result == Result.OK) { + result = context.validate(); + } + if (result == Result.OK) { + MatchGenerator generator = null; + try { + generator = generatorClass.newInstance(); + // Transfer values into gen + context.transferState(generator); + ComplexMatchResult value = generator.match(builder); + if (value != null) { + context.setResult(value); + return true; + } + } catch (InstantiationException | IllegalAccessException e) { + throw new GraalInternalError(e); + } + } else { + // This is fairly verbose for normal usage. + // if (result.code != MatchResultCode.WRONG_CLASS) { + // // Don't bother logging if it's just the wrong shape. + // Debug.log("while matching %s|%s %s %s %s", context.getRoot().toString(Verbosity.Id), + // context.getRoot().getClass().getSimpleName(), getName(), result, node.graph()); + // } + } + return false; + } + + public String formatMatch(ValueNode root) { + return pattern.formatMatch(root); + } + + public MatchPattern getPattern() { + return pattern; + } + + public String getName() { + return name; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatementSet.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,40 @@ +/* + * 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.match; + +import java.util.*; + +import com.oracle.graal.compiler.gen.*; + +public interface MatchStatementSet { + /** + * @return the {@link NodeLIRBuilder} subclass which defined this set of {@link MatchStatement} + * instances. + */ + public Class<? extends NodeLIRBuilder> forClass(); + + /** + * @return the {@link MatchStatement}s available with this {@link NodeLIRBuilder} subclass. + */ + public List<MatchStatement> statements(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,66 @@ +/* + * 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.match; + +import java.lang.annotation.*; + +import com.oracle.graal.nodes.*; + +/** + * Describes the properties of a node for use when building a {@link MatchPattern}s. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Repeatable(value = MatchableNodes.class) +public @interface MatchableNode { + + /** + * The {@link ValueNode} subclass this annotation describes. These annotations might work better + * if they were directly on the node being described but that may complicate the annotation + * processing. + */ + Class<? extends ValueNode> value(); + + /** + * The name used in match patterns. Defaults to class.getSimpleName() with the word Node removed + * from the end. + */ + String shortName() default ""; + + /** + * The number of matchable inputs, which may be less than the real number of inputs. + */ + int inputs() default 0; + + /** + * A helper class to visit the inputs in a specified order. Should be a subclass of + * {@link MatchNodeAdapter}. + */ + Class<?> adapter() default MatchableNode.class; + + /** + * Can a pattern be matched with the operands swapped. This will cause swapped versions of + * patterns to be automatically generated. + */ + boolean commutative() default false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNodeImport.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,36 @@ +/* + * 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.match; + +import java.lang.annotation.*; + +/** + * A list of classes which contain one or more {@link MatchableNode} annotations describing nodes + * that may be used in match expressions. Those {@link MatchableNode} declarations are parsed before + * processing any {@link MatchRule}s. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MatchableNodeImport { + String[] value() default {}; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNodes.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,34 @@ +/* + * 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.match; + +import java.lang.annotation.*; + +/** + * The repeatable representation of {@link MatchableNode}. Should never be used directly. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MatchableNodes { + MatchableNode[] value() default {}; +}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,14 +22,15 @@ */ package com.oracle.graal.compiler.phases; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.compiler.phases.HighTier.Options.*; -import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.cfs.IterativeFlowSensitiveReductionPhase; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; @@ -57,9 +58,14 @@ appendPhase(new InliningPhase(canonicalizer)); appendPhase(new DeadCodeEliminationPhase()); - if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) { + boolean reduceOrEliminate = FlowSensitiveReduction.getValue() || ConditionalElimination.getValue(); + if (reduceOrEliminate && OptCanonicalizer.getValue()) { appendPhase(canonicalizer); - appendPhase(new IterativeConditionalEliminationPhase(canonicalizer)); + if (FlowSensitiveReduction.getValue()) { + appendPhase(new IterativeFlowSensitiveReductionPhase(canonicalizer)); + } else { + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer)); + } } } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.phases; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.phases; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.spi.*; @@ -51,9 +51,7 @@ } if (OptFloatingReads.getValue()) { - IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer); - incCanonicalizer.appendPhase(new FloatingReadPhase()); - appendPhase(incCanonicalizer); + appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase())); if (OptReadElimination.getValue()) { appendPhase(new ReadEliminationPhase()); } @@ -84,7 +82,7 @@ appendPhase(new LoopSafepointInsertionPhase()); - appendPhase(new GuardLoweringPhase()); + appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new GuardLoweringPhase())); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER));
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Apr 28 10:31:17 2014 +0200 @@ -30,7 +30,9 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; @@ -71,17 +73,17 @@ */ public abstract FrameMap newFrameMap(RegisterConfig registerConfig); - public abstract LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes); + public abstract LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes); public abstract LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub); - public abstract NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen); + public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen); /** * @param gen the LIRGenerator the BytecodeLIRBuilder should use * @param parser the bytecode parser the BytecodeLIRBuilder should use */ - public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) { + public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) { throw GraalInternalError.unimplemented("Baseline compilation is not available for this Backend!"); }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011, 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.target; - -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.nodes.spi.*; - -/** - * An alternative to {@link LIRLowerable} for lowering that is tightly coupled to - * {@link LIRGenerator} and {@link LIRInstruction}. - */ -public interface LIRGenLowerable { - - void generate(NodeLIRBuilder generator); -}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011, 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.target; - -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.nodes.spi.*; - -/** - * An alternative to {@link LIRLowerable} for lowering that is tightly coupled to - * {@link LIRGenerationResult} and {@link LIRInstruction}. - */ -public interface LIRGenResLowerable { - - void generate(NodeLIRBuilderTool generator, LIRGenerationResult genRes); -}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2012, 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.graph; - -import java.lang.reflect.*; -import java.util.*; -import java.util.concurrent.*; - -public abstract class FieldIntrospection extends UnsafeAccess { - - /** - * Interface used by {@link #rescanAllFieldOffsets(CalcOffset)} to determine the offset (in - * bytes) of a field. - */ - public interface CalcOffset { - - long getOffset(Field field); - } - - public static class DefaultCalcOffset implements CalcOffset { - - @Override - public long getOffset(Field field) { - return unsafe.objectFieldOffset(field); - } - } - - protected static final ConcurrentHashMap<Class<?>, FieldIntrospection> allClasses = new ConcurrentHashMap<>(); - - protected final Class<?> clazz; - protected long[] dataOffsets; - protected Map<Long, String> fieldNames; - protected Map<Long, Class<?>> fieldTypes; - - public FieldIntrospection(Class<?> clazz) { - this.clazz = clazz; - } - - public static void rescanAllFieldOffsets(CalcOffset calc) { - for (FieldIntrospection nodeClass : allClasses.values()) { - nodeClass.rescanFieldOffsets(calc); - } - } - - protected abstract void rescanFieldOffsets(CalcOffset calc); - - public abstract static class BaseFieldScanner { - - private final CalcOffset calc; - - /** The offsets of fields that are not specially handled by subclasses. */ - public final ArrayList<Long> dataOffsets = new ArrayList<>(); - - public final Map<Long, String> fieldNames = new HashMap<>(); - public final Map<Long, Class<?>> fieldTypes = new HashMap<>(); - - protected BaseFieldScanner(CalcOffset calc) { - this.calc = calc; - } - - protected void scan(Class<?> clazz) { - Class<?> currentClazz = clazz; - do { - for (Field field : currentClazz.getDeclaredFields()) { - if (Modifier.isStatic(field.getModifiers())) { - continue; - } - Class<?> type = field.getType(); - long offset = calc.getOffset(field); - - // scanField() may overwrite the name with a customized name. - fieldNames.put(offset, field.getName()); - fieldTypes.put(offset, type); - - scanField(field, type, offset); - } - currentClazz = currentClazz.getSuperclass(); - } while (currentClazz.getSuperclass() != Object.class); - } - - protected abstract void scanField(Field field, Class<?> type, long offset); - } - - protected static void copyInto(long[] dest, long[] src) { - assert dest.length == src.length; - for (int i = 0; i < dest.length; i++) { - dest[i] = src[i]; - } - } - - protected static <T> void copyInto(T[] dest, T[] src) { - assert dest.length == src.length; - for (int i = 0; i < dest.length; i++) { - dest[i] = src[i]; - } - } - - protected static <T> void copyInto(T[] dest, List<T> src) { - assert dest.length == src.size(); - for (int i = 0; i < dest.length; i++) { - dest[i] = src.get(i); - } - } - - protected static <T> T[] arrayUsingSortedOffsets(Map<Long, T> map, long[] sortedOffsets, T[] result) { - for (int i = 0; i < sortedOffsets.length; i++) { - result[i] = map.get(sortedOffsets[i]); - } - return result; - } - - protected static long[] sortedLongCopy(ArrayList<Long> list1) { - Collections.sort(list1); - long[] result = new long[list1.size()]; - for (int i = 0; i < list1.size(); i++) { - result[i] = list1.get(i); - } - return result; - } - - protected static long[] sortedLongCopy(ArrayList<Long> list1, ArrayList<Long> list2) { - Collections.sort(list1); - Collections.sort(list2); - long[] result = new long[list1.size() + list2.size()]; - for (int i = 0; i < list1.size(); i++) { - result[i] = list1.get(i); - } - for (int i = 0; i < list2.size(); i++) { - result[list1.size() + i] = list2.get(i); - } - return result; - } -}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Apr 28 10:31:17 2014 +0200 @@ -184,7 +184,6 @@ class NodeUsageIterator implements Iterator<Node> { - private final int expectedModCount = usageModCount(); int index = -1; Node current; @@ -207,12 +206,10 @@ } public boolean hasNext() { - assert expectedModCount == usageModCount(); return current != null; } public Node next() { - assert expectedModCount == usageModCount(); Node result = current; if (result == null) { throw new NoSuchElementException(); @@ -227,10 +224,35 @@ } } + class NodeUsageWithModCountIterator extends NodeUsageIterator { + + private final int expectedModCount = usageModCount(); + + @Override + public boolean hasNext() { + if (expectedModCount != usageModCount()) { + throw new ConcurrentModificationException(); + } + return super.hasNext(); + } + + @Override + public Node next() { + if (expectedModCount != usageModCount()) { + throw new ConcurrentModificationException(); + } + return super.next(); + } + } + class NodeUsageIterable implements NodeIterable<Node> { public NodeUsageIterator iterator() { - return new NodeUsageIterator(); + if (MODIFICATION_COUNTS_ENABLED) { + return new NodeUsageWithModCountIterator(); + } else { + return new NodeUsageIterator(); + } } @Override @@ -651,7 +673,7 @@ NodeClassIterator iter = usage.inputs().iterator(); while (iter.hasNext()) { Position pos = iter.nextPosition(); - if (pos.getInputType(usage) == type) { + if (pos.getInputType(usage) == type && pos.get(usage) == this) { pos.set(usage, other); } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Apr 28 10:31:17 2014 +0200 @@ -83,10 +83,8 @@ private final int directInputCount; private final long[] inputOffsets; private final InputType[] inputTypes; - private final String[] inputNames; private final int directSuccessorCount; private final long[] successorOffsets; - private final String[] successorNames; private final Class<?>[] dataTypes; private final boolean canGVN; private final boolean isLeafNode; @@ -126,20 +124,12 @@ directInputCount = scanner.inputOffsets.size(); inputOffsets = sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets); inputTypes = new InputType[inputOffsets.length]; - inputNames = new String[inputOffsets.length]; for (int i = 0; i < inputOffsets.length; i++) { inputTypes[i] = scanner.types.get(inputOffsets[i]); - inputNames[i] = scanner.names.get(inputOffsets[i]); assert inputTypes[i] != null; - assert inputNames[i] != null; } directSuccessorCount = scanner.successorOffsets.size(); successorOffsets = sortedLongCopy(scanner.successorOffsets, scanner.successorListOffsets); - successorNames = new String[successorOffsets.length]; - for (int i = 0; i < successorOffsets.length; i++) { - successorNames[i] = scanner.names.get(successorOffsets[i]); - assert successorNames[i] != null; - } dataOffsets = sortedLongCopy(scanner.dataOffsets); dataTypes = new Class[dataOffsets.length]; @@ -189,10 +179,10 @@ this.iterableId = nextIterableId++; List<NodeClass> existingClasses = new LinkedList<>(); for (FieldIntrospection nodeClass : allClasses.values()) { - if (clazz.isAssignableFrom(nodeClass.clazz)) { + if (clazz.isAssignableFrom(nodeClass.getClazz())) { existingClasses.add((NodeClass) nodeClass); } - if (nodeClass.clazz.isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) { + if (nodeClass.getClazz().isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.getClazz())) { NodeClass superNodeClass = (NodeClass) nodeClass; superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1); superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId; @@ -217,7 +207,7 @@ @Override protected void rescanFieldOffsets(CalcOffset calc) { FieldScanner scanner = new FieldScanner(calc); - scanner.scan(clazz); + scanner.scan(getClazz()); assert directInputCount == scanner.inputOffsets.size(); copyInto(inputOffsets, sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets)); assert directSuccessorCount == scanner.successorOffsets.size(); @@ -334,7 +324,7 @@ @Override public String toString() { StringBuilder str = new StringBuilder(); - str.append("NodeClass ").append(clazz.getSimpleName()).append(" ["); + str.append("NodeClass ").append(getClazz().getSimpleName()).append(" ["); for (int i = 0; i < inputOffsets.length; i++) { str.append(i == 0 ? "" : ", ").append(inputOffsets[i]); } @@ -358,9 +348,9 @@ */ public static final class Position { - public final boolean input; - public final int index; - public final int subIndex; + private final boolean input; + private final int index; + private final int subIndex; public Position(boolean input, int index, int subIndex) { this.input = input; @@ -382,7 +372,7 @@ } public String getInputName(Node node) { - return node.getNodeClass().getEdgeName(this); + return node.getNodeClass().getName(this); } public void set(Node node, Node value) { @@ -426,6 +416,18 @@ } return true; } + + public int getSubIndex() { + return subIndex; + } + + public int getIndex() { + return index; + } + + public boolean isInput() { + return input; + } } private static Node getNode(Node node, long offset) { @@ -895,43 +897,39 @@ if (this == from) { return true; } - long[] offsets = pos.input ? inputOffsets : successorOffsets; - if (pos.index >= offsets.length) { + long[] offsets = pos.isInput() ? inputOffsets : successorOffsets; + if (pos.getIndex() >= offsets.length) { return false; } - long[] fromOffsets = pos.input ? from.inputOffsets : from.successorOffsets; - if (pos.index >= fromOffsets.length) { + long[] fromOffsets = pos.isInput() ? from.inputOffsets : from.successorOffsets; + if (pos.getIndex() >= fromOffsets.length) { return false; } - return offsets[pos.index] == fromOffsets[pos.index]; + return offsets[pos.getIndex()] == fromOffsets[pos.getIndex()]; } public Node get(Node node, Position pos) { - long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]; - if (pos.subIndex == NOT_ITERABLE) { + long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; + if (pos.getSubIndex() == NOT_ITERABLE) { return getNode(node, offset); } else { - return getNodeList(node, offset).get(pos.subIndex); + return getNodeList(node, offset).get(pos.getSubIndex()); } } public InputType getInputType(Position pos) { - assert pos.input; - return inputTypes[pos.index]; - } - - public String getEdgeName(Position pos) { - return pos.input ? inputNames[pos.index] : successorNames[pos.index]; + assert pos.isInput(); + return inputTypes[pos.getIndex()]; } public NodeList<?> getNodeList(Node node, Position pos) { - long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]; - assert pos.subIndex == NODE_LIST; + long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; + assert pos.getSubIndex() == NODE_LIST; return getNodeList(node, offset); } public String getName(Position pos) { - return fieldNames.get(pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]); + return fieldNames.get(pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]); } void updateInputSuccInPlace(Node node, InplaceUpdateClosure duplicationReplacement) { @@ -974,7 +972,7 @@ int index = startIndex; while (index < inputOffsets.length) { NodeList<Node> list = getNodeList(node, inputOffsets[index]); - assert list != null : clazz; + assert list != null : getClazz(); putNodeList(node, inputOffsets[index], updateInputListCopy(list, node, duplicationReplacement)); index++; } @@ -984,7 +982,7 @@ int index = startIndex; while (index < successorOffsets.length) { NodeList<Node> list = getNodeList(node, successorOffsets[index]); - assert list != null : clazz; + assert list != null : getClazz(); putNodeList(node, successorOffsets[index], updateSuccListCopy(list, node, duplicationReplacement)); index++; } @@ -1017,22 +1015,22 @@ } public void set(Node node, Position pos, Node x) { - long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]; - if (pos.subIndex == NOT_ITERABLE) { + long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; + if (pos.getSubIndex() == NOT_ITERABLE) { Node old = getNode(node, offset); - assert x == null || fieldTypes.get((pos.input ? inputOffsets : successorOffsets)[pos.index]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")"; + assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")"; putNode(node, offset, x); - if (pos.input) { + if (pos.isInput()) { node.updateUsages(old, x); } else { node.updatePredecessor(old, x); } } else { NodeList<Node> list = getNodeList(node, offset); - if (pos.subIndex < list.size()) { - list.set(pos.subIndex, x); + if (pos.getSubIndex() < list.size()) { + list.set(pos.getSubIndex(), x); } else { - while (pos.subIndex < list.size() - 1) { + while (pos.getSubIndex() < list.size() - 1) { list.add(null); } list.add(x); @@ -1041,7 +1039,7 @@ } public NodeClassIterable getInputIterable(final Node node) { - assert clazz.isInstance(node); + assert getClazz().isInstance(node); return new NodeClassIterable() { @Override @@ -1061,7 +1059,7 @@ } public NodeClassIterable getSuccessorIterable(final Node node) { - assert clazz.isInstance(node); + assert getClazz().isInstance(node); return new NodeClassIterable() { @Override @@ -1094,7 +1092,7 @@ } while (index < inputOffsets.length) { NodeList<Node> list = getNodeList(node, inputOffsets[index]); - assert list != null : clazz; + assert list != null : getClazz(); if (list.replaceFirst(old, other)) { return true; } @@ -1117,7 +1115,7 @@ } while (index < successorOffsets.length) { NodeList<Node> list = getNodeList(node, successorOffsets[index]); - assert list != null : clazz + " " + successorOffsets[index] + " " + node; + assert list != null : getClazz() + " " + successorOffsets[index] + " " + node; if (list.replaceFirst(old, other)) { return true; } @@ -1174,7 +1172,7 @@ * @param newNode the node to which the inputs should be copied. */ public void copyInputs(Node node, Node newNode) { - assert node.getClass() == clazz && newNode.getClass() == clazz; + assert node.getClass() == getClazz() && newNode.getClass() == getClazz(); int index = 0; while (index < directInputCount) { @@ -1196,7 +1194,7 @@ * @param newNode the node to which the successors should be copied. */ public void copySuccessors(Node node, Node newNode) { - assert node.getClass() == clazz && newNode.getClass() == clazz; + assert node.getClass() == getClazz() && newNode.getClass() == getClazz(); int index = 0; while (index < directSuccessorCount) { @@ -1215,7 +1213,7 @@ } public boolean inputsEqual(Node node, Node other) { - assert node.getClass() == clazz && other.getClass() == clazz; + assert node.getClass() == getClazz() && other.getClass() == getClazz(); int index = 0; while (index < directInputCount) { if (getNode(other, inputOffsets[index]) != getNode(node, inputOffsets[index])) { @@ -1234,7 +1232,7 @@ } public boolean successorsEqual(Node node, Node other) { - assert node.getClass() == clazz && other.getClass() == clazz; + assert node.getClass() == getClazz() && other.getClass() == getClazz(); int index = 0; while (index < directSuccessorCount) { if (getNode(other, successorOffsets[index]) != getNode(node, successorOffsets[index])) { @@ -1253,7 +1251,7 @@ } public boolean inputContains(Node node, Node other) { - assert node.getClass() == clazz; + assert node.getClass() == getClazz(); int index = 0; while (index < directInputCount) { @@ -1273,7 +1271,7 @@ } public boolean successorContains(Node node, Node other) { - assert node.getClass() == clazz; + assert node.getClass() == getClazz(); int index = 0; while (index < directSuccessorCount) { @@ -1355,7 +1353,7 @@ } public Class<?> getJavaClass() { - return clazz; + return getClazz(); } /** @@ -1455,7 +1453,7 @@ replacement = replacements.replacement(input); } if (replacement != input) { - assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.index]), replacement); + assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.getIndex()]), replacement); target = replacement; } else if (input.graph() == graph) { // patch to the outer world target = input; @@ -1474,7 +1472,7 @@ if (target == null) { Node replacement = replacements.replacement(succ); if (replacement != succ) { - assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.index]), replacement); + assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.getIndex()]), replacement); target = replacement; } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Mon Apr 28 10:31:17 2014 +0200 @@ -257,7 +257,7 @@ } @Override - public void snapshotTo(Collection<T> to) { + public void snapshotTo(Collection<? super T> to) { for (int i = 0; i < size; i++) { to.add(get(i)); }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2012, 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.graph; - -import java.lang.reflect.*; - -import sun.misc.*; - -public class UnsafeAccess { - - /** - * An instance of {@link Unsafe} for use within Graal. - */ - public static final Unsafe unsafe = getUnsafe(); - - private static Unsafe getUnsafe() { - try { - // this will fail if Graal is not part of the boot class path - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - // nothing to do - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - // currently we rely on being able to use Unsafe... - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - - /** - * Copies the contents of a {@link String} to a native memory buffer as a {@code '\0'} - * terminated C string. The native memory buffer is allocated via - * {@link Unsafe#allocateMemory(long)}. The caller is responsible for releasing the buffer when - * it is no longer needed via {@link Unsafe#freeMemory(long)}. - * - * @return the native memory pointer of the C string created from {@code s} - */ - public static long createCString(String s) { - return writeCString(s, unsafe.allocateMemory(s.length() + 1)); - } - - /** - * Reads a {@code '\0'} terminated C string from native memory and converts it to a - * {@link String}. - * - * @return a Java string - */ - public static String readCString(long address) { - if (address == 0) { - return null; - } - StringBuffer sb = new StringBuffer(); - for (int i = 0;; i++) { - char c = (char) unsafe.getByte(address + i); - if (c == 0) { - break; - } - sb.append(c); - } - return sb.toString(); - } - - /** - * Writes the contents of a {@link String} to a native memory buffer as a {@code '\0'} - * terminated C string. The caller is responsible for ensuring the buffer is at least - * {@code s.length() + 1} bytes long. The caller is also responsible for releasing the buffer - * when it is no longer. - * - * @return the value of {@code buf} - */ - public static long writeCString(String s, long buf) { - int size = s.length(); - for (int i = 0; i < size; i++) { - unsafe.putByte(buf + i, (byte) s.charAt(i)); - } - unsafe.putByte(buf + size, (byte) '\0'); - return buf; - } -}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Mon Apr 28 10:31:17 2014 +0200 @@ -55,7 +55,7 @@ return list; } - default void snapshotTo(Collection<T> to) { + default void snapshotTo(Collection<? super T> to) { for (T n : this) { to.add(n); }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,9 +25,7 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; - +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import sun.misc.*; @@ -48,7 +46,9 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; /** * HotSpot AMD64 specific backend. @@ -72,7 +72,7 @@ } @Override - public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { return new AMD64HotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); } @@ -82,12 +82,12 @@ } @Override - public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) { + public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { return new AMD64HotSpotNodeLIRBuilder(graph, lirGen); } @Override - public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) { + public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) { return new AMD64HotSpotBytecodeLIRBuilder(gen, parser); } @@ -264,7 +264,7 @@ */ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedEntry) { HotSpotProviders providers = getProviders(); - if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) { + if (installedCodeOwner != null && !installedCodeOwner.isStatic()) { MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY); CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false); Register inlineCacheKlass = rax; // see definition of IC_Klass in
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,17 +24,16 @@ import static com.oracle.graal.amd64.AMD64.*; -import java.lang.reflect.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.SaveRbp; import com.oracle.graal.lir.StandardOp.NoOp; +import com.oracle.graal.lir.gen.*; public class AMD64HotSpotBytecodeLIRBuilder extends BytecodeLIRBuilder { - public AMD64HotSpotBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) { + public AMD64HotSpotBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) { super(gen, parser); } @@ -72,7 +71,7 @@ gen.append(getSaveRbp().placeholder); Signature sig = method.getSignature(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); for (int i = 0; i < sig.getParameterCount(!isStatic); i++) { Value paramValue = params[i]; assert paramValue.getKind() == sig.getParameterKind(i).getStackKind();
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,10 +25,10 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.gen.*; public class AMD64HotSpotLIRGenerationResult extends LIRGenerationResultBase {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,27 +26,28 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import java.util.*; import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; -import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.LoadCompressedPointer; -import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedConstantOp; -import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedPointer; +import com.oracle.graal.hotspot.data.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.NoOp; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp; @@ -55,8 +56,8 @@ import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; /** * LIR generator specialized for AMD64 HotSpot. @@ -64,6 +65,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator { final HotSpotVMConfig config; + private HotSpotLockStack lockStack; protected AMD64HotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) { super(providers, cc, lirGenRes); @@ -130,7 +132,17 @@ @Override public StackSlot getLockSlot(int lockDepth) { - return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth); + return getLockStack().makeLockSlot(lockDepth); + } + + private HotSpotLockStack getLockStack() { + assert lockStack != null; + return lockStack; + } + + protected void setLockStack(HotSpotLockStack lockStack) { + assert this.lockStack == null; + this.lockStack = lockStack; } private Register findPollOnReturnScratchRegister() { @@ -159,7 +171,7 @@ } @Override - protected boolean needOnlyOopMaps() { + public boolean needOnlyOopMaps() { // Stubs only need oop maps return ((AMD64HotSpotLIRGenerationResult) getResult()).getStub() != null; } @@ -245,7 +257,7 @@ } @Override - public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { + public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; boolean destroysRegisters = hotspotLinkage.destroysRegisters(); @@ -260,9 +272,10 @@ } Variable result; - DeoptimizingNode deoptInfo = null; + // TODO (je) check if we can remove this + LIRFrameState deoptInfo = null; if (hotspotLinkage.canDeoptimize()) { - deoptInfo = info; + deoptInfo = state; assert deoptInfo != null || getStub() != null; assert hotspotLinkage.needsJavaFrameAnchor(); } @@ -273,7 +286,8 @@ result = super.emitForeignCall(hotspotLinkage, deoptInfo, args); append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread)); } else { - result = super.emitForeignCall(hotspotLinkage, deoptInfo, args); + assert deoptInfo == null; + result = super.emitForeignCall(hotspotLinkage, null, args); } if (destroysRegisters) { @@ -371,9 +385,9 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { moveDeoptValuesToThread(actionAndReason, speculation); - append(new AMD64DeoptimizeOp(state(deopting))); + append(new AMD64DeoptimizeOp(state)); } @Override @@ -397,13 +411,6 @@ } /** - * Returns whether or not the input access should be (de)compressed. - */ - private boolean isCompressedOperation(PlatformKind kind, Access access) { - return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops)); - } - - /** * @return a compressed version of the incoming constant */ protected static Constant compress(Constant c, CompressEncoding encoding) { @@ -444,85 +451,25 @@ } @Override - public Variable emitLoad(PlatformKind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { AMD64AddressValue loadAddress = asAddressValue(address); Variable result = newVariable(toStackKind(kind)); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - /** - * Currently, the (de)compression of pointers applies conditionally to some objects (oops, - * kind==Object) and some addresses (klass pointers, kind==Long). Initially, the input - * operation is checked to discover if it has been tagged as a potential "compression" - * candidate. Consequently, depending on the appropriate kind, the specific (de)compression - * functions are being called. - */ - if (isCompressedOperation(kind, access)) { - if (kind == Kind.Object) { - append(new LoadCompressedPointer(Kind.Object, result, getProviders().getRegisters().getHeapBaseRegister().asValue(), loadAddress, state, config.getOopEncoding())); - } else if (kind == Kind.Long) { - Variable scratch = config.getKlassEncoding().base != 0 ? newVariable(Kind.Long) : null; - append(new LoadCompressedPointer(Kind.Long, result, scratch, loadAddress, state, config.getKlassEncoding())); - } else { - throw GraalInternalError.shouldNotReachHere("can't handle: " + access); - } - } else { - append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); - } + append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); return result; } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { AMD64AddressValue storeAddress = asAddressValue(address); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - boolean isCompressed = isCompressedOperation(kind, access); if (isConstant(inputVal)) { Constant c = asConstant(inputVal); - if (canStoreConstant(c, isCompressed)) { - if (isCompressed) { - if (c.getKind() == Kind.Object) { - append(new StoreCompressedConstantOp(Kind.Object, storeAddress, c, state)); - } else if (c.getKind() == Kind.Long) { - // It's always a good idea to directly store compressed constants since they - // have to be materialized as 64 bits encoded otherwise. - Constant value = compress(c, config.getKlassEncoding()); - append(new StoreCompressedConstantOp(Kind.Long, storeAddress, value, state)); - } else { - throw GraalInternalError.shouldNotReachHere("can't handle: " + access); - } - return; - } else { - append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); - return; - } + if (canStoreConstant(c, false)) { + append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); + return; } } Variable input = load(inputVal); - if (isCompressed) { - if (kind == Kind.Object) { - if (input.getKind() == Kind.Object) { - Variable scratch = newVariable(Kind.Long); - Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister(); - append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, config.getOopEncoding(), heapBaseReg)); - } else { - // the input oop is already compressed - append(new StoreOp(input.getKind(), storeAddress, input, state)); - } - } else if (kind == Kind.Long) { - Variable scratch = newVariable(Kind.Long); - Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister(); - append(new StoreCompressedPointer(Kind.Long, storeAddress, input, scratch, state, config.getKlassEncoding(), heapBaseReg)); - } else { - append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); - } - } else { - append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); - } + append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); } @Override @@ -576,7 +523,6 @@ } } - @Override public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { PlatformKind kind = newValue.getPlatformKind(); assert kind == expectedValue.getPlatformKind(); @@ -592,4 +538,73 @@ append(new CondMoveOp(result, Condition.EQ, asAllocatable(trueValue), falseValue)); return result; } + + public Value emitAtomicReadAndAdd(Value address, Value delta) { + PlatformKind kind = delta.getPlatformKind(); + Kind memKind = getMemoryKind(kind); + Variable result = newVariable(kind); + AMD64AddressValue addressValue = asAddressValue(address); + append(new AMD64Move.AtomicReadAndAddOp(memKind, result, addressValue, asAllocatable(delta))); + return result; + } + + public Value emitAtomicReadAndWrite(Value address, Value newValue) { + PlatformKind kind = newValue.getPlatformKind(); + Kind memKind = getMemoryKind(kind); + Variable result = newVariable(kind); + AMD64AddressValue addressValue = asAddressValue(address); + append(new AMD64Move.AtomicReadAndWriteOp(memKind, result, addressValue, asAllocatable(newValue))); + return result; + } + + public static class CompareMemoryCompressedOp extends AMD64LIRInstruction { + @Alive({COMPOSITE}) protected AMD64AddressValue x; + @Use({CONST, REG}) protected Value y; + @State protected LIRFrameState state; + + public CompareMemoryCompressedOp(AMD64AddressValue x, Value y, LIRFrameState state) { + assert HotSpotGraalRuntime.runtime().getConfig().useCompressedOops; + this.x = x; + this.y = y; + this.state = state; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } + if (y instanceof Constant) { + Constant constant = (Constant) y; + if (constant.isNull()) { + masm.cmpl(x.toAddress(), 0); + } else { + if (y.getKind() == Kind.Object) { + crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(constant), true)); + } else if (y.getKind() == Kind.Long) { + crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), true)); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + masm.cmpl(x.toAddress(), 0xdeaddead); + } + } else { + masm.cmpl(asRegister(y), x.toAddress()); + } + } + } + + protected void emitCompareBranchMemoryCompressed(Value left, Value right, Condition cond, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability, LIRFrameState state) { + boolean mirrored = false; + if (left instanceof AMD64AddressValue) { + append(new CompareMemoryCompressedOp((AMD64AddressValue) left, right, state)); + } else { + assert right instanceof AMD64AddressValue; + append(new CompareMemoryCompressedOp((AMD64AddressValue) right, left, state)); + mirrored = true; + } + + Condition finalCondition = mirrored ? cond.mirror() : cond; + append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); + } }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,21 +23,14 @@ package com.oracle.graal.hotspot.amd64; -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; - import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.compiler.amd64.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.data.*; -import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.CompareMemoryCompressedOp; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; -import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -46,46 +39,13 @@ */ public class AMD64HotSpotMemoryPeephole extends AMD64MemoryPeephole { - public static class CompareMemoryCompressedOp extends AMD64LIRInstruction { - @Alive({COMPOSITE}) protected AMD64AddressValue x; - @Use({CONST}) protected Value y; - @State protected LIRFrameState state; - - public CompareMemoryCompressedOp(AMD64AddressValue x, Constant y, LIRFrameState state) { - assert HotSpotGraalRuntime.runtime().getConfig().useCompressedOops; - this.x = x; - this.y = y; - this.state = state; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - Constant constant = (Constant) y; - if (constant.isNull()) { - masm.cmpl(x.toAddress(), 0); - } else { - if (y.getKind() == Kind.Object) { - crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(constant), true)); - } else if (y.getKind() == Kind.Long) { - crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), true)); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - if (state != null) { - crb.recordImplicitException(masm.position(), state); - } - masm.cmpl(x.toAddress(), 0xdeaddead); - } - } - } - AMD64HotSpotMemoryPeephole(AMD64NodeLIRBuilder gen) { super(gen); } @Override protected Kind getMemoryKind(Access access) { - PlatformKind kind = gen.getLIRGenerator().getPlatformKind(access.asNode().stamp()); + PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(access.asNode().stamp()); if (kind == NarrowOopStamp.NarrowOop) { return Kind.Int; } else {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,15 +26,15 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotBackend.*; -import java.lang.reflect.*; - import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.compiler.amd64.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.match.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; @@ -45,17 +45,55 @@ import com.oracle.graal.lir.StandardOp.NoOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; /** * LIR generator specialized for AMD64 HotSpot. */ +@MatchableNodeImport({"com.oracle.graal.hotspot.nodes.HotSpotMatchableNodes"}) public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements HotSpotNodeLIRBuilder { - public AMD64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) { + private static ValueNode filterCompression(ValueNode node) { + ValueNode result = node; + while (result instanceof CompressionNode) { + result = ((CompressionNode) result).getInput(); + } + return result; + } + + private void emitCompareCompressedMemory(IfNode ifNode, ValueNode value, Access access, CompareNode compare) { + Condition cond = compare.condition(); + LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor()); + double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); + Value left; + Value right; + if (access == filterCompression(compare.x())) { + if (value.isConstant()) { + left = value.asConstant(); + } else { + left = gen.loadNonConst(operand(value)); + } + right = makeAddress(access); + } else { + assert access == filterCompression(compare.y()); + left = makeAddress(access); + right = gen.loadNonConst(operand(value)); + cond = cond.mirror(); + } + getGen().emitCompareBranchMemoryCompressed(left, right, cond, trueLabel, falseLabel, trueLabelProbability, getState(access)); + } + + public AMD64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen) { super(graph, gen); memoryPeephole = new AMD64HotSpotMemoryPeephole(this); + assert gen instanceof AMD64HotSpotLIRGenerator; + assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder; + ((AMD64HotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack()); } private AMD64HotSpotLIRGenerator getGen() { @@ -107,7 +145,7 @@ @Override public void visitSafepointNode(SafepointNode i) { - LIRFrameState info = gen.state(i); + LIRFrameState info = state(i); append(new AMD64HotSpotSafepointOp(info, getGen().config, this)); } @@ -119,7 +157,7 @@ } else { assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); - assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; + assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method."; append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); } } @@ -160,7 +198,7 @@ @Override public void visitInfopointNode(InfopointNode i) { - if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) { + if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { Debug.log("Ignoring InfopointNode for AFTER_BCI"); } else { super.visitInfopointNode(i); @@ -199,4 +237,40 @@ gen.emitMove(result, raxLocal); setResult(x, result); } + + /** + * Helper class to convert the NodeLIRBuilder into the current subclass. + */ + static abstract class AMD64HotSpotMatchGenerator implements MatchGenerator { + public AMD64HotSpotMatchGenerator() { + } + + public ComplexMatchResult match(NodeLIRBuilder gen) { + return match((AMD64HotSpotNodeLIRBuilder) gen); + } + + abstract public ComplexMatchResult match(AMD64HotSpotNodeLIRBuilder gen); + } + + @MatchRule("(If (ObjectEquals=compare Constant=value (Compression Read=access)))") + @MatchRule("(If (ObjectEquals=compare Constant=value (Compression FloatingRead=access)))") + @MatchRule("(If (ObjectEquals=compare (Compression value) (Compression Read=access)))") + @MatchRule("(If (ObjectEquals=compare (Compression value) (Compression FloatingRead=access)))") + public static class IfCompareMemory extends AMD64HotSpotMatchGenerator { + IfNode root; + Access access; + ValueNode value; + CompareNode compare; + + @Override + public ComplexMatchResult match(AMD64HotSpotNodeLIRBuilder gen) { + if (HotSpotGraalRuntime.runtime().getConfig().useCompressedOops) { + return builder -> { + gen.emitCompareCompressedMemory(root, value, access, compare); + return null; + }; + } + return null; + } + } }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.amd64; import static com.oracle.graal.amd64.AMD64.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -34,7 +34,6 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.type.*; -import com.oracle.graal.phases.*; public class AMD64HotSpotRegisterConfig implements RegisterConfig {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.asm.NumUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,13 +26,12 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.amd64.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRGenLowerable { +public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { private final Constant functionPointer; @Input private final NodeInputList<ValueNode> args; @@ -44,7 +43,7 @@ } @Override - public void generate(NodeLIRBuilder generator) { + public void generate(NodeLIRBuilderTool generator) { AMD64NodeLIRBuilder gen = (AMD64NodeLIRBuilder) generator; Value[] parameter = new Value[args.count()]; JavaType[] parameterTypes = new JavaType[args.count()]; @@ -55,7 +54,7 @@ ResolvedJavaType returnType = stamp().javaType(gen.getLIRGeneratorTool().getMetaAccess()); CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, generator.getLIRGeneratorTool().target(), false); - ((AMD64LIRGenerator) gen.getLIRGeneratorTool()).emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); + gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); if (this.getKind() != Kind.Void) { generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn())); }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Apr 28 10:31:17 2014 +0200 @@ -48,7 +48,7 @@ import com.oracle.graal.asm.hsail.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.gpu.*; @@ -60,15 +60,16 @@ import com.oracle.graal.java.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp; -import com.oracle.graal.lir.hsail.HSAILMove.AtomicGetAndAddOp; +import com.oracle.graal.lir.hsail.HSAILMove.AtomicReadAndAddOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -301,9 +302,8 @@ for (CodeAnnotation annotation : hostCode.getAnnotations()) { result.addAnnotation(annotation); } - CompilationResult.Mark[] noMarks = {}; for (Mark mark : hostCode.getMarks()) { - result.recordMark(mark.pcOffset, mark.id, noMarks); + result.recordMark(mark.pcOffset, mark.id); } for (ExceptionHandler handler : hostCode.getExceptionHandlers()) { result.recordExceptionHandler(handler.pcOffset, handler.handlerPos); @@ -375,7 +375,7 @@ } @Override - public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { return new HSAILHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); } @@ -385,7 +385,7 @@ } @Override - public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) { + public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { return new HSAILHotSpotNodeLIRBuilder(graph, lirGen); } @@ -451,7 +451,7 @@ boolean usesThreadRegister = false; search: for (AbstractBlock<?> b : lir.linearScanOrder()) { for (LIRInstruction op : lir.getLIRforBlock(b)) { - if (op instanceof AtomicGetAndAddOp && ((AtomicGetAndAddOp) op).getAddress().toAddress().getBase().equals(HSAIL.threadRegister)) { + if (op instanceof AtomicReadAndAddOp) { usesThreadRegister = true; assert useHSAILDeoptimization : "cannot use thread register if HSAIL deopt support is disabled"; break search; @@ -468,7 +468,7 @@ // We're subtracting 1 because we're not making the final gid as a parameter. int nonConstantParamCount = sigParamCount - 1; - boolean isStatic = (Modifier.isStatic(method.getModifiers())); + boolean isStatic = (method.isStatic()); // Determine if this is an object lambda. boolean isObjectLambda = true;
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,8 @@ import java.util.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp; public class HSAILHotSpotLIRGenerationResult extends LIRGenerationResultBase {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.hsail.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; @@ -37,6 +36,7 @@ import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp; @@ -44,15 +44,11 @@ import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall2ArgOp; import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp; import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp; -import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer; import com.oracle.graal.lir.hsail.HSAILMove.LoadOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; -import com.oracle.graal.lir.hsail.HSAILMove.StoreCompressedPointer; import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp; import com.oracle.graal.lir.hsail.HSAILMove.StoreOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.util.*; /** @@ -96,22 +92,11 @@ return config.narrowKlassBase; } - private static boolean isCompressCandidate(Access access) { - return access != null && access.isCompressible(); - } - @Override public boolean canStoreConstant(Constant c, boolean isCompressed) { return true; } - /** - * Returns whether or not the input access should be (de)compressed. - */ - private boolean isCompressedOperation(PlatformKind kind, Access access) { - return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops)); - } - private static Kind getMemoryKind(PlatformKind kind) { if (kind == NarrowOopStamp.NarrowOop) { return Kind.Int; @@ -121,20 +106,10 @@ } @Override - public Variable emitLoad(PlatformKind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { HSAILAddressValue loadAddress = asAddressValue(address); Variable result = newVariable(kind); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) { - Variable scratch = newVariable(Kind.Long); - append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); - } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) { - Variable scratch = newVariable(Kind.Long); - append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment())); - } else if (kind == NarrowOopStamp.NarrowOop) { + if (kind == NarrowOopStamp.NarrowOop) { append(new LoadOp(Kind.Int, result, loadAddress, state)); } else { append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); @@ -143,43 +118,17 @@ } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { HSAILAddressValue storeAddress = asAddressValue(address); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - boolean isCompressed = isCompressedOperation(kind, access); if (isConstant(inputVal)) { Constant c = asConstant(inputVal); - if (canStoreConstant(c, isCompressed)) { - if (isCompressed) { - if ((c.getKind() == Kind.Object) && c.isNull()) { - // Constant value = c.isNull() ? c : compress(c, config.getOopEncoding()); - append(new StoreConstantOp(Kind.Int, storeAddress, Constant.forInt(0), state)); - } else if (c.getKind() == Kind.Long) { - // It's always a good idea to directly store compressed constants since they - // have to be materialized as 64 bits encoded otherwise. - Constant value = compress(c, config.getKlassEncoding()); - append(new StoreConstantOp(Kind.Int, storeAddress, value, state)); - } else { - throw GraalInternalError.shouldNotReachHere("can't handle: " + access); - } - return; - } else { - append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); - return; - } + if (canStoreConstant(c, false)) { + append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); + return; } } Variable input = load(inputVal); - if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) { - Variable scratch = newVariable(Kind.Long); - append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); - } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) { - Variable scratch = newVariable(Kind.Long); - append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment())); - } else if (kind == NarrowOopStamp.NarrowOop) { + if (kind == NarrowOopStamp.NarrowOop) { append(new StoreOp(Kind.Int, storeAddress, input, state)); } else { append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); @@ -203,8 +152,28 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting) { - emitDeoptimizeInner(actionAndReason, state(deopting), "emitDeoptimize"); + public Value emitAtomicReadAndAdd(Value address, Value delta) { + PlatformKind kind = delta.getPlatformKind(); + Kind memKind = getMemoryKind(kind); + Variable result = newVariable(kind); + HSAILAddressValue addressValue = asAddressValue(address); + append(new HSAILMove.AtomicReadAndAddOp(memKind, result, addressValue, asAllocatable(delta))); + return result; + } + + @Override + public Value emitAtomicReadAndWrite(Value address, Value newValue) { + PlatformKind kind = newValue.getPlatformKind(); + Kind memKind = getMemoryKind(kind); + Variable result = newVariable(kind); + HSAILAddressValue addressValue = asAddressValue(address); + append(new HSAILMove.AtomicReadAndWriteOp(memKind, result, addressValue, asAllocatable(newValue))); + return result; + } + + @Override + public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state) { + emitDeoptimizeInner(actionAndReason, state, "emitDeoptimize"); } /*** @@ -222,7 +191,7 @@ * emitting a comment as to what Foreign call they would have made. */ @Override - public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { + public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { Variable result = newVariable(Kind.Object); // linkage.getDescriptor().getResultType()); // to make the LIRVerifier happy, we move any constants into registers
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -33,7 +33,6 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.hotspot.hsail.nodes.*; import com.oracle.graal.hotspot.hsail.replacements.*; import java.util.HashMap; @@ -104,29 +103,6 @@ } }; - LoweringStrategy AtomicGetAndAddStrategy = new LoweringStrategy() { - @Override - void lower(Node n, LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) n.graph(); - - // Note: this code adapted from CompareAndSwapNode - // lowering but since we are not dealing with an object - // but a word (thread passed in), I wasn't sure what - // should be done with the Location stuff so leaving it - // out for now - - AtomicGetAndAddNode getAdd = (AtomicGetAndAddNode) n; - // LocationNode location = IndexedLocationNode.create(ANY_LOCATION, Kind.Long, 0, - // getAdd.offset(), graph, 1); - LocationNode location = IndexedLocationNode.create(getAdd.getLocationIdentity(), Kind.Long, 0, getAdd.offset(), graph, 1); - // note: getAdd.base() used to be getAdd.object() - LoweredAtomicGetAndAddNode loweredAtomicGetAdd = graph.add(new LoweredAtomicGetAndAddNode(getAdd.base(), location, getAdd.delta(), HeapAccess.BarrierType.NONE, - getAdd.getKind() == Kind.Object)); - loweredAtomicGetAdd.setStateAfter(getAdd.stateAfter()); - graph.replaceFixedWithFixed(getAdd, loweredAtomicGetAdd); - } - }; - private HashMap<Class<?>, LoweringStrategy> strategyMap = new HashMap<>(); void initStrategyMap() { @@ -139,7 +115,6 @@ strategyMap.put(MonitorEnterNode.class, RejectStrategy); strategyMap.put(MonitorExitNode.class, RejectStrategy); strategyMap.put(UnwindNode.class, UnwindNodeStrategy); - strategyMap.put(AtomicGetAndAddNode.class, AtomicGetAndAddStrategy); } private LoweringStrategy getStrategy(Node n) {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,17 +27,15 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.hsail.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; -import com.oracle.graal.hotspot.hsail.nodes.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; -import com.oracle.graal.lir.hsail.HSAILMove.AtomicGetAndAddOp; import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp; import com.oracle.graal.nodes.*; @@ -46,7 +44,7 @@ */ public class HSAILHotSpotNodeLIRBuilder extends HSAILNodeLIRBuilder implements HotSpotNodeLIRBuilder { - public HSAILHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public HSAILHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } @@ -79,14 +77,6 @@ } } - public void visitAtomicGetAndAdd(LoweredAtomicGetAndAddNode node, Value address) { - Variable nodeResult = newVariable(node.getKind()); - Value delta = getGen().loadNonConst(operand(node.getDelta())); - HSAILAddressValue addressValue = getGen().asAddressValue(address); - append(new AtomicGetAndAddOp(nodeResult, addressValue, delta)); - setResult(node, nodeResult); - } - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { Kind kind = x.newValue().getKind(); assert kind == x.expectedValue().getKind(); @@ -115,7 +105,7 @@ public void visitSafepointNode(SafepointNode i) { HotSpotVMConfig config = getGen().config; if (config.useHSAILSafepoints == true) { - LIRFrameState info = gen.state(i); + LIRFrameState info = state(i); HSAILHotSpotSafepointOp safepoint = new HSAILHotSpotSafepointOp(info, config, this); ((HSAILHotSpotLIRGenerationResult) getGen().getResult()).addDeopt(safepoint); append(safepoint);
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/nodes/AtomicGetAndAddNode.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2011, 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.hotspot.hsail.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * Represents an atomic get-and-add operation. The result is the get value (before the delta is - * added) - */ -public class AtomicGetAndAddNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single { - - @Input private ValueNode base; - @Input private ValueNode offset; - @Input private ValueNode delta; - @Input private LocationIdentity locationIdentity; - - public ValueNode base() { - return base; - } - - public ValueNode offset() { - return offset; - } - - public ValueNode delta() { - return delta; - } - - @SuppressWarnings("unused") - public AtomicGetAndAddNode(ValueNode base, ValueNode offset, ValueNode location /* ignored */, ValueNode delta) { - super(StampFactory.forKind(Kind.Long.getStackKind())); - this.base = base; - this.offset = offset; - this.delta = delta; - } - - @Override - public LocationIdentity getLocationIdentity() { - return locationIdentity; - } - - @Override - public void lower(LoweringTool tool) { - tool.getLowerer().lower(this, tool); - } - - @NodeIntrinsic - public native static long atomicGetAndAdd(long base, int offset, LocationIdentity locationIdentity, int delta); - - public MemoryCheckpoint asMemoryCheckpoint() { - return this; - } - - public MemoryPhiNode asMemoryPhi() { - return null; - } - -}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/nodes/LoweredAtomicGetAndAddNode.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.hsail.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.hotspot.hsail.*; - -/** - * Represents the lowered version of an atomic get-and-add operation{@code AtomicGetAndAddNode}. - */ -public class LoweredAtomicGetAndAddNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { - - @Input private ValueNode delta; - @Input(InputType.State) private FrameState stateAfter; - - public FrameState stateAfter() { - return stateAfter; - } - - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - updateUsages(stateAfter, x); - stateAfter = x; - } - - public boolean hasSideEffect() { - return true; - } - - public ValueNode getDelta() { - return delta; - } - - public LoweredAtomicGetAndAddNode(ValueNode object, LocationNode location, ValueNode delta, BarrierType barrierType, boolean compressible) { - super(object, location, StampFactory.forKind(Kind.Long.getStackKind()), barrierType, compressible); - this.delta = delta; - } - - @Override - public LocationIdentity getLocationIdentity() { - return location().getLocationIdentity(); - } - - @Override - public boolean canNullCheck() { - return false; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - HSAILHotSpotNodeLIRBuilder hsailGen = (HSAILHotSpotNodeLIRBuilder) gen; - hsailGen.visitAtomicGetAndAdd(this, location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()))); - } - - @Override - public MemoryCheckpoint asMemoryCheckpoint() { - return this; - } - - @Override - public MemoryPhiNode asMemoryPhi() { - return null; - } - -}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 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,11 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.word.*; import com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.hsail.nodes.*; //JaCoCo Exclude @@ -56,7 +56,7 @@ } public static Word atomicGetAndAddTlabTop(Word thread, int size) { - return Word.unsigned(AtomicGetAndAddNode.atomicGetAndAdd(thread.rawValue(), threadTlabTopOffset(), TLAB_TOP_LOCATION, size)); + return Word.unsigned(AtomicReadAndAddNode.getAndAddLong(null, thread.rawValue() + threadTlabTopOffset(), size, TLAB_TOP_LOCATION)); } public static final LocationIdentity TLAB_PFTOP_LOCATION = new NamedLocationIdentity("TlabPfTop");
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,15 +23,16 @@ package com.oracle.graal.hotspot.hsail.replacements; import static com.oracle.graal.api.code.UnsignedMath.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.hsail.replacements.HSAILHotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.hsail.replacements.HSAILNewObjectSnippets.Options.*; import static com.oracle.graal.nodes.PiArrayNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; @@ -40,7 +41,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.options.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter;
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Apr 28 10:31:17 2014 +0200 @@ -38,7 +38,6 @@ import com.oracle.graal.asm.ptx.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.cfg.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.gpu.*; @@ -50,9 +49,12 @@ import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.ptx.*; +import com.oracle.graal.lir.ptx.PTXControlFlow.PTXPredicatedLIRInstruction; import com.oracle.graal.lir.ptx.PTXMemOp.LoadReturnAddrOp; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -354,12 +356,12 @@ } @Override - public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { return new PTXHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); } @Override - public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) { + public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { return new PTXHotSpotNodeLIRBuilder(graph, lirGen); } @@ -409,12 +411,20 @@ assert codeCacheOwner != null : lir + " is not associated with a method"; RegisterAnalysis registerAnalysis = new RegisterAnalysis(); + // Assume no predicate registers are used + int maxPredRegNum = -1; for (AbstractBlock<?> b : lir.codeEmittingOrder()) { for (LIRInstruction op : lir.getLIRforBlock(b)) { if (op instanceof LabelOp) { // Don't consider this as a definition } else { + if (op instanceof PTXPredicatedLIRInstruction) { + // Update maximum predicate register number if op uses a larger number + int opPredRegNum = ((PTXPredicatedLIRInstruction) op).getPredRegNum(); + maxPredRegNum = (opPredRegNum > maxPredRegNum) ? opPredRegNum : maxPredRegNum; + } + // Record registers used in the kernel registerAnalysis.op = op; op.forEachTemp(registerAnalysis); op.forEachOutput(registerAnalysis); @@ -422,13 +432,13 @@ } } + // Emit register declarations Assembler asm = crb.asm; registerAnalysis.emitDeclarations(asm); // emit predicate register declaration - int maxPredRegNum = lir.numVariables(); - if (maxPredRegNum > 0) { - asm.emitString(".reg .pred %p<" + maxPredRegNum + ">;"); + if (maxPredRegNum > -1) { + asm.emitString(".reg .pred %p<" + ++maxPredRegNum + ">;"); } }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,12 +26,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.ptx.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.gen.*; /** * LIR generator specialized for PTX HotSpot.
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,10 +24,10 @@ package com.oracle.graal.hotspot.ptx; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.ptx.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; /** @@ -35,7 +35,7 @@ */ public class PTXHotSpotNodeLIRBuilder extends PTXNodeLIRBuilder implements HotSpotNodeLIRBuilder { - protected PTXHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + protected PTXHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -31,8 +31,6 @@ import static com.oracle.graal.hotspot.ptx.PTXWrapperBuilder.LaunchArg.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.ConstantNode.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.meta.*; @@ -48,7 +46,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -62,8 +59,8 @@ * <li>PINNED: a buffer into which the address of pinned objects is saved.</li> * <li>OBJECT_OFFSETS: the offsets of the object values in PARAMS.</li> * </ul> - * - * + * + * * The PARAMS buffer is the {@code CU_LAUNCH_PARAM_BUFFER_POINTER} buffer passed in the * {@code extra} argument to the {@code cuLaunchKernel} function. This buffer contains the * parameters to the call. The buffer is word aligned and each parameter is aligned in the buffer @@ -75,13 +72,13 @@ * The object pointers in PARAMS are specified by OBJECT_OFFSETS. * <p> * As a concrete example, for a kernel whose Java method signature is: - * + * * <pre> * static int kernel(int p1, short p2, Object p3, long p4) * </pre> - * + * * the graph created is shown below as psuedo-code: - * + * * <pre> * int kernel_wrapper(int p1, short p2, oop p3, long p4) { * address kernelAddr = kernel.start; @@ -122,7 +119,7 @@ /** * The size of the buffer holding the kernel parameters and the extra word for storing the * pointer to device memory for the return value. - * + * * @see LaunchArg#ParametersAndReturnValueBufferSize */ int bufSize; @@ -153,7 +150,7 @@ /** * Creates the graph implementing the CPU to GPU transition. - * + * * @param method a method that has been compiled to GPU binary code * @param kernel the installed GPU binary for {@code method} * @see PTXWrapperBuilder @@ -164,7 +161,7 @@ int intSize = Integer.SIZE / Byte.SIZE; Kind wordKind = providers.getCodeCache().getTarget().wordKind; Signature sig = method.getSignature(); - boolean isStatic = isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); int sigCount = sig.getParameterCount(false); javaParameters = new ParameterNode[(!isStatic ? 1 : 0) + sigCount]; javaParameterOffsetsInKernelParametersBuffer = new int[javaParameters.length]; @@ -301,7 +298,7 @@ /** * Computes offset and size of space in PARAMS for a Java parameter. - * + * * @param kind the kind of the parameter * @param javaParametersIndex the index of the Java parameter */
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -35,11 +35,14 @@ public SPARCDeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { super(providers, target, linkage); - registerConfig = new SPARCHotSpotRegisterConfig(target, new Register[]{o0, o1, o2, o3, o4, o5, o7, l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, f0, f1, f2, f3, f4, f5, f6, f7}); + // This is basically the maximum we can spare. All other G and O register are used. + Register[] allocatable = new Register[]{g1, g3, g4, g5, o0, o1, o2, o3, o4}; + registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable); } @Override public RegisterConfig getRegisterConfig() { return registerConfig; } + }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,10 +24,8 @@ import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.sparc.SPARC.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import sun.misc.*; @@ -46,7 +44,6 @@ import com.oracle.graal.asm.sparc.SPARCMacroAssembler.RestoreWindow; import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.meta.*; @@ -54,8 +51,10 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; /** * HotSpot SPARC specific backend. @@ -79,12 +78,17 @@ } @Override - public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { return new SPARCHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); } @Override - public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) { + public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + return new SPARCHotSpotLIRGenerationResult(lir, frameMap, stub); + } + + @Override + public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { return new SPARCHotSpotNodeLIRBuilder(graph, lirGen); } @@ -191,17 +195,12 @@ } @Override - public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { - return new LIRGenerationResultBase(lir, frameMap); - } - - @Override public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; RegisterConfig regConfig = frameMap.registerConfig; HotSpotVMConfig config = getRuntime().getConfig(); - Label unverifiedStub = installedCodeOwner == null || isStatic(installedCodeOwner.getModifiers()) ? null : new Label(); + Label unverifiedStub = installedCodeOwner == null || installedCodeOwner.isStatic() ? null : new Label(); // Emit the prefix
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -48,9 +48,8 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - // Save last Java frame. - new Add(stackPointer, new SPARCAddress(stackPointer, 0).getDisplacement(), g4).emit(masm); + new Add(stackPointer, STACK_BIAS, g4).emit(masm); new Stx(g4, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); // Save the thread register when calling out to the runtime.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,96 @@ +/* + * 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.hotspot.sparc; + +import static com.oracle.graal.sparc.SPARC.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits code that enters a stack frame which is tailored to call the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") +final class SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction { + + private final Register thread; + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + @Alive(REG) AllocatableValue framePc; + @Alive(REG) AllocatableValue senderSp; + @Temp(REG) AllocatableValue scratch; + + SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch) { + this.thread = thread; + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.framePc = framePc; + this.senderSp = senderSp; + this.scratch = scratch; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + final int totalFrameSize = crb.frameMap.totalFrameSize(); + Register framePcRegister = asRegister(framePc); + Register senderSpRegister = asRegister(senderSp); + Register scratchRegister = asRegister(scratch); + + // Save final sender SP to O5_savedSP. + new Mov(senderSpRegister, o5).emit(masm); + + // Load final frame PC. + new Mov(framePcRegister, o7).emit(masm); + + // Allocate a full sized frame. + new Save(sp, -totalFrameSize, sp).emit(masm); + + new Mov(i0, o0).emit(masm); + new Mov(i1, o1).emit(masm); + new Mov(i2, o2).emit(masm); + new Mov(i3, o3).emit(masm); + new Mov(i4, o4).emit(masm); + + // Set up last Java values. + new Add(sp, STACK_BIAS, scratchRegister).emit(masm); + new Stx(scratchRegister, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); + + // Clear last Java PC. + new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm); + + /* + * Safe thread register manually since we are not using LEAF_SP for {@link + * DeoptimizationStub#UNPACK_FRAMES}. + */ + new Mov(thread, l7).emit(masm); + } +}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,14 +22,49 @@ */ package com.oracle.graal.hotspot.sparc; +import java.util.*; + import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.gen.*; + +public class SPARCHotSpotLIRGenerationResult extends LIRGenerationResultBase { + + /** + * The slot reserved for storing the original return address when a frame is marked for + * deoptimization. The return address slot in the callee is overwritten with the address of a + * deoptimization stub. + */ + private StackSlot deoptimizationRescueSlot; + private final Object stub; -public interface SPARCHotSpotLIRGenerationResult extends LIRGenerationResult { + /** + * Map from debug infos that need to be updated with callee save information to the operations + * that provide the information. + */ + private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>(); + + public SPARCHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + super(lir, frameMap); + this.stub = stub; + } - StackSlot getDeoptimizationRescueSlot(); + StackSlot getDeoptimizationRescueSlot() { + return deoptimizationRescueSlot; + } + + public final void setDeoptimizationRescueSlot(StackSlot deoptimizationRescueSlot) { + this.deoptimizationRescueSlot = deoptimizationRescueSlot; + } - Stub getStub(); + Stub getStub() { + return (Stub) stub; + } + + Map<LIRFrameState, SaveRegistersOp> getCalleeSaveInfo() { + return calleeSaveInfo; + } }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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,11 +24,12 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; +import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.sparc.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; @@ -36,16 +37,17 @@ import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.sparc.SPARCMove.LoadOp; import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp; import com.oracle.graal.lir.sparc.SPARCMove.StoreOp; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator { final HotSpotVMConfig config; + private HotSpotLockStack lockStack; public SPARCHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) { super(providers, cc, lirGenRes); @@ -66,11 +68,21 @@ @Override public StackSlot getLockSlot(int lockDepth) { - return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth); + return getLockStack().makeLockSlot(lockDepth); + } + + private HotSpotLockStack getLockStack() { + assert lockStack != null; + return lockStack; + } + + protected void setLockStack(HotSpotLockStack lockStack) { + assert this.lockStack == null; + this.lockStack = lockStack; } @Override - protected boolean needOnlyOopMaps() { + public boolean needOnlyOopMaps() { // Stubs only need oop maps return getStub() != null; } @@ -80,12 +92,13 @@ } @Override - public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { + public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; Variable result; - DeoptimizingNode deoptInfo = null; + // TODO (je) check if this can be removed + LIRFrameState deoptInfo = null; if (hotspotLinkage.canDeoptimize()) { - deoptInfo = info; + deoptInfo = state; assert deoptInfo != null || getStub() != null; } @@ -142,9 +155,9 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { moveDeoptValuesToThread(actionAndReason, speculation); - append(new SPARCDeoptimizeOp(state(deopting))); + append(new SPARCDeoptimizeOp(state)); } @Override @@ -158,14 +171,10 @@ } @Override - public Variable emitLoad(PlatformKind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { SPARCAddressValue loadAddress = asAddressValue(address); Variable result = newVariable(kind); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - if (isCompressCandidate(access)) { + if (isCompressCandidate(null)) { if (config.useCompressedOops && kind == Kind.Object) { // append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? // state(access) : @@ -188,19 +197,15 @@ } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { SPARCAddressValue storeAddress = asAddressValue(address); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } if (isConstant(inputVal)) { Constant c = asConstant(inputVal); - if (canStoreConstant(c, isCompressCandidate(access))) { + if (canStoreConstant(c, isCompressCandidate(null))) { if (inputVal.getKind() == Kind.Object) { - append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(access))); + append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(null))); } else if (inputVal.getKind() == Kind.Long) { - append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(access))); + append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(null))); } else { append(new StoreConstantOp((Kind) kind, storeAddress, c, state, false)); } @@ -208,7 +213,7 @@ } } Variable input = load(inputVal); - if (isCompressCandidate(access)) { + if (isCompressCandidate(null)) { if (config.useCompressedOops && kind == Kind.Object) { // if (input.getKind() == Kind.Object) { // Variable scratch = newVariable(Kind.Long); @@ -235,7 +240,8 @@ } public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { - throw new InternalError("NYI"); + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); } @Override @@ -260,38 +266,78 @@ throw GraalInternalError.unimplemented(); } + /** + * @param savedRegisters the registers saved by this operation which may be subject to pruning + * @param savedRegisterLocations the slots to which the registers are saved + * @param supportsRemove determines if registers can be pruned + */ + protected SPARCSaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations, boolean supportsRemove) { + SPARCSaveRegistersOp save = new SPARCSaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); + append(save); + return save; + } + public SaveRegistersOp emitSaveAllRegisters() { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + // We save all registers that were not saved by the save instruction. + // @formatter:off + Register[] savedRegisters = { + // CPU + g1, g3, g4, g5, + // FPU + f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, f14, f15, + f16, f17, f18, f19, f20, f21, f22, f23, + f24, f25, f26, f27, f28, f29, f30, f31 + }; + // @formatter:on + StackSlot[] savedRegisterLocations = new StackSlot[savedRegisters.length]; + for (int i = 0; i < savedRegisters.length; i++) { + PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); + assert kind != Kind.Illegal; + StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind); + savedRegisterLocations[i] = spillSlot; + } + return emitSaveRegisters(savedRegisters, savedRegisterLocations, false); } public void emitLeaveCurrentStackFrame() { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + append(new SPARCHotSpotLeaveCurrentStackFrameOp()); } public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp()); } public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + Register thread = getProviders().getRegisters().getThreadRegister(); + Variable framePcVariable = load(framePc); + Variable senderSpVariable = load(senderSp); + Variable scratchVariable = newVariable(getHostWordKind()); + append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable)); } public void emitLeaveUnpackFramesStackFrame() { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset())); } public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + Variable frameSizeVariable = load(frameSize); + Variable framePcVariable = load(framePc); + Variable senderSpVariable = load(senderSp); + Variable initialInfoVariable = load(initialInfo); + append(new SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable)); } public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); + + Register threadRegister = getProviders().getRegisters().getThreadRegister(); + Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); + append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister)); + Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(Kind.Long), trapRequest); + append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister)); + + return result; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,49 @@ +/* + * 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.hotspot.sparc; + +import static com.oracle.graal.sparc.SPARC.*; + +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pops the current frame off the stack. + */ +@Opcode("LEAVE_CURRENT_STACK_FRAME") +final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCHotSpotEpilogueOp { + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + // Save O registers over restore. + new Mov(o0, i0).emit(masm); + new Mov(o1, i1).emit(masm); + new Mov(o2, i2).emit(masm); + new Mov(o3, i3).emit(masm); + new Mov(o4, i4).emit(masm); + + leaveFrame(crb); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,49 @@ +/* + * 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.hotspot.sparc; + +import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.sparc.SPARC.*; + +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pops the current frame off the stack including the return address. + */ +@Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME") +final class SPARCHotSpotLeaveDeoptimizedStackFrameOp extends SPARCHotSpotEpilogueOp { + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + // Save O registers over restore. + new Mov(o0, i0).emit(masm); + new Mov(o1, i1).emit(masm); + new Mov(o2, i2).emit(masm); + new Mov(o3, i3).emit(masm); + new Mov(o4, i4).emit(masm); + + new RestoreWindow().emit(masm); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,67 @@ +/* + * 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.hotspot.sparc; + +import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.sparc.SPARC.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits code that leaves a stack frame which is tailored to call the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") +final class SPARCHotSpotLeaveUnpackFramesStackFrameOp extends SPARCLIRInstruction { + + private final Register thread; + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + private final int threadJavaFrameAnchorFlagsOffset; + + SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) { + this.thread = thread; + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + /* + * Safe thread register manually since we are not using LEAF_SP for {@link + * DeoptimizationStub#UNPACK_FRAMES}. + */ + new Mov(l7, thread).emit(masm); + + // Clear last Java frame values. + new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); + new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm); + new Stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)).emit(masm); + } +}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,8 +26,6 @@ import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.sparc.SPARC.*; -import java.lang.reflect.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; @@ -37,6 +35,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp; import com.oracle.graal.nodes.*; @@ -44,8 +43,11 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements HotSpotNodeLIRBuilder { - public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); + assert gen instanceof SPARCHotSpotLIRGenerator; + assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder; + ((SPARCHotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack()); } @Override @@ -60,7 +62,7 @@ @Override public void visitSafepointNode(SafepointNode i) { - LIRFrameState info = gen.state(i); + LIRFrameState info = state(i); append(new SPARCHotSpotSafepointOp(info, getGen().config, gen)); } @@ -100,7 +102,7 @@ } else { assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); - assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; + assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method."; append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013, 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.hotspot.sparc; + +import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.sparc.SPARC.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pushes an interpreter frame to the stack. + */ +@Opcode("PUSH_INTERPRETER_FRAME") +final class SPARCHotSpotPushInterpreterFrameOp extends SPARCLIRInstruction { + + @Alive(REG) AllocatableValue frameSize; + @Alive(REG) AllocatableValue framePc; + @Alive(REG) AllocatableValue senderSp; + @Alive(REG) AllocatableValue initialInfo; + + SPARCHotSpotPushInterpreterFrameOp(AllocatableValue frameSize, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue initialInfo) { + this.frameSize = frameSize; + this.framePc = framePc; + this.senderSp = senderSp; + this.initialInfo = initialInfo; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + final Register frameSizeRegister = asRegister(frameSize); + final Register framePcRegister = asRegister(framePc); + final Register senderSpRegister = asRegister(senderSp); + + // Save sender SP to O5_savedSP. + new Mov(senderSpRegister, o5).emit(masm); + + new Neg(frameSizeRegister).emit(masm); + new Save(sp, frameSizeRegister, sp).emit(masm); + + new Mov(i0, o0).emit(masm); + new Mov(i1, o1).emit(masm); + new Mov(i2, o2).emit(masm); + new Mov(i3, o3).emit(masm); + new Mov(i4, o4).emit(masm); + + // NOTE: Don't touch I5 as it contains valuable saved SP! + + // Move frame's new PC into i7 + new Mov(framePcRegister, i7).emit(masm); + } +}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.sparc; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.sparc.SPARC.*; import java.util.*; @@ -98,25 +98,27 @@ private static Register[] initAllocatable(boolean reserveForHeapBase) { Register[] registers = null; - // @formatter:off if (reserveForHeapBase) { - registers = new Register[] { + // @formatter:off + registers = new Register[]{ // TODO this is not complete o0, o1, o2, o3, o4, o5, /*o6,*/ o7, l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/ f0, f1, f2, f3, f4, f5, f6, f7 - }; + }; + // @formatter:on } else { - registers = new Register[] { + // @formatter:off + registers = new Register[]{ // TODO this is not complete o0, o1, o2, o3, o4, o5, /*o6,*/ o7, l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/ f0, f1, f2, f3, f4, f5, f6, f7 - }; + }; + // @formatter:on } - // @formatter:on if (RegisterPressure.getValue() != null) { String[] names = RegisterPressure.getValue().split(",");
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -33,8 +33,10 @@ import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.nodes.spi.*; + +import edu.umd.cs.findbugs.annotations.*; /** * Emits a safepoint poll. @@ -43,7 +45,7 @@ public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction { @State protected LIRFrameState state; - @Temp({OperandFlag.REG}) private AllocatableValue temp; + @SuppressFBWarnings(value = "BC_IMPOSSIBLE_CAST", justification = "changed by the register allocator") @Temp({OperandFlag.REG}) private AllocatableValue temp; private final HotSpotVMConfig config;
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,8 @@ import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.nodes.ConstantNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import org.junit.*;
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import org.junit.*;
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,7 +24,6 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*; -import static java.lang.reflect.Modifier.*; import java.lang.reflect.*; @@ -79,7 +78,7 @@ public void testIsInObject() { for (Field f : String.class.getDeclaredFields()) { HotSpotResolvedJavaField rf = (HotSpotResolvedJavaField) runtime().getHostProviders().getMetaAccess().lookupJavaField(f); - Assert.assertEquals(rf.toString(), rf.isInObject("a string"), !isStatic(rf.getModifiers())); + Assert.assertEquals(rf.toString(), rf.isInObject("a string"), !rf.isStatic()); } } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,14 +25,13 @@ import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*; import static com.oracle.graal.nodes.StructuredGraph.*; -import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.phases.common.InliningUtil.*; import java.io.*; import java.lang.management.*; -import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; @@ -42,6 +41,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.baseline.*; import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; @@ -363,7 +363,6 @@ */ private void printCompilation() { final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; - final int mod = method.getModifiers(); String compilerName = ""; if (HotSpotCIPrintCompilerName.getValue()) { compilerName = "Graal:"; @@ -380,9 +379,9 @@ compLevelString = ""; } boolean hasExceptionHandlers = method.getExceptionHandlers().length > 0; - TTY.println(String.format("%s%7d %4d %c%c%c%c%c %s %s %s(%d bytes)", compilerName, backend.getRuntime().compilerToVm.getTimeStamp(), id, isOSR ? '%' : ' ', - Modifier.isSynchronized(mod) ? 's' : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', Modifier.isNative(mod) ? 'n' : ' ', compLevelString, - MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize())); + TTY.println(String.format("%s%7d %4d %c%c%c%c%c %s %s %s(%d bytes)", compilerName, backend.getRuntime().compilerToVm.getTimeStamp(), id, isOSR ? '%' : ' ', method.isSynchronized() ? 's' + : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', method.isNative() ? 'n' : ' ', compLevelString, MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + + " " : "", method.getCodeSize())); } private InstalledCode installMethod(final CompilationResult compResult) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.nodes.StructuredGraph.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.io.*; import java.lang.reflect.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -64,4 +64,10 @@ protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) { return new HotSpotLIRFrameState(frame, virtualObjectsArray, exceptionEdge); } + + @Override + protected BytecodeFrame computeFrameForState(FrameState state) { + assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI; + return super.computeFrameForState(state); + } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.hotspot; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.Options.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.lang.reflect.*; import java.util.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -63,7 +63,7 @@ try (Scope s = Debug.scope("RegisterReplacements", new DebugDumpScope("RegisterReplacements"))) { ServiceLoader<ReplacementsProvider> sl = ServiceLoader.loadInstalled(ReplacementsProvider.class); for (ReplacementsProvider replacementsProvider : sl) { - replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, replacements, providers.getCodeCache().getTarget()); + replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, providers.getSnippetReflection(), replacements, providers.getCodeCache().getTarget()); } if (BootstrapReplacements.getValue()) { for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,11 +24,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.lir.gen.*; /** * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.hotspot; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,10 +27,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.io.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.lang.reflect.*; import java.util.*; @@ -794,6 +794,7 @@ // offsets, ... @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages; @HotSpotVMFlag(name = "UseStackBanging") @Stable public boolean useStackBanging; + @HotSpotVMConstant(name = "STACK_BIAS") @Stable public int stackBias; @HotSpotVMField(name = "oopDesc::_mark", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset; @HotSpotVMField(name = "oopDesc::_metadata._klass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import sun.misc.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Apr 28 10:31:17 2014 +0200 @@ -345,7 +345,7 @@ private void enqueue(Method m) throws Throwable { JavaMethod javaMethod = runtime.getHostProviders().getMetaAccess().lookupJavaMethod(m); - assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) : javaMethod; + assert !((HotSpotResolvedJavaMethod) javaMethod).isAbstract() && !((HotSpotResolvedJavaMethod) javaMethod).isNative() : javaMethod; compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, false); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Mon Apr 28 10:31:17 2014 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; @@ -40,7 +41,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.options.*; import com.oracle.graal.replacements.nodes.*; @@ -99,7 +99,6 @@ private static final boolean DUMP_STATIC = false; - public static String excludedClassPrefix = null; public static boolean enabled = false; public static final ConcurrentHashMap<String, Integer> indexes = new ConcurrentHashMap<>(); @@ -108,14 +107,23 @@ public static final ArrayList<AtomicLong> staticCounters = new ArrayList<>(); @SuppressFBWarnings(value = "AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION", justification = "concurrent abstraction calls are in synchronized block") - public static int getIndex(DynamicCounterNode counter) { + private static int getIndex(DynamicCounterNode counter) { if (!enabled) { throw new GraalInternalError("counter nodes shouldn't exist when counters are not enabled: " + counter.getGroup() + ", " + counter.getName()); } - String name = counter.getName(); + String name; String group = counter.getGroup(); - name = counter.isWithContext() && counter.graph().method() != null ? name + " @ " + counter.graph().graphId() + ":" + MetaUtil.format("%h.%n", counter.graph().method()) + "#" + group : name + - "#" + group; + if (counter.isWithContext()) { + StructuredGraph graph = counter.graph(); + name = counter.getName() + " @ " + graph.graphId() + ":" + (graph.method() == null ? "" : MetaUtil.format("%h.%n", graph.method())); + if (graph.name != null) { + name += " (" + graph.name + ")"; + } + name += "#" + group; + + } else { + name = counter.getName() + "#" + group; + } Integer index = indexes.get(name); if (index == null) { synchronized (BenchmarkCounters.class) { @@ -135,7 +143,7 @@ return index; } - public static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) { + private static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) { if (!groups.isEmpty()) { out.println("====== dynamic counters (" + staticCounters.size() + " in total) ======"); for (String group : new TreeSet<>(groups)) { @@ -152,7 +160,7 @@ } } - public static synchronized void clear(long[] counters) { + private static synchronized void clear(long[] counters) { delta = counters; } @@ -228,7 +236,7 @@ return (counter * 200 + 1) / sum / 2; } - public abstract static class CallbackOutputStream extends OutputStream { + private abstract static class CallbackOutputStream extends OutputStream { protected final PrintStream delegate; private final byte[][] patterns; @@ -281,25 +289,30 @@ final class BenchmarkCountersOutputStream extends CallbackOutputStream { private long startTime; + private boolean running; private boolean waitingForEnd; private BenchmarkCountersOutputStream(PrintStream delegate, String start, String end) { - super(delegate, new String[]{start, end, "\n"}); + super(delegate, new String[]{"\n", end, start}); } @Override protected void patternFound(int index) { switch (index) { - case 0: + case 2: startTime = System.nanoTime(); BenchmarkCounters.clear(compilerToVM.collectCounters()); + running = true; break; case 1: - waitingForEnd = true; + if (running) { + waitingForEnd = true; + } break; - case 2: + case 0: if (waitingForEnd) { waitingForEnd = false; + running = false; BenchmarkCounters.dump(delegate, (System.nanoTime() - startTime) / 1000000000d, compilerToVM.collectCounters(), 100); } break; @@ -321,7 +334,6 @@ throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: err|out"); } } - excludedClassPrefix = "Lcom/oracle/graal/"; enabled = true; } if (Options.GenericDynamicCounters.getValue()) { @@ -363,26 +375,24 @@ public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) { StructuredGraph graph = counter.graph(); - if (excludedClassPrefix == null || (counter.graph().method() != null && !counter.graph().method().getDeclaringClass().getName().startsWith(excludedClassPrefix))) { - ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false)); + ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false)); - int index = BenchmarkCounters.getIndex(counter); - if (index >= config.graalCountersSize) { - throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")"); - } - ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, config.graalCountersThreadOffset, graph); - ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false)); - ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph); - ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false)); - IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement())); - WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE, false)); + int index = BenchmarkCounters.getIndex(counter); + if (index >= config.graalCountersSize) { + throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")"); + } + ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, wordKind, config.graalCountersThreadOffset, graph); + ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false)); + ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph); + ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false)); + IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement())); + WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE, false)); - graph.addBeforeFixed(counter, thread); - graph.addBeforeFixed(counter, readArray); - graph.addBeforeFixed(counter, read); - graph.addBeforeFixed(counter, write); - } + graph.addBeforeFixed(counter, thread); + graph.addBeforeFixed(counter, readArray); + graph.addBeforeFixed(counter, read); + graph.addBeforeFixed(counter, write); graph.removeFixed(counter); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -286,4 +286,8 @@ public String disassemble(ResolvedJavaMethod method) { return new BytecodeDisassembler().disassemble(method); } + + public SpeculationLog createSpeculationLog() { + return new HotSpotSpeculationLog(); + } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.lang.invoke.*; @@ -529,6 +529,9 @@ } break; case InvokeDynamic: + if (!isInvokedynamicIndex(cpi)) { + throw new IllegalArgumentException("InvokeDynamic entries must be accessed"); + } runtime().getCompilerToVM().resolveInvokeDynamic(metaspaceConstantPool, cpi); break; default:
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import java.lang.reflect.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -119,7 +119,14 @@ registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); registerForeignCall(UNCOMMON_TRAP, c.deoptimizationUncommonTrap, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + + /* + * We cannot use LEAF_SP here because on some architectures we have to align the stack + * manually before calling into the VM. See {@link + * AMD64HotSpotEnterUnpackFramesStackFrameOp#emitCode}. + */ registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import sun.misc.*; import com.oracle.graal.api.code.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,12 +26,12 @@ import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; import static com.oracle.graal.nodes.java.ArrayLengthNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; @@ -112,6 +112,8 @@ lowerStoreFieldNode((StoreFieldNode) n, tool); } else if (n instanceof CompareAndSwapNode) { lowerCompareAndSwapNode((CompareAndSwapNode) n); + } else if (n instanceof AtomicReadAndWriteNode) { + lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n); } else if (n instanceof LoadIndexedNode) { lowerLoadIndexedNode((LoadIndexedNode) n, tool); } else if (n instanceof StoreIndexedNode) { @@ -190,8 +192,10 @@ if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { newObjectSnippets.lower((NewMultiArrayNode) n, tool); } - } else if (n instanceof LoadExceptionObjectNode) { - exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool); + } else if (n instanceof ExceptionObjectNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + lowerExceptionObjectNode((ExceptionObjectNode) n, tool); + } } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. @@ -221,7 +225,7 @@ NodeInputList<ValueNode> parameters = callTarget.arguments(); ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); GuardingNode receiverNullCheck = null; - if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !ObjectStamp.isObjectNonNull(receiver)) { + if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isObjectNonNull(receiver)) { receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); invoke.setGuard(receiverNullCheck); } @@ -385,6 +389,22 @@ graph.replaceFixedWithFixed(cas, atomicNode); } + private void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) { + StructuredGraph graph = n.graph(); + Kind valueKind = n.getValueKind(); + LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1); + + ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue()); + + LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, getAtomicReadAndWriteBarrierType(n), false)); + memoryRead.setStateAfter(n.stateAfter()); + + ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); + + n.replaceAtUsages(readValue); + graph.replaceFixedWithFixed(n, memoryRead); + } + private void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) { StructuredGraph graph = loadIndexed.graph(); Kind elementKind = loadIndexed.elementKind(); @@ -411,10 +431,10 @@ CheckCastNode checkcastNode = null; CheckCastDynamicNode checkcastDynamicNode = null; - if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) { + if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) { // Store check! - ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array); - if (arrayType != null && ObjectStamp.isExactType(array)) { + ResolvedJavaType arrayType = StampTool.typeOrNull(array); + if (arrayType != null && StampTool.isExactType(array)) { ResolvedJavaType elementType = arrayType.getComponentType(); if (!MetaUtil.isJavaLangObject(elementType)) { checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true)); @@ -714,6 +734,19 @@ } } + private void lowerExceptionObjectNode(ExceptionObjectNode n, LoweringTool tool) { + LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) n.predecessor()).getLocationIdentity(); + BeginNode entry = n.graph().add(new KillingBeginNode(locationsKilledByInvoke)); + LoadExceptionObjectNode loadException = n.graph().add(new LoadExceptionObjectNode(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Throwable.class)))); + + loadException.setStateAfter(n.stateAfter()); + n.replaceAtUsages(InputType.Value, loadException); + n.graph().replaceFixedWithFixed(n, entry); + entry.graph().addAfterFixed(entry, loadException); + + exceptionObjectSnippets.lower(loadException, registers, tool); + } + protected static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) { StructuredGraph graph = commit.graph(); for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { @@ -789,8 +822,8 @@ private static boolean addReadBarrier(UnsafeLoadNode load) { if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getKind() == Kind.Object && load.accessKind() == Kind.Object && - !ObjectStamp.isObjectAlwaysNull(load.object())) { - ResolvedJavaType type = ObjectStamp.typeOrNull(load.object()); + !StampTool.isObjectAlwaysNull(load.object())) { + ResolvedJavaType type = StampTool.typeOrNull(load.object()); if (type != null && !type.isArray()) { return true; } @@ -868,7 +901,7 @@ private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) { if (store.value().getKind() == Kind.Object) { - ResolvedJavaType type = ObjectStamp.typeOrNull(store.object()); + ResolvedJavaType type = StampTool.typeOrNull(store.object()); if (type != null && !type.isArray()) { return BarrierType.IMPRECISE; } else { @@ -880,7 +913,19 @@ private static BarrierType getCompareAndSwapBarrierType(CompareAndSwapNode cas) { if (cas.expected().getKind() == Kind.Object) { - ResolvedJavaType type = ObjectStamp.typeOrNull(cas.object()); + ResolvedJavaType type = StampTool.typeOrNull(cas.object()); + if (type != null && !type.isArray()) { + return BarrierType.IMPRECISE; + } else { + return BarrierType.PRECISE; + } + } + return BarrierType.NONE; + } + + private static BarrierType getAtomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) { + if (n.newValue().getKind() == Kind.Object) { + ResolvedJavaType type = StampTool.typeOrNull(n.object()); if (type != null && !type.isArray()) { return BarrierType.IMPRECISE; } else { @@ -973,7 +1018,7 @@ } private static GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) { - if (ObjectStamp.isObjectNonNull(object)) { + if (StampTool.isObjectNonNull(object)) { return null; } return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.lang.reflect.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static java.lang.String.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,6 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import java.lang.reflect.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -84,10 +82,10 @@ } protected boolean checkThreeObjectArgs() { - assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3; + assert method.getSignature().getParameterCount(!method.isStatic()) == 3; assert method.getSignature().getParameterKind(0) == Kind.Object; assert method.getSignature().getParameterKind(1) == Kind.Object; - assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object; + assert !method.isStatic() || method.getSignature().getParameterKind(2) == Kind.Object; return true; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,9 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; import java.lang.annotation.*; import java.lang.reflect.*; @@ -200,8 +199,8 @@ assert !ImmutableCode.getValue() || isCalledForSnippets() : receiver; if (receiver == null) { - assert isStatic(modifiers); - if (Modifier.isFinal(getModifiers())) { + assert isStatic(); + if (isFinal()) { if (holder.isInitialized() && !holder.getName().equals(SystemClassName) && isEmbeddable()) { return readValue(receiver); } @@ -211,14 +210,14 @@ * for non-static final fields, we must assume that they are only initialized if they * have a non-default value. */ - assert !isStatic(modifiers); + assert !isStatic(); Object object = HotSpotObjectConstant.asObject(receiver); // Canonicalization may attempt to process an unsafe read before // processing a guard (e.g. a null check or a type check) for this read // so we need to check the object being read if (object != null && isInObject(object)) { - if (Modifier.isFinal(getModifiers())) { + if (isFinal()) { Constant value = readValue(receiver); if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) { return value; @@ -248,7 +247,7 @@ * {@code object}'s class */ public boolean isInObject(Object object) { - if (isStatic(modifiers)) { + if (isStatic()) { return false; } return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectType.fromClass(object.getClass())); @@ -257,13 +256,13 @@ @Override public Constant readValue(Constant receiver) { if (receiver == null) { - assert isStatic(modifiers); + assert isStatic(); if (holder.isInitialized()) { return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), HotSpotObjectConstant.forObject(holder.mirror()), offset); } return null; } else { - assert !isStatic(modifiers); + assert !isStatic(); assert receiver.isNonNull() && isInObject(HotSpotObjectConstant.asObject(receiver)); return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver, offset); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.lang.annotation.*; import java.lang.reflect.*; +import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -55,7 +56,6 @@ private final HotSpotSignature signature; private HotSpotMethodData methodData; private byte[] code; - private SpeculationLog speculationLog; /** * Gets the holder of a HotSpot metaspace method native object. @@ -186,8 +186,7 @@ @Override public boolean canBeStaticallyBound() { - int modifiers = getModifiers(); - return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(holder.getModifiers())) && !Modifier.isAbstract(modifiers); + return (isFinal() || isPrivate() || isStatic() || holder.isFinal()) && !isAbstract(); } @Override @@ -314,18 +313,17 @@ @Override public boolean isClassInitializer() { - return "<clinit>".equals(name) && Modifier.isStatic(getModifiers()); + return "<clinit>".equals(name) && isStatic(); } @Override public boolean isConstructor() { - return "<init>".equals(name) && !Modifier.isStatic(getModifiers()); + return "<init>".equals(name) && !isStatic(); } @Override public int getMaxLocals() { - int modifiers = getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + if (isAbstract() || isNative()) { return 0; } HotSpotVMConfig config = runtime().getConfig(); @@ -334,8 +332,7 @@ @Override public int getMaxStackSize() { - int modifiers = getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + if (isAbstract() || isNative()) { return 0; } HotSpotVMConfig config = runtime().getConfig(); @@ -616,18 +613,40 @@ * @return virtual table index */ private int getVtableIndex() { - assert !Modifier.isInterface(holder.getModifiers()); + assert !holder.isInterface(); HotSpotVMConfig config = runtime().getConfig(); int result = unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset); assert result >= config.nonvirtualVtableIndex : "must be linked"; return result; } + /** + * The {@link SpeculationLog} for methods compiled by Graal hang off this per-declaring-type + * {@link ClassValue}. The raw Method* value is safe to use as a key in the map as a) it is + * never moves and b) we never read from it. + * <p> + * One implication is that we will preserve {@link SpeculationLog}s for methods that have been + * redefined via class redefinition. It's tempting to periodically flush such logs but we cannot + * read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods + * are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal). + */ + private static final ClassValue<Map<Long, SpeculationLog>> SpeculationLogs = new ClassValue<Map<Long, SpeculationLog>>() { + @Override + protected Map<Long, SpeculationLog> computeValue(java.lang.Class<?> type) { + return new HashMap<>(4); + } + }; + public SpeculationLog getSpeculationLog() { - if (speculationLog == null) { - speculationLog = new HotSpotSpeculationLog(); + Map<Long, SpeculationLog> map = SpeculationLogs.get(holder.mirror()); + synchronized (map) { + SpeculationLog log = map.get(this.metaspaceMethod); + if (log == null) { + log = new HotSpotSpeculationLog(); + map.put(metaspaceMethod, log); + } + return log; } - return speculationLog; } public int intrinsicId() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,8 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.meta.MetaUtil.*; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static java.lang.reflect.Modifier.*; - import java.lang.annotation.*; import java.lang.reflect.*; import java.net.*; @@ -141,7 +139,7 @@ public ResolvedJavaType findUniqueConcreteSubtype() { HotSpotVMConfig config = runtime().getConfig(); if (isArray()) { - return isFinal(getElementalType(this).getModifiers()) ? this : null; + return getElementalType(this).isFinal() ? this : null; } else if (isInterface()) { final long implementorMetaspaceKlass = runtime().getCompilerToVM().getKlassImplementor(metaspaceKlass()); @@ -157,20 +155,20 @@ * than one implementors (see: InstanceKlass::add_implementor). The isInterface check * takes care of this fact since this class is an interface. */ - if (isAbstract(type.getModifiers()) || type.isInterface() || !type.isLeafClass()) { + if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) { return null; } return type; } else { HotSpotResolvedObjectType type = this; - while (isAbstract(type.getModifiers())) { + while (type.isAbstract()) { long subklass = type.getSubklass(); if (subklass == 0 || unsafeReadWord(subklass + config.nextSiblingOffset) != 0) { return null; } type = (HotSpotResolvedObjectType) fromMetaspaceKlass(subklass); } - if (isAbstract(type.getModifiers()) || type.isInterface() || !type.isLeafClass()) { + if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) { return null; } return type; @@ -255,7 +253,7 @@ if (isArray()) { return getComponentType().asExactType() != null ? this : null; } - return isFinal(getModifiers()) ? this : null; + return isFinal() ? this : null; } @Override @@ -358,7 +356,7 @@ @Override public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { assert method instanceof HotSpotMethod; - if (!isAbstract(method.getModifiers()) && method.getDeclaringClass().equals(this)) { + if (!method.isAbstract() && method.getDeclaringClass().equals(this)) { return method; } @@ -367,7 +365,7 @@ return null; } HotSpotResolvedJavaMethod resolvedMethod = HotSpotResolvedJavaMethod.fromMetaspace(resolvedMetaspaceMethod); - if (isAbstract(resolvedMethod.getModifiers())) { + if (resolvedMethod.isAbstract()) { return null; } return resolvedMethod;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.phases.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.nfi; import static com.oracle.graal.api.code.CodeUtil.*; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.nfi.NativeCallStubGraphBuilder.*; import com.oracle.graal.api.code.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -33,7 +33,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.word.phases.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,18 +26,16 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Reserves a block of memory in the stack frame of a method. The block is reserved in the frame for * the entire execution of the associated method. */ -public final class AllocaNode extends FixedWithNextNode implements LIRGenResLowerable { +public final class AllocaNode extends FixedWithNextNode implements LIRLowerable { /** * The number of slots in block. @@ -58,8 +56,8 @@ } @Override - public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) { - StackSlot array = res.getFrameMap().allocateStackSlots(slots, objects, null); + public void generate(NodeLIRBuilderTool gen) { + StackSlot array = gen.getLIRGeneratorTool().getResult().getFrameMap().allocateStackSlots(slots, objects, null); Value result = gen.getLIRGeneratorTool().emitAddress(array); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,12 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** @@ -39,7 +38,7 @@ * check on the object. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorEnter, MemoryCheckpoint.Single { +public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single { private int lockDepth; @@ -59,7 +58,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { assert lockDepth != -1; HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); StackSlot slot = hsGen.getLockSlot(lockDepth);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -32,7 +30,7 @@ /** * Converts a compile-time constant Java string into a C string installed with the generated code. */ -public final class CStringNode extends FloatingNode implements LIRGenLowerable { +public final class CStringNode extends FloatingNode implements LIRLowerable { private final String string; @@ -41,7 +39,7 @@ this.string = string; } - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { gen.setResult(this, emitCString(gen, string)); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -93,6 +93,10 @@ throw GraalInternalError.shouldNotReachHere(); } + public ValueNode getInput() { + return input; + } + @Override public Node canonical(CanonicalizerTool tool) { if (input instanceof CompressionNode) { @@ -109,7 +113,7 @@ HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); boolean nonNull; if (input.stamp() instanceof ObjectStamp) { - nonNull = ObjectStamp.isObjectNonNull(input.stamp()); + nonNull = StampTool.isObjectNonNull(input.stamp()); } else { // metaspace pointers are never null nonNull = true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,11 +27,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.hotspot.nodes; 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.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Removes the current frame and tail calls the uncommon trap routine.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -28,8 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -38,7 +37,7 @@ * Intrinsic for allocating an on-stack array of integers to hold the dimensions of a multianewarray * instruction. */ -public final class DimensionsNode extends FixedWithNextNode implements LIRGenResLowerable { +public final class DimensionsNode extends FixedWithNextNode implements LIRLowerable { private final int rank; @@ -48,12 +47,13 @@ } @Override - public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) { + public void generate(NodeLIRBuilderTool gen) { + LIRGeneratorTool lirGen = gen.getLIRGeneratorTool(); int size = rank * 4; - int wordSize = gen.getLIRGeneratorTool().target().wordSize; + int wordSize = lirGen.target().wordSize; int slots = roundUp(size, wordSize) / wordSize; - StackSlot array = res.getFrameMap().allocateStackSlots(slots, new BitSet(0), null); - Value result = gen.getLIRGeneratorTool().emitAddress(array); + StackSlot array = lirGen.getResult().getFrameMap().allocateStackSlots(slots, new BitSet(0), null); + Value result = lirGen.emitAddress(array); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,13 +23,12 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** @@ -39,7 +38,7 @@ * expected value or the compared against value instead of a boolean. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRGenLowerable, MemoryCheckpoint.Single { +public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { @Input private ValueNode object; @Input private ValueNode offset; @@ -79,7 +78,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { ((HotSpotNodeLIRBuilder) gen).visitDirectCompareAndSwap(this); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Intrinsification for getting the address of an object. The code path(s) between a call to
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotMatchableNodes.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,37 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.compiler.match.*; +import com.oracle.graal.nodes.*; + +@MatchableNode(shortName = "Compression", value = CompressionNode.class, inputs = 1, adapter = HotSpotMatchableNodes.CompressionNodeAdapter.class) +public class HotSpotMatchableNodes { + public static class CompressionNodeAdapter extends MatchNodeAdapter { + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((CompressionNode) node).getInput(); + } + } + +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Emits code to leave (pop) the current low-level stack frame. This operation also removes the
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Emits code to leave a low-level stack frame specifically to call out to the C++ method
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadExceptionObjectNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2009, 2011, 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.hotspot.nodes; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable { + + public LoadExceptionObjectNode(Stamp stamp) { + super(stamp); + } + + @Override + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,8 +26,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -35,16 +33,16 @@ /** * Node that is used to maintain a stack based counter of how many locks are currently held. */ -public final class MonitorCounterNode extends FloatingNode implements LIRGenResLowerable { +public final class MonitorCounterNode extends FloatingNode implements LIRLowerable { private MonitorCounterNode() { super(null); } @Override - public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) { + public void generate(NodeLIRBuilderTool gen) { assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance"; - StackSlot counter = res.getFrameMap().allocateStackSlots(1, new BitSet(0), null); + StackSlot counter = gen.getLIRGeneratorTool().getResult().getFrameMap().allocateStackSlots(1, new BitSet(0), null); Value result = gen.getLIRGeneratorTool().emitAddress(counter); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,19 +25,17 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** * A call to the {@link NewArrayStub}. */ -public class NewArrayStubCall extends DeoptimizingStubCall implements LIRGenLowerable { +public class NewArrayStubCall extends DeoptimizingStubCall implements LIRLowerable { private static final Stamp defaultStamp = StampFactory.objectNonNull(); @@ -62,9 +60,9 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_ARRAY); - Variable result = gen.getLIRGenerator().emitForeignCall(linkage, this, gen.operand(hub), gen.operand(length)); + Variable result = gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(hub), gen.operand(length)); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** @@ -60,7 +59,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_INSTANCE); - Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(hub)); + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(hub)); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,14 +23,13 @@ package com.oracle.graal.hotspot.nodes; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; -public class PrefetchAllocateNode extends FixedWithNextNode implements LIRGenLowerable { +public class PrefetchAllocateNode extends FixedWithNextNode implements LIRLowerable { @Input private ValueNode distance; @Input private ValueNode address; @@ -42,7 +41,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { ((HotSpotNodeLIRBuilder) gen).emitPrefetchAllocate(address, distance); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Saves all allocatable registers.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.hotspot.nodes; +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.extended.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Anchor, InputType.Guard}) public final class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.hotspot.nodes; +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.extended.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value}) public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,11 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,25 +24,23 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.java.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Performs a tail call to the specified target compiled method, with the parameter taken from the * supplied FrameState. */ -public class TailcallNode extends FixedWithNextNode implements LIRGenResLowerable { +public class TailcallNode extends FixedWithNextNode implements LIRLowerable { @Input(InputType.State) private FrameState frameState; @Input private ValueNode target; @@ -59,20 +57,21 @@ this.frameState = frameState; } - public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) { + public void generate(NodeLIRBuilderTool gen) { HotSpotVMConfig config = runtime().getConfig(); + LIRGeneratorTool lirGen = gen.getLIRGeneratorTool(); ResolvedJavaMethod method = frameState.method(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass()); - CallingConvention cc = res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.getLIRGeneratorTool().target(), false); + CallingConvention cc = lirGen.getResult().getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, lirGen.target(), false); List<ValueNode> parameters = new ArrayList<>(); for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += HIRFrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) { parameters.add(frameState.localAt(slot)); } Value[] args = gen.visitInvokeArguments(cc, parameters); - Value address = gen.getLIRGeneratorTool().emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0); - Value entry = gen.getLIRGeneratorTool().emitLoad(Kind.Long, address, null); + Value address = lirGen.emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0); + Value entry = lirGen.emitLoad(Kind.Long, address, null); HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen; hsgen.emitTailcall(args, entry); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,13 +24,13 @@ import com.oracle.graal.api.code.*; 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.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,9 +27,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,7 +26,6 @@ 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.nodes.type.*; public class NarrowOopStamp extends ObjectStamp { @@ -77,7 +76,7 @@ } @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { + public PlatformKind getPlatformKind(PlatformKindTool tool) { return NarrowOop; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -66,7 +66,7 @@ if (!isObject(node)) { return false; } - return "Ljava/lang/invoke/DirectMethodHandle;".equals(ObjectStamp.typeOrNull(node).getName()); + return "Ljava/lang/invoke/DirectMethodHandle;".equals(StampTool.typeOrNull(node).getName()); } @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -75,12 +75,12 @@ } protected void addG1PostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) { - final boolean alwaysNull = ObjectStamp.isObjectAlwaysNull(value); + final boolean alwaysNull = StampTool.isObjectAlwaysNull(value); graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(object, value, location, precise, alwaysNull))); } protected void addSerialPostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) { - final boolean alwaysNull = ObjectStamp.isObjectAlwaysNull(value); + final boolean alwaysNull = StampTool.isObjectAlwaysNull(value); final LocationNode loc = (precise ? location : null); graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(object, loc, precise, alwaysNull))); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.hotspot.replacements; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; @@ -53,7 +53,7 @@ /** * Search for an instance field with the given name in a class. - * + * * @param className name of the class to search in * @param fieldName name of the field to be searched * @return resolved java field @@ -100,7 +100,7 @@ /** * Get the receiver of a MethodHandle.invokeBasic call. - * + * * @return the receiver argument node */ private ValueNode getReceiver() { @@ -109,7 +109,7 @@ /** * Get the MemberName argument of a MethodHandle.linkTo* call. - * + * * @return the MemberName argument node (which is the last argument) */ private ValueNode getMemberName() { @@ -119,7 +119,7 @@ /** * Used from {@link MethodHandleInvokeBasicNode} to get the target {@link InvokeNode} if the * method handle receiver is constant. - * + * * @return invoke node for the {@link java.lang.invoke.MethodHandle} target */ protected InvokeNode getInvokeBasicTarget() { @@ -138,7 +138,7 @@ * Used from {@link MethodHandleLinkToStaticNode}, {@link MethodHandleLinkToSpecialNode}, * {@link MethodHandleLinkToVirtualNode}, and {@link MethodHandleLinkToInterfaceNode} to get the * target {@link InvokeNode} if the member name argument is constant. - * + * * @return invoke node for the member name target */ protected InvokeNode getLinkToTarget() { @@ -153,7 +153,7 @@ /** * Helper function to get the {@link InvokeNode} for the vmtarget of a * java.lang.invoke.MemberName. - * + * * @param memberName constant member name node * @return invoke node for the member name target */ @@ -172,7 +172,7 @@ // to a direct call we must cast the receiver and arguments to its // actual types. HotSpotSignature signature = targetMethod.getSignature(); - final boolean isStatic = Modifier.isStatic(targetMethod.getModifiers()); + final boolean isStatic = targetMethod.isStatic(); final int receiverSkip = isStatic ? 0 : 1; // Cast receiver to its type. @@ -189,7 +189,7 @@ // Try to get the most accurate receiver type if (this instanceof MethodHandleLinkToVirtualNode || this instanceof MethodHandleLinkToInterfaceNode) { - ResolvedJavaType receiverType = ObjectStamp.typeOrNull(getReceiver().stamp()); + ResolvedJavaType receiverType = StampTool.typeOrNull(getReceiver().stamp()); if (receiverType != null) { ResolvedJavaMethod concreteMethod = receiverType.findUniqueConcreteMethod(targetMethod); if (concreteMethod != null) { @@ -213,7 +213,7 @@ /** * Inserts a node to cast the argument at index to the given type if the given type is more * concrete than the argument type. - * + * * @param index of the argument to be cast * @param type the type the argument should be cast to */ @@ -222,7 +222,7 @@ ResolvedJavaType targetType = (ResolvedJavaType) type; if (!targetType.isPrimitive()) { ValueNode argument = arguments.get(index); - ResolvedJavaType argumentType = ObjectStamp.typeOrNull(argument.stamp()); + ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp()); if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) { PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType))); arguments.set(index, piNode); @@ -234,12 +234,12 @@ /** * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}. - * + * * @param targetMethod the method the be called * @return invoke node for the member name target */ private InvokeNode createTargetInvokeNode(ResolvedJavaMethod targetMethod) { - InvokeKind invokeKind = Modifier.isStatic(targetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special; + InvokeKind invokeKind = targetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; JavaType returnType = targetMethod.getSignature().getReturnType(null); // MethodHandleLinkTo* nodes have a trailing MemberName argument which
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,6 +27,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -34,8 +36,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.runtime.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.loop.phases.*; @@ -33,7 +34,6 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.nodes.*; @@ -69,8 +69,8 @@ } private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) { - ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp()); - ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp()); + ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp()); + ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp()); if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { return null; @@ -143,13 +143,13 @@ * Returns true if this copy doesn't require store checks. Trivially true for primitive arrays. */ private boolean isExact() { - ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp()); + ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp()); if (srcType.getComponentType().getKind().isPrimitive() || getSource() == getDestination()) { return true; } - ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp()); - if (ObjectStamp.isExactType(getDestination().stamp())) { + ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp()); + if (StampTool.isExactType(getDestination().stamp())) { if (destType != null && destType.isAssignableFrom(srcType)) { return true; } @@ -171,10 +171,10 @@ if (state.getState() == EscapeState.Virtual) { type = state.getVirtualObject().type(); } else { - type = ObjectStamp.typeOrNull(state.getMaterializedValue()); + type = StampTool.typeOrNull(state.getMaterializedValue()); } } else { - type = ObjectStamp.typeOrNull(entry); + type = StampTool.typeOrNull(entry); } if (type == null || !destComponentType.isAssignableFrom(type)) { return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.GuardingPiNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.lang.reflect.*; import java.util.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -34,7 +34,7 @@ public class CallSiteSubstitutions implements ReplacementsProvider { @Override - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) { + public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class); replacements.registerSubstitutions(MutableCallSiteSubstitutions.class); replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -31,6 +31,7 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -38,7 +39,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @@ -32,7 +33,7 @@ public class HotSpotSubstitutions implements ReplacementsProvider { @Override - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) { + public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { replacements.registerSubstitutions(ObjectSubstitutions.class); replacements.registerSubstitutions(SystemSubstitutions.class); replacements.registerSubstitutions(ThreadSubstitutions.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -33,6 +33,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints; @@ -40,7 +41,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.options.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -28,12 +28,12 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; @@ -44,6 +44,12 @@ /** * Snippet for loading the exception object at the start of an exception dispatcher. + * <p> + * The frame state upon entry to an exception handler is such that it is a + * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly the + * exception object (per the JVM spec) to rethrow. This means that the code generated for this node + * must not cause a deoptimization as the runtime/interpreter would not have a valid location to + * find the exception object to be rethrown. */ public class LoadExceptionObjectSnippets implements Snippets {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -457,7 +457,7 @@ } static boolean isTracingEnabledForType(ValueNode object) { - ResolvedJavaType type = ObjectStamp.typeOrNull(object.stamp()); + ResolvedJavaType type = StampTool.typeOrNull(object.stamp()); if (TRACE_TYPE_FILTER == null) { return false; } else { @@ -511,7 +511,7 @@ callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType)); invoke = graph.add(new InvokeNode(callTarget, 0)); List<ValueNode> stack = Collections.emptyList(); - FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false); + FrameState stateAfter = new FrameState(graph.method(), BytecodeFrame.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false); invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,17 +24,18 @@ import static com.oracle.graal.api.code.UnsignedMath.*; import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.Options.*; import static com.oracle.graal.nodes.PiArrayNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; @@ -46,7 +47,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.options.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -60,7 +60,7 @@ return null; } - ResolvedJavaType type = ObjectStamp.typeOrNull(getObject()); + ResolvedJavaType type = StampTool.typeOrNull(getObject()); if (type != null) { if (type.isArray()) { Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getKind()); @@ -106,7 +106,7 @@ /* * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an * exact type) and if it is a cloneable type. - * + * * If yes, then the exact type is returned, otherwise it returns null. */ private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,11 +22,10 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -68,13 +67,10 @@ if (usages().isEmpty()) { return null; } else { - Stamp stamp = getObject().stamp(); - if (stamp instanceof ObjectStamp) { - ObjectStamp objectStamp = (ObjectStamp) stamp; - if (objectStamp.isExactType()) { - Constant clazz = objectStamp.type().getEncoding(Representation.JavaClass); - return ConstantNode.forConstant(clazz, tool.getMetaAccess(), graph()); - } + if (StampTool.isExactType(getObject())) { + ResolvedJavaType type = StampTool.typeOrNull(getObject()); + Constant clazz = type.getEncoding(Representation.JavaClass); + return ConstantNode.forConstant(clazz, tool.getMetaAccess(), graph()); } return this; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,11 +25,11 @@ import static com.oracle.graal.api.meta.LocationIdentity.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.SnippetTemplate.Arguments; @NodeInfo(allowedUsageTypes = {InputType.Memory})
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,13 +22,14 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; @@ -39,7 +40,6 @@ import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Mon Apr 28 10:31:17 2014 +0200 @@ -126,8 +126,8 @@ // Pop all the frames we must move/replace. // // Frame picture (youngest to oldest) - // 1: self-frame (no frame link) - // 2: deoptimizing frame (no frame link) + // 1: self-frame + // 2: deoptimizing frame // 3: caller of deoptimizing frame (could be compiled/interpreted). // Pop self-frame. @@ -136,7 +136,7 @@ // Load the initial info we should save (e.g. frame pointer). final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset()); - // Pop deoptimized frame + // Pop deoptimized frame. final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset()); LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo); @@ -144,13 +144,15 @@ * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for * total size of the interpreter frames plus shadow page size. Bang one page at a time * because large sizes can bang beyond yellow and red zones. + * + * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. */ final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages(); Word stackPointer = readRegister(stackPointerRegister); for (int i = 1; i < bangPages; i++) { - stackPointer.writeInt(-(i * pageSize()), i); + stackPointer.writeInt((-i * pageSize()) + stackBias(), 0); } // Load number of interpreter frames. @@ -221,6 +223,19 @@ return config().useStackBanging ? config().stackShadowPages : 0; } + /** + * Returns the stack bias for the host architecture. + * + * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. + * + * @return stack bias + */ + @Deprecated + @Fold + private static int stackBias() { + return config().stackBias; + } + @Fold private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Mon Apr 28 10:31:17 2014 +0200 @@ -35,7 +35,6 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.stubs.StubUtil.*; @@ -61,15 +60,9 @@ protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class); - // RuntimeStub cannot (currently) support oops or metadata embedded in the code so we - // convert the hub (i.e., Klass*) for int[] to be a naked word. This should be safe since - // the int[] class will never be unloaded. - Constant intArrayHub = intArrayType.klass(); - intArrayHub = Constant.forIntegerKind(runtime().getTarget().wordKind, intArrayHub.asLong()); - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); args.add("hub", null); - args.addConst("intArrayHub", intArrayHub); + args.addConst("intArrayHub", intArrayType.klass()); args.addConst("threadRegister", providers.getRegisters().getThreadRegister()); return args; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.hotspot.stubs; import static com.oracle.graal.compiler.GraalCompiler.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*;
--- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Mon Apr 28 10:31:17 2014 +0200 @@ -160,9 +160,12 @@ public static final Register[] allRegisters = { c0, c1, c2, c3, c4, c5, c6, c7, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, + s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, - q12, q13, q14, q15, threadRegister + q12, q13, q14, q15, + s32, s33, s34, s35, s36, s37, s38, s39, + d16, d17, d18, d19, threadRegister }; // @formatter:on
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,8 +25,6 @@ import static com.oracle.graal.api.code.TypeCheckHints.*; import static com.oracle.graal.bytecode.Bytecodes.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.code.*; @@ -39,7 +37,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -327,7 +324,7 @@ private void genArithmeticOp(Kind result, int opcode) { T y = frameState.pop(result); T x = frameState.pop(result); - boolean isStrictFP = isStrict(method.getModifiers()); + boolean isStrictFP = method.isStrict(); T v; switch (opcode) { case IADD:
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -69,6 +69,12 @@ public abstract boolean isCompatibleWith(S other); public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) { + /* + * (lstadler) if somebody is tempted to remove/disable this clearing code: it's possible to + * remove it for normal compilations, but not for OSR compilations - otherwise dead object + * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with + * Kind.Illegal, because the conflicting branch might not have been parsed. + */ if (liveness == null) { return; }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.java; import static com.oracle.graal.bytecode.Bytecodes.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,10 +25,7 @@ import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; - -import java.lang.reflect.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -38,6 +35,7 @@ import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; @@ -46,7 +44,6 @@ import com.oracle.graal.java.BciBlockMapping.LocalLiveness; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; @@ -219,9 +216,9 @@ liveness = blockMap.liveness; lastInstr = currentGraph.start(); - if (isSynchronized(method.getModifiers())) { + if (method.isSynchronized()) { // add a monitor enter to the start block - currentGraph.start().setStateAfter(frameState.create(FrameState.BEFORE_BCI)); + currentGraph.start().setStateAfter(frameState.create(BytecodeFrame.BEFORE_BCI)); methodSynchronizedObject = synchronizedObject(frameState, method); lastInstr = genMonitorEnter(methodSynchronizedObject); } @@ -289,7 +286,7 @@ unwindBlock = new ExceptionDispatchBlock(); unwindBlock.startBci = -1; unwindBlock.endBci = -1; - unwindBlock.deoptBci = FrameState.UNWIND_BCI; + unwindBlock.deoptBci = method.isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI; unwindBlock.setId(Integer.MAX_VALUE); } return unwindBlock; @@ -409,7 +406,7 @@ } private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { - assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; + assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci"; Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock(); @@ -636,7 +633,7 @@ @Override protected void emitNullCheck(ValueNode receiver) { - if (ObjectStamp.isObjectNonNull(receiver.stamp())) { + if (StampTool.isObjectNonNull(receiver.stamp())) { return; } BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); @@ -723,7 +720,7 @@ * https://wikis.oracle.com/display/HotSpotInternals/Method+handles * +and+invokedynamic */ - boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers()); + boolean hasReceiver = !((ResolvedJavaMethod) target).isStatic(); Constant appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL); if (appendix != null) { frameState.apush(ConstantNode.forConstant(appendix, metaAccess, currentGraph)); @@ -816,7 +813,7 @@ append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci()))); } - synchronizedEpilogue(FrameState.AFTER_BCI, x); + synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x); if (frameState.lockDepth() != 0) { throw new BailoutException("unbalanced monitors"); } @@ -1089,7 +1086,7 @@ } private ValueNode synchronizedObject(HIRFrameStateBuilder state, ResolvedJavaMethod target) { - if (isStatic(target.getModifiers())) { + if (target.isStatic()) { return appendConstant(target.getDeclaringClass().getEncoding(Representation.JavaClass)); } else { return state.loadLocal(0); @@ -1155,13 +1152,12 @@ private void createUnwind() { assert frameState.stackSize() == 1 : frameState; ValueNode exception = frameState.apop(); - append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); - synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null); + synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null); append(new UnwindNode(exception)); } private void synchronizedEpilogue(int bci, ValueNode returnValue) { - if (Modifier.isSynchronized(method.getModifiers())) { + if (method.isSynchronized()) { MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue); if (returnValue != null) { frameState.push(returnValue.getKind(), returnValue);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.java; import static com.oracle.graal.graph.iterators.NodePredicates.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.code.*; @@ -35,7 +33,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; public class HIRFrameStateBuilder extends AbstractFrameStateBuilder<ValueNode, HIRFrameStateBuilder> { @@ -56,7 +53,7 @@ int javaIndex = 0; int index = 0; - if (!isStatic(method.getModifiers())) { + if (!method.isStatic()) { // add the receiver ParameterNode receiver = graph.unique(new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass()))); storeLocal(javaIndex, receiver); @@ -329,6 +326,7 @@ } finally { lockedObjects = lockedObjects.length == 1 ? EMPTY_ARRAY : Arrays.copyOf(lockedObjects, lockedObjects.length - 1); monitorIds = monitorIds.length == 1 ? EMPTY_MONITOR_ARRAY : Arrays.copyOf(monitorIds, monitorIds.length - 1); + assert lockedObjects.length == monitorIds.length; } }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,6 @@ package com.oracle.graal.java; import static com.oracle.graal.api.meta.MetaUtil.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.meta.*; @@ -115,9 +113,9 @@ if (node instanceof StoreFieldNode) { ResolvedJavaField field = ((StoreFieldNode) node).field(); verify(field.getDeclaringClass().equals(declaringClass), node, "store to field " + format("%H.%n", field)); - verify(isStatic(field.getModifiers()), node, "store to field " + format("%H.%n", field)); + verify(field.isStatic(), node, "store to field " + format("%H.%n", field)); if (optionValueType.isAssignableFrom((ResolvedJavaType) field.getType())) { - verify(isFinal(field.getModifiers()), node, "option field " + format("%H.%n", field) + " not final"); + verify(field.isFinal(), node, "option field " + format("%H.%n", field) + " not final"); } else { verify((field.isSynthetic()), node, "store to non-synthetic field " + format("%H.%n", field)); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NPE_07.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NPE_07.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,9 @@ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -61,12 +62,12 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -49,17 +50,17 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 3); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -56,17 +57,17 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Throw_InNested extends JTTTest { @@ -48,12 +49,12 @@ return i; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Throw_Synchronized01 extends JTTTest { @@ -38,12 +39,12 @@ throw new Exception(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Throw_Synchronized02 extends JTTTest { @@ -36,12 +37,12 @@ throw new Exception(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Throw_Synchronized03 extends JTTTest { @@ -41,12 +42,12 @@ throw new Exception(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -37,27 +38,27 @@ return sum; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 80); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,9 @@ // Checkstyle: stop package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -55,12 +56,12 @@ return (int) (b + c + s + i + l + f + d); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 40); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1000); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -104,12 +105,12 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 40); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 80); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,8 +25,9 @@ import java.util.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -106,7 +107,7 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 5); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,9 @@ // Checkstyle: stop package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -48,7 +49,7 @@ return sum; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 15); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,6 +24,8 @@ package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; /* @@ -104,7 +106,8 @@ * different implementation may return different results. The 11 ulp delta allowed for test(100) * tries to account for that but is not guaranteed to work forever. */ - // @Test + @Ignore("failure-prone because of the variabiliy of pow/cos/sin") + @Test public void run0() throws Throwable { double expected = 0.6248571921291398d; runTestWithDelta(11 * Math.ulp(expected), "test", 100);
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6196102.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6196102.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.hotspot; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /** * @bug 6196102 @@ -46,7 +47,7 @@ return "ok"; } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.hotspot; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; //@formatter:off @@ -50,7 +51,7 @@ return 95; } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,30 +22,16 @@ */ package com.oracle.graal.jtt.hotspot; +import org.junit.*; + import com.oracle.graal.jtt.*; -//@formatter:off - -/** - * @test - * @bug 6959129 - * @summary COMPARISON WITH INTEGER.MAX_INT DOES NOT WORK CORRECTLY IN THE CLIENT VM. - * - * This test will not run properly without assertions - * - * @run main/othervm -ea Test6959129 - */ public class Test6959129 extends JTTTest { - public static int test() { + public static long test() { int min = Integer.MAX_VALUE - 30000; int max = Integer.MAX_VALUE; - try { - maxMoves(min, max); - } catch (AssertionError e) { - return 95; - } - return 97; + return maxMoves(min, max); } /** @@ -55,7 +41,9 @@ long n = n2; long moves = 0; while (n != 1) { - assert n > 1; + if (n <= 1) { + throw new IllegalStateException(); + } if (isEven(n)) { n = n / 2; } else { @@ -86,7 +74,7 @@ return maxmoves; } - //@Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/EnumMap02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/EnumMap02.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.util.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -45,17 +46,17 @@ C } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.io.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -58,7 +59,7 @@ out.println(test(10000)); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 10000); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,10 +24,11 @@ import java.lang.reflect.*; +import org.junit.*; + import sun.misc.*; import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -55,7 +56,7 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.net.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -43,22 +44,22 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 5); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_Literal01 extends JTTTest { @@ -45,27 +46,27 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_asSubclass01 extends JTTTest { @@ -53,27 +54,27 @@ return i; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_cast01 extends JTTTest { @@ -57,27 +58,27 @@ return i; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_forName01 extends JTTTest { @@ -45,27 +46,27 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_forName02 extends JTTTest { @@ -51,27 +52,27 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.net.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -56,32 +57,32 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -48,32 +49,32 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.net.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -41,17 +42,17 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 5); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -81,27 +82,27 @@ } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/LambdaEagerTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/LambdaEagerTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,11 +29,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; import com.oracle.graal.options.*; import com.oracle.graal.options.OptionValue.OverrideScope; -import com.oracle.graal.phases.*; public class LambdaEagerTest extends GraalCompilerTest {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Object_getClass01 extends JTTTest { @@ -49,27 +50,27 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_toString01 extends JTTTest { @@ -47,17 +48,17 @@ return string; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -33,17 +34,17 @@ return ("id" + i).intern() == ("id" + i).intern(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -33,17 +34,17 @@ return ("id" + i).intern().equals("id" + i); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.loop; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class LoopParseLong extends JTTTest { @@ -98,7 +99,7 @@ return negative ? result : -result; } - @LongTest + @Test public void run0() throws Throwable { runTest("testShortened", "7", 10); runTest("testShortened", "-100", 10);
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.loop; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -58,7 +59,7 @@ return "" + ('a' + count); } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -33,7 +34,7 @@ return p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; public class FloatingReads extends JTTTest { @@ -61,22 +63,22 @@ return a + b + c; } - // @Test + @Test public void run0() { runTest("test", 10); } - // @Test + @Test public void run1() { runTest("test", 1000); } - // @Test + @Test public void run2() { runTest("test", 1); } - // @Test + @Test public void run3() { runTest("test", 0); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/Matrix01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/Matrix01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -155,32 +156,32 @@ ((Matrix[]) array)[val % array.length] = new Matrix(number); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -57,7 +58,7 @@ return Integer.valueOf(foo(new String[]{"asdf"})); } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -58,7 +59,7 @@ Object c = b; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.util.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -117,22 +118,22 @@ return c2 ? 1 : 0; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 10); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 20); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 40); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.io.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -44,7 +45,7 @@ return (String) arg; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", (Object) null); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.optimize; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* * Tests value numbering of instanceof operations. @@ -76,17 +77,17 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -37,22 +38,22 @@ return Class_getField01.class.getField(input).getName(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "field"); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", "field2"); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", "field3"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -42,27 +43,27 @@ public String field4; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "field"); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", "field2"); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", "field3"); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", "field4"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -39,17 +40,17 @@ field = args[0]; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "main"); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", "xx"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -52,37 +53,37 @@ field = args[0]; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Class_newInstance03 extends JTTTest { @@ -45,27 +46,27 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -59,47 +60,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -61,47 +62,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -87,47 +88,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -61,47 +62,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -59,47 +60,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -67,47 +68,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -69,47 +70,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -69,47 +70,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -56,27 +57,27 @@ return arg.length; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -44,12 +45,12 @@ field = args[0]; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test1"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "test2"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -48,12 +49,12 @@ field = args[0]; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test1"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "test2"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -51,22 +52,22 @@ public void method3(int arg1, Object arg2) { } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -51,22 +52,22 @@ public void method3() { } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Monitor_contended01 extends JTTTest implements Runnable { @@ -71,7 +72,7 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Monitor_notowner01 extends JTTTest { @@ -62,7 +63,7 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java Mon Apr 28 10:31:17 2014 +0200 @@ -41,7 +41,7 @@ } } - @Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter02.java Mon Apr 28 10:31:17 2014 +0200 @@ -45,7 +45,7 @@ } } - @Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_wait01 extends JTTTest implements Runnable { @@ -57,22 +58,22 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 3); } - @LongTest + @Test(timeout = 20000) public void run3() throws Throwable { runTest("test", 15); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_wait02 extends JTTTest implements Runnable { @@ -57,17 +58,17 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 2); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_wait03 extends JTTTest implements Runnable { @@ -63,17 +64,17 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 2); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_wait04 extends JTTTest implements Runnable { @@ -67,32 +68,32 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test(timeout = 20000) public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test(timeout = 20000) public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test(timeout = 20000) public void run5() throws Throwable { runTest("test", 5); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java Mon Apr 28 10:31:17 2014 +0200 @@ -30,9 +30,9 @@ /** * Inspired by {@code com.sun.media.sound.DirectAudioDevice$DirectDL.drain()}. - * + * * Two loop exits hold a monitor while merging. - * + * */ public final class SynchronizedLoopExit01 extends JTTTest { @@ -53,7 +53,7 @@ return b; } - @Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/ThreadLocal03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/ThreadLocal03.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -59,22 +60,22 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Thread_getState02 extends JTTTest { @@ -33,7 +34,7 @@ return new Thread().getState() == Thread.State.NEW; } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,8 +26,9 @@ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; //Test all, mainly monitors public class Thread_isInterrupted02 extends JTTTest { @@ -85,12 +86,12 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0, 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1, 500); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -68,7 +69,7 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -66,7 +67,7 @@ } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -66,7 +67,7 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Thread_join01 extends JTTTest implements Runnable { @@ -43,7 +44,7 @@ cont = false; } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,8 +27,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Thread_join02 extends JTTTest implements Runnable { @@ -50,7 +51,7 @@ cont = false; } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,8 +27,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Thread_join03 extends JTTTest implements Runnable { @@ -47,7 +48,7 @@ cont = false; } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Thread_new01 extends JTTTest { @@ -45,27 +46,27 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Thread_new02 extends JTTTest implements Runnable { @@ -51,27 +52,27 @@ // do nothing. } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Thread_sleep01 extends JTTTest { @@ -35,17 +36,17 @@ return System.currentTimeMillis() - before >= i; } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 10); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 20); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 100); }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_yield01.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_yield01.java Mon Apr 28 10:31:17 2014 +0200 @@ -35,7 +35,7 @@ return true; } - @Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Apr 28 10:31:17 2014 +0200 @@ -39,8 +39,8 @@ // @formatter:off - IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, - LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, + IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, IROL, IROR, + LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, LROL, LROR, FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR, DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR, INEG, LNEG, INOT, LNOT, @@ -82,6 +82,27 @@ } /** + * Unary operation with separate source and destination operand but register only. + */ + public static class Unary2RegOp extends AMD64LIRInstruction { + + @Opcode private final AMD64Arithmetic opcode; + @Def({REG}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue x; + + public Unary2RegOp(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { + this.opcode = opcode; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + emit(crb, masm, opcode, result, x, null); + } + } + + /** * Unary operation with single operand for source and destination. */ public static class Unary1Op extends AMD64LIRInstruction { @@ -431,9 +452,6 @@ case LNOT: masm.notq(asLongReg(result)); break; - case L2I: - masm.andl(asIntReg(result), 0xFFFFFFFF); - break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -473,6 +491,14 @@ assert asIntReg(src).equals(AMD64.rcx); masm.shrl(asIntReg(dst)); break; + case IROL: + assert asIntReg(src).equals(AMD64.rcx); + masm.roll(asIntReg(dst)); + break; + case IROR: + assert asIntReg(src).equals(AMD64.rcx); + masm.roll(asIntReg(dst)); + break; case LADD: masm.addq(asLongReg(dst), asLongReg(src)); @@ -504,6 +530,14 @@ assert asIntReg(src).equals(AMD64.rcx); masm.shrq(asLongReg(dst)); break; + case LROL: + assert asIntReg(src).equals(AMD64.rcx); + masm.rolq(asLongReg(dst)); + break; + case LROR: + assert asIntReg(src).equals(AMD64.rcx); + masm.rorq(asLongReg(dst)); + break; case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); @@ -568,6 +602,9 @@ case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break; + case L2I: + masm.movl(asIntReg(dst), asLongReg(src)); + break; case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break; @@ -674,6 +711,12 @@ case IUSHR: masm.shrl(asIntReg(dst), crb.asIntConst(src) & 31); break; + case IROL: + masm.roll(asIntReg(dst), crb.asIntConst(src) & 31); + break; + case IROR: + masm.rorl(asIntReg(dst), crb.asIntConst(src) & 31); + break; case LADD: masm.addq(asLongReg(dst), crb.asIntConst(src)); @@ -702,6 +745,12 @@ case LUSHR: masm.shrq(asLongReg(dst), crb.asIntConst(src) & 63); break; + case LROL: + masm.rolq(asLongReg(dst), crb.asIntConst(src) & 31); + break; + case LROR: + masm.rorq(asLongReg(dst), crb.asIntConst(src) & 31); + break; case FADD: masm.addss(asFloatReg(dst), (AMD64Address) crb.asFloatConstRef(src));
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.lir.amd64; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import java.lang.reflect.*; @@ -38,7 +38,7 @@ import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.lir.gen.*; /** * Emits code which compares two arrays of the same length. If the CPU supports any vector
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Mon Apr 28 10:31:17 2014 +0200 @@ -132,6 +132,9 @@ default: throw GraalInternalError.shouldNotReachHere(); } + + } else { + throw GraalInternalError.shouldNotReachHere(); } }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Mon Apr 28 10:31:17 2014 +0200 @@ -432,6 +432,74 @@ } } + @Opcode("ATOMIC_READ_AND_ADD") + public static class AtomicReadAndAddOp extends AMD64LIRInstruction { + + private final Kind accessKind; + + @Def protected AllocatableValue result; + @Alive({COMPOSITE}) protected AMD64AddressValue address; + @Use protected AllocatableValue delta; + + public AtomicReadAndAddOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue delta) { + this.accessKind = accessKind; + this.result = result; + this.address = address; + this.delta = delta; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + move(accessKind, crb, masm, result, delta); + if (crb.target.isMP) { + masm.lock(); + } + switch (accessKind) { + case Int: + masm.xaddl(address.toAddress(), asRegister(result)); + break; + case Long: + masm.xaddq(address.toAddress(), asRegister(result)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + @Opcode("ATOMIC_READ_AND_WRITE") + public static class AtomicReadAndWriteOp extends AMD64LIRInstruction { + + private final Kind accessKind; + + @Def protected AllocatableValue result; + @Alive({COMPOSITE}) protected AMD64AddressValue address; + @Use protected AllocatableValue newValue; + + public AtomicReadAndWriteOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue newValue) { + this.accessKind = accessKind; + this.result = result; + this.address = address; + this.newValue = newValue; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + move(accessKind, crb, masm, result, newValue); + switch (accessKind) { + case Int: + masm.xchgl(asRegister(result), address.toAddress()); + break; + case Long: + case Object: + masm.xchgq(asRegister(result), address.toAddress()); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + public static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) { move(result.getKind(), crb, masm, result, input); }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Mon Apr 28 10:31:17 2014 +0200 @@ -446,6 +446,65 @@ } } + @Opcode("ATOMIC_READ_AND_ADD") + public static class AtomicReadAndAddOp extends HSAILLIRInstruction { + + private final Kind accessKind; + + @Def protected AllocatableValue result; + @Use({COMPOSITE}) protected HSAILAddressValue address; + @Use({REG, CONST}) protected Value delta; + + public AtomicReadAndAddOp(Kind accessKind, AllocatableValue result, HSAILAddressValue address, Value delta) { + this.accessKind = accessKind; + this.result = result; + this.address = address; + this.delta = delta; + } + + public HSAILAddressValue getAddress() { + return address; + } + + @Override + public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { + switch (accessKind) { + case Int: + case Long: + masm.emitAtomicAdd(result, address.toAddress(), delta); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + @Opcode("ATOMIC_READ_AND_WRITE") + public static class AtomicReadAndWriteOp extends HSAILLIRInstruction { + + private final Kind accessKind; + + @Def protected AllocatableValue result; + @Use({COMPOSITE}) protected HSAILAddressValue address; + @Use({REG, CONST}) protected Value newValue; + + public AtomicReadAndWriteOp(Kind accessKind, AllocatableValue result, HSAILAddressValue address, Value newValue) { + this.accessKind = accessKind; + this.result = result; + this.address = address; + this.newValue = newValue; + } + + public HSAILAddressValue getAddress() { + return address; + } + + @Override + public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { + masm.emitAtomicExch(accessKind, result, address.toAddress(), newValue); + } + } + public static class NullCheckOp extends HSAILLIRInstruction { @Use protected Value input; @@ -489,27 +548,4 @@ } } - @Opcode("ATOMICADD") - public static class AtomicGetAndAddOp extends HSAILLIRInstruction { - - @Def protected AllocatableValue result; - @Use({COMPOSITE}) protected HSAILAddressValue address; - @Use({REG, CONST}) protected Value delta; - - public AtomicGetAndAddOp(AllocatableValue result, HSAILAddressValue address, Value delta) { - this.result = result; - this.address = address; - this.delta = delta; - } - - public HSAILAddressValue getAddress() { - return address; - } - - @Override - public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { - masm.emitAtomicAdd(result, address.toAddress(), delta); - } - } - }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Mon Apr 28 10:31:17 2014 +0200 @@ -42,6 +42,18 @@ public class PTXControlFlow { + public static abstract class PTXPredicatedLIRInstruction extends PTXLIRInstruction { + private int predRegNum; + + PTXPredicatedLIRInstruction(int regNum) { + predRegNum = regNum; + } + + public int getPredRegNum() { + return predRegNum; + } + } + public static class ReturnOp extends PTXLIRInstruction { @Use({REG, ILLEGAL}) protected Value x; @@ -69,26 +81,25 @@ } } - public static class BranchOp extends PTXLIRInstruction implements StandardOp.BranchOp { + public static class BranchOp extends PTXPredicatedLIRInstruction implements StandardOp.BranchOp { protected final Condition condition; protected final LabelRef trueDestination; protected final LabelRef falseDestination; - protected int predRegNum; public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, int predReg) { + super(predReg); this.condition = condition; this.trueDestination = trueDestination; this.falseDestination = falseDestination; - this.predRegNum = predReg; } @Override public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) { if (crb.isSuccessorEdge(trueDestination)) { - masm.bra(masm.nameOf(falseDestination.label()), predRegNum, false); + masm.bra(masm.nameOf(falseDestination.label()), getPredRegNum(), false); } else { - masm.bra(masm.nameOf(trueDestination.label()), predRegNum, true); + masm.bra(masm.nameOf(trueDestination.label()), getPredRegNum(), true); if (!crb.isSuccessorEdge(falseDestination)) { masm.jmp(falseDestination.label()); } @@ -96,49 +107,47 @@ } } - public static class CondMoveOp extends PTXLIRInstruction { + public static class CondMoveOp extends PTXPredicatedLIRInstruction { @Def({REG, HINT}) protected Value result; @Alive({REG}) protected Value trueValue; @Use({REG, STACK, CONST}) protected Value falseValue; private final Condition condition; - private final int predicate; public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue, int predicateRegister) { + super(predicateRegister); this.result = result; this.condition = condition; this.trueValue = trueValue; this.falseValue = falseValue; - this.predicate = predicateRegister; } @Override public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) { - cmove(crb, masm, result, false, condition, false, trueValue, falseValue, predicate); + cmove(crb, masm, result, false, condition, false, trueValue, falseValue, getPredRegNum()); } } - public static class FloatCondMoveOp extends PTXLIRInstruction { + public static class FloatCondMoveOp extends PTXPredicatedLIRInstruction { @Def({REG}) protected Value result; @Alive({REG}) protected Value trueValue; @Alive({REG}) protected Value falseValue; private final Condition condition; private final boolean unorderedIsTrue; - private final int predicate; public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue, int predicateRegister) { + super(predicateRegister); this.result = result; this.condition = condition; this.unorderedIsTrue = unorderedIsTrue; this.trueValue = trueValue; this.falseValue = falseValue; - this.predicate = predicateRegister; } @Override public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) { - cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue, predicate); + cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue, getPredRegNum()); } } @@ -193,7 +202,7 @@ } } - public static class StrategySwitchOp extends PTXLIRInstruction implements BlockEndOp { + public static class StrategySwitchOp extends PTXPredicatedLIRInstruction implements BlockEndOp { @Use({CONST}) protected Constant[] keyConstants; private final LabelRef[] keyTargets; @@ -201,10 +210,9 @@ @Alive({REG}) protected Value key; @Temp({REG, ILLEGAL}) protected Value scratch; private final SwitchStrategy strategy; - // Number of predicate register that would be set by this instruction. - protected int predRegNum; public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch, int predReg) { + super(predReg); this.strategy = strategy; this.keyConstants = strategy.keyConstants; this.keyTargets = keyTargets; @@ -214,7 +222,6 @@ assert keyConstants.length == keyTargets.length; assert keyConstants.length == strategy.keyProbabilities.length; assert (scratch.getKind() == Kind.Illegal) == (key.getKind() == Kind.Int || key.getKind() == Kind.Long); - predRegNum = predReg; } @Override @@ -228,40 +235,38 @@ if (crb.codeCache.needsDataPatch(keyConstants[index])) { crb.recordInlineDataInCode(keyConstants[index]); } - new Setp(EQ, keyConstants[index], key, predRegNum).emit(masm); + new Setp(EQ, keyConstants[index], key, getPredRegNum()).emit(masm); break; case Object: assert condition == Condition.EQ || condition == Condition.NE; PTXMove.move(crb, masm, scratch, keyConstants[index]); - new Setp(condition, scratch, key, predRegNum).emit(masm); + new Setp(condition, scratch, key, getPredRegNum()).emit(masm); break; default: throw new GraalInternalError("switch only supported for int, long and object"); } - masm.bra(masm.nameOf(target), predRegNum, true); + masm.bra(masm.nameOf(target), getPredRegNum(), true); } }; strategy.run(closure); } } - public static class TableSwitchOp extends PTXLIRInstruction implements BlockEndOp { + public static class TableSwitchOp extends PTXPredicatedLIRInstruction implements BlockEndOp { private final int lowKey; private final LabelRef defaultTarget; private final LabelRef[] targets; @Alive protected Value index; @Temp protected Value scratch; - // Number of predicate register that would be set by this instruction. - protected int predRegNum; public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch, int predReg) { + super(predReg); this.lowKey = lowKey; this.defaultTarget = defaultTarget; this.targets = targets; this.index = index; this.scratch = scratch; - predRegNum = predReg; } @Override @@ -272,14 +277,14 @@ if (lowKey != 0) { // subtract the low value from the switch value // new Sub(value, value, lowKey).emit(masm); - new Setp(GT, index, Constant.forInt(highKey - lowKey), predRegNum).emit(masm); + new Setp(GT, index, Constant.forInt(highKey - lowKey), getPredRegNum()).emit(masm); } else { - new Setp(GT, index, Constant.forInt(highKey), predRegNum).emit(masm); + new Setp(GT, index, Constant.forInt(highKey), getPredRegNum()).emit(masm); } // Jump to default target if index is not within the jump table if (defaultTarget != null) { - masm.bra(masm.nameOf(defaultTarget.label()), predRegNum, true); + masm.bra(masm.nameOf(defaultTarget.label()), getPredRegNum(), true); } // address of jump table
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Mon Apr 28 10:31:17 2014 +0200 @@ -59,7 +59,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.lir.gen.*; public enum SPARCArithmetic { // @formatter:off @@ -68,7 +68,7 @@ FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR, DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR, INEG, LNEG, FNEG, DNEG, INOT, LNOT, - I2L, L2I, I2B, I2C, I2S, + L2I, B2I, S2I, B2L, S2L, I2L, F2D, D2F, I2F, I2D, F2I, D2I, L2F, L2D, F2L, D2L, @@ -572,11 +572,11 @@ case L2I: new Signx(asLongReg(src), asIntReg(dst)).emit(masm); break; - case I2B: + case B2I: new Sll(asIntReg(src), 24, asIntReg(dst)).emit(masm); new Srl(asIntReg(dst), 24, asIntReg(dst)).emit(masm); break; - case I2C: + case S2I: new Sll(asIntReg(src), 16, asIntReg(dst)).emit(masm); new Srl(asIntReg(dst), 16, asIntReg(dst)).emit(masm); break;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -40,7 +40,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.lir.gen.*; public class SPARCBitManipulationOp extends SPARCLIRInstruction {
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Apr 28 10:31:17 2014 +0200 @@ -270,13 +270,16 @@ @Opcode("CMOVE") public static class CondMoveOp extends SPARCLIRInstruction { + private final Kind kind; + @Def({REG, HINT}) protected Value result; @Alive({REG}) protected Value trueValue; @Use({REG, STACK, CONST}) protected Value falseValue; private final ConditionFlag condition; - public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) { + public CondMoveOp(Kind kind, Variable result, Condition condition, Variable trueValue, Value falseValue) { + this.kind = kind; this.result = result; this.condition = intCond(condition); this.trueValue = trueValue; @@ -285,20 +288,28 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - cmove(crb, masm, result, false, condition, false, trueValue, falseValue); + // check that we don't overwrite an input operand before it is used. + assert !result.equals(trueValue); + + SPARCMove.move(crb, masm, result, falseValue); + cmove(crb, masm, kind, result, condition, trueValue); } } @Opcode("CMOVE") public static class FloatCondMoveOp extends SPARCLIRInstruction { + private final Kind kind; + @Def({REG}) protected Value result; @Alive({REG}) protected Value trueValue; @Alive({REG}) protected Value falseValue; + private final ConditionFlag condition; private final boolean unorderedIsTrue; - public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + public FloatCondMoveOp(Kind kind, Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + this.kind = kind; this.result = result; this.condition = floatCond(condition); this.unorderedIsTrue = unorderedIsTrue; @@ -308,18 +319,12 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue); - } - } + // check that we don't overwrite an input operand before it is used. + assert !result.equals(trueValue); - private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, boolean isFloat, ConditionFlag condition, boolean unorderedIsTrue, Value trueValue, Value falseValue) { - // check that we don't overwrite an input operand before it is used. - assert !result.equals(trueValue); + SPARCMove.move(crb, masm, result, falseValue); + cmove(crb, masm, kind, result, condition, trueValue); - SPARCMove.move(crb, masm, result, falseValue); - cmove(crb, masm, result, condition, trueValue); - - if (isFloat) { if (unorderedIsTrue && !trueOnUnordered(condition)) { // cmove(crb, masm, result, ConditionFlag.Parity, trueValue); throw GraalInternalError.unimplemented(); @@ -330,18 +335,20 @@ } } - private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, ConditionFlag cond, Value other) { + private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Kind kind, Value result, ConditionFlag cond, Value other) { if (!isRegister(other)) { SPARCMove.move(crb, masm, result, other); - throw new InternalError("result should be scratch"); + throw GraalInternalError.shouldNotReachHere("result should be scratch"); } assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move"; - switch (other.getKind()) { + switch (kind) { case Int: - // XXX CC depends on compare new Movcc(cond, CC.Icc, asRegister(other), asRegister(result)).emit(masm); break; case Long: + case Object: + new Movcc(cond, CC.Xcc, asRegister(other), asRegister(result)).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere(); }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; import com.oracle.graal.lir.*; /** @@ -33,7 +34,7 @@ * * <pre> * Base Contents - * + * * : : ----- * caller | incoming overflow argument n | ^ * frame : ... : | positive @@ -88,8 +89,7 @@ @Override protected int alignFrameSize(int size) { - int x = size + (target.stackAlignment - 1); - return (x / target.stackAlignment) * target.stackAlignment; + return NumUtil.roundUp(size, target.stackAlignment); } @Override
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -23,32 +23,14 @@ package com.oracle.graal.lir.sparc; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCAssembler.Add; -import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf; -import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf; -import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb; -import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsh; -import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw; -import com.oracle.graal.asm.sparc.SPARCAssembler.Lduh; -import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx; -import com.oracle.graal.asm.sparc.SPARCAssembler.Membar; -import com.oracle.graal.asm.sparc.SPARCAssembler.Rdpc; -import com.oracle.graal.asm.sparc.SPARCAssembler.Stb; -import com.oracle.graal.asm.sparc.SPARCAssembler.Sth; -import com.oracle.graal.asm.sparc.SPARCAssembler.Stw; -import com.oracle.graal.asm.sparc.SPARCAssembler.Stx; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cas; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Casx; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Clr; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setuw; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; @@ -154,32 +136,33 @@ @Override public void emitMemAccess(SPARCMacroAssembler masm) { - SPARCAddress addr = address.toAddress(); + final SPARCAddress addr = address.toAddress(); + final Register dst = asRegister(result); switch (kind) { case Boolean: case Byte: - new Ldsb(addr, asRegister(result)).emit(masm); + new Ldsb(addr, dst).emit(masm); break; case Short: - new Ldsh(addr, asRegister(result)).emit(masm); + new Ldsh(addr, dst).emit(masm); break; case Char: - new Lduh(addr, asRegister(result)).emit(masm); + new Lduh(addr, dst).emit(masm); break; case Int: - new Ldsw(addr, asRegister(result)).emit(masm); + new Ldsw(addr, dst).emit(masm); break; case Long: - new Ldx(addr, asRegister(result)).emit(masm); + new Ldx(addr, dst).emit(masm); break; case Float: - new Ldf(addr, asRegister(result)).emit(masm); + new Ldf(addr, dst).emit(masm); break; case Double: - new Lddf(addr, asRegister(result)).emit(masm); + new Lddf(addr, dst).emit(masm); break; case Object: - new Ldx(addr, asRegister(result)).emit(masm); + new Ldx(addr, dst).emit(masm); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -208,6 +191,26 @@ } } + public static class LoadDataAddressOp extends SPARCLIRInstruction { + + @Def({REG}) protected AllocatableValue result; + private final byte[] data; + + public LoadDataAddressOp(AllocatableValue result, byte[] data) { + this.result = result; + this.data = data; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + RawData rawData = new RawData(data, 16); + SPARCAddress addr = (SPARCAddress) crb.recordDataReferenceInCode(rawData); + assert addr == masm.getPlaceholder(); + final boolean forceRelocatable = true; + new Setx(0, asRegister(result), forceRelocatable).emit(masm); + } + } + public static class MembarOp extends SPARCLIRInstruction { private final int barriers; @@ -395,19 +398,25 @@ } private static void reg2reg(SPARCAssembler masm, Value result, Value input) { - if (asRegister(input).equals(asRegister(result))) { + final Register src = asRegister(input); + final Register dst = asRegister(result); + if (src.equals(dst)) { return; } switch (input.getKind()) { case Int: case Long: case Object: - new Mov(asRegister(input), asRegister(result)).emit(masm); + new Mov(src, dst).emit(masm); break; case Float: + new Fmovs(src, dst).emit(masm); + break; case Double: + new Fmovd(src, dst).emit(masm); + break; default: - throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind()); + throw GraalInternalError.shouldNotReachHere(); } } @@ -423,7 +432,11 @@ new Stx(src, dst).emit(masm); break; case Float: + new Stf(src, dst).emit(masm); + break; case Double: + new Stdf(src, dst).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -461,7 +474,7 @@ } } break; - case Long: { + case Long: if (crb.codeCache.needsDataPatch(input)) { crb.recordInlineDataInCode(input); new Setx(input.asLong(), asRegister(result), true).emit(masm); @@ -473,8 +486,10 @@ } } break; - } - case Object: { + case Float: + new Ldf((SPARCAddress) crb.asFloatConstRef(input), asFloatReg(result)).emit(masm); + break; + case Object: if (input.isNull()) { new Clr(asRegister(result)).emit(masm); } else if (crb.target.inlineObjects) { @@ -488,7 +503,6 @@ throw GraalInternalError.shouldNotReachHere("the patched offset might be too big for the load"); } break; - } default: throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind()); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,133 @@ +/* + * 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.lir.sparc; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.asm.*; + +/** + * Saves registers to stack slots. + */ +@Opcode("SAVE_REGISTER") +public class SPARCSaveRegistersOp extends SPARCLIRInstruction implements SaveRegistersOp { + + /** + * The registers (potentially) saved by this operation. + */ + protected final Register[] savedRegisters; + + /** + * The slots to which the registers are saved. + */ + @Def(STACK) protected final StackSlot[] slots; + + /** + * Specifies if {@link #remove(Set)} should have an effect. + */ + protected final boolean supportsRemove; + + /** + * + * @param savedRegisters the registers saved by this operation which may be subject to + * {@linkplain #remove(Set) pruning} + * @param slots the slots to which the registers are saved + * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned} + */ + public SPARCSaveRegistersOp(Register[] savedRegisters, StackSlot[] slots, boolean supportsRemove) { + this.savedRegisters = savedRegisters; + this.slots = slots; + this.supportsRemove = supportsRemove; + } + + private static void saveRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, StackSlot result, Register register) { + RegisterValue input = register.asValue(result.getKind()); + SPARCMove.move(crb, masm, result, input); + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + for (int i = 0; i < savedRegisters.length; i++) { + if (savedRegisters[i] != null) { + saveRegister(crb, masm, slots[i], savedRegisters[i]); + } + } + } + + public StackSlot[] getSlots() { + return slots; + } + + public boolean supportsRemove() { + return supportsRemove; + } + + public int remove(Set<Register> doNotSave) { + if (!supportsRemove) { + throw new UnsupportedOperationException(); + } + return prune(doNotSave, savedRegisters); + } + + static int prune(Set<Register> toRemove, Register[] registers) { + int pruned = 0; + for (int i = 0; i < registers.length; i++) { + if (registers[i] != null) { + if (toRemove.contains(registers[i])) { + registers[i] = null; + pruned++; + } + } + } + return pruned; + } + + public RegisterSaveLayout getMap(FrameMap frameMap) { + int total = 0; + for (int i = 0; i < savedRegisters.length; i++) { + if (savedRegisters[i] != null) { + total++; + } + } + Register[] keys = new Register[total]; + int[] values = new int[total]; + if (total != 0) { + int mapIndex = 0; + for (int i = 0; i < savedRegisters.length; i++) { + if (savedRegisters[i] != null) { + keys[mapIndex] = savedRegisters[i]; + values[mapIndex] = frameMap.indexForStackSlot(slots[i]); + mapIndex++; + } + } + assert mapIndex == total; + } + return new RegisterSaveLayout(keys, values); + } +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Mon Apr 28 10:31:17 2014 +0200 @@ -86,7 +86,7 @@ @Override protected void rescanFieldOffsets(CalcOffset calc) { ValueFieldScanner scanner = new ValueFieldScanner(calc); - scanner.scan(clazz); + scanner.scan(getClazz()); OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class); copyInto(componentOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets)); @@ -108,7 +108,7 @@ } @Override - protected void scan(Class<?> clazz) { + public void scan(Class<?> clazz) { super.scan(clazz); } @@ -127,7 +127,7 @@ @Override public String toString() { StringBuilder str = new StringBuilder(); - str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" component["); + str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" component["); for (int i = 0; i < componentOffsets.length; i++) { str.append(i == 0 ? "" : ", ").append(componentOffsets[i]); }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Mon Apr 28 10:31:17 2014 +0200 @@ -118,7 +118,7 @@ @Override protected void rescanFieldOffsets(CalcOffset calc) { InstructionFieldScanner scanner = new InstructionFieldScanner(calc); - scanner.scan(clazz); + scanner.scan(getClazz()); OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class); copyInto(useOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets)); @@ -177,7 +177,7 @@ } @Override - protected void scan(Class<?> clazz) { + public void scan(Class<?> clazz) { if (clazz.getAnnotation(Opcode.class) != null) { opcodeConstant = clazz.getAnnotation(Opcode.class).value(); } @@ -213,7 +213,7 @@ @Override public String toString() { StringBuilder str = new StringBuilder(); - str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" use["); + str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" use["); for (int i = 0; i < useOffsets.length; i++) { str.append(i == 0 ? "" : ", ").append(useOffsets[i]); }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Mon Apr 28 10:31:17 2014 +0200 @@ -31,7 +31,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,12 +26,11 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.lir.StandardOp.BranchOp; import com.oracle.graal.lir.StandardOp.JumpOp; -import com.oracle.graal.nodes.cfg.*; /** * LIR instructions such as {@link JumpOp} and {@link BranchOp} need to reference their target - * {@link Block}. However, direct references are not possible since the control flow graph (and - * therefore successors lists) can be changed by optimizations - and fixing the instructions is + * {@link AbstractBlock}. However, direct references are not possible since the control flow graph + * (and therefore successors lists) can be changed by optimizations - and fixing the instructions is * error prone. Therefore, we represent an edge to block B from block A via the tuple {@code (A, * successor-index-of-B)}. That is, indirectly by storing the index into the successor list of A. * Note therefore that the successor list cannot be re-ordered.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Mon Apr 28 10:31:17 2014 +0200 @@ -92,14 +92,8 @@ compilationResult.setTotalFrameSize(frameSize); } - private static final CompilationResult.Mark[] NO_REFS = {}; - public CompilationResult.Mark recordMark(Object id) { - return compilationResult.recordMark(asm.position(), id, NO_REFS); - } - - public CompilationResult.Mark recordMark(Object id, CompilationResult.Mark... references) { - return compilationResult.recordMark(asm.position(), id, references); + return compilationResult.recordMark(asm.position(), id); } public void blockComment(String s) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.gen; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.lir.*; + +/** + * This interface can be used to generate LIR for arithmetic operations. + */ +public interface ArithmeticLIRGenerator { + + PlatformKind getPlatformKind(Stamp stamp); + + Value emitNegate(Value input); + + Value emitAdd(Value a, Value b); + + Value emitSub(Value a, Value b); + + Value emitMul(Value a, Value b); + + Value emitDiv(Value a, Value b, LIRFrameState state); + + Value emitRem(Value a, Value b, LIRFrameState state); + + Value emitUDiv(Value a, Value b, LIRFrameState state); + + Value emitURem(Value a, Value b, LIRFrameState state); + + Value emitNot(Value input); + + Value emitAnd(Value a, Value b); + + Value emitOr(Value a, Value b); + + Value emitXor(Value a, Value b); + + Value emitShl(Value a, Value b); + + Value emitShr(Value a, Value b); + + Value emitUShr(Value a, Value b); + + Value emitFloatConvert(FloatConvert op, Value inputVal); + + Value emitReinterpret(PlatformKind to, Value inputVal); + + Value emitNarrow(Value inputVal, int bits); + + Value emitSignExtend(Value inputVal, int fromBits, int toBits); + + Value emitZeroExtend(Value inputVal, int fromBits, int toBits); + + Value emitMathAbs(Value input); + + Value emitMathSqrt(Value input); + + Value emitMathLog(Value input, boolean base10); + + Value emitMathCos(Value input); + + Value emitMathSin(Value input); + + Value emitMathTan(Value input); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,35 @@ +/* + * 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.lir.gen; + +import com.oracle.graal.lir.*; + +public interface LIRGenerationResult { + FrameMap getFrameMap(); + + LIR getLIR(); + + boolean hasForeignCall(); + + void setForeignCall(boolean b); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,59 @@ +/* + * 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.lir.gen; + +import com.oracle.graal.lir.*; + +public class LIRGenerationResultBase implements LIRGenerationResult { + private final LIR lir; + private final FrameMap frameMap; + /** + * Records whether the code being generated makes at least one foreign call. + */ + private boolean hasForeignCall; + + public LIRGenerationResultBase(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + } + + public LIR getLIR() { + return lir; + } + + /** + * Determines whether the code being generated makes at least one foreign call. + */ + public boolean hasForeignCall() { + return hasForeignCall; + } + + public final void setForeignCall(boolean hasForeignCall) { + this.hasForeignCall = hasForeignCall; + } + + public final FrameMap getFrameMap() { + return frameMap; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,594 @@ +/* + * Copyright (c) 2009, 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.lir.gen; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.api.meta.Value.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.lir.LIR.*; +import static com.oracle.graal.lir.LIRValueUtil.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.compiler.common.spi.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.BlockEndOp; +import com.oracle.graal.lir.StandardOp.LabelOp; +import com.oracle.graal.lir.StandardOp.NoOp; +import com.oracle.graal.options.*; + +/** + * This class traverses the HIR instructions and generates LIR instructions from them. + */ +public abstract class LIRGenerator implements LIRGeneratorTool, PlatformKindTool { + + public static class Options { + // @formatter:off + @Option(help = "Print HIR along side LIR as the latter is generated") + public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false); + @Option(help = "The trace level for the LIR generator") + public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0); + // @formatter:on + } + + private final CodeGenProviders providers; + private final CallingConvention cc; + + private AbstractBlock<?> currentBlock; + + /** + * Handle for an operation that loads a constant into a variable. The operation starts in the + * first block where the constant is used but will eventually be + * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the + * constant. + */ + public static class LoadConstant implements Comparable<LoadConstant> { + /** + * The index of {@link #op} within {@link #block}'s instruction list or -1 if {@code op} is + * to be moved to a dominator block. + */ + int index; + + /** + * The operation that loads the constant. + */ + private final LIRInstruction op; + + /** + * The block that does or will contain {@link #op}. This is initially the block where the + * first usage of the constant is seen during LIR generation. + */ + AbstractBlock<?> block; + + /** + * The variable into which the constant is loaded. + */ + final Variable variable; + + public LoadConstant(Variable variable, AbstractBlock<?> block, int index, LIRInstruction op) { + this.variable = variable; + this.block = block; + this.index = index; + this.op = op; + } + + /** + * Sorts {@link LoadConstant} objects according to their enclosing blocks. This is used to + * group loads per block in {@link LIRGenerator#insertConstantLoads()}. + */ + public int compareTo(LoadConstant o) { + if (block.getId() < o.block.getId()) { + return -1; + } + if (block.getId() > o.block.getId()) { + return 1; + } + return 0; + } + + @Override + public String toString() { + return block + "#" + op; + } + + /** + * Removes the {@link #op} from its original location if it is still at that location. + */ + public void unpin(LIR lir) { + if (index >= 0) { + // Replace the move with a filler op so that the operation + // list does not need to be adjusted. + List<LIRInstruction> instructions = lir.getLIRforBlock(block); + instructions.set(index, new NoOp(null, -1)); + index = -1; + } + } + + public AbstractBlock<?> getBlock() { + return block; + } + + public void setBlock(AbstractBlock<?> block) { + this.block = block; + } + + public Variable getVariable() { + return variable; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + } + + private Map<Constant, LoadConstant> constantLoads; + + private LIRGenerationResult res; + + /** + * Checks whether the supplied constant can be used without loading it into a register for store + * operations, i.e., on the right hand side of a memory access. + * + * @param c The constant to check. + * @return True if the constant can be used directly, false if the constant needs to be in a + * register. + */ + public abstract boolean canStoreConstant(Constant c, boolean isCompressed); + + public LIRGenerator(CodeGenProviders providers, CallingConvention cc, LIRGenerationResult res) { + this.res = res; + this.providers = providers; + this.cc = cc; + } + + /** + * Returns true if the redundant move elimination optimization should be done after register + * allocation. + */ + public boolean canEliminateRedundantMoves() { + return true; + } + + @Override + public TargetDescription target() { + return getCodeCache().getTarget(); + } + + public CodeGenProviders getProviders() { + return providers; + } + + @Override + public MetaAccessProvider getMetaAccess() { + return providers.getMetaAccess(); + } + + @Override + public CodeCacheProvider getCodeCache() { + return providers.getCodeCache(); + } + + @Override + public ForeignCallsProvider getForeignCalls() { + return providers.getForeignCalls(); + } + + /** + * Creates a new {@linkplain Variable variable}. + * + * @param platformKind The kind of the new variable. + * @return a new variable + */ + @Override + public Variable newVariable(PlatformKind platformKind) { + return new Variable(platformKind, res.getLIR().nextVariable()); + } + + @Override + public RegisterAttributes attributes(Register register) { + return res.getFrameMap().registerConfig.getAttributesMap()[register.number]; + } + + @Override + public abstract Variable emitMove(Value input); + + public AllocatableValue asAllocatable(Value value) { + if (isAllocatableValue(value)) { + return asAllocatableValue(value); + } else { + return emitMove(value); + } + } + + public Variable load(Value value) { + if (!isVariable(value)) { + return emitMove(value); + } + return (Variable) value; + } + + public Value loadNonConst(Value value) { + if (isConstant(value) && !canInlineConstant((Constant) value)) { + return emitMove(value); + } + return value; + } + + /** + * Determines if only oop maps are required for the code generated from the LIR. + */ + public boolean needOnlyOopMaps() { + return false; + } + + /** + * Gets the ABI specific operand used to return a value of a given kind from a method. + * + * @param kind the kind of value being returned + * @return the operand representing the ABI defined location used return a value of kind + * {@code kind} + */ + public AllocatableValue resultOperandFor(Kind kind) { + if (kind == Kind.Void) { + return ILLEGAL; + } + return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind); + } + + public void append(LIRInstruction op) { + if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { + TTY.println(op.toStringWithIdPrefix()); + TTY.println(); + } + assert LIRVerifier.verify(op); + res.getLIR().getLIRforBlock(currentBlock).add(op); + } + + public boolean hasBlockEnd(AbstractBlock<?> block) { + List<LIRInstruction> ops = getResult().getLIR().getLIRforBlock(block); + if (ops.size() == 0) { + return false; + } + return ops.get(ops.size() - 1) instanceof BlockEndOp; + } + + public final void doBlockStart(AbstractBlock<?> block) { + if (Options.PrintIRWithLIR.getValue()) { + TTY.print(block.toString()); + } + + currentBlock = block; + + // set up the list of LIR instructions + assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block"; + res.getLIR().setLIRforBlock(block, new ArrayList<LIRInstruction>()); + + append(new LabelOp(new Label(block.getId()), block.isAligned())); + + if (Options.TraceLIRGeneratorLevel.getValue() >= 1) { + TTY.println("BEGIN Generating LIR for block B" + block.getId()); + } + } + + public final void doBlockEnd(AbstractBlock<?> block) { + + if (Options.TraceLIRGeneratorLevel.getValue() >= 1) { + TTY.println("END Generating LIR for block B" + block.getId()); + } + + currentBlock = null; + + if (Options.PrintIRWithLIR.getValue()) { + TTY.println(); + } + } + + public void emitIncomingValues(Value[] params) { + ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params); + } + + public abstract void emitJump(LabelRef label); + + public abstract void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, + double trueDestinationProbability); + + public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability); + + public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability); + + public abstract Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); + + public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue); + + protected abstract void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info); + + public static AllocatableValue toStackKind(AllocatableValue value) { + if (value.getKind().getStackKind() != value.getKind()) { + // We only have stack-kinds in the LIR, so convert the operand kind for values from the + // calling convention. + if (isRegister(value)) { + return asRegister(value).asValue(value.getKind().getStackKind()); + } else if (isStackSlot(value)) { + return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize()); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + return value; + } + + @Override + public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState frameState, Value... args) { + LIRFrameState state = null; + if (linkage.canDeoptimize()) { + if (frameState != null) { + state = frameState; + } else { + assert needOnlyOopMaps(); + state = new LIRFrameState(null, null, null); + } + } + + // move the arguments into the correct location + CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); + res.getFrameMap().callsMethod(linkageCc); + assert linkageCc.getArgumentCount() == args.length : "argument count mismatch"; + Value[] argLocations = new Value[args.length]; + for (int i = 0; i < args.length; i++) { + Value arg = args[i]; + AllocatableValue loc = linkageCc.getArgument(i); + emitMove(loc, arg); + argLocations[i] = loc; + } + res.setForeignCall(true); + emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state); + + if (isLegal(linkageCc.getReturn())) { + return emitMove(linkageCc.getReturn()); + } else { + return null; + } + } + + public void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) { + int keyCount = keyConstants.length; + SwitchStrategy strategy = SwitchStrategy.getBestStrategy(keyProbabilities, keyConstants, keyTargets); + long valueRange = keyConstants[keyCount - 1].asLong() - keyConstants[0].asLong() + 1; + double tableSwitchDensity = keyCount / (double) valueRange; + /* + * This heuristic tries to find a compromise between the effort for the best switch strategy + * and the density of a tableswitch. If the effort for the strategy is at least 4, then a + * tableswitch is preferred if better than a certain value that starts at 0.5 and lowers + * gradually with additional effort. + */ + if (strategy.getAverageEffort() < 4 || tableSwitchDensity < (1 / Math.sqrt(strategy.getAverageEffort()))) { + emitStrategySwitch(strategy, value, keyTargets, defaultTarget); + } else { + int minValue = keyConstants[0].asInt(); + assert valueRange < Integer.MAX_VALUE; + LabelRef[] targets = new LabelRef[(int) valueRange]; + for (int i = 0; i < valueRange; i++) { + targets[i] = defaultTarget; + } + for (int i = 0; i < keyCount; i++) { + targets[keyConstants[i].asInt() - minValue] = keyTargets[i]; + } + emitTableSwitch(minValue, defaultTarget, targets, value); + } + } + + public abstract void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget); + + protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key); + + public CallingConvention getCallingConvention() { + return cc; + } + + @Override + public void beforeRegisterAllocation() { + insertConstantLoads(); + } + + /** + * Moves deferred {@linkplain LoadConstant loads} of constants into blocks dominating all usages + * of the constant. Any operations inserted into a block are guaranteed to be immediately prior + * to the first control flow instruction near the end of the block. + */ + private void insertConstantLoads() { + if (constantLoads != null) { + // Remove loads where all usages are in the same block. + for (Iterator<Map.Entry<Constant, LoadConstant>> iter = constantLoads.entrySet().iterator(); iter.hasNext();) { + LoadConstant lc = iter.next().getValue(); + + // Move loads of constant outside of loops + if (OptScheduleOutOfLoops.getValue()) { + AbstractBlock<?> outOfLoopDominator = lc.block; + while (outOfLoopDominator.getLoop() != null) { + outOfLoopDominator = outOfLoopDominator.getDominator(); + } + if (outOfLoopDominator != lc.block) { + lc.unpin(res.getLIR()); + lc.block = outOfLoopDominator; + } + } + + if (lc.index != -1) { + assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op; + iter.remove(); + } + } + if (constantLoads.isEmpty()) { + return; + } + + // Sorting groups the loads per block. + LoadConstant[] groupedByBlock = constantLoads.values().toArray(new LoadConstant[constantLoads.size()]); + Arrays.sort(groupedByBlock); + + int groupBegin = 0; + while (true) { + int groupEnd = groupBegin + 1; + AbstractBlock<?> block = groupedByBlock[groupBegin].block; + while (groupEnd < groupedByBlock.length && groupedByBlock[groupEnd].block == block) { + groupEnd++; + } + int groupSize = groupEnd - groupBegin; + + List<LIRInstruction> ops = res.getLIR().getLIRforBlock(block); + int lastIndex = ops.size() - 1; + assert ops.get(lastIndex) instanceof BlockEndOp; + int insertionIndex = lastIndex; + for (int i = Math.max(0, lastIndex - MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END); i < lastIndex; i++) { + if (getExceptionEdge(ops.get(i)) != null) { + insertionIndex = i; + break; + } + } + + if (groupSize == 1) { + ops.add(insertionIndex, groupedByBlock[groupBegin].op); + } else { + assert groupSize > 1; + List<LIRInstruction> moves = new ArrayList<>(groupSize); + for (int i = groupBegin; i < groupEnd; i++) { + moves.add(groupedByBlock[i].op); + } + ops.addAll(insertionIndex, moves); + } + + if (groupEnd == groupedByBlock.length) { + break; + } + groupBegin = groupEnd; + } + constantLoads = null; + } + } + + /** + * Gets a garbage value for a given kind. + */ + protected Constant zapValueForKind(PlatformKind kind) { + long dead = 0xDEADDEADDEADDEADL; + switch ((Kind) kind) { + case Boolean: + return Constant.FALSE; + case Byte: + return Constant.forByte((byte) dead); + case Char: + return Constant.forChar((char) dead); + case Short: + return Constant.forShort((short) dead); + case Int: + return Constant.forInt((int) dead); + case Double: + return Constant.forDouble(Double.longBitsToDouble(dead)); + case Float: + return Constant.forFloat(Float.intBitsToFloat((int) dead)); + case Long: + return Constant.forLong(dead); + case Object: + return Constant.NULL_OBJECT; + default: + throw new IllegalArgumentException(kind.toString()); + } + } + + /** + * Default implementation: Return the Java stack kind for each stamp. + */ + public PlatformKind getPlatformKind(Stamp stamp) { + return stamp.getPlatformKind(this); + } + + public PlatformKind getIntegerKind(int bits) { + if (bits <= 8) { + return Kind.Byte; + } else if (bits <= 16) { + return Kind.Short; + } else if (bits <= 32) { + return Kind.Int; + } else { + assert bits <= 64; + return Kind.Long; + } + } + + public PlatformKind getFloatingKind(int bits) { + switch (bits) { + case 32: + return Kind.Float; + case 64: + return Kind.Double; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + public PlatformKind getObjectKind() { + return Kind.Object; + } + + public abstract void emitBitCount(Variable result, Value operand); + + public abstract void emitBitScanForward(Variable result, Value operand); + + public abstract void emitBitScanReverse(Variable result, Value operand); + + public abstract void emitByteSwap(Variable result, Value operand); + + public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); + + public AbstractBlock<?> getCurrentBlock() { + return currentBlock; + } + + void setCurrentBlock(AbstractBlock<?> block) { + currentBlock = block; + } + + public LIRGenerationResult getResult() { + return res; + } + + public Map<Constant, LoadConstant> getConstantLoads() { + return constantLoads; + } + + public void setConstantLoads(Map<Constant, LoadConstant> constantLoads) { + this.constantLoads = constantLoads; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2011, 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.lir.gen; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.compiler.common.spi.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.LIRGenerator.*; + +public interface LIRGeneratorTool extends ArithmeticLIRGenerator { + + CodeGenProviders getProviders(); + + TargetDescription target(); + + MetaAccessProvider getMetaAccess(); + + CodeCacheProvider getCodeCache(); + + ForeignCallsProvider getForeignCalls(); + + AbstractBlock<?> getCurrentBlock(); + + LIRGenerationResult getResult(); + + boolean hasBlockEnd(AbstractBlock<?> block); + + void doBlockStart(AbstractBlock<?> block); + + void doBlockEnd(AbstractBlock<?> block); + + Map<Constant, LoadConstant> getConstantLoads(); + + void setConstantLoads(Map<Constant, LoadConstant> constantLoads); + + Value emitLoad(PlatformKind kind, Value address, LIRFrameState state); + + void emitStore(PlatformKind kind, Value address, Value input, LIRFrameState state); + + Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue); + + /** + * Emit an atomic read-and-add instruction. + * + * @param address address of the value to be read and written + * @param delta the value to be added + */ + default Value emitAtomicReadAndAdd(Value address, Value delta) { + throw GraalInternalError.unimplemented(); + } + + /** + * Emit an atomic read-and-write instruction. + * + * @param address address of the value to be read and written + * @param newValue the new value to be written + */ + default Value emitAtomicReadAndWrite(Value address, Value newValue) { + throw GraalInternalError.unimplemented(); + } + + void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state); + + Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args); + + /** + * Checks whether the supplied constant can be used without loading it into a register for most + * operations, i.e., for commonly used arithmetic, logical, and comparison operations. + * + * @param c The constant to check. + * @return True if the constant can be used directly, false if the constant needs to be in a + * register. + */ + boolean canInlineConstant(Constant c); + + boolean canStoreConstant(Constant c, boolean isCompressed); + + RegisterAttributes attributes(Register register); + + Variable newVariable(PlatformKind kind); + + Variable emitMove(Value input); + + void emitMove(AllocatableValue dst, Value src); + + /** + * Emits an op that loads the address of some raw data. + * + * @param dst the variable into which the address is loaded + * @param data the data to be installed with the generated code + */ + void emitData(AllocatableValue dst, byte[] data); + + Value emitAddress(Value base, long displacement, Value index, int scale); + + Value emitAddress(StackSlot slot); + + void emitMembar(int barriers); + + void emitUnwind(Value operand); + + /** + * Called just before register allocation is performed on the LIR owned by this generator. + * Overriding implementations of this method must call the overridden method. + */ + void beforeRegisterAllocation(); + + void emitIncomingValues(Value[] params); + + /** + * Emits a return instruction. Implementations need to insert a move if the input is not in the + * correct location. + */ + void emitReturn(Value input); + + AllocatableValue asAllocatable(Value value); + + Variable load(Value value); + + Value loadNonConst(Value value); + + /** + * Returns true if the redundant move elimination optimization should be done after register + * allocation. + */ + boolean canEliminateRedundantMoves(); + + /** + * Determines if only oop maps are required for the code generated from the LIR. + */ + boolean needOnlyOopMaps(); + + /** + * Gets the ABI specific operand used to return a value of a given kind from a method. + * + * @param kind the kind of value being returned + * @return the operand representing the ABI defined location used return a value of kind + * {@code kind} + */ + AllocatableValue resultOperandFor(Kind kind); + + void append(LIRInstruction op); + + void emitJump(LabelRef label); + + void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, + double trueDestinationProbability); + + void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability); + + void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability); + + Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); + + Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue); + + void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value); + + void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget); + + CallingConvention getCallingConvention(); + + void emitBitCount(Variable result, Value operand); + + void emitBitScanForward(Variable result, Value operand); + + void emitBitScanReverse(Variable result, Value operand); + + void emitByteSwap(Variable result, Value operand); + + void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); + +}
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; public class BasicInductionVariable extends InductionVariable {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Mon Apr 28 10:31:17 2014 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; public class CountedLoopInfo {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; public class DerivedScaledInductionVariable extends InductionVariable {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Mon Apr 28 10:31:17 2014 +0200 @@ -114,7 +114,7 @@ FrameState exitState = exit.stateAfter(); if (exitState != null) { exitState.applyToVirtual(v -> { - if (v.usages().filter(n -> nodes.isMarked(n) && !(n instanceof VirtualState && exitState.isPartOfThisState((VirtualState) n))).isEmpty()) { + if (v.usages().filter(n -> nodes.isMarked(n) && n != exit).isEmpty()) { nodes.clear(v); } });
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.loop; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.loop; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.graph.Graph.Mark;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.loop.phases; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.debug.*; import com.oracle.graal.loop.*;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.loop.phases; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope;
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/ObjectStampJoinTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/ObjectStampJoinTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -81,7 +81,7 @@ public void testJoin3() { Stamp d = StampFactory.declared(getType(D.class)); Stamp c = StampFactory.declared(getType(C.class)); - Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join(c, d))); + Assert.assertTrue(StampTool.isObjectAlwaysNull(join(c, d))); } @Test @@ -96,9 +96,9 @@ Stamp dExact = StampFactory.exact(getType(D.class)); Stamp c = StampFactory.declared(getType(C.class)); Stamp join = join(c, dExact); - Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join)); - Assert.assertNull(ObjectStamp.typeOrNull(join)); - Assert.assertFalse(ObjectStamp.isExactType(join)); + Assert.assertTrue(StampTool.isObjectAlwaysNull(join)); + Assert.assertNull(StampTool.typeOrNull(join)); + Assert.assertFalse(StampTool.isExactType(join)); } @Test @@ -107,8 +107,8 @@ Stamp alwaysNull = StampFactory.alwaysNull(); Stamp join = join(alwaysNull, dExactNonNull); Assert.assertFalse(join.isLegal()); - Assert.assertFalse(ObjectStamp.isObjectNonNull(join)); - Assert.assertFalse(ObjectStamp.isObjectAlwaysNull(join)); + Assert.assertFalse(StampTool.isObjectNonNull(join)); + Assert.assertFalse(StampTool.isObjectAlwaysNull(join)); } @Test @@ -116,9 +116,9 @@ Stamp aExact = StampFactory.exact(getType(A.class)); Stamp e = StampFactory.declared(getType(E.class)); Stamp join = join(aExact, e); - Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join)); - Assert.assertNull(ObjectStamp.typeOrNull(join)); - Assert.assertFalse(ObjectStamp.isExactType(join)); + Assert.assertTrue(StampTool.isObjectAlwaysNull(join)); + Assert.assertNull(StampTool.typeOrNull(join)); + Assert.assertFalse(StampTool.isExactType(join)); } @Test
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.type.*; /** * This node represents an unconditional explicit request for immediate deoptimization.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,9 +24,9 @@ import java.util.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes; 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.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor}) public class BeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryLogicNode.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * 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 - * 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; - -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; - -public abstract class BinaryLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable { - - @Input private ValueNode x; - @Input private ValueNode y; - - public ValueNode x() { - return x; - } - - public ValueNode y() { - return y; - } - - protected void setX(ValueNode x) { - updateUsages(this.x, x); - this.x = x; - } - - protected void setY(ValueNode y) { - updateUsages(this.y, y); - this.y = y; - } - - public BinaryLogicNode(ValueNode x, ValueNode y) { - assert x != null && y != null && x.getKind() == y.getKind(); - this.x = x; - this.y = y; - } - - @Override - public boolean verify() { - assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp()); - return super.verify(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - } - - @Override - public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) { - return false; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,88 @@ +/* + * 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 + * 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; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable, Canonicalizable { + + @Input private ValueNode x; + @Input private ValueNode y; + + public ValueNode x() { + return x; + } + + public ValueNode y() { + return y; + } + + protected void setX(ValueNode x) { + updateUsages(this.x, x); + this.x = x; + } + + protected void setY(ValueNode y) { + updateUsages(this.y, y); + this.y = y; + } + + public BinaryOpLogicNode(ValueNode x, ValueNode y) { + assert x != null && y != null && x.getKind() == y.getKind(); + this.x = x; + this.y = y; + } + + public abstract TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY); + + @Override + public boolean verify() { + assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp()); + return super.verify(); + } + + @Override + public Node canonical(CanonicalizerTool tool) { + switch (evaluate(tool.getConstantReflection(), x(), y())) { + case FALSE: + return LogicConstantNode.contradiction(graph()); + case TRUE: + return LogicConstantNode.tautology(graph()); + } + return this; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + } + + @Override + public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) { + return false; + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A node that results in a platform dependent breakpoint instruction being emitted. A number of
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Extension}) public abstract class CallTargetNode extends ValueNode implements LIRLowerable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard}) public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable, Lowerable, GuardingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code ConstantNode} represents a {@link Constant constant}.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -63,7 +63,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, this); + gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, gen.state(this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -55,7 +55,7 @@ } public void generate(NodeLIRBuilderTool generator) { - generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), this); + generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), generator.state(this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Mon Apr 28 10:31:17 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 @@ -44,4 +44,9 @@ public FixedWithNextNode(Stamp stamp) { super(stamp); } + + @Override + public FixedWithNextNode asNode() { + return this; + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Mon Apr 28 10:31:17 2014 +0200 @@ -51,41 +51,6 @@ private boolean duringCall; - /** - * This BCI should be used for frame states that are built for code with no meaningful BCI. - */ - public static final int UNKNOWN_BCI = -5; - - /** - * The BCI for the exception unwind block, i.e., the block containing the {@link UnwindNode}. - * This block and node is synthetic and has no representation in bytecode. - */ - public static final int UNWIND_BCI = -1; - - /** - * When a node whose frame state has this BCI value is inlined, its frame state will be replaced - * with the frame state before the inlined invoke node. - */ - public static final int BEFORE_BCI = -2; - - /** - * When a node whose frame state has this BCI value is inlined, its frame state will be replaced - * with the frame state {@linkplain Invoke#stateAfter() after} the inlined invoke node. - */ - public static final int AFTER_BCI = -3; - - /** - * When a node whose frame state has this BCI value is inlined, its frame state will be replaced - * with the frame state at the exception edge of the inlined invoke node. - */ - public static final int AFTER_EXCEPTION_BCI = -4; - - /** - * This BCI should be used for frame states that cannot be the target of a deoptimization, like - * snippet frame states. - */ - public static final int INVALID_FRAMESTATE_BCI = -6; - @Input(InputType.State) private FrameState outerFrameState; /** @@ -130,8 +95,8 @@ this.virtualObjectMappings = new NodeInputList<>(this, virtualObjectMappings); this.rethrowException = rethrowException; this.duringCall = duringCall; - assert !rethrowException || stackSize == 1 : "must have exception on top of the stack"; - assert values.size() - localsSize - stackSize == monitorIds.size(); + assert !this.rethrowException || this.stackSize == 1 : "must have exception on top of the stack"; + assert this.locksSize() == this.monitorIds.size(); } /** @@ -141,7 +106,8 @@ */ public FrameState(int bci) { this(null, bci, Collections.<ValueNode> emptyList(), 0, 0, false, false, Collections.<MonitorIdNode> emptyList(), Collections.<EscapeObjectState> emptyList()); - assert bci == BEFORE_BCI || bci == AFTER_BCI || bci == AFTER_EXCEPTION_BCI || bci == UNKNOWN_BCI || bci == INVALID_FRAMESTATE_BCI; + assert bci == BytecodeFrame.BEFORE_BCI || bci == BytecodeFrame.AFTER_BCI || bci == BytecodeFrame.AFTER_EXCEPTION_BCI || bci == BytecodeFrame.UNKNOWN_BCI || + bci == BytecodeFrame.INVALID_FRAMESTATE_BCI; } public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List<ValueNode> stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, boolean duringCall) { @@ -254,6 +220,19 @@ * correctly in slot encoding: a long or double will be followed by a null slot. */ public FrameState duplicateModified(int newBci, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) { + return duplicateModified(newBci, method, newRethrowException, popKind, pushedValues); + } + + /** + * Creates a copy of this frame state with one stack element of type popKind popped from the + * stack and the values in pushedValues pushed on the stack. The pushedValues will be formatted + * correctly in slot encoding: a long or double will be followed by a null slot. + */ + public FrameState duplicateModified(Kind popKind, ValueNode... pushedValues) { + return duplicateModified(bci, method, rethrowException, popKind, pushedValues); + } + + private FrameState duplicateModified(int newBci, ResolvedJavaMethod newMethod, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) { ArrayList<ValueNode> copy = new ArrayList<>(values.subList(0, localsSize + stackSize)); if (popKind != Kind.Void) { if (stackAt(stackSize() - 1) == null) { @@ -272,7 +251,7 @@ int newStackSize = copy.size() - localsSize; copy.addAll(values.subList(localsSize + stackSize, values.size())); - FrameState other = graph().add(new FrameState(method, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings)); + FrameState other = graph().add(new FrameState(newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings)); other.setOuterFrameState(outerFrameState()); return other; } @@ -401,13 +380,26 @@ properties.put("sourceLine", ste.getLineNumber()); } } + if (bci == BytecodeFrame.AFTER_BCI) { + properties.put("bci", "AFTER_BCI"); + } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { + properties.put("bci", "AFTER_EXCEPTION_BCI"); + } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { + properties.put("bci", "INVALID_FRAMESTATE_BCI"); + } else if (bci == BytecodeFrame.BEFORE_BCI) { + properties.put("bci", "BEFORE_BCI"); + } else if (bci == BytecodeFrame.UNKNOWN_BCI) { + properties.put("bci", "UNKNOWN_BCI"); + } else if (bci == BytecodeFrame.UNWIND_BCI) { + properties.put("bci", "UNWIND_BCI"); + } properties.put("locksSize", values.size() - stackSize - localsSize); return properties; } @Override public boolean verify() { - assertTrue(values.size() - localsSize - stackSize == monitorIds.size(), "mismatch in number of locks"); + assertTrue(locksSize() == monitorIds.size(), "mismatch in number of locks"); for (ValueNode value : values) { assertTrue(value == null || !value.isDeleted(), "frame state must not contain deleted nodes"); assertTrue(value == null || value instanceof VirtualObjectNode || (value.getKind() != Kind.Void), "unexpected value: %s", value);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes; 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.extended.*; -import com.oracle.graal.nodes.type.*; /** * A guard is a node that deoptimizes based on a conditional expression. Guards are not attached to @@ -107,7 +107,8 @@ } else if (condition() instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition(); if (c.getValue() != negated) { - return graph().start(); + this.replaceAtUsages(null); + return null; } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(nameTemplate = "GuardPhi({i#values})", allowedUsageTypes = {InputType.Guard}) public class GuardPhiNode extends PhiNode implements GuardingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,13 +22,13 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Guard}) -public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy { +public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy, LIRLowerable { @Input(InputType.Guard) private GuardingNode value; @@ -38,6 +38,10 @@ } @Override + public void generate(NodeLIRBuilderTool generator) { + } + + @Override public ValueNode value() { return value.asNode(); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A node that changes the type of its input, usually narrowing it. For example, a GuardedValueNode @@ -78,7 +77,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (getGuard() == graph().start() || getGuard() == null) { + if (getGuard() == null) { if (stamp().equals(object().stamp())) { return object(); } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -51,6 +51,18 @@ return condition; } + public boolean isNegated() { + return negated; + } + + public DeoptimizationReason getReason() { + return reason; + } + + public DeoptimizationAction getAction() { + return action; + } + /** * Constructor for {@link #guardingNonNull(Object)} node intrinsic. */ @@ -88,7 +100,7 @@ @Override public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object); - if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) { + if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) { tool.replaceWithVirtual(state.getVirtualObject()); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -37,7 +37,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; /** @@ -158,6 +157,41 @@ this.safeDelete(); return; } + if (trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty()) { + // push similar nodes upwards through the if, thereby deduplicating them + do { + BeginNode trueSucc = trueSuccessor(); + BeginNode falseSucc = falseSuccessor(); + if (trueSucc.getClass() == BeginNode.class && falseSucc.getClass() == BeginNode.class && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) { + FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next(); + FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next(); + NodeClass nodeClass = trueNext.getNodeClass(); + if (trueNext.getClass() == falseNext.getClass()) { + if (nodeClass.inputsEqual(trueNext, falseNext) && nodeClass.valueEqual(trueNext, falseNext)) { + falseNext.replaceAtUsages(trueNext); + graph().removeFixed(falseNext); + FixedNode next = trueNext.next(); + trueNext.setNext(null); + trueNext.replaceAtPredecessor(next); + graph().addBeforeFixed(this, trueNext); + for (Node usage : trueNext.usages().snapshot()) { + if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) { + Node newNode = graph().findDuplicate(usage); + if (newNode != null) { + usage.replaceAtUsages(newNode); + usage.safeDelete(); + } + } + if (usage.isAlive()) { + tool.addToWorkList(usage); + } + } + continue; + } + } + } + } while (false); + } if (condition() instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -43,6 +43,6 @@ @Override public String targetName() { - return "Indirect#" + ((JavaMethod) target()).getName(); + return MetaUtil.format("Indirect#%h.%n", target()); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Nodes of this type are inserted into the graph to denote points of interest to debugging.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Mon Apr 28 10:31:17 2014 +0200 @@ -78,4 +78,11 @@ default ResolvedJavaType getContextType() { return getContextMethod().getDeclaringClass(); } + + @Override + default void computeStateDuring(FrameState stateAfter) { + FrameState newStateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), asNode().getKind()); + newStateDuring.setDuringCall(true); + setStateDuring(newStateDuring); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -185,13 +185,6 @@ } @Override - public void computeStateDuring(FrameState stateAfter) { - FrameState newStateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), getKind()); - newStateDuring.setDuringCall(true); - setStateDuring(newStateDuring); - } - - @Override public GuardingNode getGuard() { return guard; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -37,7 +37,7 @@ private static final double EXCEPTION_PROBA = 1e-5; @Successor private BeginNode next; - @Successor private DispatchBeginNode exceptionEdge; + @Successor private BeginNode exceptionEdge; @Input(InputType.Extension) private CallTargetNode callTarget; @Input(InputType.State) private FrameState stateDuring; @Input(InputType.State) private FrameState stateAfter; @@ -47,7 +47,7 @@ private boolean useForInlining; private double exceptionProbability; - public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci) { + public InvokeWithExceptionNode(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) { super(callTarget.returnStamp()); this.exceptionEdge = exceptionEdge; this.bci = bci; @@ -57,11 +57,11 @@ this.exceptionProbability = EXCEPTION_PROBA; } - public DispatchBeginNode exceptionEdge() { + public BeginNode exceptionEdge() { return exceptionEdge; } - public void setExceptionEdge(DispatchBeginNode x) { + public void setExceptionEdge(BeginNode x) { updatePredecessor(exceptionEdge, x); exceptionEdge = x; } @@ -223,13 +223,6 @@ } @Override - public void computeStateDuring(FrameState tempStateAfter) { - FrameState newStateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), getKind()); - newStateDuring.setDuringCall(true); - setStateDuring(newStateDuring); - } - - @Override public GuardingNode getGuard() { return guard; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,9 +24,9 @@ import static com.oracle.graal.graph.InputType.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {Condition}) public abstract class LogicNode extends FloatingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,10 +25,10 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Extension}) public abstract class MemoryMapNode extends FloatingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; /** * The {@code PhiNode} represents the merging of dataflow in the memory graph.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class MemoryProxyNode extends ProxyNode implements MemoryProxy, LIRLowerable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -132,6 +132,10 @@ return super.anchored().filter(n -> !isPhiAtMerge(n)); } + /** + * This simplify method can deal with a null value for tool, so that it can be used outside of + * canonicalization. + */ @Override public void simplify(SimplifierTool tool) { FixedNode next = next(); @@ -151,7 +155,7 @@ return; } for (PhiNode phi : phis()) { - if (phi.usages().filter(isNotA(FrameState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) { + if (phi.usages().filter(isNotA(VirtualState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) { return; } } @@ -180,7 +184,9 @@ this.removeEnd(end); end.replaceAtPredecessor(newEnd); end.safeDelete(); - tool.addToWorkList(newEnd.predecessor()); // ? + if (tool != null) { + tool.addToWorkList(newEnd.predecessor()); + } } graph().reduceTrivialMerge(this); } else if (next instanceof ReturnNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -59,7 +59,7 @@ } public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { - this(object, StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp()))); + this(object, StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp()))); } @Override @@ -80,7 +80,7 @@ @Override public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object); - if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) { + if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) { tool.replaceWithVirtual(state.getVirtualObject()); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Marks a position in the graph where a safepoint should be emitted.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,6 +29,8 @@ */ public interface StateSplit extends NodeWithState { + FixedNode asNode(); + /** * Gets the {@link FrameState} corresponding to the state of the JVM after execution of this * node.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -75,7 +75,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (ObjectStamp.isExactType(object)) { + if (StampTool.isExactType(object)) { // The profile is useless - we know the type! return object; } else if (object instanceof TypeProfileProxyNode) { @@ -96,8 +96,8 @@ Debug.log("Improved profile via other profile."); return TypeProfileProxyNode.create(object, newProfile); } - } else if (ObjectStamp.typeOrNull(object) != null) { - ResolvedJavaType type = ObjectStamp.typeOrNull(object); + } else if (StampTool.typeOrNull(object) != null) { + ResolvedJavaType type = StampTool.typeOrNull(object); ResolvedJavaType uniqueConcrete = type.findUniqueConcreteSubtype(); if (uniqueConcrete != null) { // Profile is useless => remove. @@ -109,7 +109,7 @@ return this; } lastCheckedType = type; - JavaTypeProfile newProfile = this.profile.restrict(type, ObjectStamp.isObjectNonNull(object)); + JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(object)); if (newProfile != this.profile) { Debug.log("Improved profile via static type information."); if (newProfile.getTypes().length == 0) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,57 @@ +/* + * 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 + * 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; + +import com.oracle.graal.api.meta.ProfilingInfo.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable { + + @Input private ValueNode object; + + public ValueNode object() { + return object; + } + + protected void setX(ValueNode object) { + updateUsages(this.object, object); + this.object = object; + } + + public UnaryOpLogicNode(ValueNode object) { + assert object != null; + this.object = object; + } + + public abstract TriState evaluate(ValueNode forObject); + + @Override + public void generate(NodeLIRBuilderTool gen) { + } + + @Override + public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) { + return false; + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Unwinds the current frame to an exception handler in the caller frame.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; -import com.oracle.graal.nodes.type.*; /** * This class represents a value within the graph, including local variables, phis, and all other
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Mon Apr 28 10:31:17 2014 +0200 @@ -45,6 +45,10 @@ public abstract void applyToNonVirtual(NodeClosure<? super ValueNode> closure); + /** + * Performs a <b>pre-order</b> iteration over all elements reachable from this state that are a + * subclass of {@link VirtualState}. + */ public abstract void applyToVirtual(VirtualClosure closure); public abstract boolean isPartOfThisState(VirtualState state);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; /** * The {@code BinaryNode} class is the base of arithmetic and logic operations with two inputs.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.*; @@ -35,7 +36,7 @@ * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed * into variants that do not materialize the value (CompareIf, CompareGuard...) */ -public abstract class CompareNode extends BinaryLogicNode implements Canonicalizable { +public abstract class CompareNode extends BinaryOpLogicNode { /** * Constructs a new Compare instruction. @@ -90,9 +91,18 @@ } @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (x().isConstant() && y().isConstant()) { + return TriState.get(condition().foldCondition(x().asConstant(), y().asConstant(), constantReflection, unorderedIsTrue())); + } + return TriState.UNKNOWN; + } + + @Override public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant() && tool.getMetaAccess() != null) { - return LogicConstantNode.forBoolean(condition().foldCondition(x().asConstant(), y().asConstant(), tool.getConstantReflection(), unorderedIsTrue()), graph()); + Node result = super.canonical(tool); + if (result != this) { + return result; } if (x().isConstant()) { if (y() instanceof ConditionalNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,12 +26,12 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; +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.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public abstract class FloatArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,13 +24,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A {@code FloatConvert} converts between integers and floating point numbers according to Java @@ -38,46 +39,6 @@ */ public class FloatConvertNode extends ConvertNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable { - public enum FloatConvert { - F2I, - D2I, - F2L, - D2L, - I2F, - L2F, - D2F, - I2D, - L2D, - F2D; - - public FloatConvert reverse() { - switch (this) { - case D2F: - return F2D; - case D2I: - return I2D; - case D2L: - return L2D; - case F2D: - return D2F; - case F2I: - return I2F; - case F2L: - return L2F; - case I2D: - return D2I; - case I2F: - return F2I; - case L2D: - return D2L; - case L2F: - return F2L; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - } - private final FloatConvert op; public FloatConvertNode(FloatConvert op, ValueNode input) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,17 +22,20 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") public final class FloatEqualsNode extends CompareNode { /** * Constructs a new floating point equality comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -51,4 +54,18 @@ public boolean unorderedIsTrue() { return false; } + + @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (forX.stamp() instanceof FloatStamp && forY.stamp() instanceof FloatStamp) { + FloatStamp xStamp = (FloatStamp) forX.stamp(); + FloatStamp yStamp = (FloatStamp) forY.stamp(); + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) { + return TriState.TRUE; + } else if (xStamp.alwaysDistinct(yStamp)) { + return TriState.FALSE; + } + } + return super.evaluate(constantReflection, forX, forY); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,11 +22,13 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.calc.*; +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.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "<") public final class FloatLessThanNode extends CompareNode { @@ -35,7 +37,7 @@ /** * Constructs a new floating point comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction * @param unorderedIsTrue whether a comparison that is undecided (involving NaNs, etc.) leads to @@ -59,10 +61,10 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y() && !unorderedIsTrue()) { - return LogicConstantNode.contradiction(graph()); + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && !unorderedIsTrue()) { + return TriState.FALSE; } - return super.canonical(tool); + return super.evaluate(constantReflection, forX, forY); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Mon Apr 28 10:31:17 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,4 +31,9 @@ public FloatingNode(Stamp stamp) { super(stamp); } + + @Override + public FloatingNode asNode() { + return this; + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,18 +23,20 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; +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.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "|<|") public final class IntegerBelowThanNode extends CompareNode { /** * Constructs a new unsigned integer comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -55,28 +57,33 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return LogicConstantNode.contradiction(graph()); - } else { - if (x().isConstant() && x().asConstant().asLong() == 0) { - // 0 |<| y is the same as 0 != y - return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y()))); - } - - if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) { - IntegerStamp xStamp = (IntegerStamp) x().stamp(); - IntegerStamp yStamp = (IntegerStamp) y().stamp(); - if (yStamp.isPositive()) { - if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) { - return LogicConstantNode.tautology(graph()); - } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { - return LogicConstantNode.contradiction(graph()); - } + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return TriState.FALSE; + } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { + IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + if (yStamp.isPositive()) { + if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) { + return TriState.TRUE; + } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { + return TriState.FALSE; } } } + return super.evaluate(constantReflection, forX, forY); + } - return super.canonical(tool); + @Override + public Node canonical(CanonicalizerTool tool) { + Node result = super.canonical(tool); + if (result != this) { + return result; + } + if (x().isConstant() && x().asConstant().asLong() == 0) { + // 0 |<| y is the same as 0 != y + return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y()))); + } + return this; } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * An {@code IntegerConvert} converts an integer to an integer of different width.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -108,7 +108,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), this)); + gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), gen.state(this))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,12 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; +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.type.*; import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") @@ -35,7 +36,7 @@ /** * Constructs a new integer equality comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -71,24 +72,28 @@ } @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return TriState.TRUE; + } else if (forX.stamp().alwaysDistinct(forY.stamp())) { + return TriState.FALSE; + } + return super.evaluate(constantReflection, forX, forY); + } + + @Override public Node canonical(CanonicalizerTool tool) { - if (GraphUtil.unproxify(x()) == GraphUtil.unproxify(y())) { - return LogicConstantNode.tautology(graph()); - } else if (x().stamp().alwaysDistinct(y().stamp())) { - return LogicConstantNode.contradiction(graph()); - } - - ValueNode result = canonicalizeSymmetric(x(), y()); - if (result != null) { + Node result = super.canonical(tool); + if (result != this) { return result; } - result = canonicalizeSymmetric(y(), x()); - if (result != null) { + result = canonicalizeSymmetric(x(), y()); + if (result != this) { return result; } - return super.canonical(tool); + return canonicalizeSymmetric(y(), x()); } private ValueNode canonicalizeSymmetric(ValueNode x, ValueNode y) { @@ -133,6 +138,6 @@ } } } - return null; + return this; } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,18 +23,20 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; +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.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "<") public final class IntegerLessThanNode extends CompareNode { /** * Constructs a new integer comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -71,22 +73,32 @@ } @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return TriState.FALSE; + } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { + IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + if (xStamp.upperBound() < yStamp.lowerBound()) { + return TriState.TRUE; + } else if (xStamp.lowerBound() >= yStamp.upperBound()) { + return TriState.FALSE; + } + } + return super.evaluate(constantReflection, forX, forY); + } + + @Override public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return LogicConstantNode.contradiction(graph()); + Node result = super.canonical(tool); + if (result != this) { + return result; } if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) { - IntegerStamp xStamp = (IntegerStamp) x().stamp(); - IntegerStamp yStamp = (IntegerStamp) y().stamp(); - if (xStamp.upperBound() < yStamp.lowerBound()) { - return LogicConstantNode.tautology(graph()); - } else if (xStamp.lowerBound() >= yStamp.upperBound()) { - return LogicConstantNode.contradiction(graph()); - } - if (IntegerStamp.sameSign(xStamp, yStamp)) { + if (IntegerStamp.sameSign((IntegerStamp) x().stamp(), (IntegerStamp) y().stamp())) { return graph().unique(new IntegerBelowThanNode(x(), y())); } } - return super.canonical(tool); + return this; } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,10 +27,10 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "*") public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "%") public class IntegerRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { @@ -63,7 +62,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), this)); + gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), gen.state(this))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,17 +22,17 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; /** * This node will perform a "test" operation on its arguments. Its result is equivalent to the * expression "(x & y) == 0", meaning that it will return true if (and only if) no bit is set in * both x and y. */ -public class IntegerTestNode extends BinaryLogicNode implements Canonicalizable { +public class IntegerTestNode extends BinaryOpLogicNode { /** * Constructs a new Test instruction. @@ -45,19 +45,19 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - return LogicConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph()); + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + return TriState.get((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0); } if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) { - IntegerStamp xStamp = (IntegerStamp) x().stamp(); - IntegerStamp yStamp = (IntegerStamp) y().stamp(); + IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(); if ((xStamp.upMask() & yStamp.upMask()) == 0) { - return LogicConstantNode.tautology(graph()); + return TriState.TRUE; } else if ((xStamp.downMask() & yStamp.downMask()) != 0) { - return LogicConstantNode.contradiction(graph()); + return TriState.FALSE; } } - return this; + return TriState.UNKNOWN; } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -32,21 +34,15 @@ /** * An IsNullNode will be true if the supplied value is null, and false if it is non-null. */ -public final class IsNullNode extends LogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable { - - @Input private ValueNode object; - - public ValueNode object() { - return object; - } +public final class IsNullNode extends UnaryOpLogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable { /** * Constructs a new IsNullNode instruction. - * + * * @param object the instruction producing the object to check against null */ public IsNullNode(ValueNode object) { - this.object = object; + super(object); } @Override @@ -63,20 +59,31 @@ @Override public Node canonical(CanonicalizerTool tool) { - Constant constant = object().asConstant(); - if (constant != null) { - assert constant.getKind() == Kind.Object; - return LogicConstantNode.forBoolean(constant.isNull(), graph()); - } - if (ObjectStamp.isObjectNonNull(object.stamp())) { - return LogicConstantNode.contradiction(graph()); + switch (evaluate(object())) { + case FALSE: + return LogicConstantNode.contradiction(graph()); + case TRUE: + return LogicConstantNode.tautology(graph()); } return this; } @Override + public TriState evaluate(ValueNode forObject) { + Constant constant = forObject.asConstant(); + if (constant != null) { + assert constant.getKind() == Kind.Object; + return TriState.get(constant.isNull()); + } + if (StampTool.isObjectNonNull(forObject.stamp())) { + return TriState.FALSE; + } + return TriState.UNKNOWN; + } + + @Override public void virtualize(VirtualizerTool tool) { - if (tool.getObjectState(object) != null) { + if (tool.getObjectState(object()) != null) { tool.replaceWithValue(LogicConstantNode.contradiction(graph())); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,10 @@ package com.oracle.graal.nodes.calc; 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.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Returns -1, 0, or 1 if either x < y, x == y, or x > y. If the comparison is undecided (one
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,10 @@ package com.oracle.graal.nodes.calc; 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.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,19 +23,21 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; 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.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") public final class ObjectEqualsNode extends CompareNode implements Virtualizable { /** * Constructs a new object equality comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -56,21 +58,28 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return LogicConstantNode.tautology(graph()); + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return TriState.TRUE; + } else if (forX.stamp().alwaysDistinct(forY.stamp())) { + return TriState.FALSE; + } else { + return super.evaluate(constantReflection, forX, forY); } + } - if (ObjectStamp.isObjectAlwaysNull(x())) { + @Override + public Node canonical(CanonicalizerTool tool) { + Node result = super.canonical(tool); + if (result != this) { + return result; + } + if (StampTool.isObjectAlwaysNull(x())) { return graph().unique(new IsNullNode(y())); - } else if (ObjectStamp.isObjectAlwaysNull(y())) { + } else if (StampTool.isObjectAlwaysNull(y())) { return graph().unique(new IsNullNode(x())); } - if (x().stamp().alwaysDistinct(y().stamp())) { - return LogicConstantNode.contradiction(graph()); - } - - return super.canonical(tool); + return this; } private void virtualizeNonVirtualComparison(State state, ValueNode other, VirtualizerTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,10 +27,10 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code ReinterpretNode} class represents a reinterpreting conversion that changes the stamp
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,9 +26,9 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = ">>") public final class RightShiftNode extends ShiftNode implements Canonicalizable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,10 @@ package com.oracle.graal.nodes.calc; 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.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "|/|") public class UnsignedDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { @@ -73,7 +72,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), this)); + gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), gen.state(this))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "|%|") public class UnsignedRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { @@ -72,7 +71,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), this)); + gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), gen.state(this))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,8 +25,8 @@ import java.util.*; import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; public final class Block extends AbstractBlockBase<Block> { @@ -67,7 +67,8 @@ } public boolean isExceptionEntry() { - return getBeginNode() instanceof ExceptionObjectNode; + Node predecessor = getBeginNode().predecessor(); + return predecessor != null && predecessor instanceof InvokeWithExceptionNode && getBeginNode() == ((InvokeWithExceptionNode) predecessor).exceptionEdge(); } public Block getFirstPredecessor() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,15 +22,15 @@ */ package com.oracle.graal.nodes.debug; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * This node can be used to add a counter to the code that will estimate the dynamic number of calls * by adding an increment to the compiled code. This should of course only be used for * debugging/testing purposes. - * + * * A unique counter will be created for each unique name passed to the constructor. Depending on the * value of withContext, the name of the root method is added to the counter's name. */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,12 +23,13 @@ package com.oracle.graal.nodes.extended; 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.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Location node that is the sum of two other location nodes. Can represent locations in the form of @@ -37,8 +38,8 @@ @NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}") public final class AddLocationNode extends LocationNode implements Canonicalizable { - @Input private ValueNode x; - @Input private ValueNode y; + @Input(InputType.Association) private ValueNode x; + @Input(InputType.Association) private ValueNode y; protected LocationNode getX() { return (LocationNode) x;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,6 +25,7 @@ import java.util.*; 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.*; @@ -77,7 +78,7 @@ @Override public void virtualize(VirtualizerTool tool) { ValueNode v = tool.getReplacedValue(getValue()); - ResolvedJavaType type = ObjectStamp.typeOrNull(stamp()); + ResolvedJavaType type = StampTool.typeOrNull(stamp()); VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind); assert newVirtual.getFields().length == 1;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A node that represents an exception thrown implicitly by a Java bytecode. It can be lowered to
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,9 +23,10 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Location node that has a constant displacement. Can represent addresses of the form [base + disp]
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -63,7 +63,7 @@ public void generate(NodeLIRBuilderTool gen) { Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp()); - gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this)); + gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, null)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Node for a {@linkplain ForeignCallDescriptor foreign} call. @@ -95,7 +94,7 @@ public void generate(NodeLIRBuilderTool gen) { ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor); Value[] operands = operands(gen); - Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, operands); + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), operands); if (result != null) { gen.setResult(this, result); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GuardedNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GuardedNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; /** * A node that may be guarded by a {@linkplain GuardingNode guarding node}. */ -public interface GuardedNode { +public interface GuardedNode extends NodeInterface { GuardingNode getGuard();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,12 @@ package com.oracle.graal.nodes.extended; 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.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Location node that has a displacement and a scaled index. Can represent locations in the form of
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,10 +25,10 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Read a raw memory location according to Java field or array read semantics. It will perform read
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Loads an object's {@linkplain Representation#ObjectHub hub}. The object is not null-checked by
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,12 +22,10 @@ */ package com.oracle.graal.nodes.extended; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; 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. @@ -45,8 +43,8 @@ super(kind == Kind.Object ? StampFactory.objectNonNull() : StampFactory.forKind(kind)); this.hub = hub; this.method = method; - assert !Modifier.isAbstract(method.getModifiers()) : "Cannot load abstract method from a hub"; - assert !Modifier.isStatic(method.getModifiers()) : "Cannot load a static method from a hub"; + assert !method.isAbstract() : "Cannot load abstract method from a hub"; + assert !method.isStatic() : "Cannot load a static method from a hub"; assert method.isInVirtualMethodTable(); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.nodes.extended; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.lang.reflect.*; @@ -31,10 +31,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Creates a memory barrier.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Mon Apr 28 10:31:17 2014 +0200 @@ -31,7 +31,7 @@ * represented by location identities (i.e. change a value at one or more locations that belong to * these location identities). */ -public interface MemoryCheckpoint extends MemoryNode { +public interface MemoryCheckpoint extends MemoryNode, NodeInterface { FixedNode asNode(); @@ -40,7 +40,7 @@ /** * This method is used to determine which memory location is killed by this node. Returning * the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory locations. - * + * * @return the identity of the location killed by this node. */ LocationIdentity getLocationIdentity(); @@ -53,7 +53,7 @@ * This method is used to determine which set of memory locations is killed by this node. * Returning the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory * locations. - * + * * @return the identities of all locations killed by this node. */ LocationIdentity[] getLocationIdentities();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; /** * This interface marks nodes that are part of the memory graph. */ -public interface MemoryNode { +public interface MemoryNode extends NodeInterface { ValueNode asNode();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -57,7 +57,7 @@ public void generate(NodeLIRBuilderTool gen) { Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp()); - gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this)); + gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, gen.state(this))); } @Override @@ -144,7 +144,7 @@ } ObjectStamp valueStamp = (ObjectStamp) parent.object().stamp(); - ResolvedJavaType valueType = ObjectStamp.typeOrNull(valueStamp); + ResolvedJavaType valueType = StampTool.typeOrNull(valueStamp); if (valueType != null && field.getDeclaringClass().isAssignableFrom(valueType)) { if (piStamp.nonNull() == valueStamp.nonNull() && piStamp.alwaysNull() == valueStamp.alwaysNull()) { replaceFirstInput(parent, parent.object());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public final class StoreHubNode extends FixedWithNextNode implements Lowerable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,9 +26,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; /** * The {@code SwitchNode} class is the base of both lookup and table switches.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,12 +23,12 @@ package com.oracle.graal.nodes.extended; 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 UnboxNode extends FloatingNode implements Virtualizable, Lowerable, Canonicalizable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -67,7 +67,7 @@ long constantOffset = offset().asConstant().asLong(); // Try to canonicalize to a field access. - ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object()); + ResolvedJavaType receiverType = StampTool.typeOrNull(object()); if (receiverType != null) { ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(constantOffset); // No need for checking that the receiver is non-null. The field access includes @@ -79,15 +79,15 @@ } } } - // Temporarily disable this as it appears to break truffle. - // ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object()); - // if (receiverType != null && receiverType.isArray()) { - // LocationIdentity identity = - // NamedLocationIdentity.getArrayLocation(receiverType.getComponentType().getKind()); - // // Try to build a better location node - // ValueNode location = offset(); - // return cloneAsArrayAccess(location, identity); - // } + if (this.getLocationIdentity() == LocationIdentity.ANY_LOCATION) { + ResolvedJavaType receiverType = StampTool.typeOrNull(object()); + // Try to build a better location identity. + if (receiverType != null && receiverType.isArray()) { + LocationIdentity identity = NamedLocationIdentity.getArrayLocation(receiverType.getComponentType().getKind()); + assert !graph().isAfterFloatingReadPhase() : "cannot add more precise memory location after floating read phase"; + return cloneAsArrayAccess(offset(), identity); + } + } return this; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -51,7 +51,7 @@ } public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { - this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind())); + this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind())); } @Override @@ -80,7 +80,7 @@ @Override public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object); - if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) { + if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) { tool.replaceWithVirtual(state.getVirtualObject()); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,14 +22,14 @@ */ package com.oracle.graal.nodes.extended; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Load of a value from a location specified as an offset relative to an object. No null check is
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,14 +22,14 @@ */ package com.oracle.graal.nodes.extended; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Store of a value at a location specified as an offset relative to an object. No null check is
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Mon Apr 28 10:31:17 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 @@ -22,19 +22,19 @@ */ package com.oracle.graal.nodes.extended; +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.*; import com.oracle.graal.nodes.util.*; /** * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph. */ @NodeInfo(allowedUsageTypes = {InputType.Anchor, InputType.Guard}) -public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, GuardingNode { +public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode { @Input(InputType.Guard) private ValueNode anchored;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -54,7 +54,7 @@ v = gen.operand(value()); } PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(value().stamp()); - gen.getLIRGeneratorTool().emitStore(writeKind, address, v, this); + gen.getLIRGeneratorTool().emitStore(writeKind, address, v, gen.state(this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.java; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; @@ -70,7 +68,7 @@ * @return {@code true} if this field access is to a static field */ public boolean isStatic() { - return Modifier.isStatic(field.getModifiers()); + return field.isStatic(); } /** @@ -79,7 +77,7 @@ * @return {@code true} if the field is resolved and declared volatile */ public boolean isVolatile() { - return Modifier.isVolatile(field.getModifiers()); + return field.isVolatile(); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; /** * The {@code AccessMonitorNode} is the base class of both monitor acquisition and release.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.nodes.java; 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.*; import com.oracle.graal.nodes.util.*; /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,88 @@ +/* + * 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.nodes.java; + +import static com.oracle.graal.compiler.common.UnsafeAccess.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +import sun.misc.*; + +/** + * Represents an atomic read-and-add operation like {@link Unsafe#getAndAddInt(Object, long, int)}. + */ +@NodeInfo(allowedUsageTypes = {InputType.Memory}) +public class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single { + + @Input private ValueNode object; + @Input private ValueNode offset; + @Input private ValueNode delta; + + private final LocationIdentity locationIdentity; + + public AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) { + super(StampFactory.forKind(delta.getKind())); + this.object = object; + this.offset = offset; + this.delta = delta; + this.locationIdentity = locationIdentity; + } + + public ValueNode object() { + return object; + } + + public ValueNode offset() { + return offset; + } + + public ValueNode delta() { + return delta; + } + + public LocationIdentity getLocationIdentity() { + return locationIdentity; + } + + public void generate(NodeLIRBuilderTool gen) { + LocationNode location = IndexedLocationNode.create(getLocationIdentity(), delta.getKind(), 0, offset, graph(), 1); + Value address = location.generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); + Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(address, gen.operand(delta)); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static int getAndAddInt(Object object, long offset, int delta, @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { + return unsafe.getAndAddInt(object, offset, delta); + } + + @NodeIntrinsic + public static long getAndAddLong(Object object, long offset, long delta, @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { + return unsafe.getAndAddLong(object, offset, delta); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,99 @@ +/* + * 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.nodes.java; + +import static com.oracle.graal.compiler.common.UnsafeAccess.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +import sun.misc.*; + +/** + * Represents an atomic read-and-write operation like {@link Unsafe#getAndSetInt(Object, long, int)} + * . + */ +public class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { + + @Input private ValueNode object; + @Input private ValueNode offset; + @Input private ValueNode newValue; + + private final Kind valueKind; + private final LocationIdentity locationIdentity; + + public AtomicReadAndWriteNode(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { + super(StampFactory.forKind(newValue.getKind())); + this.object = object; + this.offset = offset; + this.newValue = newValue; + this.valueKind = valueKind; + this.locationIdentity = locationIdentity; + } + + public ValueNode object() { + return object; + } + + public ValueNode offset() { + return offset; + } + + public ValueNode newValue() { + return newValue; + } + + public Kind getValueKind() { + return valueKind; + } + + public LocationIdentity getLocationIdentity() { + return locationIdentity; + } + + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } + + @NodeIntrinsic + public static int getAndSetInt(Object object, long offset, int newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, + @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { + return unsafe.getAndSetInt(object, offset, newValue); + } + + @NodeIntrinsic + public static long getAndSetLong(Object object, long offset, long newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, + @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { + return unsafe.getAndSetLong(object, offset, newValue); + } + + @NodeIntrinsic + public static Object getAndSetObject(Object object, long offset, Object newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, + @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { + return unsafe.getAndSetObject(object, offset, newValue); + } + +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -73,7 +73,7 @@ public Node canonical(CanonicalizerTool tool) { assert object() != null : this; - if (ObjectStamp.isObjectAlwaysNull(object())) { + if (StampTool.isObjectAlwaysNull(object())) { return object(); } if (hub.isConstant()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -107,7 +107,7 @@ // This is a check cast that will always fail condition = LogicConstantNode.contradiction(graph()); stamp = StampFactory.declared(type); - } else if (ObjectStamp.isObjectNonNull(object)) { + } else if (StampTool.isObjectNonNull(object)) { condition = graph().addWithoutUnique(new InstanceOfNode(type, object, profile)); } else { if (profile != null && profile.getNullSeen() == TriState.FALSE) { @@ -142,7 +142,7 @@ public Node canonical(CanonicalizerTool tool) { assert object() != null : this; - ResolvedJavaType objectType = ObjectStamp.typeOrNull(object()); + ResolvedJavaType objectType = StampTool.typeOrNull(object()); if (objectType != null && type.isAssignableFrom(objectType)) { // we don't have to check for null types here because they will also pass the // checkcast. @@ -161,7 +161,7 @@ } } - if (ObjectStamp.isObjectAlwaysNull(object())) { + if (StampTool.isObjectAlwaysNull(object())) { return object(); } if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Apr 28 10:31:17 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 @@ -22,14 +22,14 @@ */ package com.oracle.graal.nodes.java; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the @@ -45,6 +45,19 @@ private final Kind valueKind; private final int displacement; + private final LocationIdentity locationIdentity; + + public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) { + super(StampFactory.forKind(Kind.Boolean.getStackKind())); + assert expected.stamp().isCompatible(newValue.stamp()); + this.object = object; + this.offset = offset; + this.expected = expected; + this.newValue = newValue; + this.displacement = displacement; + this.valueKind = valueKind; + this.locationIdentity = locationIdentity; + } public ValueNode object() { return object; @@ -70,20 +83,9 @@ return valueKind; } - public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind) { - super(StampFactory.forKind(Kind.Boolean.getStackKind())); - assert expected.stamp().isCompatible(newValue.stamp()); - this.object = object; - this.offset = offset; - this.expected = expected; - this.newValue = newValue; - this.displacement = displacement; - this.valueKind = valueKind; - } - @Override public LocationIdentity getLocationIdentity() { - return LocationIdentity.ANY_LOCATION; + return locationIdentity; } @Override @@ -94,19 +96,19 @@ // specialized on value type until boxing/unboxing is sorted out in intrinsification @NodeIntrinsic public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, Object expected, Object newValue, - @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) { + @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) { return unsafe.compareAndSwapObject(object, displacement + offset, expected, newValue); } @NodeIntrinsic public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, long expected, long newValue, - @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) { + @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) { return unsafe.compareAndSwapLong(object, displacement + offset, expected, newValue); } @NodeIntrinsic public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, int expected, int newValue, - @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) { + @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) { return unsafe.compareAndSwapInt(object, displacement + offset, expected, newValue); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,10 +26,10 @@ import java.util.*; 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.type.*; /** * The {@code DynamicNewArrayNode} is used for allocation of arrays when the type is not a
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.java; 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.type.*; public class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,21 +22,18 @@ */ package com.oracle.graal.nodes.java; -import java.util.*; - -import com.oracle.graal.api.code.*; 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.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The entry to an exception handler with the exception coming from a call (as opposed to a local * throw instruction or implicit exception). */ +@NodeInfo(allowedUsageTypes = {InputType.Memory}) public class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint.Single { public ExceptionObjectNode(MetaAccessProvider metaAccess) { @@ -49,56 +46,13 @@ } @Override - public void simplify(SimplifierTool tool) { - // - } - - private boolean isLowered() { - return (stamp() == StampFactory.forVoid()); - } - - /** - * The frame state upon entry to an exception handler is such that it is a - * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly - * the exception object (per the JVM spec) to rethrow. This means that the code creating this - * state (i.e. the {@link LoadExceptionObjectNode}) cannot cause a deoptimization as the - * runtime/interpreter would not have a valid location for the exception object to be rethrown. - */ - @Override public void lower(LoweringTool tool) { - if (isLowered()) { - return; - } - LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp())); - loadException.setStateAfter(stateAfter()); - List<GuardedNode> guardedNodes = new ArrayList<>(); - for (Node usage : usages().snapshot()) { - if (usage instanceof GuardedNode) { - // can't replace the guard with LoadExceptionObjectNode as it is not a GuardingNode - // so temporarily change it to remove the GuardedNode from usages - GuardedNode guardedNode = (GuardedNode) usage; - guardedNode.setGuard(graph().add(new BeginNode())); - guardedNodes.add(guardedNode); - } - } - replaceAtUsages(loadException); - for (GuardedNode guardedNode : guardedNodes) { - BeginNode dummyGuard = (BeginNode) guardedNode.getGuard(); - guardedNode.setGuard(this); - graph().removeFixed(dummyGuard); - } - graph().addAfterFixed(this, loadException); - setStateAfter(null); - setStamp(StampFactory.forVoid()); - loadException.lower(tool); + tool.getLowerer().lower(this, tool); } @Override public boolean verify() { - if (isLowered()) { - return true; - } - assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state"); + assertTrue(stateAfter() != null, "an exception handler needs a frame state"); return super.verify(); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -47,8 +47,8 @@ this.mirror = mirror; this.object = object; assert mirror.getKind() == Kind.Object : mirror.getKind(); - assert ObjectStamp.isExactType(mirror); - assert ObjectStamp.typeOrNull(mirror).getName().equals("Ljava/lang/Class;"); + assert StampTool.isExactType(mirror); + assert StampTool.typeOrNull(mirror).getName().equals("Ljava/lang/Class;"); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,32 +23,31 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; 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.*; /** * The {@code InstanceOfNode} represents an instanceof test. */ -public final class InstanceOfNode extends LogicNode implements Canonicalizable, Lowerable, Virtualizable { +public final class InstanceOfNode extends UnaryOpLogicNode implements Canonicalizable, Lowerable, Virtualizable { - @Input private ValueNode object; private final ResolvedJavaType type; private JavaTypeProfile profile; /** * Constructs a new InstanceOfNode. - * + * * @param type the target type of the instanceof check * @param object the object being tested by the instanceof */ public InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { + super(object); this.type = type; - this.object = object; this.profile = profile; assert type != null; } @@ -60,13 +59,39 @@ @Override public Node canonical(CanonicalizerTool tool) { - Stamp stamp = object().stamp(); + switch (evaluate(object())) { + case FALSE: + return LogicConstantNode.contradiction(graph()); + case TRUE: + return LogicConstantNode.tautology(graph()); + case UNKNOWN: + Stamp stamp = object().stamp(); + if (stamp instanceof ObjectStamp) { + ObjectStamp objectStamp = (ObjectStamp) stamp; + ResolvedJavaType stampType = objectStamp.type(); + if (stampType != null && type().isAssignableFrom(stampType)) { + if (!objectStamp.nonNull()) { + // the instanceof matches if the object is non-null, so return true + // depending on the null-ness. + IsNullNode isNull = graph().unique(new IsNullNode(object())); + return graph().unique(new LogicNegationNode(isNull)); + } + } + } + return this; + } + return this; + } + + @Override + public TriState evaluate(ValueNode forObject) { + Stamp stamp = forObject.stamp(); if (!(stamp instanceof ObjectStamp)) { - return this; + return TriState.UNKNOWN; } ObjectStamp objectStamp = (ObjectStamp) stamp; if (objectStamp.alwaysNull()) { - return LogicConstantNode.contradiction(graph()); + return TriState.FALSE; } ResolvedJavaType stampType = objectStamp.type(); @@ -75,34 +100,25 @@ if (subType) { if (objectStamp.nonNull()) { // the instanceOf matches, so return true - return LogicConstantNode.tautology(graph()); - } else { - // the instanceof matches if the object is non-null, so return true depending on - // the null-ness. - IsNullNode isNull = graph().unique(new IsNullNode(object())); - return graph().unique(new LogicNegationNode(isNull)); + return TriState.TRUE; } } else { if (objectStamp.isExactType()) { // since this type check failed for an exact type we know that it can never // succeed at run time. we also don't care about null values, since they will // also make the check fail. - return LogicConstantNode.contradiction(graph()); + return TriState.FALSE; } else { boolean superType = stampType.isAssignableFrom(type()); if (!superType && !stampType.isInterface() && !type().isInterface()) { - return LogicConstantNode.contradiction(graph()); + return TriState.FALSE; } // since the subtype comparison was only performed on a declared type we don't // really know if it might be true at run time... } } } - return this; - } - - public ValueNode object() { - return object; + return TriState.UNKNOWN; } /** @@ -122,7 +138,7 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object); + State state = tool.getObjectState(object()); if (state != null) { tool.replaceWithValue(LogicConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph())); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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.java; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -/** - * Loads an exception object passed by the runtime from a callee to an exception handler in a - * caller. The node is only produced when lowering an {@link ExceptionObjectNode}. - * <p> - * The frame state upon entry to an exception handler is such that it is a - * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly the - * exception object (per the JVM spec) to rethrow. This means that the code generated for this node - * must not cause a deoptimization as the runtime/interpreter would not have a valid location to - * find the exception object to be rethrown. - */ -public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable { - - public LoadExceptionObjectNode(Stamp stamp) { - super(stamp); - } - - @Override - public void lower(LoweringTool tool) { - tool.getLowerer().lower(this, tool); - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,8 +24,6 @@ import static com.oracle.graal.graph.iterators.NodePredicates.*; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -62,7 +60,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (usages().isEmpty() && !isVolatile() && (isStatic() || ObjectStamp.isObjectNonNull(object().stamp()))) { + if (usages().isEmpty() && !isVolatile() && (isStatic() || StampTool.isObjectNonNull(object().stamp()))) { return null; } MetaAccessProvider metaAccess = tool.getMetaAccess(); @@ -99,7 +97,7 @@ } private PhiNode asPhi(MetaAccessProvider metaAccess) { - if (!isStatic() && Modifier.isFinal(field.getModifiers()) && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(isNotA(ConstantNode.class)).isEmpty()) { + if (!isStatic() && field.isFinal() && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(isNotA(ConstantNode.class)).isEmpty()) { PhiNode phi = (PhiNode) object(); Constant[] constants = new Constant[phi.valueCount()]; for (int i = 0; i < phi.valueCount(); i++) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -45,7 +45,7 @@ } private static Stamp createStamp(ValueNode array, Kind kind) { - ResolvedJavaType type = ObjectStamp.typeOrNull(array); + ResolvedJavaType type = StampTool.typeOrNull(array); if (kind == Kind.Object && type != null) { return StampFactory.declared(type.getComponentType()); } else {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,84 @@ +/* + * 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.nodes.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +import sun.misc.*; + +/** + * Represents the lowered version of an atomic read-and-write operation like + * {@link Unsafe#getAndSetInt(Object, long, int)} . + */ +@NodeInfo(allowedUsageTypes = {InputType.Memory}) +public class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { + + @Input private ValueNode newValue; + @Input(InputType.State) private FrameState stateAfter; + + public LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType, boolean compressible) { + super(object, location, newValue.stamp(), barrierType, compressible); + this.newValue = newValue; + } + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } + + public LocationIdentity getLocationIdentity() { + return location().getLocationIdentity(); + } + + public void generate(NodeLIRBuilderTool gen) { + Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); + Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(address, gen.operand(newValue)); + gen.setResult(this, result); + } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } + + public boolean canNullCheck() { + return false; + } + +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Represents the lowered version of an atomic compare-and-swap operation{@code CompareAndSwapNode}.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.java; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -109,12 +107,12 @@ assertTrue(n instanceof Invoke, "call target can only be used from an invoke (%s)", n); } if (invokeKind == InvokeKind.Special || invokeKind == InvokeKind.Static) { - assertFalse(Modifier.isAbstract(targetMethod.getModifiers()), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod); + assertFalse(targetMethod.isAbstract(), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod); } if (invokeKind == InvokeKind.Static) { - assertTrue(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for static methods (%s)", targetMethod); + assertTrue(targetMethod.isStatic(), "static calls are only allowed for static methods (%s)", targetMethod); } else { - assertFalse(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for non-static methods (%s)", targetMethod); + assertFalse(targetMethod.isStatic(), "static calls are only allowed for non-static methods (%s)", targetMethod); } return super.verify(); } @@ -143,11 +141,11 @@ // check if the type of the receiver can narrow the result ValueNode receiver = receiver(); - ResolvedJavaType type = ObjectStamp.typeOrNull(receiver); + ResolvedJavaType type = StampTool.typeOrNull(receiver); if (type != null) { // either the holder class is exact, or the receiver object has an exact type ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod); - if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || ObjectStamp.isExactType(receiver))) { + if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver))) { invokeKind = InvokeKind.Special; targetMethod = resolvedMethod; return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -58,7 +59,7 @@ @Override public void simplify(SimplifierTool tool) { - if (escapedReturnValue != null && stateAfter() != null && stateAfter().bci != FrameState.AFTER_BCI) { + if (escapedReturnValue != null && stateAfter() != null && stateAfter().bci != BytecodeFrame.AFTER_BCI) { ValueNode returnValue = escapedReturnValue; setEscapedReturnValue(null); tool.removeIfUnused(returnValue); @@ -74,7 +75,7 @@ public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object()); // the monitor exit for a synchronized method should never be virtualized - assert stateAfter().bci != FrameState.AFTER_BCI || state == null; + assert stateAfter().bci != BytecodeFrame.AFTER_BCI || state == null; if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { MonitorIdNode removedLock = state.removeLock(); assert removedLock == getMonitorId() : "mismatch at " + this + ": " + removedLock + " vs. " + getMonitorId();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * This node describes one locking scope; it ties the monitor enter, monitor exit and the frame
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -54,7 +55,7 @@ * @return the element type of the array */ public ResolvedJavaType elementType() { - return ObjectStamp.typeOrNull(this).getComponentType(); + return StampTool.typeOrNull(this).getComponentType(); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,10 +26,10 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code NewMultiArrayNode} represents an allocation of a multi-dimensional object array.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,11 +24,11 @@ import com.oracle.graal.api.code.*; 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.*; /** * This node is used to perform the finalizer registration at the end of the java.lang.Object @@ -53,7 +53,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(REGISTER_FINALIZER); - gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(object())); + gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(object())); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.java; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; @@ -66,7 +64,7 @@ @Override public void lower(LoweringTool tool) { - InvokeKind invokeKind = Modifier.isStatic(replacementTargetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special; + InvokeKind invokeKind = replacementTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; MethodCallTargetNode replacement = graph().add( new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -75,8 +76,8 @@ int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) { ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType(); - if (componentType.isPrimitive() || ObjectStamp.isObjectAlwaysNull(value) || componentType.getSuperclass() == null || - (ObjectStamp.typeOrNull(value) != null && componentType.isAssignableFrom(ObjectStamp.typeOrNull(value)))) { + if (componentType.isPrimitive() || StampTool.isObjectAlwaysNull(value) || componentType.getSuperclass() == null || + (StampTool.typeOrNull(value) != null && componentType.isAssignableFrom(StampTool.typeOrNull(value)))) { tool.setVirtualEntry(arrayState, index, value(), false); tool.delete(); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,11 +26,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.spi; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; - -/** - * This interface can be used to generate LIR for arithmetic operations. - */ -public interface ArithmeticLIRGenerator { - /** - * TODO remove reference to {@link Stamp}. - */ - PlatformKind getPlatformKind(Stamp stamp); - - Value emitNegate(Value input); - - Value emitAdd(Value a, Value b); - - Value emitSub(Value a, Value b); - - Value emitMul(Value a, Value b); - - /** - * TODO remove {@link DeoptimizeNode}. - */ - Value emitDiv(Value a, Value b, DeoptimizingNode deopting); - - /** - * TODO remove {@link DeoptimizeNode}. - */ - Value emitRem(Value a, Value b, DeoptimizingNode deopting); - - /** - * TODO remove {@link DeoptimizeNode}. - */ - Value emitUDiv(Value a, Value b, DeoptimizingNode deopting); - - /** - * TODO remove {@link DeoptimizeNode}. - */ - Value emitURem(Value a, Value b, DeoptimizingNode deopting); - - Value emitNot(Value input); - - Value emitAnd(Value a, Value b); - - Value emitOr(Value a, Value b); - - Value emitXor(Value a, Value b); - - Value emitShl(Value a, Value b); - - Value emitShr(Value a, Value b); - - Value emitUShr(Value a, Value b); - - Value emitFloatConvert(FloatConvert op, Value inputVal); - - Value emitReinterpret(PlatformKind to, Value inputVal); - - Value emitNarrow(Value inputVal, int bits); - - Value emitSignExtend(Value inputVal, int fromBits, int toBits); - - Value emitZeroExtend(Value inputVal, int fromBits, int toBits); - - Value emitMathAbs(Value input); - - Value emitMathSqrt(Value input); - - Value emitMathLog(Value input, boolean base10); - - Value emitMathCos(Value input); - - Value emitMathSin(Value input); - - Value emitMathTan(Value input); -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.spi; import com.oracle.graal.api.code.*; +import com.oracle.graal.lir.gen.*; public interface ArithmeticLIRLowerable extends ArithmeticOperation {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2011, 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.nodes.spi; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; - -public interface LIRGeneratorTool extends ArithmeticLIRGenerator { - - TargetDescription target(); - - MetaAccessProvider getMetaAccess(); - - CodeCacheProvider getCodeCache(); - - ForeignCallsProvider getForeignCalls(); - - Value emitLoad(PlatformKind kind, Value address, Access access); - - void emitStore(PlatformKind kind, Value address, Value input, Access access); - - Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue); - - void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting); - - Value emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args); - - /** - * Checks whether the supplied constant can be used without loading it into a register for most - * operations, i.e., for commonly used arithmetic, logical, and comparison operations. - * - * @param c The constant to check. - * @return True if the constant can be used directly, false if the constant needs to be in a - * register. - */ - boolean canInlineConstant(Constant c); - - boolean canStoreConstant(Constant c, boolean isCompressed); - - RegisterAttributes attributes(Register register); - - AllocatableValue newVariable(PlatformKind kind); - - AllocatableValue emitMove(Value input); - - void emitMove(AllocatableValue dst, Value src); - - /** - * Emits an op that loads the address of some raw data. - * - * @param dst the variable into which the address is loaded - * @param data the data to be installed with the generated code - */ - void emitData(AllocatableValue dst, byte[] data); - - Value emitAddress(Value base, long displacement, Value index, int scale); - - Value emitAddress(StackSlot slot); - - void emitMembar(int barriers); - - void emitUnwind(Value operand); - - /** - * Called just before register allocation is performed on the LIR owned by this generator. - * Overriding implementations of this method must call the overridden method. - */ - void beforeRegisterAllocation(); - - void emitIncomingValues(Value[] params); - - /** - * Emits a return instruction. Implementations need to insert a move if the input is not in the - * correct location. - */ - void emitReturn(Value input); -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,13 +22,14 @@ */ package com.oracle.graal.nodes.spi; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; /** * Interface implemented by nodes that can replace themselves with lower level nodes during a phase * that transforms a graph to replace higher level nodes with lower level nodes. */ -public interface Lowerable { +public interface Lowerable extends NodeInterface { /** * Expand this node into lower level nodes expressing the same semantics. If the introduced
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,9 +25,9 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,12 +26,19 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; public interface NodeLIRBuilderTool extends NodeMappableLIRBuilder { + // TODO (je) remove and move into the Node + LIRFrameState state(DeoptimizingNode deopt); + void emitNullCheck(ValueNode v, DeoptimizingNode deopting); void emitIf(IfNode i); @@ -64,4 +71,14 @@ Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments); MemoryArithmeticLIRLowerer getMemoryLowerer(); + + Variable newVariable(Kind kind); + + void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); + + void emitBitCount(Variable result, Value operand); + + void emitBitScanForward(Variable result, Value operand); + + void doBlock(Block block, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java Mon Apr 28 10:31:17 2014 +0200 @@ -29,9 +29,7 @@ /** * Interface for nodes which have {@link FrameState} nodes as input. */ -public interface NodeWithState { - - Node asNode(); +public interface NodeWithState extends NodeInterface { default NodeIterable<FrameState> states() { return asNode().inputs().filter(FrameState.class);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,11 +24,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; /** * Interface for service providers that register replacements with the compiler. */ public interface ReplacementsProvider { - void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, Replacements replacements, TargetDescription target); + void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,235 +0,0 @@ -/* - * 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 - * 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.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.spi.*; -import com.oracle.graal.compiler.common.type.*; - -public class FloatStamp extends PrimitiveStamp { - - private final double lowerBound; - private final double upperBound; - private final boolean nonNaN; - - protected FloatStamp(int bits) { - this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false); - } - - protected FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) { - super(bits); - this.lowerBound = lowerBound; - this.upperBound = upperBound; - this.nonNaN = nonNaN; - } - - @Override - public Stamp unrestricted() { - return new FloatStamp(getBits()); - } - - @Override - public Stamp illegal() { - return new FloatStamp(getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, true); - } - - @Override - public boolean isLegal() { - return lowerBound <= upperBound || !nonNaN; - } - - @Override - public Kind getStackKind() { - if (getBits() > 32) { - return Kind.Double; - } else { - return Kind.Float; - } - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - return tool.getFloatingKind(getBits()); - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - switch (getBits()) { - case 32: - return metaAccess.lookupJavaType(Float.TYPE); - case 64: - return metaAccess.lookupJavaType(Double.TYPE); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - /** - * The (inclusive) lower bound on the value described by this stamp. - */ - public double lowerBound() { - return lowerBound; - } - - /** - * The (inclusive) upper bound on the value described by this stamp. - */ - public double upperBound() { - return upperBound; - } - - public boolean isNonNaN() { - return nonNaN; - } - - public boolean isUnrestricted() { - return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; - } - - public boolean contains(double value) { - if (Double.isNaN(value)) { - return !nonNaN; - } else { - return value >= lowerBound && value <= upperBound; - } - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - str.append('f'); - str.append(getBits()); - str.append(nonNaN ? "!" : ""); - if (lowerBound == upperBound) { - str.append(" [").append(lowerBound).append(']'); - } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) { - str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); - } - return str.toString(); - } - - @Override - public Stamp meet(Stamp otherStamp) { - if (otherStamp == this) { - return this; - } - if (!(otherStamp instanceof FloatStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - FloatStamp other = (FloatStamp) otherStamp; - assert getBits() == other.getBits(); - double meetUpperBound = Math.max(upperBound, other.upperBound); - double meetLowerBound = Math.min(lowerBound, other.lowerBound); - boolean meetNonNaN = nonNaN && other.nonNaN; - if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) { - return this; - } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) { - return other; - } else { - return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN); - } - } - - @Override - public Stamp join(Stamp otherStamp) { - if (otherStamp == this) { - return this; - } - if (!(otherStamp instanceof FloatStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - FloatStamp other = (FloatStamp) otherStamp; - assert getBits() == other.getBits(); - double joinUpperBound = Math.min(upperBound, other.upperBound); - double joinLowerBound = Math.max(lowerBound, other.lowerBound); - boolean joinNonNaN = nonNaN || other.nonNaN; - if (joinLowerBound == lowerBound && joinUpperBound == upperBound && joinNonNaN == nonNaN) { - return this; - } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) { - return other; - } else { - return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN); - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - result = prime * result + super.hashCode(); - temp = Double.doubleToLongBits(lowerBound); - result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + (nonNaN ? 1231 : 1237); - temp = Double.doubleToLongBits(upperBound); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean isCompatible(Stamp stamp) { - if (this == stamp) { - return true; - } - if (stamp instanceof FloatStamp) { - FloatStamp other = (FloatStamp) stamp; - return getBits() == other.getBits(); - } - return false; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { - return false; - } - FloatStamp other = (FloatStamp) obj; - if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) { - return false; - } - if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) { - return false; - } - if (nonNaN != other.nonNaN) { - return false; - } - return true; - } - - @Override - public Constant asConstant() { - if (nonNaN && lowerBound == upperBound) { - switch (getBits()) { - case 32: - return Constant.forFloat((float) lowerBound); - case 64: - return Constant.forDouble(lowerBound); - } - } - return null; - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * 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 - * 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.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.spi.*; -import com.oracle.graal.compiler.common.type.*; - -/** - * This stamp represents the illegal type. Values with this type can not exist at run time. - */ -public final class IllegalStamp extends Stamp { - - private IllegalStamp() { - } - - @Override - public Kind getStackKind() { - return Kind.Illegal; - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - throw GraalInternalError.shouldNotReachHere("illegal stamp should not reach backend"); - } - - @Override - public Stamp unrestricted() { - return this; - } - - @Override - public Stamp illegal() { - return this; - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - throw GraalInternalError.shouldNotReachHere("illegal stamp has no Java type"); - } - - @Override - public Stamp meet(Stamp other) { - return this; - } - - @Override - public Stamp join(Stamp other) { - return this; - } - - @Override - public boolean isCompatible(Stamp stamp) { - return false; - } - - @Override - public String toString() { - return "ILLEGAL"; - } - - @Override - public boolean isLegal() { - return false; - } - - private static IllegalStamp instance = new IllegalStamp(); - - static IllegalStamp getInstance() { - return instance; - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,319 +0,0 @@ -/* - * 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 - * 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.type; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.spi.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.nodes.*; - -/** - * Describes the possible values of a {@link ValueNode} that produces an int or long result. - * - * The description consists of (inclusive) lower and upper bounds and up (may be set) and down - * (always set) bit-masks. - */ -public class IntegerStamp extends PrimitiveStamp { - - private final long lowerBound; - private final long upperBound; - private final long downMask; - private final long upMask; - - public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { - super(bits); - this.lowerBound = lowerBound; - this.upperBound = upperBound; - this.downMask = downMask; - this.upMask = upMask; - assert lowerBound >= defaultMinValue(bits) : this; - assert upperBound <= defaultMaxValue(bits) : this; - assert (downMask & defaultMask(bits)) == downMask : this; - assert (upMask & defaultMask(bits)) == upMask : this; - } - - @Override - public Stamp unrestricted() { - return new IntegerStamp(getBits(), defaultMinValue(getBits()), defaultMaxValue(getBits()), 0, defaultMask(getBits())); - } - - @Override - public Stamp illegal() { - return new IntegerStamp(getBits(), defaultMaxValue(getBits()), defaultMinValue(getBits()), defaultMask(getBits()), 0); - } - - @Override - public boolean isLegal() { - return lowerBound <= upperBound; - } - - @Override - public Kind getStackKind() { - if (getBits() > 32) { - return Kind.Long; - } else { - return Kind.Int; - } - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - return tool.getIntegerKind(getBits()); - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - switch (getBits()) { - case 1: - return metaAccess.lookupJavaType(Boolean.TYPE); - case 8: - return metaAccess.lookupJavaType(Byte.TYPE); - case 16: - return metaAccess.lookupJavaType(Short.TYPE); - case 32: - return metaAccess.lookupJavaType(Integer.TYPE); - case 64: - return metaAccess.lookupJavaType(Long.TYPE); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - /** - * The signed inclusive lower bound on the value described by this stamp. - */ - public long lowerBound() { - return lowerBound; - } - - /** - * The signed inclusive upper bound on the value described by this stamp. - */ - public long upperBound() { - return upperBound; - } - - /** - * This bit-mask describes the bits that are always set in the value described by this stamp. - */ - public long downMask() { - return downMask; - } - - /** - * This bit-mask describes the bits that can be set in the value described by this stamp. - */ - public long upMask() { - return upMask; - } - - public boolean isUnrestricted() { - return lowerBound == defaultMinValue(getBits()) && upperBound == defaultMaxValue(getBits()) && downMask == 0 && upMask == defaultMask(getBits()); - } - - public boolean contains(long value) { - return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & defaultMask(getBits())); - } - - public boolean isPositive() { - return lowerBound() >= 0; - } - - public boolean isNegative() { - return upperBound() <= 0; - } - - public boolean isStrictlyPositive() { - return lowerBound() > 0; - } - - public boolean isStrictlyNegative() { - return upperBound() < 0; - } - - public boolean canBePositive() { - return upperBound() > 0; - } - - public boolean canBeNegative() { - return lowerBound() < 0; - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - str.append('i'); - str.append(getBits()); - if (lowerBound == upperBound) { - str.append(" [").append(lowerBound).append(']'); - } else if (lowerBound != defaultMinValue(getBits()) || upperBound != defaultMaxValue(getBits())) { - str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); - } - if (downMask != 0) { - str.append(" \u21ca"); - new Formatter(str).format("%016x", downMask); - } - if (upMask != defaultMask(getBits())) { - str.append(" \u21c8"); - new Formatter(str).format("%016x", upMask); - } - return str.toString(); - } - - private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { - assert getBits() == other.getBits(); - if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0) { - return illegal(); - } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) { - return this; - } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) { - return other; - } else { - return new IntegerStamp(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); - } - } - - @Override - public Stamp meet(Stamp otherStamp) { - if (otherStamp == this) { - return this; - } - if (!(otherStamp instanceof IntegerStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - IntegerStamp other = (IntegerStamp) otherStamp; - return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask); - } - - @Override - public Stamp join(Stamp otherStamp) { - if (otherStamp == this) { - return this; - } - if (!(otherStamp instanceof IntegerStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - IntegerStamp other = (IntegerStamp) otherStamp; - long newDownMask = downMask | other.downMask; - long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; - return createStamp(other, Math.min(upperBound, other.upperBound), newLowerBound, newDownMask, upMask & other.upMask); - } - - @Override - public boolean isCompatible(Stamp stamp) { - if (this == stamp) { - return true; - } - if (stamp instanceof IntegerStamp) { - IntegerStamp other = (IntegerStamp) stamp; - return getBits() == other.getBits(); - } - return false; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + super.hashCode(); - result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32)); - result = prime * result + (int) (upperBound ^ (upperBound >>> 32)); - result = prime * result + (int) (downMask ^ (downMask >>> 32)); - result = prime * result + (int) (upMask ^ (upMask >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { - return false; - } - IntegerStamp other = (IntegerStamp) obj; - if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) { - return false; - } - return true; - } - - public static long defaultMask(int bits) { - assert 0 <= bits && bits <= 64; - if (bits == 64) { - return 0xffffffffffffffffL; - } else { - return (1L << bits) - 1; - } - } - - public static long defaultMinValue(int bits) { - return -1L << (bits - 1); - } - - public static long defaultMaxValue(int bits) { - return defaultMask(bits - 1); - } - - public static long upMaskFor(int bits, long lowerBound, long upperBound) { - long mask = lowerBound | upperBound; - if (mask == 0) { - return 0; - } else { - return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & defaultMask(bits); - } - } - - /** - * Checks if the 2 stamps represent values of the same sign. Returns true if the two stamps are - * both positive of null or if they are both strictly negative - * - * @return true if the two stamps are both positive of null or if they are both strictly - * negative - */ - public static boolean sameSign(IntegerStamp s1, IntegerStamp s2) { - return s1.isPositive() && s2.isPositive() || s1.isStrictlyNegative() && s2.isStrictlyNegative(); - } - - @Override - public Constant asConstant() { - if (lowerBound == upperBound) { - switch (getBits()) { - case 1: - return Constant.forBoolean(lowerBound != 0); - case 8: - return Constant.forByte((byte) lowerBound); - case 16: - return Constant.forShort((short) lowerBound); - case 32: - return Constant.forInt((int) lowerBound); - case 64: - return Constant.forLong(lowerBound); - } - } - return null; - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,337 +0,0 @@ -/* - * 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 - * 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.type; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.spi.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.nodes.*; - -public class ObjectStamp extends Stamp { - - private final ResolvedJavaType type; - private final boolean exactType; - private final boolean nonNull; - private final boolean alwaysNull; - - public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { - this.type = type; - this.exactType = exactType; - this.nonNull = nonNull; - this.alwaysNull = alwaysNull; - } - - @Override - public Stamp unrestricted() { - return StampFactory.object(); - } - - @Override - public Stamp illegal() { - return new ObjectStamp(null, true, true, false); - } - - @Override - public boolean isLegal() { - return !exactType || (type != null && (isConcreteType(type))); - } - - @Override - public Kind getStackKind() { - return Kind.Object; - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - return tool.getObjectKind(); - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - if (type != null) { - return type; - } - return metaAccess.lookupJavaType(Object.class); - } - - public boolean nonNull() { - return nonNull; - } - - public boolean alwaysNull() { - return alwaysNull; - } - - public ResolvedJavaType type() { - return type; - } - - public boolean isExactType() { - return exactType; - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - str.append('a'); - str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.getName()).append(alwaysNull ? " NULL" : ""); - return str.toString(); - } - - @Override - public Stamp meet(Stamp otherStamp) { - if (this == otherStamp) { - return this; - } - if (!(otherStamp instanceof ObjectStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - ObjectStamp other = (ObjectStamp) otherStamp; - ResolvedJavaType meetType; - boolean meetExactType; - boolean meetNonNull; - boolean meetAlwaysNull; - if (other.alwaysNull) { - meetType = type(); - meetExactType = exactType; - meetNonNull = false; - meetAlwaysNull = alwaysNull; - } else if (alwaysNull) { - meetType = other.type(); - meetExactType = other.exactType; - meetNonNull = false; - meetAlwaysNull = other.alwaysNull; - } else { - meetType = meetTypes(type(), other.type()); - meetExactType = exactType && other.exactType; - if (meetExactType && type != null && other.type != null) { - // meeting two valid exact types may result in a non-exact type - meetExactType = Objects.equals(meetType, type) && Objects.equals(meetType, other.type); - } - meetNonNull = nonNull && other.nonNull; - meetAlwaysNull = false; - } - - if (Objects.equals(meetType, type) && meetExactType == exactType && meetNonNull == nonNull && meetAlwaysNull == alwaysNull) { - return this; - } else if (Objects.equals(meetType, other.type) && meetExactType == other.exactType && meetNonNull == other.nonNull && meetAlwaysNull == other.alwaysNull) { - return other; - } else { - return new ObjectStamp(meetType, meetExactType, meetNonNull, meetAlwaysNull); - } - } - - @Override - public Stamp join(Stamp otherStamp) { - return join0(otherStamp, false); - } - - @Override - public boolean isCompatible(Stamp other) { - if (this == other) { - return true; - } - if (other instanceof ObjectStamp) { - return true; - } - return false; - } - - /** - * Returns the stamp representing the type of this stamp after a cast to the type represented by - * the {@code to} stamp. While this is very similar to a {@link #join} operation, in the case - * where both types are not obviously related, the cast operation will prefer the type of the - * {@code to} stamp. This is necessary as long as ObjectStamps are not able to accurately - * represent intersection types. - * - * For example when joining the {@link RandomAccess} type with the {@link AbstractList} type, - * without intersection types, this would result in the most generic type ({@link Object} ). For - * this reason, in some cases a {@code castTo} operation is preferable in order to keep at least - * the {@link AbstractList} type. - * - * @param to the stamp this stamp should be casted to - * @return This stamp casted to the {@code to} stamp - */ - public Stamp castTo(ObjectStamp to) { - return join0(to, true); - } - - private Stamp join0(Stamp otherStamp, boolean castToOther) { - if (this == otherStamp) { - return this; - } - if (!(otherStamp instanceof ObjectStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - ObjectStamp other = (ObjectStamp) otherStamp; - if (!isLegal()) { - return this; - } else if (!other.isLegal()) { - return other; - } - - ResolvedJavaType joinType; - boolean joinAlwaysNull = alwaysNull || other.alwaysNull; - boolean joinNonNull = nonNull || other.nonNull; - boolean joinExactType = exactType || other.exactType; - if (Objects.equals(type, other.type)) { - joinType = type; - } else if (type == null && other.type == null) { - joinType = null; - } else if (type == null) { - joinType = other.type; - } else if (other.type == null) { - joinType = type; - } else { - // both types are != null and different - if (type.isAssignableFrom(other.type)) { - joinType = other.type; - if (exactType) { - joinAlwaysNull = true; - } - } else if (other.type.isAssignableFrom(type)) { - joinType = type; - if (other.exactType) { - joinAlwaysNull = true; - } - } else { - if (castToOther) { - joinType = other.type; - joinExactType = other.exactType; - } else { - joinType = null; - } - if (joinExactType || (!type.isInterface() && !other.type.isInterface())) { - joinAlwaysNull = true; - } - } - } - if (joinAlwaysNull) { - joinType = null; - joinExactType = false; - } - if (joinExactType && joinType == null) { - return StampFactory.illegal(Kind.Object); - } - if (joinAlwaysNull && joinNonNull) { - return StampFactory.illegal(Kind.Object); - } else if (joinExactType && !isConcreteType(joinType)) { - return StampFactory.illegal(Kind.Object); - } - if (Objects.equals(joinType, type) && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) { - return this; - } else if (Objects.equals(joinType, other.type) && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) { - return other; - } else { - return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull); - } - } - - public static boolean isConcreteType(ResolvedJavaType type) { - return !(Modifier.isAbstract(type.getModifiers()) && !type.isArray()); - } - - private static ResolvedJavaType meetTypes(ResolvedJavaType a, ResolvedJavaType b) { - if (Objects.equals(a, b)) { - return a; - } else if (a == null || b == null) { - return null; - } else { - return a.findLeastCommonAncestor(b); - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (exactType ? 1231 : 1237); - result = prime * result + (nonNull ? 1231 : 1237); - result = prime * result + (alwaysNull ? 1231 : 1237); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - ObjectStamp other = (ObjectStamp) obj; - if (exactType != other.exactType || nonNull != other.nonNull || alwaysNull != other.alwaysNull) { - return false; - } - if (type == null) { - if (other.type != null) { - return false; - } - } else if (!type.equals(other.type)) { - return false; - } - return true; - } - - public static boolean isObjectAlwaysNull(ValueNode node) { - return isObjectAlwaysNull(node.stamp()); - } - - public static boolean isObjectAlwaysNull(Stamp stamp) { - return (stamp instanceof ObjectStamp && ((ObjectStamp) stamp).isLegal() && ((ObjectStamp) stamp).alwaysNull()); - } - - public static boolean isObjectNonNull(ValueNode node) { - return isObjectNonNull(node.stamp()); - } - - public static boolean isObjectNonNull(Stamp stamp) { - return stamp instanceof ObjectStamp && ((ObjectStamp) stamp).isLegal() && ((ObjectStamp) stamp).nonNull(); - } - - public static ResolvedJavaType typeOrNull(ValueNode node) { - return typeOrNull(node.stamp()); - } - - public static ResolvedJavaType typeOrNull(Stamp stamp) { - if (stamp instanceof ObjectStamp) { - return ((ObjectStamp) stamp).type(); - } - return null; - } - - public static boolean isExactType(ValueNode node) { - return isExactType(node.stamp()); - } - - public static boolean isExactType(Stamp stamp) { - if (stamp instanceof ObjectStamp) { - return ((ObjectStamp) stamp).isExactType(); - } - return false; - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * 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.nodes.type; - -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.nodes.*; - -/** - * Describes the possible values of a {@link ValueNode} that produces a primitive value as result. - */ -public abstract class PrimitiveStamp extends Stamp { - - private final int bits; - - protected PrimitiveStamp(int bits) { - this.bits = bits; - } - - /** - * The width in bits of the value described by this stamp. - */ - public int getBits() { - return bits; - } - - public static int getBits(Stamp stamp) { - if (stamp instanceof PrimitiveStamp) { - return ((PrimitiveStamp) stamp).getBits(); - } else { - return 0; - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + bits; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof PrimitiveStamp) { - PrimitiveStamp other = (PrimitiveStamp) obj; - return bits == other.bits; - } - return false; - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2011, 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.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.type.*; - -public class StampFactory { - - // JaCoCo Exclude - - private static final Stamp[] stampCache = new Stamp[Kind.values().length]; - private static final Stamp[] illegalStampCache = new Stamp[Kind.values().length]; - private static final Stamp objectStamp = new ObjectStamp(null, false, false, false); - private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false); - private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true); - private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false); - private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); - - private static void setCache(Kind kind, Stamp stamp) { - stampCache[kind.ordinal()] = stamp; - } - - private static void setIntCache(Kind kind) { - int bits = kind.getStackKind().getBitCount(); - long mask; - if (kind.isUnsigned()) { - mask = IntegerStamp.defaultMask(kind.getBitCount()); - } else { - mask = IntegerStamp.defaultMask(bits); - } - setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); - } - - private static void setFloatCache(Kind kind) { - setCache(kind, new FloatStamp(kind.getBitCount())); - } - - static { - setIntCache(Kind.Boolean); - setIntCache(Kind.Byte); - setIntCache(Kind.Short); - setIntCache(Kind.Char); - setIntCache(Kind.Int); - setIntCache(Kind.Long); - - setFloatCache(Kind.Float); - setFloatCache(Kind.Double); - - setCache(Kind.Object, objectStamp); - setCache(Kind.Void, VoidStamp.getInstance()); - - for (Kind k : Kind.values()) { - if (stampCache[k.ordinal()] != null) { - illegalStampCache[k.ordinal()] = stampCache[k.ordinal()].illegal(); - } else { - illegalStampCache[k.ordinal()] = IllegalStamp.getInstance(); - } - } - } - - /** - * Return a stamp for a Java kind, as it would be represented on the bytecode stack. - */ - public static Stamp forKind(Kind kind) { - assert stampCache[kind.ordinal()] != null : "unexpected forKind(" + kind + ")"; - return stampCache[kind.ordinal()]; - } - - /** - * Return the stamp for the {@code void} type. This will return a singleton instance than can be - * compared using {@code ==}. - */ - public static Stamp forVoid() { - return VoidStamp.getInstance(); - } - - /** - * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an - * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated. - */ - public static Stamp forNodeIntrinsic() { - return nodeIntrinsicStamp; - } - - public static Stamp intValue() { - return forKind(Kind.Int); - } - - public static Stamp positiveInt() { - return positiveInt; - } - - public static Stamp illegal() { - return illegal(Kind.Illegal); - } - - public static Stamp illegal(Kind kind) { - return illegalStampCache[kind.ordinal()]; - } - - public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) { - return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); - } - - public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound) { - return forInteger(kind.getBitCount(), lowerBound, upperBound); - } - - public static IntegerStamp forInteger(int bits) { - return new IntegerStamp(bits, IntegerStamp.defaultMinValue(bits), IntegerStamp.defaultMaxValue(bits), 0, IntegerStamp.defaultMask(bits)); - } - - public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) { - long defaultMask = IntegerStamp.defaultMask(bits); - if (lowerBound == upperBound) { - return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask); - } - final long downMask; - final long upMask; - if (lowerBound >= 0) { - int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); - - upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount); - downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); - } else { - if (upperBound >= 0) { - upMask = defaultMask; - downMask = 0; - } else { - int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); - - upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); - downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); - } - } - return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask); - } - - public static FloatStamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) { - assert kind.isNumericFloat(); - return new FloatStamp(kind.getBitCount(), lowerBound, upperBound, nonNaN); - } - - public static Stamp forConstant(Constant value) { - Kind kind = value.getKind(); - switch (kind) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - case Long: - long mask = value.asLong() & IntegerStamp.defaultMask(kind.getBitCount()); - return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), mask, mask); - case Float: - return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat())); - case Double: - return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble())); - case Illegal: - return illegal(Kind.Illegal); - case Object: - if (value.isNull()) { - return alwaysNull(); - } else { - return objectNonNull(); - } - default: - throw new GraalInternalError("unexpected kind: %s", kind); - } - } - - public static Stamp forConstant(Constant value, MetaAccessProvider metaAccess) { - assert value.getKind() == Kind.Object; - if (value.getKind() == Kind.Object) { - ResolvedJavaType type = value.isNull() ? null : metaAccess.lookupJavaType(value); - return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull()); - } else { - throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.getKind()); - } - } - - public static Stamp object() { - return objectStamp; - } - - public static Stamp objectNonNull() { - return objectNonNullStamp; - } - - public static Stamp alwaysNull() { - return objectAlwaysNullStamp; - } - - public static Stamp declared(ResolvedJavaType type) { - return declared(type, false); - } - - public static Stamp declaredNonNull(ResolvedJavaType type) { - return declared(type, true); - } - - public static Stamp declared(ResolvedJavaType type, boolean nonNull) { - return object(type, false, nonNull); - } - - public static Stamp object(ResolvedJavaType type, boolean exactType, boolean nonNull) { - assert type != null; - assert type.getKind() == Kind.Object; - ResolvedJavaType exact = type.asExactType(); - if (exact != null) { - assert !exactType || type.equals(exact); - return new ObjectStamp(exact, true, nonNull, false); - } else { - return new ObjectStamp(type, exactType, nonNull, false); - } - } - - public static Stamp exactNonNull(ResolvedJavaType type) { - if (ObjectStamp.isConcreteType(type)) { - return new ObjectStamp(type, true, true, false); - } else { - return illegal(Kind.Object); - } - } - - public static Stamp exact(ResolvedJavaType type) { - return new ObjectStamp(type, true, false, false); - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampProvider.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2011, 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.type; - -import com.oracle.graal.compiler.common.type.*; - -public interface StampProvider { - - Stamp stamp(); -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; /** @@ -451,4 +452,110 @@ } return null; } + + /** + * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object + * value which is known to be always null. + * + * @param node the node to check + * @return true if this node represents a legal object value which is known to be always null + */ + public static boolean isObjectAlwaysNull(ValueNode node) { + return isObjectAlwaysNull(node.stamp()); + } + + /** + * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object + * stamp whose values are known to be always null. + * + * @param stamp the stamp to check + * @return true if this stamp represents a legal object stamp whose values are known to be + * always null + */ + public static boolean isObjectAlwaysNull(Stamp stamp) { + if (stamp instanceof ObjectStamp && stamp.isLegal()) { + return ((ObjectStamp) stamp).alwaysNull(); + } + return false; + } + + /** + * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object + * value which is known to never be null. + * + * @param node the node to check + * @return true if this node represents a legal object value which is known to never be null + */ + public static boolean isObjectNonNull(ValueNode node) { + return isObjectNonNull(node.stamp()); + } + + /** + * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object + * stamp whose values known to be always null. + * + * @param stamp the stamp to check + * @return true if this stamp represents a legal object stamp whose values are known to be + * always null + */ + public static boolean isObjectNonNull(Stamp stamp) { + if (stamp instanceof ObjectStamp && stamp.isLegal()) { + return ((ObjectStamp) stamp).nonNull(); + } + return false; + } + + /** + * Returns the {@linkplain ResolvedJavaType Java type} this {@linkplain ValueNode} has if it is + * a {@linkplain Stamp#isLegal() legal} Object value. + * + * @param node the node to check + * @return the Java type this value has if it is a legal Object type, null otherwise + */ + public static ResolvedJavaType typeOrNull(ValueNode node) { + return typeOrNull(node.stamp()); + } + + /** + * Returns the {@linkplain ResolvedJavaType Java type} this {@linkplain Stamp} has if it is a + * {@linkplain Stamp#isLegal() legal} Object stamp. + * + * @param stamp the stamp to check + * @return the Java type this stamp has if it is a legal Object stamp, null otherwise + */ + public static ResolvedJavaType typeOrNull(Stamp stamp) { + if (stamp instanceof ObjectStamp && stamp.isLegal()) { + return ((ObjectStamp) stamp).type(); + } + return null; + } + + /** + * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object + * value whose Java type is known exactly. If this method returns true then the + * {@linkplain ResolvedJavaType Java type} returned by {@link #typeOrNull(ValueNode)} is the + * concrete dynamic/runtime Java type of this value. + * + * @param node the node to check + * @return true if this node represents a legal object value whose Java type is known exactly + */ + public static boolean isExactType(ValueNode node) { + return isExactType(node.stamp()); + } + + /** + * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object + * stamp whose {@linkplain ResolvedJavaType Java type} is known exactly. If this method returns + * true then the Java type returned by {@link #typeOrNull(Stamp)} is the only concrete + * dynamic/runtime Java type possible for values of this stamp. + * + * @param stamp the stamp to check + * @return true if this node represents a legal object stamp whose Java type is known exactly + */ + public static boolean isExactType(Stamp stamp) { + if (stamp instanceof ObjectStamp && stamp.isLegal()) { + return ((ObjectStamp) stamp).isExactType(); + } + return false; + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/VoidStamp.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * 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.nodes.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.spi.*; -import com.oracle.graal.compiler.common.type.*; - -/** - * Singleton stamp representing the value of type {@code void}. - */ -public final class VoidStamp extends Stamp { - - private VoidStamp() { - } - - @Override - public Stamp unrestricted() { - return this; - } - - @Override - public Kind getStackKind() { - return Kind.Void; - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - throw GraalInternalError.shouldNotReachHere("void stamp has no value"); - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - return metaAccess.lookupJavaType(Void.TYPE); - } - - @Override - public String toString() { - return "void"; - } - - @Override - public boolean alwaysDistinct(Stamp other) { - return this != other; - } - - @Override - public Stamp meet(Stamp other) { - if (other instanceof IllegalStamp) { - return other.join(this); - } - if (this == other) { - return this; - } - return StampFactory.illegal(Kind.Illegal); - } - - @Override - public Stamp join(Stamp other) { - if (other instanceof IllegalStamp) { - return other.join(this); - } - if (this == other) { - return this; - } - return StampFactory.illegal(Kind.Illegal); - } - - @Override - public boolean isCompatible(Stamp stamp) { - return this == stamp; - } - - @Override - public Stamp illegal() { - // there is no illegal void stamp - return this; - } - - @Override - public boolean isLegal() { - return true; - } - - private static VoidStamp instance = new VoidStamp(); - - static VoidStamp getInstance() { - return instance; - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Apr 28 10:31:17 2014 +0200 @@ -137,6 +137,11 @@ } public static void removeFixedWithUnusedInputs(FixedWithNextNode fixed) { + if (fixed instanceof StateSplit) { + FrameState stateAfter = ((StateSplit) fixed).stateAfter(); + ((StateSplit) fixed).setStateAfter(null); + killWithUnusedFloatingInputs(stateAfter); + } FixedNode next = fixed.next(); fixed.setNext(null); fixed.replaceAtPredecessor(next); @@ -326,6 +331,14 @@ return v; } + public static boolean tryKillUnused(Node node) { + if (node.isAlive() && isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) { + killWithUnusedFloatingInputs(node); + return true; + } + return false; + } + /** * Exhaustive search for {@link GraphUtil#originalValue(ValueNode)} when a simple search fails. * This can happen in the presence of complicated phi/proxy/phi constructs.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.nodes.virtual; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Selects one object from a {@link CommitAllocationNode}. The object is identified by its
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,12 +25,12 @@ import java.util.*; 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.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Extension}) public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, IterableNodeType {
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Mon Apr 28 10:31:17 2014 +0200 @@ -40,8 +40,10 @@ * * <pre> * ServiceLoader<Options> sl = ServiceLoader.loadInstalled(Options.class); - * for (OptionDescriptor desc : sl) { - * // use desc + * for (Options opts : sl) { + * for (OptionDescriptor desc : sl) { + * // use desc + * } * } * </pre> */
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -178,7 +178,7 @@ } StructuredGraph graph = (StructuredGraph) node.graph(); Mark mark = graph.getMark(); - if (!tryKillUnused(node)) { + if (!GraphUtil.tryKillUnused(node)) { if (!tryCanonicalize(node, nodeClass)) { if (node instanceof ValueNode) { ValueNode valueNode = (ValueNode) node; @@ -200,14 +200,6 @@ } } - private static boolean tryKillUnused(Node node) { - if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(node); - return true; - } - return false; - } - public static boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) { if (nodeClass.valueNumberable() && !nodeClass.isLeafNode()) { Node newNode = node.graph().findDuplicate(node); @@ -383,7 +375,7 @@ @Override public void removeIfUnused(Node node) { - tryKillUnused(node); + GraphUtil.tryKillUnused(node); } @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.phases.common; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; @@ -152,7 +151,7 @@ break; } } - if (type != null && type != ObjectStamp.typeOrNull(node)) { + if (type != null && type != StampTool.typeOrNull(node)) { newKnownTypes.put(node, type); } } @@ -235,15 +234,15 @@ public ResolvedJavaType getNodeType(ValueNode node) { ResolvedJavaType result = knownTypes.get(GraphUtil.unproxify(node)); - return result == null ? ObjectStamp.typeOrNull(node) : result; + return result == null ? StampTool.typeOrNull(node) : result; } public boolean isNull(ValueNode value) { - return ObjectStamp.isObjectAlwaysNull(value) || knownNull.contains(GraphUtil.unproxify(value)); + return StampTool.isObjectAlwaysNull(value) || knownNull.contains(GraphUtil.unproxify(value)); } public boolean isNonNull(ValueNode value) { - return ObjectStamp.isObjectNonNull(value) || knownNonNull.contains(GraphUtil.unproxify(value)); + return StampTool.isObjectNonNull(value) || knownNonNull.contains(GraphUtil.unproxify(value)); } @Override @@ -812,10 +811,10 @@ ValueNode receiver = callTarget.receiver(); if (receiver != null && (callTarget.invokeKind() == InvokeKind.Interface || callTarget.invokeKind() == InvokeKind.Virtual)) { ResolvedJavaType type = state.getNodeType(receiver); - if (!Objects.equals(type, ObjectStamp.typeOrNull(receiver))) { + if (!Objects.equals(type, StampTool.typeOrNull(receiver))) { ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod()); if (method != null) { - if (method.canBeStaticallyBound() || Modifier.isFinal(type.getModifiers())) { + if (method.canBeStaticallyBound() || type.isFinal()) { callTarget.setInvokeKind(InvokeKind.Special); callTarget.setTargetMethod(method); }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,9 +26,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import java.util.Map.Entry;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -40,6 +40,11 @@ this.canonicalizer = canonicalizer; } + public IncrementalCanonicalizerPhase(CanonicalizerPhase canonicalizer, BasePhase<? super C> phase) { + this.canonicalizer = canonicalizer; + appendPhase(phase); + } + @Override protected void run(StructuredGraph graph, C context) { Mark newNodesMark = graph.getMark();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.phases.common.InliningPhase.Options.*; import java.util.*; @@ -174,28 +174,30 @@ Mark markBeforeInlining = callerGraph.getMark(); InlineInfo callee = calleeInfo.callee(); try { - List<Node> invokeUsages = callee.invoke().asNode().usages().snapshot(); - callee.inline(new Providers(context), callerAssumptions); - callerAssumptions.record(calleeInfo.assumptions()); - metricInliningRuns.increment(); - Debug.dump(callerGraph, "after %s", callee); + try (Scope scope = Debug.scope("doInline", callerGraph)) { + List<Node> invokeUsages = callee.invoke().asNode().usages().snapshot(); + callee.inline(new Providers(context), callerAssumptions); + callerAssumptions.record(calleeInfo.assumptions()); + metricInliningRuns.increment(); + Debug.dump(callerGraph, "after %s", callee); - if (OptCanonicalizer.getValue()) { - Mark markBeforeCanonicalization = callerGraph.getMark(); - canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining); + if (OptCanonicalizer.getValue()) { + Mark markBeforeCanonicalization = callerGraph.getMark(); + canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining); - // process invokes that are possibly created during canonicalization - for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) { - if (newNode instanceof Invoke) { - callerGraphInfo.pushInvoke((Invoke) newNode); + // process invokes that are possibly created during canonicalization + for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) { + if (newNode instanceof Invoke) { + callerGraphInfo.pushInvoke((Invoke) newNode); + } } } - } + + callerGraphInfo.computeProbabilities(); - callerGraphInfo.computeProbabilities(); - - inliningCount++; - metricInliningPerformed.increment(); + inliningCount++; + metricInliningPerformed.increment(); + } } catch (BailoutException bailout) { throw bailout; } catch (AssertionError | RuntimeException e) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,11 +24,8 @@ import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; -import static com.oracle.graal.nodes.type.StampFactory.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; - -import java.lang.reflect.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.compiler.common.type.StampFactory.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -140,13 +137,12 @@ */ private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final int inliningDepth, final boolean success, final String msg, final Object... args) { if (HotSpotPrintInlining.getValue()) { - final int mod = method.getModifiers(); // 1234567 TTY.print(" "); // print timestamp // 1234 TTY.print(" "); // print compilation number // % s ! b n - TTY.print("%c%c%c%c%c ", ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' '); + TTY.print("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' '); TTY.print(" "); // more indent TTY.print(" "); // initial inlining indent for (int i = 0; i < inliningDepth; i++) { @@ -435,7 +431,7 @@ super(invoke); this.concrete = concrete; this.type = type; - assert type.isArray() || !isAbstract(type.getModifiers()) : type; + assert type.isArray() || !type.isAbstract() : type; } @Override @@ -1114,7 +1110,7 @@ private static InlineInfo getAssumptionInlineInfo(InliningData data, Invoke invoke, Replacements replacements, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod concrete, Assumption takenAssumption) { - assert !Modifier.isAbstract(concrete.getModifiers()); + assert !concrete.isAbstract(); if (!checkTargetConditions(data, replacements, invoke, concrete, optimisticOpts)) { return null; } @@ -1122,7 +1118,7 @@ } private static InlineInfo getExactInlineInfo(InliningData data, Invoke invoke, Replacements replacements, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod targetMethod) { - assert !Modifier.isAbstract(targetMethod.getModifiers()); + assert !targetMethod.isAbstract(); if (!checkTargetConditions(data, replacements, invoke, targetMethod, optimisticOpts)) { return null; } @@ -1152,7 +1148,7 @@ } ResolvedJavaType type = ptypes[0].getType(); - assert type.isArray() || !isAbstract(type.getModifiers()); + assert type.isArray() || !type.isAbstract(); ResolvedJavaMethod concrete = type.resolveMethod(targetMethod); if (!checkTargetConditions(data, replacements, invoke, concrete, optimisticOpts)) { return null; @@ -1224,7 +1220,7 @@ if (index == -1) { notRecordedTypeProbability += type.getProbability(); } else { - assert type.getType().isArray() || !isAbstract(type.getType().getModifiers()) : type + " " + concrete; + assert type.getType().isArray() || !type.getType().isAbstract() : type + " " + concrete; usedTypes.add(type); typesToConcretes.add(index); } @@ -1277,9 +1273,9 @@ private static boolean checkTargetConditions(InliningData data, Replacements replacements, Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) { if (method == null) { return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method is not resolved"); - } else if (Modifier.isNative(method.getModifiers()) && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) { + } else if (method.isNative() && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) { return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is a non-intrinsic native method"); - } else if (Modifier.isAbstract(method.getModifiers())) { + } else if (method.isAbstract()) { return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is an abstract method"); } else if (!method.getDeclaringClass().isInitialized()) { return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method's class is not initialized"); @@ -1320,8 +1316,6 @@ assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal(); assert !invokeNode.graph().isAfterFloatingReadPhase() : "inline isn't handled correctly after floating reads phase"; - Kind returnKind = invokeNode.getKind(); - FrameState stateAfter = invoke.stateAfter(); assert stateAfter == null || stateAfter.isAlive(); if (receiverNullCheck && !((MethodCallTargetNode) invoke.callTarget()).isStatic()) { @@ -1399,52 +1393,14 @@ } else { if (unwindNode != null) { UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode); - MonitorExitNode monitorExit = findPrecedingMonitorExit(unwindDuplicate); - DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); - unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode)); - // move the deopt upwards if there is a monitor exit that tries to use the - // "after exception" frame state - // (because there is no "after exception" frame state!) - if (monitorExit != null) { - if (monitorExit.stateAfter() != null && monitorExit.stateAfter().bci == FrameState.AFTER_EXCEPTION_BCI) { - FrameState monitorFrameState = monitorExit.stateAfter(); - graph.removeFixed(monitorExit); - monitorFrameState.safeDelete(); - } - } + DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + unwindDuplicate.replaceAndDelete(deoptimizeNode); } } if (stateAfter != null) { - FrameState outerFrameState = null; + processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge); int callerLockDepth = stateAfter.nestedLockDepth(); - for (FrameState original : inlineGraph.getNodes(FrameState.class)) { - FrameState frameState = (FrameState) duplicates.get(original); - if (frameState != null) { - assert frameState.bci != FrameState.BEFORE_BCI : frameState; - if (frameState.bci == FrameState.AFTER_BCI) { - frameState.replaceAndDelete(returnKind == Kind.Void ? stateAfter : stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), returnKind, - frameState.stackAt(0))); - } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) { - if (frameState.isAlive()) { - assert stateAtExceptionEdge != null; - frameState.replaceAndDelete(stateAtExceptionEdge); - } else { - assert stateAtExceptionEdge == null; - } - } else { - // only handle the outermost frame states - if (frameState.outerFrameState() == null) { - assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method()); - if (outerFrameState == null) { - outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invokeNode.getKind()); - outerFrameState.setDuringCall(true); - } - frameState.setOuterFrameState(outerFrameState); - } - } - } - } if (callerLockDepth != 0) { for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.class)) { MonitorIdNode monitor = (MonitorIdNode) duplicates.get(original); @@ -1482,6 +1438,93 @@ return duplicates; } + protected static void processFrameStates(Invoke invoke, StructuredGraph inlineGraph, Map<Node, Node> duplicates, FrameState stateAtExceptionEdge) { + FrameState stateAtReturn = invoke.stateAfter(); + FrameState outerFrameState = null; + Kind invokeReturnKind = invoke.asNode().getKind(); + for (FrameState original : inlineGraph.getNodes(FrameState.class)) { + FrameState frameState = (FrameState) duplicates.get(original); + if (frameState != null && frameState.isAlive()) { + if (frameState.bci == BytecodeFrame.AFTER_BCI) { + /* + * pop return kind from invoke's stateAfter and replace with this frameState's + * return value (top of stack) + */ + FrameState stateAfterReturn = stateAtReturn; + if (invokeReturnKind != Kind.Void && frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0)) { + stateAfterReturn = stateAtReturn.duplicateModified(invokeReturnKind, frameState.stackAt(0)); + } + frameState.replaceAndDelete(stateAfterReturn); + } else if (stateAtExceptionEdge != null && isStateAfterException(frameState)) { + /* + * pop exception object from invoke's stateAfter and replace with this + * frameState's exception object (top of stack) + */ + FrameState stateAfterException = stateAtExceptionEdge; + if (frameState.stackSize() > 0 && stateAtExceptionEdge.stackAt(0) != frameState.stackAt(0)) { + stateAfterException = stateAtExceptionEdge.duplicateModified(Kind.Object, frameState.stackAt(0)); + } + frameState.replaceAndDelete(stateAfterException); + } else if (frameState.bci == BytecodeFrame.UNWIND_BCI || frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { + handleMissingAfterExceptionFrameState(frameState); + } else { + // only handle the outermost frame states + if (frameState.outerFrameState() == null) { + assert frameState.bci != BytecodeFrame.BEFORE_BCI : frameState; + assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method()); + assert frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI && frameState.bci != BytecodeFrame.BEFORE_BCI && frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI && + frameState.bci != BytecodeFrame.UNWIND_BCI : frameState.bci; + if (outerFrameState == null) { + outerFrameState = stateAtReturn.duplicateModified(invoke.bci(), stateAtReturn.rethrowException(), invokeReturnKind); + outerFrameState.setDuringCall(true); + } + frameState.setOuterFrameState(outerFrameState); + } + } + } + } + } + + private static boolean isStateAfterException(FrameState frameState) { + return frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI || (frameState.bci == BytecodeFrame.UNWIND_BCI && !frameState.method().isSynchronized()); + } + + protected static void handleMissingAfterExceptionFrameState(FrameState nonReplaceableFrameState) { + Graph graph = nonReplaceableFrameState.graph(); + NodeWorkList workList = graph.createNodeWorkList(); + workList.add(nonReplaceableFrameState); + for (Node node : workList) { + FrameState fs = (FrameState) node; + for (Node usage : fs.usages().snapshot()) { + if (!usage.isAlive()) { + continue; + } + if (usage instanceof FrameState) { + workList.add(usage); + } else { + StateSplit stateSplit = (StateSplit) usage; + FixedNode fixedStateSplit = stateSplit.asNode(); + if (fixedStateSplit instanceof MergeNode) { + MergeNode merge = (MergeNode) fixedStateSplit; + while (merge.isAlive()) { + AbstractEndNode end = merge.forwardEnds().first(); + DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + end.replaceAtPredecessor(deoptimizeNode); + GraphUtil.killCFG(end); + } + } else { + FixedNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + if (fixedStateSplit instanceof BeginNode) { + deoptimizeNode = BeginNode.begin(deoptimizeNode); + } + fixedStateSplit.replaceAtPredecessor(deoptimizeNode); + GraphUtil.killCFG(fixedStateSplit); + } + } + } + } + } + public static ValueNode mergeReturns(MergeNode merge, List<? extends ReturnNode> returnNodes) { PhiNode returnValuePhi = null; @@ -1507,7 +1550,7 @@ for (Node node : duplicates.values()) { if (node instanceof FrameState) { FrameState frameState = (FrameState) node; - assert frameState.bci == FrameState.AFTER_BCI || frameState.bci == FrameState.INVALID_FRAMESTATE_BCI : node.toString(Verbosity.Debugger); + assert frameState.bci == BytecodeFrame.AFTER_BCI || frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI : node.toString(Verbosity.Debugger); } } return true; @@ -1521,7 +1564,7 @@ assert !callTarget.isStatic() : callTarget.targetMethod(); StructuredGraph graph = callTarget.graph(); ValueNode firstParam = callTarget.arguments().get(0); - if (firstParam.getKind() == Kind.Object && !ObjectStamp.isObjectNonNull(firstParam)) { + if (firstParam.getKind() == Kind.Object && !StampTool.isObjectNonNull(firstParam)) { IsNullNode condition = graph.unique(new IsNullNode(firstParam)); Stamp stamp = firstParam.stamp().join(objectNonNull()); GuardingPiNode nonNullReceiver = graph.add(new GuardingPiNode(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp));
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -62,7 +62,7 @@ canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); listener.getChangedNodes().clear(); if (++count > MAX_ITERATIONS) { - throw new BailoutException("Number of iterations in conditional elimination phase exceeds " + MAX_ITERATIONS); + throw new BailoutException("Number of iterations in ConditionalEliminationPhase phase exceeds " + MAX_ITERATIONS); } } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; @@ -36,7 +37,6 @@ import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.phases.common; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; /**
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -55,8 +55,11 @@ private static final String GROUP_NAME = "~profiled weight"; private static final String GROUP_NAME_WITHOUT = "~profiled weight (invoke-free sections)"; + private static final String GROUP_NAME_INVOKES = "~profiled invokes"; private static final boolean WITH_SECTION_HEADER = false; + private static boolean WITH_INVOKE_FREE_SECTIONS = false; + private static boolean WITH_INVOKES = true; @Override protected void run(StructuredGraph graph) { @@ -72,7 +75,22 @@ addSectionCounters(loop.header.getBeginNode(), loop.blocks, loop.children, schedule, probabilities); } } - addSectionCounters(graph.start(), Arrays.asList(cfg.getBlocks()), cfg.getLoops(), schedule, probabilities); + // don't put the counter increase directly after the start (problems with OSR) + FixedWithNextNode current = graph.start(); + while (current.next() instanceof FixedWithNextNode) { + current = (FixedWithNextNode) current.next(); + } + addSectionCounters(current, Arrays.asList(cfg.getBlocks()), cfg.getLoops(), schedule, probabilities); + + if (WITH_INVOKES) { + for (Node node : graph.getNodes()) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + DynamicCounterNode.addCounterBefore(GROUP_NAME_INVOKES, invoke.callTarget().targetName(), 1, true, invoke.asNode()); + + } + } + } } private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop<Block>> childLoops, SchedulePhase schedule, NodesToDoubles probabilities) { @@ -82,7 +100,7 @@ } double weight = getSectionWeight(schedule, probabilities, blocks) / probabilities.get(start); DynamicCounterNode.addCounterBefore(GROUP_NAME, sectionHead(start), (long) weight, true, start.next()); - if (!hasInvoke(blocks)) { + if (WITH_INVOKE_FREE_SECTIONS && !hasInvoke(blocks)) { DynamicCounterNode.addCounterBefore(GROUP_NAME_WITHOUT, sectionHead(start), (long) weight, true, start.next()); } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -39,7 +39,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,233 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.code.Assumptions; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugMetric; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.spi.CanonicalizerTool; +import com.oracle.graal.nodes.*; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.phases.graph.PostOrderNodeIterator; +import com.oracle.graal.phases.tiers.PhaseContext; + +import java.util.ArrayList; + +/** + * <p> + * For readability purposes the code realizing control-flow-sensitive reductions is chopped into + * several classes in an inheritance hierarchy, this class being their common ancestor. That way, + * many dependencies can be ruled out immediately (e.g., private members of a class aren't needed by + * other classes). The whole thing is reminiscent of trait-based patterns, minus their + * disadvantages. + * </p> + * + * + * <p> + * This class makes available little more than a few fields and a few utility methods used + * throughout the remaining components making up control-flow sensitive reductions. + * </p> + * */ +public abstract class BaseReduction extends PostOrderNodeIterator<State> { + + protected static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved"); + protected static final DebugMetric metricGuardingPiNodeRemoved = Debug.metric("GuardingPiNodeRemoved"); + protected static final DebugMetric metricFixedGuardNodeRemoved = Debug.metric("FixedGuardNodeRemoved"); + protected static final DebugMetric metricMethodResolved = Debug.metric("MethodResolved"); + + /** + * <p> + * Upon visiting a {@link com.oracle.graal.nodes.FixedNode FixedNode} in + * {@link #node(com.oracle.graal.nodes.FixedNode)}, an impossible path may be detected. We'd + * like to insert an unconditional deoptimizing node as a hint for Dead Code Elimination to kill + * that branch. However that can't be made on the go (a + * {@link com.oracle.graal.nodes.ControlSinkNode} can't have successors). Thus their insertion + * is postponed till the end of a round of + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction}. + * </p> + * + * @see State#impossiblePath() + * @see com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#finished() + * */ + public static class PostponedDeopt { + + private final boolean goesBeforeFixed; + private final FixedWithNextNode fixed; + private final DeoptimizationReason deoptReason; + + public PostponedDeopt(boolean goesBeforeFixed, FixedWithNextNode fixed, DeoptimizationReason deoptReason) { + this.goesBeforeFixed = goesBeforeFixed; + this.fixed = fixed; + this.deoptReason = deoptReason; + } + + public void doRewrite(LogicNode falseConstant) { + StructuredGraph graph = fixed.graph(); + // have to insert a FixedNode other than a ControlSinkNode + FixedGuardNode buckStopsHere = graph.add(new FixedGuardNode(falseConstant, deoptReason, DeoptimizationAction.None)); + if (goesBeforeFixed) { + fixed.replaceAtPredecessor(buckStopsHere); + } else { + graph.addAfterFixed(fixed, buckStopsHere); + } + } + + } + + protected static class PostponedDeopts extends ArrayList<PostponedDeopt> { + + private static final long serialVersionUID = 7188324432387121238L; + + /** + * Enqueue adding a {@link com.oracle.graal.nodes.DeoptimizeNode} right before the fixed + * argument, will be done once we're done traversing the graph. + * + * @see #finished() + * */ + void addDeoptBefore(FixedWithNextNode fixed, DeoptimizationReason deoptReason) { + add(new PostponedDeopt(true, fixed, deoptReason)); + } + + /** + * Enqueue adding a {@link com.oracle.graal.nodes.DeoptimizeNode} right after the fixed + * argument, will be done once we're done traversing the graph. + * + * @see #finished() + * */ + void addDeoptAfter(FixedWithNextNode fixed, DeoptimizationReason deoptReason) { + add(new PostponedDeopt(false, fixed, deoptReason)); + } + + } + + /** + * <p> + * One of the promises of + * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)} + * is that a "maximally reduced" node is returned. That is achieved in part by leveraging + * {@link com.oracle.graal.graph.Node#canonical(com.oracle.graal.graph.spi.CanonicalizerTool)}. + * Doing so, in turn, requires this subclass of + * {@link com.oracle.graal.graph.spi.CanonicalizerTool}. + * </p> + * */ + public final class Tool implements CanonicalizerTool { + + private final PhaseContext context; + + public Tool(PhaseContext context) { + this.context = context; + } + + @Override + public Assumptions assumptions() { + return context.getAssumptions(); + } + + @Override + public MetaAccessProvider getMetaAccess() { + return context.getMetaAccess(); + } + + @Override + public ConstantReflectionProvider getConstantReflection() { + return context.getConstantReflection(); + } + + /** + * Postpone + * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} + * until {@link FlowSensitiveReduction#finished()} for the reasons covered there. + * */ + @Override + public void removeIfUnused(Node node) { + // GraphUtil.tryKillUnused(node); + } + + @Override + public boolean canonicalizeReads() { + return false; + } + } // end of class FlowSensitiveReduction.Tool + + protected final LogicConstantNode trueConstant; + protected final LogicConstantNode falseConstant; + protected final ConstantNode nullConstant; + + protected final CanonicalizerTool tool; + protected final StructuredGraph graph; + + protected EquationalReasoner reasoner; + + protected final PostponedDeopts postponedDeopts = new PostponedDeopts(); + + protected BaseReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState); + graph = start.graph(); + trueConstant = LogicConstantNode.tautology(graph); + falseConstant = LogicConstantNode.contradiction(graph); + nullConstant = ConstantNode.defaultForKind(Kind.Object, graph); // ConstantNode.forObject(null, + // metaAccess, graph); + tool = new Tool(context); + reasoner = new EquationalReasoner(graph, tool, trueConstant, falseConstant, nullConstant); + } + + /** + * <p> + * Test whether the output's stamp is an upcast of that of the input. For example, upon + * replacing a CheckCastNode in + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode, com.oracle.graal.nodes.ValueNode)} + * we don't want to be left with an upcast, as it loses precision. + * </p> + * + * <p> + * As usual with object stamps, they can be compared along different dimensions (alwaysNull, + * etc.) It's enough for one such dimension to show precision loss for the end result to be + * reported as such. + * </p> + * + * */ + protected static boolean precisionLoss(ValueNode input, ValueNode output) { + ObjectStamp inputStamp = (ObjectStamp) input.stamp(); + ObjectStamp outputStamp = (ObjectStamp) output.stamp(); + if (FlowUtil.isMorePrecise(inputStamp.type(), outputStamp.type())) { + return true; + } + if (lessThan(outputStamp.alwaysNull(), inputStamp.alwaysNull())) { + return true; + } + if (lessThan(outputStamp.nonNull(), inputStamp.nonNull())) { + return true; + } + if (lessThan(outputStamp.isExactType(), inputStamp.isExactType())) { + return true; + } + return false; + } + + private static boolean lessThan(boolean a, boolean b) { + return a == false && b == true; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,87 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.nodes.LogicNode; +import com.oracle.graal.nodes.ShortCircuitOrNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.java.InstanceOfNode; + +/** + * @see #extract(com.oracle.graal.nodes.LogicNode) + * */ +class CastCheckExtractor { + + public final ResolvedJavaType type; + public final ValueNode subject; + + CastCheckExtractor(ResolvedJavaType type, ValueNode subject) { + this.type = type; + this.subject = subject; + } + + static CastCheckExtractor extractCastCheckInfo(LogicNode x, LogicNode y) { + if (x instanceof IsNullNode) { + IsNullNode isNull = (IsNullNode) x; + ValueNode subject = isNull.object(); + if (isInstanceOfCheckOn(y, subject)) { + InstanceOfNode iOf = (InstanceOfNode) y; + return new CastCheckExtractor(iOf.type(), subject); + } + } + return null; + } + + /** + * This method detects whether the argument realizes the CheckCast pattern. If so, distills and + * returns the essentials of such check, otherwise returns null. + * */ + static CastCheckExtractor extract(LogicNode cond) { + if (!(cond instanceof ShortCircuitOrNode)) { + return null; + } + ShortCircuitOrNode orNode = (ShortCircuitOrNode) cond; + if (orNode.isXNegated() || orNode.isYNegated()) { + return null; + } + CastCheckExtractor result = extractCastCheckInfo(orNode.getX(), orNode.getY()); + if (result != null) { + return result; + } + result = extractCastCheckInfo(orNode.getY(), orNode.getX()); + return result; + } + + /** + * Porcelain method. + * */ + public static boolean isInstanceOfCheckOn(LogicNode cond, ValueNode subject) { + if (!(cond instanceof InstanceOfNode)) { + return false; + } + InstanceOfNode io = (InstanceOfNode) cond; + return io.object() == subject; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,337 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.phases.tiers.PhaseContext; + +import static com.oracle.graal.api.meta.DeoptimizationAction.InvalidateReprofile; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; + +/** + * <p> + * This class implements control-flow sensitive reductions for + * {@link com.oracle.graal.nodes.java.CheckCastNode}. + * </p> + * + * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * */ +public abstract class CheckCastReduction extends GuardingPiReduction { + + public CheckCastReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState, context); + } + + /** + * <p> + * This phase is able to refine the types of reference-values at use sites provided a + * {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} is available witnessing + * that fact. + * </p> + * + * <p> + * This method turns non-redundant {@link com.oracle.graal.nodes.java.CheckCastNode}s into + * {@link com.oracle.graal.nodes.GuardingPiNode}s. Once such lowering has been performed (during + * run N of this phase) follow-up runs attempt to further simplify the resulting node, see + * {@link EquationalReasoner#downcastedGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode, Witness)} + * and {@link #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)} + * </p> + * + * <p> + * Precondition: the inputs (ie, object) hasn't been deverbosified yet. + * </p> + * */ + protected final void visitCheckCastNode(CheckCastNode checkCast) { + + /* + * checkCast.object() hasn't been deverbosified yet. + */ + + if (!FlowUtil.hasLegalObjectStamp(checkCast)) { + // This situation is exercised by test Class_cast01 + return; + } + + final ValueNode subject = checkCast.object(); + final ResolvedJavaType toType = checkCast.type(); + ObjectStamp subjectStamp = (ObjectStamp) subject.stamp(); + ResolvedJavaType subjectType = subjectStamp.type(); + + // --------- checkCast deemed redundant by subject-stamp alone --------- + // --------- in particular due to stamp informing always null ---------- + boolean isRedundantPerStamp = StampTool.isObjectAlwaysNull(subject) || (subjectType != null && toType.isAssignableFrom(subjectType)); + if (isRedundantPerStamp) { + metricCheckCastRemoved.increment(); + checkCast.replaceAtUsages(subject); + graph.removeFixed(checkCast); + return; + } + + assert !StampTool.isObjectAlwaysNull(subject) : "Null as per stamp subjects should have been handled above"; + + // --------- checkCast deemed unsatisfiable by subject-stamp alone --------- + if (state.knownNotToConform(subject, toType)) { + postponedDeopts.addDeoptBefore(checkCast, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException); + state.impossiblePath(); + // let FixedGuardNode(false).simplify() prune the dead-code control-path + return; + } + + /* + * Remark: subject may be TypeProxyNode, GuardedValueNode, ProxyNode, GuardingPiNode, among + * others. + */ + + PiNode untrivialNull = reasoner.untrivialNull(subject); + if (untrivialNull != null) { + metricCheckCastRemoved.increment(); + checkCast.replaceAtUsages(untrivialNull); + graph.removeFixed(checkCast); + return; + } + + Witness w = state.typeInfo(subject); + + if (w == null) { + /* + * If there's no witness, attempting `downcasted(subject)` is futile. + */ + visitCheckCastNodeLackingWitness(checkCast); + return; + } + + visitCheckCastNodeWithWitness(checkCast); + + } + + /** + * Given that no witness is available for the {@link com.oracle.graal.nodes.java.CheckCastNode} + * 's subject there's no point in downcasting such subject, ie no + * {@link com.oracle.graal.nodes.PiNode} can be fabricated for the subject. + * + * @see #lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode, + * com.oracle.graal.nodes.ValueNode) + * + * */ + private void visitCheckCastNodeLackingWitness(CheckCastNode checkCast) { + final ValueNode subject = checkCast.object(); + final ResolvedJavaType toType = checkCast.type(); + if (toType.isInterface()) { + return; + } + assert reasoner.downcasted(subject) == subject; + lowerCheckCastAnchorFriendlyWay(checkCast, subject); + } + + /** + * Porcelain method. + * + * <p> + * Rather than tracking the CheckCastNode via {@link com.oracle.graal.phases.common.cfs.State + * State} (doing so woud add a special case because a + * {@link com.oracle.graal.nodes.java.CheckCastNode} isn't a + * {@link com.oracle.graal.nodes.extended.GuardingNode}) this method creates an anchor by + * lowering the CheckCastNode into a FixedGuardNode. Not the same way as done by + * {@link com.oracle.graal.nodes.java.CheckCastNode#lower(com.oracle.graal.nodes.spi.LoweringTool)} + * which lowers into a {@link com.oracle.graal.nodes.GuardingPiNode} (which is not a + * {@link com.oracle.graal.nodes.extended.GuardingNode}). + * </p> + * + * <p> + * With that, state tracking can proceed as usual. + * </p> + * + * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * + * */ + public void lowerCheckCastAnchorFriendlyWay(CheckCastNode checkCast, ValueNode subject) { + ValueNode originalCheckCastObject = checkCast.object(); + + ObjectStamp subjectStamp = (ObjectStamp) subject.stamp(); + final ResolvedJavaType toType = checkCast.type(); + ObjectStamp resultStamp = (ObjectStamp) StampFactory.declared(toType); + JavaTypeProfile profile = checkCast.profile(); + + assert FlowUtil.isLegalObjectStamp(subjectStamp); + assert subjectStamp.type() == null || !toType.isAssignableFrom(subjectStamp.type()) : "No need to lower in an anchor-friendly way in the first place"; + + /* + * Depending on what is known about the subject: + * + * (a) definitely-non-null + * + * (b) null-not-seen-in-profiling + * + * (c) runtime-null-check-needed + * + * the condition (of the cast-guard to be emitted) and the stamp (of the PiNode to be + * emitted) are going to be different. Each of the three branches below deals with one of + * the cases above. + */ + LogicNode condition; + if (subjectStamp.nonNull()) { + /* + * (1 of 3) definitely-non-null + */ + // addWithoutUnique for the same reason as in CheckCastNode.lower() + condition = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile)); + reasoner.added.add(condition); + resultStamp = FlowUtil.asNonNullStamp(resultStamp); + // TODO fix in CheckCastNode.lower() + } else { + if (profile != null && profile.getNullSeen() == ProfilingInfo.TriState.FALSE) { + /* + * (2 of 3) null-not-seen-in-profiling + */ + IsNullNode isNN = graph.unique(new IsNullNode(subject)); + reasoner.added.add(isNN); + FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true)); + graph.addBeforeFixed(checkCast, nullCheck); + // not calling wrapInPiNode() because we don't want to rememberSubstitution() + PiNode nonNullGuarded = graph.unique(new PiNode(subject, FlowUtil.asNonNullStamp(subjectStamp), nullCheck)); + reasoner.added.add(nonNullGuarded); + // addWithoutUnique for the same reason as in CheckCastNode.lower() + condition = graph.addWithoutUnique(new InstanceOfNode(toType, nonNullGuarded, profile)); + reasoner.added.add(condition); + resultStamp = FlowUtil.asNonNullStamp(resultStamp); + } else { + /* + * (3 of 3) runtime-null-check-needed + */ + // addWithoutUnique for the same reason as in CheckCastNode.lower() + InstanceOfNode typeTest = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile)); + reasoner.added.add(typeTest); + LogicNode nullTest = graph.unique(new IsNullNode(subject)); + reasoner.added.add(nullTest); + // TODO (ds) replace with probability of null-seen when available + final double shortCircuitProbability = NOT_FREQUENT_PROBABILITY; + condition = LogicNode.or(nullTest, typeTest, shortCircuitProbability); + reasoner.added.add(condition); + } + } + + /* + * Add a cast-guard (checking only what needs to be checked) and a PiNode (to be used in + * place of the CheckCastNode). + */ + FixedGuardNode castGuard = graph.add(new FixedGuardNode(condition, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException, InvalidateReprofile)); + graph.addBeforeFixed(checkCast, castGuard); + + assert FlowUtil.isLegalObjectStamp(resultStamp); + Witness w = state.typeInfo(subject); + assert !isTypeOfWitnessBetter(w, resultStamp); + + if (!FlowUtil.lacksUsages(checkCast)) { + // not calling wrapInPiNode() because we don't want to rememberSubstitution() + PiNode checkedObject = graph.unique(new PiNode(subject, resultStamp, castGuard)); + reasoner.added.add(checkedObject); + assert !precisionLoss(originalCheckCastObject, checkedObject); + assert !precisionLoss(subject, checkedObject); + checkCast.replaceAtUsages(checkedObject); + } + + graph.removeFixed(checkCast); + + if (resultStamp.nonNull()) { + state.trackIO(subject, toType, castGuard); + } else { + state.trackCC(subject, toType, castGuard); + } + } + + /** + * Porcelain method. + * */ + public static boolean isTypeOfWitnessBetter(Witness w, ObjectStamp stamp) { + if (w == null) { + return false; + } + return FlowUtil.isMorePrecise(w.type(), stamp.type()); + } + + /** + * + * Please note in this method "subject" refers to the downcasted input to the checkCast. + * + * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * */ + private void visitCheckCastNodeWithWitness(CheckCastNode checkCast) { + + final ResolvedJavaType toType = checkCast.type(); + + ValueNode subject; + if (checkCast.object() instanceof CheckCastNode) { + subject = reasoner.downcasted(checkCast); + if (subject == checkCast) { + subject = reasoner.downcasted(checkCast.object()); + } + } else { + subject = reasoner.downcasted(checkCast.object()); + } + + ObjectStamp subjectStamp = (ObjectStamp) subject.stamp(); + ResolvedJavaType subjectType = subjectStamp.type(); + + // TODO move this check to downcasted() + assert !precisionLoss(checkCast.object(), subject); + + /* + * At this point, two sources of (partial) information: the witness and the stamp of + * subject. The latter might be more precise than the witness (eg, subject might be + * GuardedValueNode) + */ + + // --------- checkCast made redundant by downcasting its input --------- + if (subjectType != null && toType.isAssignableFrom(subjectType)) { + checkCast.replaceAtUsages(subject); + graph.removeFixed(checkCast); + return; + } + + /* + * At this point, `downcasted()` might or might not have delivered a more precise value. If + * more precise, it wasn't precise enough to conform to `toType`. Even so, for the + * `toType.isInterface()` case (dealt with below) we'll replace the checkCast's input with + * that value (its class-stamp being more precise than the original). + */ + + if (toType.isInterface()) { + boolean wasDowncasted = (subject != checkCast.object()); + if (wasDowncasted) { + FlowUtil.replaceInPlace(checkCast, checkCast.object(), subject); + } + return; + } + + lowerCheckCastAnchorFriendlyWay(checkCast, subject); + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,946 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugMetric; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeBitMap; +import com.oracle.graal.graph.spi.CanonicalizerTool; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.calc.ObjectEqualsNode; +import com.oracle.graal.nodes.extended.GuardedNode; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.java.CheckCastNode; +import com.oracle.graal.nodes.java.InstanceOfNode; +import com.oracle.graal.nodes.spi.ValueProxy; +import com.oracle.graal.compiler.common.type.IllegalStamp; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.nodes.util.GraphUtil; + +import java.util.IdentityHashMap; +import java.util.Set; + +/** + * <p> + * This class implements a simple partial evaluator that recursively reduces a given + * {@link com.oracle.graal.nodes.calc.FloatingNode} into a simpler one based on the current state. + * Such evaluator comes handy when visiting a {@link com.oracle.graal.nodes.FixedNode} N, just + * before updating the state for N. At the pre-state, an {@link EquationalReasoner + * EquationalReasoner} can be used to reduce N's inputs (actually only those inputs of Value and + * Condition {@link com.oracle.graal.graph.InputType InputType}). For an explanation of where it's + * warranted to replace "old input" with "reduced input", see the inline comments in method + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node n) deverbosify(Node n)} + * </p> + * + * <p> + * The name {@link EquationalReasoner EquationalReasoner} was chosen because it conveys what it + * does. + * </p> + */ +public final class EquationalReasoner { + + private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved"); + private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved"); + private static final DebugMetric metricObjectEqualsRemoved = Debug.metric("ObjectEqualsRemoved"); + private static final DebugMetric metricEquationalReasoning = Debug.metric("EquationalReasoning"); + private static final DebugMetric metricDowncasting = Debug.metric("Downcasting"); + + private final StructuredGraph graph; + private final CanonicalizerTool tool; + private final LogicConstantNode trueConstant; + private final LogicConstantNode falseConstant; + private final ConstantNode nullConstant; + + private State state; + private NodeBitMap visited; + + /** + * The reduction of a {@link com.oracle.graal.nodes.calc.FloatingNode} performed by + * {@link EquationalReasoner EquationalReasoner} may result in a FloatingNode being added to the + * graph. Those nodes aren't tracked in the {@link EquationalReasoner#visited visited} + * {@link com.oracle.graal.graph.NodeBitMap NodeBitMap} but in this set instead (those nodes are + * added after the {@link com.oracle.graal.graph.NodeBitMap} was obtained). + */ + final Set<ValueNode> added = java.util.Collections.newSetFromMap(new IdentityHashMap<ValueNode, Boolean>()); + + /** + * The reduction of a FloatingNode performed by {@link EquationalReasoner EquationalReasoner} + * may result in a FloatingNode being added to the graph. Those nodes are tracked in this map, + * to avoid recomputing them. + * + * The substitutions tracked in this field become invalid as described in + * {@link #updateState(com.oracle.graal.phases.common.cfs.State) updateState(State)} + */ + private final IdentityHashMap<ValueNode, ValueNode> substs = new IdentityHashMap<>(); + + public EquationalReasoner(StructuredGraph graph, CanonicalizerTool tool, LogicConstantNode trueConstant, LogicConstantNode falseConstant, ConstantNode nullConstant) { + this.graph = graph; + this.tool = tool; + this.trueConstant = trueConstant; + this.falseConstant = falseConstant; + this.nullConstant = nullConstant; + } + + /** + * {@link #added} grows during a run of + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase + * FlowSensitiveReductionPhase}, and doesn't survive across runs. + * */ + public void forceState(State s) { + state = s; + substs.clear(); + added.clear(); + visited = null; + versionNrAsofLastForce = s.versionNr; + } + + /** + * <p> + * Gaining more precise type information about an SSA value doesn't "invalidate" as such any of + * the substitutions tracked in {@link EquationalReasoner#substs substs}, at least not in the + * sense of making the value tracked by one such entry "wrong". However, clearing the + * {@link EquationalReasoner#substs substs} is still justified because next time they are + * computed, the newly computed reduction could (in principle) be more effective (due to the + * more precise type information). + * </p> + * + * <p> + * Between clearings of cached substitutions, it is expected they get applied a number of times + * to justify the bookkeeping cost. + * </p> + * + */ + public void updateState(State s) { + assert s != null; + if (state == null || state != s || state.versionNr != versionNrAsofLastForce) { + forceState(s); + } + } + + private int versionNrAsofLastForce = 0; + + /** + * Reduce the argument based on the state at the program point where the argument is consumed. + * For most FixedNodes, that's how their inputs can be reduced. Two exceptions: + * <ul> + * <li> + * the condition of a {@link com.oracle.graal.nodes.GuardingPiNode}, see + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)} + * </li> + * <li> + * the condition of a {@link com.oracle.graal.nodes.FixedGuardNode}, see + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)} + * </li> + * + * </ul> + * + * + * <p> + * Part of the reduction work is delegated to baseCase-style reducers, whose contract explicitly + * requires them not to deverbosify the argument's inputs --- the decision is made based on the + * argument only (thus "base case"). Returning the unmodified argument is how a baseCase-style + * tells this method to fall to the default case (for a floating node only: walk into the + * argument's inputs, canonicalize followed by + * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode) + * rememberSubstitution()} if any input changed). + * </p> + * + * <p> + * This method must behave as a function (idempotent query method), ie refrain from mutating the + * state other than updating caches: + * <ul> + * <li>{@link EquationalReasoner#added EquationalReasoner#added},</li> + * <li>{@link EquationalReasoner#visited EquationalReasoner#visited} and</li> + * <li>the cache updated via + * {@link EquationalReasoner#rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode) + * EquationalReasoner#rememberSubstitution(ValueNode, FloatingNode)}.</li> + * </ul> + * </p> + * + * <p> + * In turn, baseCase-style reducers are even more constrained: besides behaving as functions, + * their contract prevents them from updating any caches (basically because they already grab + * the answer from caches, if the answer isn't there they should just return their unmodified + * argument). + * </p> + * + * <p> + * This method returns: + * <ul> + * <li> + * the original argument, in case no reduction possible.</li> + * <li> + * a {@link com.oracle.graal.nodes.ValueNode ValueNode} different from the argument, in case the + * conditions for a reduction were met. The node being returned might be already in the graph. + * In any case it's canonicalized already, the caller need not perform that again.</li> + * <li> + * the unmodified argument, in case no reduction was made. Otherwise, a maximally reduced + * {@link com.oracle.graal.nodes.ValueNode}.</li> + * </ul> + * </p> + * + * @see com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode) + * + * @see com.oracle.graal.phases.common.cfs.BaseReduction.Tool + * + */ + public Node deverbosify(final Node n) { + + // -------------------------------------------------------------------- + // cases that don't initiate any call-chain that may enter this method + // -------------------------------------------------------------------- + + if (n == null) { + return null; + } + assert !(n instanceof GuardNode) : "This phase not yet ready to run during MidTier"; + if (!(n instanceof ValueNode)) { + return n; + } + ValueNode v = (ValueNode) n; + if (v.stamp() instanceof IllegalStamp) { + return v; + } + if (FlowUtil.isLiteralNode(v)) { + return v; + } + ValueNode result = substs.get(v); + if (result != null) { + // picked cached substitution + return result; + } + if ((visited != null && visited.contains(n)) || added.contains(v)) { + return v; + } + + // -------------------------------------------------------------------- + // stack overflow prevention via added, visited + // -------------------------------------------------------------------- + + if (visited == null) { + visited = graph.createNodeBitMap(); + } + visited.mark(n); + + /* + * Past this point, if we ever want `n` to be deverbosified, it must be looked-up by one of + * the cases above. One sure way to achieve that is with `rememberSubstitution(old, new)` + */ + if (v instanceof ValueProxy) { + return downcasted(v); + } + + if (n instanceof FloatingNode) { + /* + * `deverbosifyFloatingNode()` will drill down over floating inputs, when that not + * possible anymore it resorts to calling `downcasted()`. Thus it's ok to take the + * `deverbosifyFloatingNode()` route first, as no downcasting opportunity will be + * missed. + */ + return deverbosifyFloatingNode((FloatingNode) n); + } + + if (FlowUtil.hasLegalObjectStamp(v)) { + return downcasted(v); + } + + return n; + } + + /** + * This method: + * + * <ul> + * <li> + * Recurses only over floating inputs to attempt reductions, leave anything else as is.</li> + * <li> + * Performs copy-on-write aka lazy-DAG-copying as described in source comments, in-line.</li> + * <li> + * Usage: must be called only from {@link #deverbosify(com.oracle.graal.graph.Node) + * deverbosify(Node)}.</li> + * </ul> + * */ + public Node deverbosifyFloatingNode(final FloatingNode n) { + + assert n != null : "Should have been caught in deverbosify()"; + assert !(n instanceof ValueProxy) : "Should have been caught in deverbosify()"; + assert !FlowUtil.isLiteralNode(n) : "Should have been caught in deverbosify()"; + + if (n instanceof PhiNode) { + /* + * Each input to a PhiNode should be deverbosified with the state applicable to the path + * providing such input, as done in visitAbstractEndNode() + */ + return n; + } + + final FloatingNode f = baseCaseFloating(n); + if (f != n) { + return f; + } + + FloatingNode changed = null; + for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(f)) { + /* + * Although deverbosify() is invoked below, it's only for floating inputs. That way, the + * state can't be used to make invalid conclusions. + */ + Node j = (i instanceof FloatingNode) ? deverbosify(i) : i; + if (i != j) { + assert j != f; + if (changed == null) { + changed = (FloatingNode) f.copyWithInputs(); + added.add(changed); + // copyWithInputs() implies graph.unique(changed) + assert changed.isAlive(); + assert FlowUtil.lacksUsages(changed); + } + /* + * Note: we don't trade i for j at each usage of i (doing so would change meaning) + * but only at those usages consumed by `changed`. In turn, `changed` won't replace + * `n` at arbitrary usages, but only where such substitution is valid as per the + * state holding there. In practice, this means the buck stops at the "root" + * FixedNode on whose inputs deverbosify() is invoked for the first time, via + * deverbosifyInputsInPlace(). + */ + FlowUtil.replaceInPlace(changed, i, j); + } + } + if (changed == null) { + assert visited.contains(f) || added.contains(f); + if (FlowUtil.hasLegalObjectStamp(f)) { + /* + * No input has changed doesn't imply there's no witness to refine the + * floating-object value. + */ + ValueNode d = downcasted(f); + return d; + } else { + return f; + } + } + FlowUtil.inferStampAndCheck(changed); + added.add(changed); + ValueNode canon = (ValueNode) changed.canonical(tool); + // might be already in `added`, no problem adding it again. + added.add(canon); + rememberSubstitution(f, canon); + return canon; + } + + /** + * In case of doubt (on whether a reduction actually triggered) it's always ok to invoke " + * <code>rememberSubstitution(f, downcasted(f))</code>": this method records a map entry only if + * pre-image and image differ. + * + * @return the image of the substitution (ie, the second argument) unmodified. + * */ + private <M extends ValueNode> M rememberSubstitution(ValueNode from, M to) { + assert from != null && to != null; + if (from == to) { + return to; + } + // we don't track literals because they map to themselves + if (FlowUtil.isLiteralNode(from)) { + assert from == to; + return to; + } + /* + * It's ok for different keys (which were not unique in the graph after all) to map to the + * same value. However any given key can't map to different values. + */ + ValueNode image = substs.get(from); + if (image != null) { + assert image == to; + return to; + } + substs.put(from, to); + return to; + } + + /** + * The contract for this baseCase-style method is covered in + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) + * EquationalReasoner#deverbosify()} + * + * @return a {@link com.oracle.graal.nodes.calc.FloatingNode} different from the argument, in + * case a reduction was made. The node being returned might be already in the graph. In + * any case it's canonicalized already, the caller need not perform that again. In case + * no reduction was made, this method returns the unmodified argument. + */ + private FloatingNode baseCaseFloating(final FloatingNode f) { + if (f instanceof LogicNode) { + FloatingNode result = baseCaseLogicNode((LogicNode) f); + return rememberSubstitution(f, result); + } + return f; + } + + /** + * <p> + * Reduce the argument based on the state at the program point for it (ie, based on + * "valid facts" only, without relying on any floating-guard-assumption). + * </p> + * + * <p> + * The inputs of the argument aren't traversed into, for that + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) + * EquationalReasoner#deverbosify()} should be used instead. + * </p> + * <p> + * This method must behave as a function (idempotent query method): it should refrain from + * changing the state, as well as from updating caches (other than DebugMetric-s). + * </p> + * + * @return a {@link com.oracle.graal.nodes.LogicNode} different from the argument, in case a + * reduction was made. The node being returned might be already in the graph. In any + * case it's canonicalized already, the caller need not perform that again. In case no + * reduction was made, this method returns the unmodified argument. + * + */ + public FloatingNode baseCaseLogicNode(LogicNode condition) { + assert condition != null; + if (condition instanceof LogicConstantNode) { + return condition; + } else if (state.trueFacts.containsKey(condition)) { + metricEquationalReasoning.increment(); + return trueConstant; + } else if (state.falseFacts.containsKey(condition)) { + metricEquationalReasoning.increment(); + return falseConstant; + } else { + if (condition instanceof InstanceOfNode) { + return baseCaseInstanceOfNode((InstanceOfNode) condition); + } else if (condition instanceof IsNullNode) { + return baseCaseIsNullNode((IsNullNode) condition); + } else if (condition instanceof ObjectEqualsNode) { + return baseCaseObjectEqualsNode((ObjectEqualsNode) condition); + } + } + return condition; + } + + /** + * Actually the same result delivered by this method could be obtained by just letting + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) + * EquationalReasoner#deverbosify()} handle the argument in the default case for floating nodes + * (ie, deverbosify inputs followed by canonicalize). However it's done here for metrics + * purposes. + * + * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made; + * otherwise the unmodified argument. + * + */ + private LogicNode baseCaseInstanceOfNode(InstanceOfNode instanceOf) { + ValueNode scrutinee = GraphUtil.unproxify(instanceOf.object()); + if (!FlowUtil.hasLegalObjectStamp(scrutinee)) { + return instanceOf; + } + if (state.isNull(scrutinee)) { + metricInstanceOfRemoved.increment(); + return falseConstant; + } else if (state.isNonNull(scrutinee) && state.knownToConform(scrutinee, instanceOf.type())) { + metricInstanceOfRemoved.increment(); + return trueConstant; + } + return instanceOf; + } + + /** + * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was + * performed; otherwise the unmodified argument. + * + */ + private FloatingNode baseCaseIsNullNode(IsNullNode isNull) { + ValueNode object = isNull.object(); + if (!FlowUtil.hasLegalObjectStamp(object)) { + return isNull; + } + ValueNode scrutinee = GraphUtil.unproxify(isNull.object()); + GuardingNode evidence = untrivialNullAnchor(scrutinee); + if (evidence != null) { + metricNullCheckRemoved.increment(); + return trueConstant; + } else if (state.isNonNull(scrutinee)) { + metricNullCheckRemoved.increment(); + return falseConstant; + } + return isNull; + } + + /** + * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made; + * otherwise the unmodified argument. + */ + private LogicNode baseCaseObjectEqualsNode(ObjectEqualsNode equals) { + if (!FlowUtil.hasLegalObjectStamp(equals.x()) || !FlowUtil.hasLegalObjectStamp(equals.y())) { + return equals; + } + ValueNode x = GraphUtil.unproxify(equals.x()); + ValueNode y = GraphUtil.unproxify(equals.y()); + if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) { + metricObjectEqualsRemoved.increment(); + return falseConstant; + } else if (state.isNull(x) && state.isNull(y)) { + metricObjectEqualsRemoved.increment(); + return trueConstant; + } + return equals; + } + + /** + * It's always ok to use "<code>downcasted(object)</code>" instead of " <code>object</code>" + * because this method re-wraps the argument in a {@link com.oracle.graal.nodes.PiNode} only if + * the new stamp is strictly more refined than the original. + * + * <p> + * This method does not + * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)} + * . + * </p> + * + * @return One of: + * <ul> + * <li>a {@link com.oracle.graal.nodes.PiNode} with more precise stamp than the input if + * the state warrants such downcasting</li> + * <li>a {@link com.oracle.graal.nodes.java.CheckCastNode CheckCastNode} for the same + * scrutinee in question</li> + * <li>the unmodified argument otherwise.</li> + * </ul> + */ + ValueNode downcasted(final ValueNode object) { + + // ------------------------------------------------- + // actions based only on the stamp of the input node + // ------------------------------------------------- + + if (!FlowUtil.hasLegalObjectStamp(object)) { + return object; + } + if (FlowUtil.isLiteralNode(object)) { + return object; + } + if (StampTool.isObjectAlwaysNull(object.stamp())) { + return untrivialNull(object); + } + + // ------------------------------------------ + // actions based on the stamp and the witness + // ------------------------------------------ + + ValueNode scrutinee = GraphUtil.unproxify(object); + + PiNode untrivialNull = untrivialNull(scrutinee); + if (untrivialNull != null) { + return untrivialNull; + } + + Witness w = state.typeInfo(scrutinee); + if (w == null) { + // no additional hints being tracked for the scrutinee + return object; + } + + assert !w.clueless(); + + ObjectStamp inputStamp = (ObjectStamp) object.stamp(); + ObjectStamp witnessStamp = w.asStamp(); + if (inputStamp.equals(witnessStamp) || !FlowUtil.isMorePrecise(witnessStamp, inputStamp)) { + // the witness offers no additional precision over current one + fixupTypeProfileStamp(object); + return object; + } + + assert !FlowUtil.isMorePrecise(inputStamp.type(), w.type()); + + ValueNode result; + if (object instanceof ValueProxy) { + result = downcastedValueProxy((ValueProxy) object, w); + } else { + result = downcastedUtil(object, w); + } + + return result; + } + + /** + * TODO TypeProfileProxyNode.inferStamp doesn't infer non-null from non-null payload + * + * <p> + * And there's a bunch of asserts in + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} that assert no + * type-precision gets lost. Thus the need to fix-up on our own, as done here. + * </p> + * */ + private static void fixupTypeProfileStamp(ValueNode object) { + if (!(object instanceof TypeProfileProxyNode)) { + return; + } + TypeProfileProxyNode profile = (TypeProfileProxyNode) object; + ObjectStamp outgoinStamp = (ObjectStamp) profile.stamp(); + ObjectStamp payloadStamp = (ObjectStamp) profile.getObject().stamp(); + if (payloadStamp.nonNull() && !outgoinStamp.nonNull()) { + profile.setStamp(FlowUtil.asNonNullStamp(outgoinStamp)); + } + } + + /** + * <p> + * Porcelain method. + * </p> + * + * <p> + * Utility to create, add to the graph, + * {@link EquationalReasoner#rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)} + * , and return a {@link com.oracle.graal.nodes.PiNode} that narrows into the given stamp, + * anchoring the payload. + * </p> + * + * <p> + * The resulting node might not have been in the graph already. + * </p> + * */ + private PiNode wrapInPiNode(ValueNode payload, GuardingNode anchor, ObjectStamp newStamp, boolean remember) { + try (Debug.Scope s = Debug.scope("Downcast", payload)) { + assert payload != anchor : payload.graph().toString(); + metricDowncasting.increment(); + PiNode result = graph.unique(new PiNode(payload, newStamp, anchor.asNode())); + // we've possibly got a new node in the graph --- bookkeeping is in order. + added.add(result); + if (remember) { + rememberSubstitution(payload, result); + } + Debug.log("Downcasting from %s to %s", payload, result); + return result; + } catch (Throwable e) { + throw Debug.handle(e); + } + } + + /** + * <p> + * If the argument is known null due to its stamp, there's no need to have an anchor for that + * fact and this method returns null. + * </p> + * + * <p> + * Otherwise, if an anchor is found it is returned, null otherwise. + * </p> + */ + public GuardingNode untrivialNullAnchor(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + if (StampTool.isObjectAlwaysNull(object)) { + return null; + } + return state.knownNull.get(GraphUtil.unproxify(object)); + } + + /** + * + * This method returns: + * <ul> + * <li><b>null</b>, if the argument is known null due to its stamp. Otherwise,</li> + * <li><b>a PiNode</b> wrapping the null constant and an anchor offering evidence as to why the + * argument is known null, if such anchor is available. Otherwise,</li> + * <li><b>null</b></li> + * </ul> + * <p> + * This method does not + * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)} + * . + * </p> + */ + public PiNode untrivialNull(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + GuardingNode anchor = untrivialNullAnchor(object); + if (anchor == null) { + return null; + } + if (object instanceof GuardedNode && StampTool.isObjectAlwaysNull(object.stamp())) { + return (PiNode) object; + } + // notice nullConstant is wrapped, not object + PiNode result = wrapInPiNode(nullConstant, anchor, (ObjectStamp) StampFactory.alwaysNull(), false); + return result; + } + + // @formatter:off + /** + * <p>ValueProxys can be classified along two dimensions, + * in addition to the fixed-floating dichotomy.</p> + * + * <p> + * First, we might be interested in separating those ValueProxys + * that are entitled to change (usually narrow) their stamp from those that aren't. + * In the first category are: + * PiNode, PiArrayNode, GuardingPiNode, + * CheckCastNode, UnsafeCastNode, and + * GuardedValueNode. + * </p> + * + * <p> + * A note on stamp-narrowing ValueProxys: + * our state abstraction tracks only the type refinements induced by CheckCastNode and GuardingPiNode + * (which are fixed nodes, unlike the other stamp-narrowing ValueProxys; + * the reason being that the state abstraction can be updated only at fixed nodes). + * As a result, the witness for a (PiNode, PiArrayNode, UnsafeCastNode, or GuardedValueNode) + * may be less precise than the proxy's stamp. We don't want to lose such precision, + * thus <code>downcasted(proxy) == proxy</code> in such cases. + * </p> + * + * <p> + * The second classification focuses on + * the additional information that travels with the proxy + * (in addition to its "payload", ie getOriginalValue(), and any narrowing-stamp). + * Such additional information boils down to: + * + * (a) type profile (TypeProfileProxyNode) + * (b) type profile (CheckCastNode) + * (c) anchor (GuardedValueNode) + * (d) anchor (PiNode) + * (e) anchor and array length (PiArrayNode) + * (f) optional anchor (UnsafeCastNode) + * (g) deopt-condition (GuardingPiNode) + * (h) LocationIdentity (MemoryProxyNOde) + * (i) control-flow dependency (FixedValueAnchorNode) + * (j) proxyPoint (ProxyNode -- think loops) + *</p> + */ + // @formatter:on + private ValueNode downcastedValueProxy(ValueProxy proxy, Witness w) { + assert FlowUtil.hasLegalObjectStamp((ValueNode) proxy); + assert FlowUtil.hasLegalObjectStamp((proxy).getOriginalNode()); + assert GraphUtil.unproxify((ValueNode) proxy) == GraphUtil.unproxify(proxy.getOriginalNode()); + + assert GraphUtil.unproxify((ValueNode) proxy) == GraphUtil.unproxify((proxy).getOriginalNode()); + + if (proxy instanceof PiNode) { + return downcastedPiNodeOrPiArrayNode((PiNode) proxy, w); + } else if (proxy instanceof GuardingPiNode) { + return downcastedGuardingPiNode((GuardingPiNode) proxy, w); + } else if (proxy instanceof TypeProfileProxyNode) { + return downcastedTypeProfileProxyNode((TypeProfileProxyNode) proxy); + } else if (proxy instanceof CheckCastNode) { + return downcastedCheckCastNode((CheckCastNode) proxy, w); + } else if (proxy instanceof ProxyNode || proxy instanceof GuardedValueNode) { + // TODO scaladacapo return downcastedUtil((ValueNode) proxy, w); + return (ValueNode) proxy; + } + + assert false : "TODO case not yet handled"; + + // TODO complete the missing implementation for the cases not yet handled + + return ((ValueNode) proxy); + } + + /** + * <p> + * Why would we want to downcast a GuardingPiNode? Is it even possible? Like, for example, a + * GuardingPiNode originating in the lowering of a CheckCastNode (carried out by + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * visitCheckCastNode()}). + * </p> + * + * <p> + * It's both possible and desirable. Example: <code> + * Number n = (Number) o; + * if (n instanceof Integer) { + * return n.intValue(); + * } + * </code> + * + * The receiver of intValue() is a usage of a previous checkCast, for which the current witness + * provides a more refined type (and an anchor). In this case, the advantage of downcasting a + * GuardingPiNode is clear: devirtualizing the `intValue()` callsite. + * </p> + * + * @see #downcastedValueProxy + * */ + public ValueNode downcastedGuardingPiNode(GuardingPiNode envelope, Witness w) { + assert envelope != w.guard().asNode() : "The stamp of " + envelope + " would lead to downcasting with that very same GuardingPiNode as guard."; + return downcastedUtil(envelope, w); + } + + /** + * <p> + * This method accepts both {@link com.oracle.graal.nodes.PiNode} and + * {@link com.oracle.graal.nodes.PiArrayNode} argument. + * </p> + * + * <p> + * In case a witness reveals a strictly more precise type than the + * {@link com.oracle.graal.nodes.PiNode}'s stamp, this method wraps the argument in a new + * {@link com.oracle.graal.nodes.PiNode} with updated stamp, and returns it. + * </p> + * + * <p> + * A {@link com.oracle.graal.nodes.PiArrayNode} argument ends up wrapped in a + * {@link com.oracle.graal.nodes.PiNode}. Thus, the + * {@link com.oracle.graal.nodes.PiArrayNode#length} information doesn't get lost. + * </p> + * + * <p> + * Note: {@link com.oracle.graal.nodes.PiNode}'s semantics allow un-packing its payload as soon + * as it type conforms to that of the {@link com.oracle.graal.nodes.PiNode} (that's what + * {@link com.oracle.graal.nodes.PiNode#canonical(com.oracle.graal.graph.spi.CanonicalizerTool) + * PiNode.canonical()} does). Not clear the benefits of duplicating that logic here. + * </p> + * + * @see #downcastedValueProxy + * */ + private ValueNode downcastedPiNodeOrPiArrayNode(PiNode envelope, Witness w) { + return downcastedUtil(envelope, w); + } + + /** + * <p> + * In a case the payload of the {@link com.oracle.graal.nodes.TypeProfileProxyNode} can be + * downcasted, this method returns a copy-on-write version with the downcasted payload. + * </p> + * + * <p> + * Otherwise returns the unmodified argument. + * </p> + * + * @see #downcastedValueProxy + * */ + private ValueNode downcastedTypeProfileProxyNode(TypeProfileProxyNode envelope) { + ValueNode payload = envelope.getOriginalNode(); + ValueNode d = downcasted(payload); + if (payload != d) { + TypeProfileProxyNode changed = (TypeProfileProxyNode) envelope.copyWithInputs(); + added.add(changed); + // copyWithInputs() implies graph.unique(changed) + FlowUtil.replaceInPlace(changed, payload, d); + FlowUtil.inferStampAndCheck(changed); + fixupTypeProfileStamp(changed); + /* + * It's not prudent to (1) obtain the canonical() of the (changed) TypeProfileProxyNode + * to (2) replace its usages; because we're potentially walking a DAG (after all, + * TypeProfileProxyNode is a floating-node). Those steps, which admittedly are needed, + * are better performed upon replacing in-place the inputs of a FixedNode, or during + * Canonicalize. + */ + return changed; + } + fixupTypeProfileStamp(envelope); + return envelope; + } + + /** + * <p> + * Re-wrap the checkCast in a type-refining {@link com.oracle.graal.nodes.PiNode PiNode} only if + * the downcasted scrutinee does not conform to the checkCast's target-type. + * </p> + * */ + private ValueNode downcastedCheckCastNode(CheckCastNode checkCast, Witness w) { + + final ResolvedJavaType toType = checkCast.type(); + + if (checkCast.object() instanceof CheckCastNode) { + ValueNode innerMost = checkCast; + while (innerMost instanceof CheckCastNode) { + innerMost = ((CheckCastNode) innerMost).object(); + } + ValueNode deepest = downcasted(innerMost); + ResolvedJavaType deepestType = ((ObjectStamp) deepest.stamp()).type(); + if ((deepestType != null && deepestType.equals(toType)) || FlowUtil.isMorePrecise(deepestType, toType)) { + assert !w.knowsBetterThan(deepest); + return deepest; + } + } + + ValueNode subject = downcasted(checkCast.object()); + ObjectStamp subjectStamp = (ObjectStamp) subject.stamp(); + ResolvedJavaType subjectType = subjectStamp.type(); + + if (subjectType != null && toType.isAssignableFrom(subjectType)) { + assert !w.knowsBetterThan(subject); + return subject; + } + + return downcastedUtil(checkCast, w); + } + + /** + * <p> + * Porcelain method. + * </p> + * + * <p> + * This method wraps the argument in a new {@link com.oracle.graal.nodes.PiNode PiNode} (created + * to hold an updated stamp) provided the argument's stamp can be strictly refined, and returns + * it. + * </p> + * */ + private ValueNode downcastedUtil(ValueNode subject, Witness w) { + + ObjectStamp originalStamp = (ObjectStamp) subject.stamp(); + ObjectStamp outgoingStamp = originalStamp; + + if (w.isNonNull() && !outgoingStamp.nonNull()) { + outgoingStamp = FlowUtil.asNonNullStamp(outgoingStamp); + } + if (FlowUtil.isMorePrecise(w.type(), outgoingStamp.type())) { + outgoingStamp = FlowUtil.asRefinedStamp(outgoingStamp, w.type()); + } + + if (outgoingStamp != originalStamp) { + assert FlowUtil.isMorePrecise(outgoingStamp, originalStamp); + + boolean isWitnessGuardAnAliasForScrutinee = false; + if (w.guard() instanceof GuardingPiNode || w.guard() instanceof PiNode) { + /* + * The guard offered by the witness canonicalizes into its subject (a possibly + * type-refined scrutinee) provided its subject conforms as per stamp. + */ + if (w.guard().asNode().stamp().equals(outgoingStamp)) { + isWitnessGuardAnAliasForScrutinee = true; + } + } + + ValueNode result; + if (isWitnessGuardAnAliasForScrutinee) { + result = w.guard().asNode(); + assert !w.knowsBetterThan(result); + return result; // TODO this works. explain why. + } else { + result = wrapInPiNode(subject, w.guard(), outgoingStamp, true); + assert !w.knowsBetterThan(result); + return result; + } + + } else { + assert !w.knowsBetterThan(subject); + return subject; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,218 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.tiers.PhaseContext; + +/** + * <p> + * This class implements control-flow sensitive reductions for + * {@link com.oracle.graal.nodes.FixedGuardNode}. + * </p> + * + * @see #visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode) + * */ +public abstract class FixedGuardReduction extends CheckCastReduction { + + public FixedGuardReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState, context); + } + + /** + * In case the condition is constant, + * {@link com.oracle.graal.nodes.FixedGuardNode#simplify(com.oracle.graal.graph.spi.SimplifierTool) + * FixedGuardNode#simplify(SimplifierTool)} will eventually remove the + * {@link com.oracle.graal.nodes.FixedGuardNode} ("always succeeds") or kill the code that + * should be killed ("always fails"). + * + * <p> + * The only thing we do here is tracking as true fact (from this program point onwards) the + * condition of the {@link com.oracle.graal.nodes.FixedGuardNode FixedGuardNode}. + * </p> + * + * <p> + * Precondition: the condition hasn't been deverbosified yet. + * </p> + */ + protected final void visitFixedGuardNode(FixedGuardNode f) { + + /* + * A FixedGuardNode with LogicConstantNode condition is left untouched. + */ + + if (f.condition() instanceof LogicConstantNode) { + if (FlowUtil.alwaysFails(f.isNegated(), f.condition())) { + state.impossiblePath(); + // let FixedGuardNode(false).simplify() prune the dead-code control-path + return; + } + assert FlowUtil.alwaysSucceeds(f.isNegated(), f.condition()); + return; + } + + /* + * Attempt to eliminate the current FixedGuardNode by using another GuardingNode already in + * scope and with equivalent condition. + */ + + GuardingNode existingGuard = f.isNegated() ? state.falseFacts.get(f.condition()) : state.trueFacts.get(f.condition()); + if (existingGuard != null) { + // assert existingGuard instanceof FixedGuardNode; + metricFixedGuardNodeRemoved.increment(); + f.replaceAtUsages(existingGuard.asNode()); + graph.removeFixed(f); + return; + } + + final LogicNode cond = f.condition(); + final boolean isTrue = !f.isNegated(); + + /* + * FixedGuardNode requires handling similar to that of GuardingPiNode, (ie the condition + * can't simply be deverbosified in place). A replacement anchor is needed, ie an anchor + * that amounts to the same combination of (negated, condition) for the FixedGuardNode at + * hand. + */ + + // TODO what about isDependencyTainted + + if (cond instanceof IsNullNode) { + final IsNullNode isNullNode = (IsNullNode) cond; + if (isTrue) { + // grab an anchor attesting nullness + final GuardingNode replacement = reasoner.untrivialNullAnchor(isNullNode.object()); + if (replacement != null) { + removeFixedGuardNode(f, replacement); + return; + } + if (state.isNonNull(isNullNode.object())) { + markFixedGuardNodeAlwaysFails(f); + return; + } + // can't produce evidence, fall-through to addFact + } else { + // grab an anchor attesting non-nullness + final Witness w = state.typeInfo(isNullNode.object()); + if (w != null && w.isNonNull()) { + removeFixedGuardNode(f, w.guard()); + return; + } + if (state.isNull(isNullNode.object())) { + markFixedGuardNodeAlwaysFails(f); + return; + } + // can't produce evidence, fall-through to addFact + } + } else if (cond instanceof InstanceOfNode) { + final InstanceOfNode iOf = (InstanceOfNode) cond; + final Witness w = state.typeInfo(iOf.object()); + if (isTrue) { + // grab an anchor attesting instanceof + if (w != null) { + if (w.isNonNull() && w.type() != null) { + if (iOf.type().isAssignableFrom(w.type())) { + removeFixedGuardNode(f, w.guard()); + return; + } + if (State.knownNotToConform(w.type(), iOf.type())) { + markFixedGuardNodeAlwaysFails(f); + return; + } + } + } + if (state.isNull(iOf.object())) { + markFixedGuardNodeAlwaysFails(f); + return; + } + // can't produce evidence, fall-through to addFact + } else { + // grab an anchor attesting not-instanceof + // (1 of 2) attempt determining nullness + final GuardingNode nullGuard = reasoner.untrivialNullAnchor(iOf.object()); + if (nullGuard != null) { + removeFixedGuardNode(f, nullGuard); + return; + } + // (2 of 2) attempt determining known-not-to-conform + if (w != null && !w.cluelessAboutType()) { + if (State.knownNotToConform(w.type(), iOf.type())) { + removeFixedGuardNode(f, w.guard()); + return; + } + } + // can't produce evidence, fall-through to addFact + } + } else if (isTrue && cond instanceof ShortCircuitOrNode) { + CastCheckExtractor cce = CastCheckExtractor.extract(cond); + if (cce != null && !State.isDependencyTainted(cce.subject, f)) { + // grab an anchor attesting check-cast + Witness w = state.typeInfo(cce.subject); + if (w != null && w.type() != null) { + if (cce.type.isAssignableFrom(w.type())) { + removeFixedGuardNode(f, w.guard()); + return; + } + if (State.knownNotToConform(w.type(), cce.type)) { + markFixedGuardNodeAlwaysFails(f); + return; + } + } + } + // can't produce evidence, fall-through to addFact + } + + state.addFact(isTrue, cond, f); + } + + /** + * Porcelain method. + * */ + private void markFixedGuardNodeAlwaysFails(FixedGuardNode f) { + metricFixedGuardNodeRemoved.increment(); + state.impossiblePath(); + f.setCondition(f.isNegated() ? trueConstant : falseConstant); + // `f.condition()` if unused will be removed in finished() + } + + /** + * Porcelain method. + * + * <p> + * The `replacement` guard must be such that it implies the `old` guard. + * </p> + * */ + private void removeFixedGuardNode(FixedGuardNode old, GuardingNode replacement) { + if (replacement == null) { + return; + } + metricFixedGuardNodeRemoved.increment(); + old.replaceAtUsages(replacement.asNode()); + graph.removeFixed(old); + // `old.condition()` if unused will be removed in finished() + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,545 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Node; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.extended.LoadHubNode; +import com.oracle.graal.nodes.extended.NullCheckNode; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.compiler.common.type.IllegalStamp; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.common.DeadCodeEliminationPhase; +import com.oracle.graal.phases.tiers.PhaseContext; + +import java.lang.reflect.Modifier; + +import static com.oracle.graal.api.meta.DeoptimizationReason.*; + +/** + * <p> + * All control-flow-sensitive reductions follow the common pattern of + * <ul> + * <li>Recognizing properties of interest (ie, LogicNode-s) at control-flow splits, as well as upon + * check-casts and fixed-guards.</li> + * <li>Using the information thus tracked to simplify + * <ul> + * <li>side-effects free expressions, via + * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)} + * </li> + * <li>control-flow, eg. by eliminating redundant fixed-guards and check-casts, ie which are known + * always to hold.</li> + * </ul> + * </li> + * </ul> + * </p> + * + * @see com.oracle.graal.phases.common.cfs.CheckCastReduction + * @see com.oracle.graal.phases.common.cfs.GuardingPiReduction + * @see com.oracle.graal.phases.common.cfs.FixedGuardReduction + * + * */ +public class FlowSensitiveReduction extends FixedGuardReduction { + + public FlowSensitiveReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState, context); + } + + /** + * <p> + * This method performs two kinds of cleanup: + * <ol> + * <li> + * marking as unreachable certain code-paths, as described in + * {@link com.oracle.graal.phases.common.cfs.BaseReduction.PostponedDeopt}</li> + * <li> + * Removing nodes not in use that were added during this phase, as described next.</li> + * </ol> + * </p> + * + * + * <p> + * Methods like + * {@link com.oracle.graal.phases.common.cfs.FlowUtil#replaceInPlace(com.oracle.graal.graph.Node, com.oracle.graal.graph.Node, com.oracle.graal.graph.Node)} + * may result in old inputs becoming disconnected from the graph. It's not advisable to + * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} at + * that moment, because one of the inputs that might get killed is one of {@link #nullConstant}, + * {@link #falseConstant}, or {@link #trueConstant}; which thus could get killed too early, + * before another invocation of + * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)} + * needs them. To recap, + * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} also + * recursively visits the inputs of the its argument. + * </p> + * + * <p> + * This method goes over all of the nodes that deverbosification might have added, which are + * either: + * <ul> + * <li> + * {@link com.oracle.graal.nodes.calc.FloatingNode}, added by + * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosifyFloatingNode(com.oracle.graal.nodes.calc.FloatingNode)} + * ; or</li> + * <li> + * {@link com.oracle.graal.nodes.java.MethodCallTargetNode}, added by + * {@link #deverbosifyInputsCopyOnWrite(com.oracle.graal.nodes.java.MethodCallTargetNode)}</li> + * </ul> + * + * Checking if they aren't in use, proceeding to remove them in that case. + * </p> + * + * */ + @Override + public void finished() { + if (!postponedDeopts.isEmpty()) { + for (PostponedDeopt postponed : postponedDeopts) { + postponed.doRewrite(falseConstant); + } + new DeadCodeEliminationPhase().apply(graph); + } + for (MethodCallTargetNode mcn : graph.getNodes().filter(MethodCallTargetNode.class)) { + if (mcn.isAlive() && FlowUtil.lacksUsages(mcn)) { + mcn.safeDelete(); + } + } + for (Node n : graph.getNodes().filter(FloatingNode.class)) { + GraphUtil.tryKillUnused(n); + } + assert !isAliveWithoutUsages(trueConstant); + assert !isAliveWithoutUsages(falseConstant); + assert !isAliveWithoutUsages(nullConstant); + } + + private static boolean isAliveWithoutUsages(FloatingNode node) { + return node.isAlive() && node.usages().isEmpty(); + } + + private void registerControlSplit(Node pred, BeginNode begin) { + assert pred != null && begin != null; + assert !state.isUnreachable; + + if (begin instanceof LoopExitNode) { + state.clear(); + } + + if (pred instanceof IfNode) { + registerIfNode((IfNode) pred, begin); + } else if (pred instanceof TypeSwitchNode) { + registerTypeSwitchNode((TypeSwitchNode) pred, begin); + } + } + + private void registerIfNode(IfNode ifNode, BeginNode begin) { + final boolean isThenBranch = (begin == ifNode.trueSuccessor()); + + if (ifNode.condition() instanceof LogicConstantNode) { + final LogicConstantNode constCond = (LogicConstantNode) ifNode.condition(); + if (isThenBranch != constCond.getValue()) { + state.impossiblePath(); + // let IfNode(constant) prune the dead-code control-path + } + } + + if (state.isUnreachable) { + if (!(ifNode.condition() instanceof LogicConstantNode)) { + // if condition constant, no need to add a Deopt node + postponedDeopts.addDeoptAfter(begin, UnreachedCode); + } + } else { + state.addFact(isThenBranch, ifNode.condition(), begin); + } + } + + /** + * TODO When tracking integer-stamps, the state at each successor of a TypeSwitchNode should + * track an integer-stamp for the LoadHubNode (meet over the constants leading to that + * successor). However, are LoadHubNode-s shared frequently enough? + * */ + private void registerTypeSwitchNode(TypeSwitchNode typeSwitch, BeginNode begin) { + if (typeSwitch.value() instanceof LoadHubNode) { + LoadHubNode loadHub = (LoadHubNode) typeSwitch.value(); + ResolvedJavaType type = null; + for (int i = 0; i < typeSwitch.keyCount(); i++) { + if (typeSwitch.keySuccessor(i) == begin) { + if (type == null) { + type = typeSwitch.typeAt(i); + } else { + type = FlowUtil.widen(type, typeSwitch.typeAt(i)); + } + } + } + if (type == null) { + // `begin` denotes the default case of the TypeSwitchNode + return; + } + // preferable would be trackExact, but not there yet + state.addNullness(false, loadHub.object(), begin); + if (state.knownNotToConform(loadHub.object(), type)) { + postponedDeopts.addDeoptAfter(begin, UnreachedCode); + state.impossiblePath(); + return; + } + if (type.isInterface()) { + state.trackNN(loadHub.object(), begin); + } else { + state.trackIO(loadHub.object(), type, begin); + } + } + } + + /** + * + * <p> + * Reduce input nodes based on the state at the program point for the argument (ie, based on + * "valid facts" only, without relying on any floating-guard-assumption). + * </p> + * + * <p> + * For each (direct or indirect) child, a copy-on-write version is made in case any of its + * children changed, with the copy accommodating the updated children. If the parent was shared, + * copy-on-write prevents the updates from becoming visible to anyone but the invoker of this + * method. + * </p> + * + * <p> + * <b> Please note the parent node is mutated upon any descendant changing. No copy-on-write is + * performed for the parent node itself. </b> + * </p> + * + * <p> + * In more detail, for each direct {@link com.oracle.graal.nodes.ValueNode} input of the node at + * hand, + * + * <ol> + * <li> + * Obtain a lazy-copied version (via spanning tree) of the DAG rooted at the input-usage in + * question. Lazy-copying is done by walking a spanning tree of the original DAG, stopping at + * non-FloatingNodes but transitively walking FloatingNodes and their inputs. Upon arriving at a + * (floating) node N, the state's facts are checked to determine whether a constant C can be + * used instead in the resulting lazy-copied DAG. A NodeBitMap is used to realize the spanning + * tree.</li> + * + * <li> + * Provided one or more N-to-C node replacements took place, the resulting lazy-copied DAG has a + * parent different from the original (ie different object identity) which indicates the + * (copied, updated) DAG should replace the original via replaceFirstInput(), and inferStamp() + * should be invoked to reflect the updated inputs.</li> + * + * </ol> + * </p> + * + * @return whether any reduction was performed on the inputs of the arguments. + * */ + public boolean deverbosifyInputsInPlace(ValueNode parent) { + boolean changed = false; + for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) { + assert !(i instanceof GuardNode) : "ConditionalElim shouldn't run in MidTier"; + ValueNode j = (ValueNode) reasoner.deverbosify(i); + if (i != j) { + changed = true; + FlowUtil.replaceInPlace(parent, i, j); + } + } + if (changed) { + FlowUtil.inferStampAndCheck(parent); + } + return changed; + } + + /** + * Similar to {@link #deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode)}, except that + * not the parent but a fresh clone is updated upon any of its children changing. + * + * @return the original parent if no updated took place, a copy-on-write version of it + * otherwise. + * + * */ + private MethodCallTargetNode deverbosifyInputsCopyOnWrite(MethodCallTargetNode parent) { + MethodCallTargetNode changed = null; + for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) { + Node j = reasoner.deverbosify(i); + if (i != j) { + assert j != parent; + if (changed == null) { + changed = (MethodCallTargetNode) parent.copyWithInputs(); + reasoner.added.add(changed); + // copyWithInputs() implies graph.unique(changed) + assert changed.isAlive(); + assert FlowUtil.lacksUsages(changed); + } + FlowUtil.replaceInPlace(changed, i, j); + } + } + if (changed == null) { + return parent; + } + FlowUtil.inferStampAndCheck(changed); + /* + * No need to rememberSubstitution() because not called from deverbosify(). In detail, it's + * only deverbosify() that skips visited nodes (thus we'd better have recorded any + * substitutions we want for them). Not this case. + */ + return changed; + } + + /** + * Precondition: This method assumes that either: + * + * <ul> + * <li>the state has already stabilized (ie no more pending iterations in the "iterative" + * dataflow algorithm); or</li> + * <li>any rewritings made based on the state in its current form are conservative enough to be + * safe.</li> + * </ul> + * + * <p> + * The overarching goal is to perform just enough rewriting to trigger other phases ( + * {@link com.oracle.graal.graph.spi.SimplifierTool SimplifierTool}, + * {@link com.oracle.graal.phases.common.DeadCodeEliminationPhase DeadCodeEliminationPhase}, + * etc) to perform the bulk of rewriting, thus lowering the maintenance burden. + * </p> + * + */ + @Override + protected void node(FixedNode node) { + + assert node.isAlive(); + + /*------------------------------------------------------------------------------------- + * Step 1: Unreachable paths are still visited (PostOrderNodeIterator requires all ends + * of a merge to have been visited), but time is saved by neither updating the state nor + * rewriting anything while on an an unreachable path. + *------------------------------------------------------------------------------------- + */ + if (state.isUnreachable) { + return; + } + + /*------------------------------------------------------------------------------------- + * Step 2: For an AbstractBeginNode, determine whether this path is reachable, register + * any associated guards. + *------------------------------------------------------------------------------------- + */ + if (node instanceof BeginNode) { + BeginNode begin = (BeginNode) node; + Node pred = node.predecessor(); + + if (pred != null) { + registerControlSplit(pred, begin); + } + return; + } + + /*------------------------------------------------------------------------------------- + * Step 3: Check whether EquationalReasoner caches should be cleared upon state updates. + *------------------------------------------------------------------------------------- + */ + reasoner.updateState(state); + + /*------------------------------------------------------------------------------------- + * Step 4: Whatever special-case handling makes sense for the FixedNode at hand before + * its inputs are reduced. + *------------------------------------------------------------------------------------- + */ + + if (node instanceof AbstractEndNode) { + visitAbstractEndNode((AbstractEndNode) node); + return; + } else if (node instanceof Invoke) { + visitInvoke((Invoke) node); + return; + } else if (node instanceof CheckCastNode) { + // it's important not to call deverbosification for visitCheckCastNode() + visitCheckCastNode((CheckCastNode) node); + return; + } else if (node instanceof GuardingPiNode) { + visitGuardingPiNode((GuardingPiNode) node); + return; + } else if (node instanceof NullCheckNode) { + visitNullCheckNode((NullCheckNode) node); + return; + } else if (node instanceof FixedGuardNode) { + visitFixedGuardNode((FixedGuardNode) node); + return; + } else if (node instanceof ConditionAnchorNode) { + // ConditionAnchorNode shouldn't occur during HighTier + return; + } + + /*------------------------------------------------------------------------------------- + * Step 5: After special-case handling, we do our best for those FixedNode-s + * where the effort to reduce their inputs might pay off. + * + * Why is this useful? For example, by the time the AbstractBeginNode for an If-branch + * is visited (in general a ControlSplitNode), the If-condition will have gone already + * through simplification (and thus potentially have been reduced to a + * LogicConstantNode). + *------------------------------------------------------------------------------------- + */ + boolean paysOffToReduce = false; + if (node instanceof ControlSplitNode) { + // desire to simplify control flow + paysOffToReduce = true; + } else if (node instanceof ReturnNode) { + paysOffToReduce = true; + } else if (node instanceof AccessFieldNode || node instanceof AccessArrayNode) { + // desire to remove null-checks + paysOffToReduce = true; + } + + // TODO comb the remaining FixedWithNextNode subclasses, pick those with good changes of + // paying-off + + // TODO UnsafeLoadNode takes a condition + + if (paysOffToReduce) { + deverbosifyInputsInPlace(node); + } + + /*--------------------------------------------------------------------------------------- + * Step 6: Any additional special-case handling, this time after having inputs reduced. + * For example, leverage anchors provided by the FixedNode, to add facts to the factbase. + *--------------------------------------------------------------------------------------- + */ + + // TODO some nodes are GuardingNodes (eg, FixedAccessNode) we could use them to track state + // TODO others are additionally guarded (eg JavaReadNode), thus *their* guards could be + // simplified. + + } + + /** + * In case the scrutinee: + * + * <ul> + * <li>is known to be null, an unconditional deopt is added.</li> + * <li>is known to be non-null, the NullCheckNode is removed.</li> + * </ul> + * + * <p> + * Precondition: the input (ie, object) hasn't been deverbosified yet. + * </p> + * */ + private void visitNullCheckNode(NullCheckNode ncn) { + ValueNode object = ncn.getObject(); + if (state.isNull(object)) { + postponedDeopts.addDeoptBefore(ncn, NullCheckException); + state.impossiblePath(); + return; + } + if (state.isNonNull(object)) { + /* + * Redundant NullCheckNode. Unlike GuardingPiNode or FixedGuardNode, NullCheckNode-s + * aren't used as GuardingNode-s, thus in this case can be removed without further ado. + */ + assert FlowUtil.lacksUsages(ncn); + graph.removeFixed(ncn); + return; + } + // TODO ANCHOR NEEDED: state.trackNN(object, ncn); + } + + /** + * The {@link com.oracle.graal.nodes.AbstractEndNode} at the end of the current code path + * contributes values to {@link com.oracle.graal.nodes.PhiNode}s. Now is a good time to + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) + * EquationalReasoner#deverbosify} those values. + * + * <p> + * Precondition: inputs haven't been deverbosified yet. + * </p> + * */ + private void visitAbstractEndNode(AbstractEndNode endNode) { + MergeNode merge = endNode.merge(); + for (PhiNode phi : merge.phis()) { + if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) { + assert phi.verify(); + int index = merge.phiPredecessorIndex(endNode); + ValueNode original = phi.valueAt(index); + ValueNode reduced = (ValueNode) reasoner.deverbosify(original); + if (reduced != original) { + phi.setValueAt(index, reduced); + // `original` if unused will be removed in finished() + } + } + } + } + + /** + * One or more arguments at `invoke` may have control-flow sensitive simplifications. In such + * case, a new {@link com.oracle.graal.nodes.java.MethodCallTargetNode MethodCallTargetNode} is + * prepared just for this callsite, consuming reduced arguments. This proves useful in + * connection with inlining, in order to specialize callees on the types of arguments other than + * the receiver (examples: multi-methods, the inlining problem, lambdas as arguments). + * + * <p> + * Precondition: inputs haven't been deverbosified yet. + * </p> + * */ + private void visitInvoke(Invoke invoke) { + if (invoke.asNode().stamp() instanceof IllegalStamp) { + return; // just to be safe + } + boolean isMethodCallTarget = invoke.callTarget() instanceof MethodCallTargetNode; + if (!isMethodCallTarget) { + return; + } + FlowUtil.replaceInPlace(invoke.asNode(), invoke.callTarget(), deverbosifyInputsCopyOnWrite((MethodCallTargetNode) invoke.callTarget())); + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + if (callTarget.invokeKind() != MethodCallTargetNode.InvokeKind.Interface && callTarget.invokeKind() != MethodCallTargetNode.InvokeKind.Virtual) { + return; + } + ValueNode receiver = callTarget.receiver(); + if (receiver == null) { + return; + } + if (!FlowUtil.hasLegalObjectStamp(receiver)) { + return; + } + Witness w = state.typeInfo(receiver); + ResolvedJavaType type; + ResolvedJavaType stampType = StampTool.typeOrNull(receiver); + if (w == null || w.cluelessAboutType()) { + // can't improve on stamp but wil try to devirtualize anyway + type = stampType; + } else { + type = FlowUtil.tighten(w.type(), stampType); + } + if (type == null) { + return; + } + ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod()); + if (method == null) { + return; + } + if (method.canBeStaticallyBound() || Modifier.isFinal(type.getModifiers())) { + metricMethodResolved.increment(); + callTarget.setInvokeKind(MethodCallTargetNode.InvokeKind.Special); + callTarget.setTargetMethod(method); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,52 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.PhaseContext; + +public class FlowSensitiveReductionPhase extends BasePhase<PhaseContext> { + + private final MetaAccessProvider metaAccess; + + public MetaAccessProvider getMetaAccess() { + return metaAccess; + } + + public FlowSensitiveReductionPhase(MetaAccessProvider metaAccess) { + this.metaAccess = metaAccess; + } + + @Override + protected final void run(StructuredGraph graph, PhaseContext context) { + try (Debug.Scope s = Debug.scope("FlowSensitiveReduction")) { + new FlowSensitiveReduction(graph.start(), new State(), context).apply(); + } catch (Throwable e) { + throw Debug.handle(e); + } + } + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,317 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugConfig; +import com.oracle.graal.debug.DebugConfigScope; +import com.oracle.graal.debug.internal.DebugScope; +import com.oracle.graal.graph.InputType; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodes.*; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.compiler.common.type.StampFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class FlowUtil { + + private FlowUtil() { + // no instances of this class + } + + public static boolean lacksUsages(Node n) { + return n.recordsUsages() && n.usages().isEmpty(); + } + + public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null || b == null) { + return null; + } else if (a.equals(b)) { + return a; + } else { + return a.findLeastCommonAncestor(b); + } + } + + /** + * @return whether the first argument is strictly more precise than the second. + * */ + public static boolean isMorePrecise(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null) { + return false; + } + if (b == null) { + return true; + } + assert !a.isPrimitive(); + assert !b.isPrimitive(); + if (a.equals(b)) { + return false; + } + if (b.isInterface()) { + return b.isAssignableFrom(a); + } + if (a.isInterface()) { + return b.isInterface() && b.isAssignableFrom(a); + } + return b.isAssignableFrom(a); + } + + public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null) { + assert b == null || !b.isPrimitive(); + return b; + } + if (b == null) { + assert !a.isPrimitive(); + return a; + } + assert !a.isPrimitive(); + assert !b.isPrimitive(); + if (a.equals(b)) { + return a; + } + if (isMorePrecise(a, b)) { + return a; + } else if (isMorePrecise(b, a)) { + return b; + } else { + /* + * Not comparable, two cases: + * + * Example 1: 'a' standing for j.l.Number and 'b' for j.l.String We return null for lack + * of a value representing NullType, the right answer. Same goes when both arguments are + * non-comparable interfaces. + * + * Example 2: 'a' standing for sun/nio/ch/DirectBuffer (an interface) and b for + * java/nio/Buffer (an abstract class). The class always takes precedence. + */ + if (a.isInterface()) { + return b.isInterface() ? null : b; + } + if (b.isInterface()) { + return a.isInterface() ? null : a; + } + return null; // a and b aren't comparable, can't tighten() them + } + } + + /** + * + * There are "illegal" stamps that are not of type IllegalStamp. + * + * For example, there may be an IntegerStamp with upperBound < lowerBound that returns + * !isLegal() but we still know it's an integer and thus not of type IllegalStamp. + * + * An IllegalStamp should never happen. In contrast, !isLegal() values could happen due to dead + * code not yet removed, or upon some non-sideeffecting instructions floating out of a dead + * branch. + * */ + public static boolean isLegalObjectStamp(Stamp s) { + return isObjectStamp(s) && s.isLegal(); + } + + public static boolean hasLegalObjectStamp(ValueNode v) { + return isLegalObjectStamp(v.stamp()); + } + + public static boolean isObjectStamp(Stamp stamp) { + return stamp instanceof ObjectStamp; + } + + public static void inferStampAndCheck(ValueNode n) { + n.inferStamp(); + if (n.stamp() instanceof ObjectStamp) { + ObjectStamp objectStamp = (ObjectStamp) n.stamp(); + assert !objectStamp.isExactType() || objectStamp.type() != null; + } + } + + /** + * Compares the arguments along three dimensions (nullness, exactness, and type). For the first + * argument to be more precise than the second, it may not score lower in any dimension and must + * score higher in at least one dimension. + * + * When comparing types s and t, sameness counts as 0; while being more precise is awarded with + * a score of 1. In all other cases (non-comparable, or supertype) the score is -1. + * + * @return whether the first argument is strictly more precise than the second. + * */ + public static boolean isMorePrecise(ObjectStamp a, ObjectStamp b) { + int d0 = MINUS(a.alwaysNull(), b.alwaysNull()); + if (d0 == -1) { + return false; + } + int d1 = MINUS(a.nonNull(), b.nonNull()); + if (d1 == -1) { + return false; + } + int d2 = MINUS(a.isExactType(), b.isExactType()); + if (d2 == -1) { + return false; + } + int d3; + ResolvedJavaType ta = a.type(); + ResolvedJavaType tb = b.type(); + if (ta == null) { + d3 = (tb == null) ? 0 : -1; + } else if (tb == null) { + d3 = 1; + } else if (isMorePrecise(ta, tb)) { + d3 = 1; + } else if (ta.equals(tb)) { + d3 = 0; + } else { + d3 = -1; + } + if (d3 == -1) { + return false; + } + int maxScore = Math.max(Math.max(d0, d1), Math.max(d2, d3)); + return maxScore > 0; + } + + private static int MINUS(boolean a, boolean b) { + int aa = a ? 1 : 0; + int bb = b ? 1 : 0; + return aa - bb; + } + + public static LogicConstantNode asLogicConstantNode(LogicNode cond) { + return (cond instanceof LogicConstantNode) ? (LogicConstantNode) cond : null; + } + + public static boolean isLiteralNode(ValueNode f) { + return f instanceof ConstantNode || f instanceof LogicConstantNode; + } + + public static boolean isConstantTrue(LogicNode cond) { + LogicConstantNode c = asLogicConstantNode(cond); + return (c != null) && c.getValue(); + } + + public static boolean isConstantFalse(LogicNode cond) { + LogicConstantNode c = asLogicConstantNode(cond); + return (c != null) && !c.getValue(); + } + + public static boolean alwaysFails(boolean isNegated, LogicNode cond) { + LogicConstantNode c = asLogicConstantNode(cond); + return (c != null) && (c.getValue() == isNegated); + } + + public static boolean alwaysSucceeds(boolean isNegated, LogicNode cond) { + LogicConstantNode c = asLogicConstantNode(cond); + return (c != null) && (c.getValue() != isNegated); + } + + /** + * Returns (preserving order) the ValueNodes without duplicates found among the argument's + * direct inputs. + * */ + @SuppressWarnings("unchecked") + public static List<ValueNode> distinctValueAndConditionInputs(Node n) { + ArrayList<ValueNode> result = null; + NodeClass.NodeClassIterator iter = n.inputs().iterator(); + while (iter.hasNext()) { + NodeClass.Position pos = iter.nextPosition(); + InputType inputType = pos.getInputType(n); + boolean isReducibleInput = (inputType == InputType.Value || inputType == InputType.Condition); + if (isReducibleInput) { + ValueNode i = (ValueNode) pos.get(n); + if (!isLiteralNode(i)) { + if (result == null) { + result = new ArrayList<>(); + } + if (!result.contains(i)) { + result.add(i); + } + } + } + } + return result == null ? Collections.EMPTY_LIST : result; + } + + public static ObjectStamp asNonNullStamp(ObjectStamp stamp) { + ObjectStamp result = (ObjectStamp) stamp.join(StampFactory.objectNonNull()); + assert result.isLegal(); + return result; + } + + public static ObjectStamp asRefinedStamp(ObjectStamp stamp, ResolvedJavaType joinType) { + assert !joinType.isInterface(); + ObjectStamp result = (ObjectStamp) stamp.join(StampFactory.declared(joinType)); + assert result.isLegal(); + return result; + } + + /** + * Start situation: the parent node has <code>oldInput</code> among its (direct) inputs. After + * this method has run, all such occurrences have been replaced with <code>newInput</code>. In + * case that makes <code>oldInput</code> disconnected, it is removed from the graph. + * */ + public static void replaceInPlace(Node parent, Node oldInput, Node newInput) { + assert parent != null; + assert parent.inputs().contains(oldInput); + if (oldInput == newInput) { + return; + } + assert oldInput != null && newInput != null; + assert !isLiteralNode((ValueNode) oldInput); + do { + parent.replaceFirstInput(oldInput, newInput); + } while (parent.inputs().contains(oldInput)); + // `oldInput` if unused wil be removed in finished() + } + + public static StructuredGraph visualize(StructuredGraph graph, String title) { + DebugConfig debugConfig = DebugScope.getConfig(); + DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, debugConfig.dumpHandlers(), debugConfig.output()); + try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { + Debug.dump(graph, title); + + return graph; + } + } + + public static final String ANSI_RESET = "\u001B[0m"; + public static final String ANSI_BLACK = "\u001B[30m"; + public static final String ANSI_RED = "\u001B[31m"; + public static final String ANSI_GREEN = "\u001B[32m"; + public static final String ANSI_YELLOW = "\u001B[33m"; + public static final String ANSI_BLUE = "\u001B[34m"; + public static final String ANSI_PURPLE = "\u001B[35m"; + public static final String ANSI_CYAN = "\u001B[36m"; + public static final String ANSI_WHITE = "\u001B[37m"; + + public static void highlightInRed(String msg) { + System.out.println(ANSI_RED + msg + ANSI_RESET); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,373 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.phases.tiers.PhaseContext; + +/** + * <p> + * This class implements control-flow sensitive reductions for + * {@link com.oracle.graal.nodes.GuardingPiNode}. + * </p> + * + * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) + * */ +public abstract class GuardingPiReduction extends BaseReduction { + + public GuardingPiReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState, context); + } + + /** + * <p> + * By the time a {@link com.oracle.graal.nodes.GuardingPiNode GuardingPiNode} is visited, the + * available type refinements may allow reductions similar to those performed for + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * CheckCastNode}. + * </p> + * + * <ol> + * <li> + * If the condition needs no reduction (ie, it's already a + * {@link com.oracle.graal.nodes.LogicConstantNode LogicConstantNode}), this method basically + * gives up (thus letting other phases take care of it).</li> + * <li> + * Otherwise, an attempt is made to find a {@link com.oracle.graal.nodes.extended.GuardingNode} + * that implies the combination of (negated, condition) of the + * {@link com.oracle.graal.nodes.GuardingPiNode} being visited. Details in + * {@link #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}. If found, the node + * can be removed.</li> + * <li> + * Otherwise, the node is lowered to a {@link com.oracle.graal.nodes.FixedGuardNode} and its + * usages replaced with {@link com.oracle.graal.nodes.PiNode}. Details in + * {@link #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}.</li> + * </ol> + * + * <p> + * Precondition: the condition hasn't been deverbosified yet. + * </p> + * + * */ + protected final void visitGuardingPiNode(GuardingPiNode envelope) { + + if (!FlowUtil.hasLegalObjectStamp(envelope)) { + // this situation exercised by com.oracle.graal.jtt.optimize.NCE_FlowSensitive02 + return; + } + if (!FlowUtil.hasLegalObjectStamp(envelope.object())) { + return; + } + + /* + * (1 of 3) Cover the case of GuardingPiNode(LogicConstantNode, ...) + */ + + if (envelope.condition() instanceof LogicConstantNode) { + if (FlowUtil.alwaysFails(envelope.isNegated(), envelope.condition())) { + state.impossiblePath(); + // let GuardingPiNode(false).canonical() prune the dead-code control-path + return; + } + // if not always-fails and condition-constant, then it always-succeeds! + assert FlowUtil.alwaysSucceeds(envelope.isNegated(), envelope.condition()); + // let GuardingPiNode(true).canonical() replaceAtUsages + return; + } + + /* + * The trick used in visitFixedGuardNode to look up an equivalent GuardingNode for the + * combination of (negated, condition) at hand doesn't work for GuardingPiNode, because the + * condition showing up here (a ShortCircuitOrNode that can be detected by + * CastCheckExtractor) doesn't appear as key in trueFacts, falseFacts. Good thing we have + * CastCheckExtractor! + */ + + /* + * (2 of 3) Cover the case of the condition known-to-be-false or known-to-be-true, but not + * LogicConstantNode. + * + * If deverbosify(condition) == falseConstant, it would be safe to set: + * `envelope.setCondition(falseConstant)` (only the API won't allow). + * + * On the other hand, it's totally unsafe to do something like that for trueConstant. What + * we can do about that case is the province of `tryRemoveGuardingPiNode(envelope)` + */ + + if (tryRemoveGuardingPiNode(envelope)) { + return; + } + + /* + * Experience has shown that an attempt to eliminate the current GuardingPiNode by using a + * GuardingNode already in scope and with equivalent condition (grabbed from `trueFacts` + * resp. `falseFacts`) proves futile. Therefore we're not even attempting that here. + */ + + /* + * (3 of 3) Neither always-succeeds nor always-fails, ie we don't known. Converting to + * FixedGuardNode allows tracking the condition via a GuardingNode, thus potentially + * triggering simplifications down the road. + */ + FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated())); + graph.addBeforeFixed(envelope, fixedGuard); + + if (!FlowUtil.lacksUsages(envelope)) { + // not calling wrapInPiNode() because we don't want to rememberSubstitution() + PiNode replacement = graph.unique(new PiNode(envelope.object(), envelope.stamp(), fixedGuard)); + reasoner.added.add(replacement); + // before removing the GuardingPiNode replace its usages + envelope.replaceAtUsages(replacement); + } + + graph.removeFixed(envelope); + + state.addFact(!fixedGuard.isNegated(), fixedGuard.condition(), fixedGuard); + + } + + /** + * <p> + * Based on flow-sensitive knowledge, two pre-requisites have to be fulfilled in order to remove + * a {@link com.oracle.graal.nodes.GuardingPiNode}: + * + * <ul> + * <li>the condition must refer only to the payload of the + * {@link com.oracle.graal.nodes.GuardingPiNode}</li> + * <li>the condition must check properties about which the state tracks not only a true/false + * answer, but also an anchor witnessing that fact</li> + * <li>the condition may not check anything else beyond what's stated in the items above.</li> + * </ul> + * </p> + * + * <p> + * Provided a condition as above can be reduced to a constant (and an anchor obtained in the + * process), this method replaces all usages of the + * {@link com.oracle.graal.nodes.GuardingPiNode} (necessarily of + * {@link com.oracle.graal.graph.InputType#Value}) with a {@link com.oracle.graal.nodes.PiNode} + * that wraps the payload and the anchor in question. + * </p> + * + * <p> + * Precondition: the condition hasn't been deverbosified yet. + * </p> + * + * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) + * + * */ + private boolean tryRemoveGuardingPiNode(GuardingPiNode envelope) { + + LogicNode cond = envelope.condition(); + ValueNode payload = envelope.object(); + + ObjectStamp outgoingStamp = (ObjectStamp) envelope.stamp(); + ObjectStamp payloadStamp = (ObjectStamp) payload.stamp(); + + if (isNullCheckOn(cond, payload)) { + if (envelope.isNegated()) { + /* + * GuardingPiNode succeeds if payload non-null + */ + if (!outgoingStamp.equals(FlowUtil.asNonNullStamp(payloadStamp))) { + warnAboutOutOfTheBlueGuardingPiNode(envelope); + } + return tryRemoveGuardingPiNodeNonNullCond(envelope); + } else { + /* + * GuardingPiNode succeeds if payload null + */ + ValueNode replacement = StampTool.isObjectAlwaysNull(payload) ? payload : reasoner.untrivialNull(payload); + if (replacement != null) { + // replacement == null means !isKnownNull(payload) + removeGuardingPiNode(envelope, replacement); + return true; + } + return false; + } + } else if (CastCheckExtractor.isInstanceOfCheckOn(cond, payload)) { + if (envelope.isNegated()) { + return false; + } + /* + * GuardingPiNode succeeds if payload instanceof <something> + */ + InstanceOfNode io = (InstanceOfNode) cond; + assert io.type() != null; + Witness w = state.typeInfo(payload); + if (w != null && w.isNonNull() && isEqualOrMorePrecise(w.type(), io.type())) { + ValueNode d = reasoner.downcasted(payload); + removeGuardingPiNode(envelope, d); + return true; + } + return false; + } else if (cond instanceof ShortCircuitOrNode) { + if (envelope.isNegated()) { + return false; + } + CastCheckExtractor cce = CastCheckExtractor.extract(cond); + if (cce == null || cce.subject != payload) { + return false; + } + /* + * GuardingPiNode succeeds if payload check-casts toType + */ + return tryRemoveGuardingPiNodeCheckCastCond(envelope, cce.type); + } + + return false; + } + + /** + * Porcelain method. + * + * This method handles the case where the GuardingPiNode succeeds if payload known to be + * non-null. + * + * @see #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) + * */ + private boolean tryRemoveGuardingPiNodeNonNullCond(GuardingPiNode envelope) { + + ValueNode payload = envelope.object(); + + if (state.isNull(payload)) { + // the GuardingPiNode fails always + postponedDeopts.addDeoptBefore(envelope, envelope.getReason()); + state.impossiblePath(); + return true; + } + + if (StampTool.isObjectNonNull(payload)) { + // payload needs no downcasting, it satisfies as-is the GuardingPiNode's condition. + if (precisionLoss(envelope, payload)) { + /* + * TODO The GuardingPiNode has an outgoing stamp whose narrowing goes beyond what + * the condition checks. That's suspicious. + */ + PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp())); + reasoner.added.add(replacement); + removeGuardingPiNode(envelope, replacement); + return true; + } else { + removeGuardingPiNode(envelope, payload); + return true; + } + } + // if a non-null witness available, the GuardingPiNode can be removed + + Witness w = state.typeInfo(payload); + GuardingNode nonNullAnchor = (w != null && w.isNonNull()) ? w.guard() : null; + if (nonNullAnchor != null) { + PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp(), nonNullAnchor.asNode())); + reasoner.added.add(replacement); + removeGuardingPiNode(envelope, replacement); + return true; + } + + /* + * TODO What about, nodes that always denote non-null values? (Even though their stamp + * forgot to make that clear) Candidates: ObjectGetClassNode, Parameter(0) on instance + */ + + return false; + } + + /** + * Porcelain method. + * + * This method handles the case where the GuardingPiNode succeeds if payload null or its actual + * type equal or subtype of `toType` + * + * @see #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) + * + * */ + private boolean tryRemoveGuardingPiNodeCheckCastCond(GuardingPiNode envelope, ResolvedJavaType toType) { + assert toType != null; + ValueNode payload = envelope.object(); + + ObjectStamp outgoingStamp = (ObjectStamp) envelope.stamp(); + ObjectStamp payloadStamp = (ObjectStamp) payload.stamp(); + + if (!outgoingStamp.equals(FlowUtil.asRefinedStamp(payloadStamp, toType))) { + warnAboutOutOfTheBlueGuardingPiNode(envelope); + } + + ValueNode d = reasoner.downcasted(payload); + if (d == null) { + return false; + } + + if (StampTool.isObjectAlwaysNull(d)) { + removeGuardingPiNode(envelope, d); + return true; + } + ObjectStamp dStamp = (ObjectStamp) d.stamp(); + if (isEqualOrMorePrecise(dStamp.type(), toType)) { + removeGuardingPiNode(envelope, d); + return true; + } + return false; + } + + /* + * TODO There should be an assert in GuardingPiNode to detect that as soon as it happens + * (constructor, setStamp). + */ + private static void warnAboutOutOfTheBlueGuardingPiNode(GuardingPiNode envelope) { + Debug.log(String.format("GuardingPiNode has an outgoing stamp whose narrowing goes beyond what its condition checks: %s", envelope)); + } + + private static boolean isNullCheckOn(LogicNode cond, ValueNode subject) { + if (!(cond instanceof IsNullNode)) { + return false; + } + IsNullNode isNull = (IsNullNode) cond; + return isNull.object() == subject; + } + + /** + * Porcelain method. + * */ + private void removeGuardingPiNode(GuardingPiNode envelope, ValueNode replacement) { + assert !precisionLoss(envelope, replacement); + metricGuardingPiNodeRemoved.increment(); + envelope.replaceAtUsages(replacement); + assert FlowUtil.lacksUsages(envelope); + graph.removeFixed(envelope); + } + + public static boolean isEqualOrMorePrecise(ResolvedJavaType a, ResolvedJavaType b) { + return a.equals(b) || FlowUtil.isMorePrecise(a, b); + } + + public static boolean isEqualOrMorePrecise(ObjectStamp a, ObjectStamp b) { + return a.equals(b) || FlowUtil.isMorePrecise(a, b); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,70 @@ +/* + * 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.phases.common.cfs; + +import java.util.Map; +import java.util.TreeMap; + +public class Histogram extends TreeMap<Integer, Integer> { + + private static final long serialVersionUID = 7188324319057387738L; + + private final String prefix; + + public Histogram(String prefix) { + this.prefix = prefix; + } + + public void tick(int bucket) { + Integer entry = get(bucket); + put(bucket, entry == null ? 1 : entry + 1); + } + + public void print() { + + // printing takes time, allow concurrent updates during printing + Histogram histogram = clone(); + + float casesTotal = 0; + for (int i : histogram.values()) { + casesTotal += i; + } + for (Map.Entry<Integer, Integer> entry : histogram.entrySet()) { + int numCases = entry.getValue(); + int percentOut = (int) (numCases / casesTotal * 100); + String msg = prefix + String.format("%d iters in %4d cases (%2d %%)", entry.getKey(), numCases, percentOut); + if (entry.getKey() > 3) { + FlowUtil.highlightInRed(msg); + } else { + System.out.println(msg); + } + } + System.out.println(prefix + "--------------------------"); + } + + @Override + public Histogram clone() { + return (Histogram) super.clone(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,90 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.CanonicalizerPhase; +import com.oracle.graal.phases.common.util.*; +import com.oracle.graal.phases.tiers.*; + +public class IterativeFlowSensitiveReductionPhase extends BasePhase<PhaseContext> { + + private static final int MAX_ITERATIONS = 256; + + private final CanonicalizerPhase canonicalizer; + + public IterativeFlowSensitiveReductionPhase(CanonicalizerPhase canonicalizer) { + this.canonicalizer = canonicalizer; + } + + public static class CountingListener extends HashSetNodeChangeListener { + + public int count; + + @Override + public void nodeChanged(Node node) { + super.nodeChanged(node); + } + + } + + // private Histogram histogram = new Histogram("FSR-"); + + @Override + protected void run(StructuredGraph graph, PhaseContext context) { + FlowSensitiveReductionPhase eliminate = new FlowSensitiveReductionPhase(context.getMetaAccess()); + CountingListener listener = new CountingListener(); + int count = 1; + while (true) { + listener.count = count; + graph.trackInputChange(listener); + graph.trackUsagesDroppedZero(listener); + eliminate.apply(graph, context); + graph.stopTrackingInputChange(); + graph.stopTrackingUsagesDroppedZero(); + if (listener.getChangedNodes().isEmpty()) { + // histogram.tick(count); + break; + } + for (Node node : graph.getNodes()) { + if (node instanceof Simplifiable) { + listener.getChangedNodes().add(node); + } + } + canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); + listener.getChangedNodes().clear(); + if (++count > MAX_ITERATIONS) { + // System.out.println("Bailing out IterativeFlowSensitiveReductionPhase for graph: " + // + graph); + // FlowUtil.visualize(graph, "Bailout"); + throw new BailoutException("Number of iterations in FlowSensitiveReductionPhase exceeds " + MAX_ITERATIONS); + } + } + // histogram.print(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,813 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugMetric; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.calc.ObjectEqualsNode; +import com.oracle.graal.nodes.extended.GuardedNode; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.java.InstanceOfNode; +import com.oracle.graal.nodes.spi.ValueProxy; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.graph.MergeableState; + +import java.lang.reflect.Modifier; +import java.util.*; + +/** + * A State instance is mutated in place as each FixedNode is visited in a basic block of + * instructions. Basic block: starts with a {@link com.oracle.graal.nodes.BeginNode BeginNode}, ends + * at an {@link com.oracle.graal.nodes.EndNode EndNode} or + * {@link com.oracle.graal.nodes.ControlSinkNode ControlSinkNode} and lacks intervening control + * splits or merges. + */ +public final class State extends MergeableState<State> implements Cloneable { + + private static final DebugMetric metricTypeRegistered = Debug.metric("TypeRegistered"); + private static final DebugMetric metricNullnessRegistered = Debug.metric("NullnessRegistered"); + private static final DebugMetric metricObjectEqualsRegistered = Debug.metric("ObjectEqualsRegistered"); + private static final DebugMetric metricImpossiblePathDetected = Debug.metric("ImpossiblePathDetected"); + + /** + * <p> + * Each state update results in a higher {@link State#versionNr versionNr}. The + * {@link State#versionNr versionNr} of different State instances can't be meaningfully compared + * (ie, same {@link State#versionNr versionNr} just indicates they've gone through the same + * number of updates). In particular, the {@link State#versionNr versionNr} of a merged state + * doesn't guarantee any more than being different from those of the states being merged. + * </p> + * + * <p> + * Still, {@link State#versionNr versionNr} proves useful in two cases: + * + * <ul> + * <li>recording the {@link State#versionNr versionNr} right after {@link State State} cloning, + * allows finding out afterwards whether (a) both states have diverged, (b) just one of them, or + * (c) none of them.</li> + * <li>a {@link State State} may become {@link State#isUnreachable isUnreachable}. In such case, + * it may make a difference whether any updates were performed on the state from the time it was + * cloned. Those updates indicate information not available in the state is was cloned from. For + * the purposes of {@link FlowSensitiveReduction FlowSensitiveReduction} an unreachable state + * need not be merged with any other (because control-flow won't reach the merge point over the + * path of the unreachable state).</li> + * </ul> + * </p> + * + * */ + int versionNr = 0; + + boolean isUnreachable = false; + + /** + * Getting here implies an opportunity was detected for dead-code-elimination. A counterpoint + * argument goes as follows: perhaps we don't get here that often, in which case the effort to + * detect an "impossible path" could be shaved off. + * + * @see com.oracle.graal.phases.common.cfs.BaseReduction.PostponedDeopt + * */ + void impossiblePath() { + isUnreachable = true; + metricImpossiblePathDetected.increment(); + } + + /** + * <p> + * This map semantically tracks "facts" (ie, properties valid for the program-point the state + * refers to) as opposed to floating-guard-dependent properties. The + * {@link com.oracle.graal.nodes.extended.GuardingNode} being tracked comes handy at + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)} + * . + * </p> + * + * <p> + * On a related note, {@link #typeRefinements} also captures information the way + * {@link #trueFacts} and {@link #falseFacts} do, including "witnessing" guards. Why not just + * standardize on one of them, and drop the other? Because the {@link #typeRefinements} eagerly + * aggregates information for easier querying afterwards, e.g. when producing a "downcasted" + * value (which involves building a {@link com.oracle.graal.nodes.PiNode}, see + * {@link EquationalReasoner#downcasted(com.oracle.graal.nodes.ValueNode) downcasted()} + * </p> + * + * */ + private IdentityHashMap<ValueNode, Witness> typeRefinements; + + IdentityHashMap<ValueNode, GuardingNode> knownNull; + IdentityHashMap<LogicNode, GuardingNode> trueFacts; + IdentityHashMap<LogicNode, GuardingNode> falseFacts; + + public State() { + this.typeRefinements = new IdentityHashMap<>(); + this.knownNull = new IdentityHashMap<>(); + this.trueFacts = new IdentityHashMap<>(); + this.falseFacts = new IdentityHashMap<>(); + } + + public State(State other) { + this.isUnreachable = other.isUnreachable; + this.versionNr = other.versionNr; + this.typeRefinements = new IdentityHashMap<>(); + for (Map.Entry<ValueNode, Witness> entry : other.typeRefinements.entrySet()) { + this.typeRefinements.put(entry.getKey(), new Witness(entry.getValue())); + } + this.knownNull = new IdentityHashMap<>(other.knownNull); + this.trueFacts = new IdentityHashMap<>(other.trueFacts); + this.falseFacts = new IdentityHashMap<>(other.falseFacts); + } + + /** + * @return A new list containing only those states that are reachable. + * */ + private static ArrayList<State> reachableStates(List<State> states) { + ArrayList<State> result = new ArrayList<>(states); + Iterator<State> iter = result.iterator(); + while (iter.hasNext()) { + if (iter.next().isUnreachable) { + iter.remove(); + } + } + return result; + } + + private IdentityHashMap<ValueNode, Witness> mergeKnownTypes(MergeNode merge, ArrayList<State> withReachableStates) { + IdentityHashMap<ValueNode, Witness> newKnownTypes = new IdentityHashMap<>(); + + for (Map.Entry<ValueNode, Witness> entry : typeRefinements.entrySet()) { + ValueNode node = entry.getKey(); + Witness type = new Witness(entry.getValue()); + + for (State other : withReachableStates) { + Witness otherType = other.typeInfo(node); + if (otherType == null) { + type = null; + break; + } + type.merge(otherType, merge); + } + if (type != null && type.knowsBetterThan(node)) { + assert node == GraphUtil.unproxify(node); + newKnownTypes.put(node, type); + } + } + + return newKnownTypes; + } + + private IdentityHashMap<ValueNode, GuardingNode> mergeKnownNull(MergeNode merge, ArrayList<State> withReachableStates) { + // newKnownNull starts empty + IdentityHashMap<ValueNode, GuardingNode> newKnownNull = new IdentityHashMap<>(); + for (Map.Entry<ValueNode, GuardingNode> entry : knownNull.entrySet()) { + ValueNode key = entry.getKey(); + GuardingNode newGN = entry.getValue(); + boolean missing = false; + + for (State other : withReachableStates) { + GuardingNode otherGuard = other.knownNull.get(key); + if (otherGuard == null) { + missing = true; + break; + } + if (otherGuard != newGN) { + newGN = merge; + } + } + if (!missing) { + newKnownNull.put(key, newGN); + } + } + return newKnownNull; + } + + /** + * <p> + * This method handles phis, by adding to the resulting state any information that can be gained + * (about type-refinement and nullness) based on the data available at each of the incoming + * branches. + * </p> + * + * <p> + * In more detail, <code>FlowSensitiveReduction#visitAbstractEndNode()</code> has already + * deverbosified the phi-values contributed by each reachable branch. The paths that + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction} determined to be + * unreachable will be eliminated by canonicalization and dead code elimination. For now they + * still exist, thus polluting the result of + * {@link com.oracle.graal.nodes.ValuePhiNode#inferPhiStamp()} but we are careful to skip them + * when merging type-witnesses and known-null maps. + * </p> + */ + private void mergePhis(MergeNode merge, List<State> withStates, IdentityHashMap<ValueNode, Witness> newKnownPhiTypes, IdentityHashMap<ValueNode, GuardingNode> newKnownNullPhis) { + + if (merge instanceof LoopBeginNode) { + return; + } + + for (PhiNode phi : merge.phis()) { + assert phi == GraphUtil.unproxify(phi); + if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) { + ArrayList<ValueNode> reachingValues = new ArrayList<>(); + if (!isUnreachable) { + reachingValues.add(phi.valueAt(0)); + } + for (int i = 0; i < withStates.size(); i++) { + State otherState = withStates.get(i); + if (!otherState.isUnreachable) { + reachingValues.add(phi.valueAt(i + 1)); + } + } + assert !reachingValues.isEmpty(); + ObjectStamp phiStamp = (ObjectStamp) phi.stamp(); + ObjectStamp nonPollutedStamp = (ObjectStamp) StampTool.meet(reachingValues); + Witness w = new Witness(nonPollutedStamp, merge); + if (FlowUtil.isMorePrecise(w.type(), phiStamp.type())) { + // precision gain regarding type + newKnownPhiTypes.put(phi, w); + // confirm no precision loss regarding nullness + assert implies(phiStamp.nonNull(), w.isNonNull()); + } else if (w.isNonNull() && !phiStamp.nonNull()) { + // precision gain regarding nullness + newKnownPhiTypes.put(phi, w); + // confirm no precision loss regarding type + assert !FlowUtil.isMorePrecise(phiStamp.type(), w.type()); + } + if (nonPollutedStamp.alwaysNull()) { + newKnownNullPhis.put(phi, merge); + } + } + } + + } + + private static boolean implies(boolean a, boolean b) { + return !a || b; + } + + @Override + public boolean merge(MergeNode merge, List<State> withStates) { + + ArrayList<State> withReachableStates = reachableStates(withStates); + if (withReachableStates.isEmpty()) { + return true; + } + + for (State state : withReachableStates) { + versionNr = Math.max(versionNr, state.versionNr) + 1; + isUnreachable &= state.isUnreachable; + } + + if (isUnreachable) { + typeRefinements.clear(); + knownNull.clear(); + return true; + } + + // may also get updated in a moment, during processing of phi nodes. + IdentityHashMap<ValueNode, Witness> newKnownTypes = mergeKnownTypes(merge, withReachableStates); + // may also get updated in a moment, during processing of phi nodes. + IdentityHashMap<ValueNode, GuardingNode> newKnownNull = mergeKnownNull(merge, withReachableStates); + mergePhis(merge, withStates, newKnownTypes, newKnownNull); + this.typeRefinements = newKnownTypes; + this.knownNull = newKnownNull; + + this.trueFacts = mergeTrueFacts(withReachableStates, merge); + this.falseFacts = mergeFalseFacts(withReachableStates, merge); + return true; + } + + private IdentityHashMap<LogicNode, GuardingNode> mergeTrueFacts(ArrayList<State> withReachableStates, GuardingNode merge) { + IdentityHashMap<LogicNode, GuardingNode> newTrueConditions = new IdentityHashMap<>(); + for (Map.Entry<LogicNode, GuardingNode> entry : trueFacts.entrySet()) { + LogicNode check = entry.getKey(); + GuardingNode guard = entry.getValue(); + + for (State other : withReachableStates) { + GuardingNode otherGuard = other.trueFacts.get(check); + if (otherGuard == null) { + guard = null; + break; + } + if (otherGuard != guard) { + guard = merge; + } + } + if (guard != null) { + newTrueConditions.put(check, guard); + } + } + return newTrueConditions; + } + + private IdentityHashMap<LogicNode, GuardingNode> mergeFalseFacts(ArrayList<State> withReachableStates, GuardingNode merge) { + IdentityHashMap<LogicNode, GuardingNode> newFalseConditions = new IdentityHashMap<>(); + for (Map.Entry<LogicNode, GuardingNode> entry : falseFacts.entrySet()) { + LogicNode check = entry.getKey(); + GuardingNode guard = entry.getValue(); + + for (State other : withReachableStates) { + GuardingNode otherGuard = other.falseFacts.get(check); + if (otherGuard == null) { + guard = null; + break; + } + if (otherGuard != guard) { + guard = merge; + } + } + if (guard != null) { + newFalseConditions.put(check, guard); + } + } + return newFalseConditions; + } + + /** + * @retun null if no type-witness available for the argument, the witness otherwise. + */ + public Witness typeInfo(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + return typeRefinements.get(GraphUtil.unproxify(object)); + } + + /** + * @retun true iff the argument is known to stand for null. + */ + public boolean isNull(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + return StampTool.isObjectAlwaysNull(object) || knownNull.containsKey(GraphUtil.unproxify(object)); + } + + /** + * <p> + * It makes a difference calling {@link Witness#isNonNull()} as opposed to + * {@link State#isNonNull(com.oracle.graal.nodes.ValueNode)}. The former guarantees the witness + * provides a guard certifying non-nullness. The latter just tells us there exists some guard + * that certifies the property we asked about. + * </p> + * + * <p> + * TODO improvement: isKnownNonNull could be made smarter by noticing some nodes always denote a + * non-null value (eg, ObjectGetClassNode). Similarly for isKnownNull. Code that looks at the + * stamp as well as code that looks for a non-null-witness would benefit from also checking such + * extended isKnownNonNull. Alternatively, the stamp of those nodes should always have + * is-non-null set. + * </p> + * + * @retun true iff the argument is known to stand for non-null. + */ + public boolean isNonNull(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + if (StampTool.isObjectNonNull(object)) { + return true; + } + Witness w = typeInfo(object); + return w == null ? false : w.isNonNull(); + } + + /** + * @retun true iff the argument is known to stand for an object conforming to the given type. + */ + public boolean knownToConform(ValueNode object, ResolvedJavaType to) { + assert FlowUtil.hasLegalObjectStamp(object); + assert !to.isPrimitive(); + ResolvedJavaType stampType = StampTool.typeOrNull(object); + if (stampType != null && to.isAssignableFrom(stampType)) { + return true; + } + final ValueNode scrutinee = GraphUtil.unproxify(object); + if (isNull(scrutinee)) { + return true; + } + Witness w = typeInfo(scrutinee); + boolean witnessAnswer = w != null && w.type() != null && to.isAssignableFrom(w.type()); + if (witnessAnswer) { + return true; + } + return false; + } + + /** + * @retun true iff the argument is known to stand for an object that definitely does not conform + * to the given type. + */ + public boolean knownNotToConform(ValueNode object, ResolvedJavaType to) { + assert FlowUtil.hasLegalObjectStamp(object); + assert !to.isPrimitive(); + final ValueNode scrutinee = GraphUtil.unproxify(object); + if (isNull(scrutinee)) { + return false; + } + ResolvedJavaType stampType = StampTool.typeOrNull(object); + if (stampType != null && knownNotToConform(stampType, to)) { + return true; + } + Witness w = typeInfo(scrutinee); + boolean witnessAnswer = w != null && !w.cluelessAboutType() && knownNotToConform(w.type(), to); + if (witnessAnswer) { + return true; + } + return false; + } + + // @formatter:off + /** + * \ | | | | + * \ b| | | | + * a \ | | | | + * \|iface|final|non-f| + * -----+-----------------| + * iface| F | F | F | + * -----+-----------------| + * final| C | C | C | + * -----+-----------------| + * non-f| F | C | C | + * -----------------------+ + * + * where: + * F: false + * C: check + * iface: interface + * final: exact non-interface reference-type + * non-f: non-exact non-interface reference-type + * + * @retun true iff the first argument is known not to conform to the second argument. + */ + // @formatter:on + public static boolean knownNotToConform(ResolvedJavaType a, ResolvedJavaType b) { + assert !a.isPrimitive(); + assert !b.isPrimitive(); + if (b.isAssignableFrom(a)) { + return false; + } + if (a.isInterface()) { + return false; + } + boolean aFinal = Modifier.isFinal(a.getModifiers()); + if (b.isInterface() && !aFinal) { + return false; + } + if (a.isAssignableFrom(b)) { + return false; + } else { + return true; + } + } + + @Override + public State clone() { + return new State(this); + } + + /** + * Porcelain method. + */ + private Witness getOrElseAddTypeInfo(ValueNode object) { + ValueNode scrutinee = GraphUtil.unproxify(object); + Witness w = typeRefinements.get(scrutinee); + if (w == null) { + w = new Witness(); + typeRefinements.put(scrutinee, w); + } + return w; + } + + /** + * <p> + * Updates this {@link State State} to account for an observation about the scrutinee being + * non-null. In case instanceof was observed, + * {@link #trackIO(com.oracle.graal.nodes.ValueNode, com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode) + * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead. + * </p> + * + * <p> + * No check is made on whether a contradiction would be introduced into the factbase (in which + * case the state should be marked unreachable), the caller takes care of that. + * </p> + * + * @return whether state was updated (iff the observation added any new information) + */ + public boolean trackNN(ValueNode object, GuardingNode anchor) { + if (isDependencyTainted(object, anchor)) { + return false; + } + ResolvedJavaType stampType = StampTool.typeOrNull(object); + if (stampType != null && !stampType.isInterface()) { + return trackIO(object, stampType, anchor); + } + Witness w = getOrElseAddTypeInfo(object); + if (w.trackNN(anchor)) { + versionNr++; + return true; + } + return false; + } + + /** + * Updates this {@link State State} to account for an observation about the scrutinee conforming + * to a type. In case instanceof was observed, + * {@link #trackIO(com.oracle.graal.nodes.ValueNode, com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode) + * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead. + * + * <p> + * No check is made on whether a contradiction would be introduced into the factbase (in which + * case the state should be marked unreachable), the caller must take care of that. + * </p> + * + * @return false iff the observed type is an interface, or doesn't provide any new information + * not already known. Ie, this method returns true iff the observation resulted in + * information gain. + */ + public boolean trackCC(ValueNode object, ResolvedJavaType observed, GuardingNode anchor) { + if (observed.isInterface()) { + return false; + } + if (isDependencyTainted(object, anchor)) { + return false; + } + Witness w = getOrElseAddTypeInfo(object); + if (w.trackCC(observed, anchor)) { + versionNr++; + metricTypeRegistered.increment(); + return true; + } + return false; + } + + /** + * Updates this {@link State State} to account for an observation about the non-null scrutinee + * conforming to a type. + * + * <p> + * No check is made on whether a contradiction would be introduced into the factbase (in which + * case the state should be marked unreachable), the caller must take care of that. + * </p> + * + * @return whether state was updated (iff the observation added any new information) + */ + public boolean trackIO(ValueNode object, ResolvedJavaType observed, GuardingNode anchor) { + assert !observed.isInterface() : "no infrastructure yet in State.Witness to support interfaces in general"; + if (isDependencyTainted(object, anchor)) { + return false; + } + Witness w = getOrElseAddTypeInfo(object); + if (w.trackIO(observed, anchor)) { + versionNr++; + metricTypeRegistered.increment(); + return true; + } + return false; + } + + /** + * This method increases {@link #versionNr} (thus potentially invalidating + * {@link EquationalReasoner EquationalReasoner}'s caches) only if the fact wasn't known + * already. + * + * <p> + * No check is made on whether a contradiction would be introduced into the factbase (in which + * case the state should be marked unreachable), the caller must take care of that. + * </p> + * + * */ + private void addFactPrimordial(LogicNode condition, IdentityHashMap<LogicNode, GuardingNode> to, GuardingNode anchor) { + assert condition != null; + if (!to.containsKey(condition)) { + versionNr++; + to.put(condition, anchor); + } + } + + /** + * Ideas for the future: + * <ul> + * <li>track inferred less-than edges from (accumulated) CompareNode-s</li> + * <li>track set-representative for equality classes determined by (chained) IntegerTestNode</li> + * </ul> + * + * */ + public void addFact(boolean isTrue, LogicNode condition, GuardingNode anchor) { + assert anchor != null; + assert !isUnreachable; + + if (condition instanceof LogicConstantNode) { + if (((LogicConstantNode) condition).getValue() != isTrue) { + impossiblePath(); + } + return; + } + + if (condition instanceof LogicNegationNode) { + addFact(!isTrue, ((LogicNegationNode) condition).getInput(), anchor); + } else if (condition instanceof ShortCircuitOrNode) { + /* + * We can register the conditions being or-ed as long as the anchor is a fixed node, + * because floating guards will be registered at a BeginNode but might be "valid" only + * later due to data flow dependencies. Therefore, registering both conditions of a + * ShortCircuitOrNode for a floating guard could lead to cycles in data flow, because + * the guard will be used as anchor for both conditions, and one condition could be + * depending on the other. + */ + if (isTrue) { + CastCheckExtractor cce = CastCheckExtractor.extract(condition); + if (cce == null || isDependencyTainted(cce.subject, anchor)) { + addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor); + } else { + trackCC(cce.subject, cce.type, anchor); + } + } else { + ShortCircuitOrNode disjunction = (ShortCircuitOrNode) condition; + addFact(disjunction.isXNegated(), disjunction.getX(), anchor); + // previous addFact might have resulted in impossiblePath() + if (isUnreachable) { + return; + } + addFact(disjunction.isYNegated(), disjunction.getY(), anchor); + } + } else if (condition instanceof InstanceOfNode) { + addFactInstanceOf(isTrue, (InstanceOfNode) condition, anchor); + } else if (condition instanceof IsNullNode) { + IsNullNode nullCheck = (IsNullNode) condition; + addNullness(isTrue, nullCheck.object(), anchor); + } else if (condition instanceof ObjectEqualsNode) { + addFactObjectEqualsNode(isTrue, (ObjectEqualsNode) condition, anchor); + } else { + addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor); + } + } + + /** + * An instanceof hint is tracked differently depending on whether it's an interface-test or not + * (because type-refinements currently lacks the ability to track interface types). + * + */ + private void addFactInstanceOf(boolean isTrue, InstanceOfNode instanceOf, GuardingNode anchor) { + ValueNode object = instanceOf.object(); + if (isTrue) { + if (knownNotToConform(object, instanceOf.type())) { + impossiblePath(); + return; + } + addNullness(false, object, anchor); + if (instanceOf.type().isInterface()) { + if (!knownToConform(object, instanceOf.type())) { + addFactPrimordial(instanceOf, trueFacts, anchor); + } + } else { + trackIO(object, instanceOf.type(), anchor); + } + } else { + if (knownToConform(object, instanceOf.type())) { + impossiblePath(); // TODO this used to be a bug + return; + } + if (instanceOf.type().isInterface()) { + if (!knownNotToConform(object, instanceOf.type())) { + addFactPrimordial(instanceOf, falseFacts, anchor); + } + } + } + } + + private void addFactObjectEqualsNode(boolean isTrue, ObjectEqualsNode equals, GuardingNode anchor) { + if (isDependencyTainted(equals.x(), anchor)) { + return; + } + if (isDependencyTainted(equals.y(), anchor)) { + return; + } + ValueNode x = GraphUtil.unproxify(equals.x()); + ValueNode y = GraphUtil.unproxify(equals.y()); + if (isTrue) { + if (isNull(x) && isNonNull(y)) { + impossiblePath(); + return; + } + if (isNonNull(x) && isNull(y)) { + impossiblePath(); + return; + } + if (isNull(x) || isNull(y)) { + metricObjectEqualsRegistered.increment(); + addNullness(true, equals.x(), anchor); + addNullness(true, equals.y(), anchor); + } else if (isNonNull(x) || isNonNull(y)) { + metricObjectEqualsRegistered.increment(); + addNullness(false, equals.x(), anchor); + addNullness(false, equals.y(), anchor); + } + Witness wx = typeInfo(x); + Witness wy = typeInfo(y); + if (wx == null && wy == null) { + return; + } else if (wx != null && wy != null) { + // tighten their type-hints, provided at least one available + // both witnesses may have seen == null, ie they may be NN witnesses + ResolvedJavaType best = FlowUtil.tighten(wx.type(), wy.type()); + if (best != null) { + assert !best.isInterface(); + // type tightening is enough, nullness already taken care of + trackCC(equals.x(), best, anchor); + trackCC(equals.y(), best, anchor); + } + } else if (wx == null) { + typeRefinements.put(x, new Witness(wy)); + } else if (wy == null) { + typeRefinements.put(y, new Witness(wx)); + } + } else { + if (isNull(x) && !isNonNull(y)) { + metricObjectEqualsRegistered.increment(); + addNullness(false, equals.y(), anchor); + } else if (!isNonNull(x) && isNull(y)) { + metricObjectEqualsRegistered.increment(); + addNullness(false, equals.x(), anchor); + } + } + } + + /** + * Adds information about the nullness of a value. If isNull is true then the value is known to + * be null, otherwise the value is known to be non-null. + */ + public void addNullness(boolean isNull, ValueNode value, GuardingNode anchor) { + if (isDependencyTainted(value, anchor)) { + return; + } + ValueNode original = GraphUtil.unproxify(value); + boolean wasNull = isNull(original); + boolean wasNonNull = isNonNull(original); + if (isNull) { + if (wasNonNull) { + impossiblePath(); + } else { + metricNullnessRegistered.increment(); + versionNr++; + knownNull.put(original, anchor); + } + } else { + if (wasNull) { + impossiblePath(); + } else { + metricNullnessRegistered.increment(); + trackNN(original, anchor); + } + } + } + + /** + * + * @return true iff `value` may lose dependency not covered by `anchor`. + * */ + public static boolean isDependencyTainted(ValueNode value, GuardingNode anchor) { + if (value instanceof ValueProxy) { + if (value instanceof GuardedNode) { + GuardedNode gn = (GuardedNode) value; + GuardingNode guardian = gn.getGuard(); + if (guardian != null) { + boolean isGuardedByFixed = guardian instanceof FixedNode; + if (!isGuardedByFixed) { + return true; + } + } + } + // if (value instanceof GuardingNode) { + // return true; + // } + ValueProxy proxy = (ValueProxy) value; + return isDependencyTainted(proxy.getOriginalNode(), anchor); + } + return false; + } + + public void clear() { + versionNr = 0; + isUnreachable = false; + typeRefinements.clear(); + knownNull.clear(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Witness.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,440 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.compiler.common.type.ObjectStamp; + +/** + * <p> + * A witness progressively tracks more detailed properties about an object value (the scrutinee); + * the properties in question comprise whether the scrutinee has been observed: + * + * <ul> + * <li>as non-null,</li> + * <li>in a successful checkcast, or</li> + * <li>in a successful instanceof.</li> + * </ul> + * </p> + * + * <p> + * A witness is updated only when doing so increases the information content of the witness. For + * example, upon visiting a {@link com.oracle.graal.nodes.java.CheckCastNode CheckCastNode} the + * witness gets a chance to become updated. + * </p> + * + * <p> + * Therefore, at any given time, a witness represents the most detailed knowledge available so far + * about the scrutinee, which is the knowledge most relevant for upcoming program-points. + * </p> + * + * <p> + * The availability of witnesses about both non-nullness and checkcast (for a given scrutinee) + * promotes to an instanceof-style witness . The "levels" of knowledge a witness may exhibit are + * captured by {@link com.oracle.graal.phases.common.cfs.Witness.LEVEL}. For conciseness, the + * following query methods are available for a {@link com.oracle.graal.phases.common.cfs.Witness}: + * <ul> + * <li>{@link #atNonNull()}</li> + * <li>{@link #atCheckCast()}</li> + * <li>{@link #atInstanceOf()}</li> + * </ul> + * </p> + * + * <p> + * Only non-interface object types (ie, class and array types) are tracked. Small extensions are + * required to track interfaces, extensions that might be added after the current scheme proves + * itself. + * </p> + * + * <p> + * Some useful facts about the Statechart implemented by {@link Witness Witness}: + * + * <ul> + * <li>the start-state is "clueless"</li> + * <li> + * A self-transition via trackCC from whichever the current state is to itself, without information + * gain, is always possible. Just give {@link Object java.lang.Object} as observed type.</li> + * </ul> + * </p> + * + */ +public class Witness implements Cloneable { + + private static enum LEVEL { + CLUELESS, + NN, + CC, + IO + } + + private boolean atNonNull() { + return level == LEVEL.NN; + } + + private boolean atCheckCast() { + return level == LEVEL.CC; + } + + private boolean atInstanceOf() { + return level == LEVEL.IO; + } + + private void transition(LEVEL to, GuardingNode newAnchor) { + this.level = to; + this.gn = newAnchor; + assert repOK(); + } + + public Witness() { + } + + public Witness(Witness other) { + level = other.level; + seen = other.seen; + gn = other.gn; + } + + /** + * Counterpart to {@link #asStamp()} + * */ + public Witness(ObjectStamp stamp, GuardingNode anchor) { + assert stamp.isLegal(); + assert anchor != null; + boolean isNonIface = (stamp.type() != null && !stamp.type().isInterface()); + if (stamp.nonNull()) { + if (isNonIface) { + seen = stamp.type(); + transition(LEVEL.IO, anchor); + } else { + seen = null; + transition(LEVEL.NN, anchor); + } + } else { + if (isNonIface) { + seen = stamp.type(); + transition(LEVEL.CC, anchor); + } else { + seen = null; + transition(LEVEL.CLUELESS, null); + assert clueless(); + } + } + assert repOK(); + } + + /** + * Type-witnesses aren't tracked for known-to-be-null. Therefore, although method + * {@link #isNonNull() isNonNull()} can be found in this class there's on purpose no companion + * <code>isNull()</code> . + */ + public boolean isNonNull() { + return atNonNull() || atInstanceOf(); + } + + /** + * The most precise type known so far about the scrutinee. (Please notice that nothing can be + * deduced about the non-nullness-status of the scrutinee from invoking this method alone). + */ + public ResolvedJavaType type() { + return seen; + } + + public ObjectStamp asStamp() { + boolean isKnownExact = (seen != null && seen.equals(seen.asExactType())); + return new ObjectStamp(seen, isKnownExact, isNonNull(), false); + } + + private LEVEL level = LEVEL.CLUELESS; + private ResolvedJavaType seen = null; + + /** + * Evidence (ie, a {@link com.oracle.graal.nodes.extended.GuardingNode}) attesting to the status + * reported by this witness. + * + * May be one of: + * + * <ul> + * <li> + * {@link com.oracle.graal.nodes.BeginNode BeginNode},</li> + * <li> + * {@link com.oracle.graal.nodes.LoopExitNode LoopExitNode},</li> + * <li> + * {@link com.oracle.graal.nodes.FixedGuardNode FixedGuardNode}</li> + * <li>{@link com.oracle.graal.nodes.MergeNode MergeNode}, resulting from merging two witnesses + * with different values for this anchor</li> + * </ul> + * + * <p> + * An {@link com.oracle.graal.nodes.calc.ObjectEqualsNode ObjectEqualsNode} test results in the + * more-clueless of both scrutinees having its witness upgraded to that of the other (both + * scrutinees share the same {@link Witness Witness} instance from then on). For this reason, + * this field may also hold the anchors associated to an + * {@link com.oracle.graal.nodes.calc.ObjectEqualsNode ObjectEqualsNode} occurrence, ie nodes + * that can serve as {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} for the + * purposes of building a {@link com.oracle.graal.nodes.PiNode PiNode}. + * </p> + * + */ + private GuardingNode gn = null; + + /** + * Invariants of this class: + * <ul> + * <li>All fields holding null is ok, the hallmark of a {@link #clueless() clueless} witness. + * Another way for a witness to be clueless is by recording <code>java.lang.Object</code> as the + * seen type and nothing more.</li> + * <li>{@link #seen seen} may be null as long as the only hint being recorded is non-nullness</li> + * <li>A non-null value for {@link #seen seen} can't be tracked with NN, that combination + * amounts to IO and is tracked as such</li> + * <li>At most one of NN, CC, IO may be tracked at any given time</li> + * <li>A non-null CC or a non-null IO force {@link #seen seen} to be non-null</li> + * <li>{@link #seen seen} must be null or denote a non-interface reference type (ie, either a + * class-type or an array-type)</li> + * </ul> + */ + private boolean repOK() { + if (clueless()) { + assert level == LEVEL.CLUELESS; + return true; + } + if (level == LEVEL.NN) { + assert seen == null; + } + if (seen != null) { + assert !seen.isInterface(); + assert !seen.isPrimitive(); + } + boolean gnOK = gn instanceof BeginNode || gn instanceof LoopExitNode || gn instanceof MergeNode || gn instanceof FixedGuardNode; + assert gnOK; + return true; + } + + /** + * Helper method for readability in complex conditions. + */ + public boolean clueless() { + return cluelessAboutType() && cluelessAboutNonNullness(); + } + + /** + * Helper method for readability in complex conditions. + */ + public boolean cluelessAboutType() { + // TODO also clueless when `seen` is `java.lang.Object` + return seen == null; + } + + /** + * Helper method for readability in complex conditions. + */ + public boolean cluelessAboutNonNullness() { + return !atNonNull() && !atInstanceOf(); + } + + /** + * Whether this {@link Witness Witness} tracks information strictly more precise than that in + * the given {@link com.oracle.graal.compiler.common.type.ObjectStamp}. + */ + boolean knowsBetterThan(ObjectStamp other) { + return FlowUtil.isMorePrecise(asStamp(), other); + } + + /** + * Whether this {@link Witness Witness} tracks information strictly more precise than that in + * the {@link com.oracle.graal.compiler.common.type.ObjectStamp} of the given argument. + */ + boolean knowsBetterThan(ValueNode other) { + return knowsBetterThan((ObjectStamp) other.stamp()); + } + + /** + * Porcelain method for internal use only, invoked upon a Facade method being notified about + * checkcast or instanceof. + * + * @return whether the state was updated (iff the observation adds any new information) + */ + private boolean refinesSeenType(ResolvedJavaType observed) { + if (cluelessAboutType() || FlowUtil.isMorePrecise(observed, seen)) { + seen = observed; + return true; + } + return false; + } + + /** + * Updates this {@link Witness Witness} to account for an observation about the scrutinee being + * non-null. In case instanceof was observed, + * {@link #trackIO(com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode) + * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead + * + * @return whether this {@link Witness Witness} was updated (iff the observation adds any new + * information) + */ + public boolean trackNN(GuardingNode anchor) { + assert repOK(); + try { + if (atInstanceOf()) { + return false; + } + if (atCheckCast()) { + transition(LEVEL.IO, anchor); + return true; + } + if (!atNonNull()) { + transition(LEVEL.NN, anchor); + return true; + } + return false; + } finally { + assert repOK(); + } + } + + /** + * Updates this {@link Witness Witness} to account for an observation about the scrutinee + * conforming to the provided type. In case instanceof was observed, + * {@link #trackIO(com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode) + * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead. + * + * @return true iff information was gained. + */ + public boolean trackCC(ResolvedJavaType observed, GuardingNode anchor) { + assert !observed.isInterface(); + assert anchor != null; + assert repOK(); + try { + boolean anchorObsolete = refinesSeenType(observed); + if (atInstanceOf()) { + /* + * Statechart: self-transition at IO, potential information gain. + */ + if (anchorObsolete) { + transition(LEVEL.IO, anchor); + return true; + } + return false; + } + if (anchorObsolete) { + if (!atNonNull()) { + /* Statechart: transition from clueless to CC. */ + transition(LEVEL.CC, anchor); + return true; + } else { + /* Statechart: transition from NN to IO. */ + transition(LEVEL.IO, anchor); + return true; + } + } + /* + * Statechart: self-transition from whichever the current state is to itself, without + * information gain. + */ + return false; + } finally { + assert repOK(); + } + } + + /** + * Updates this {@link Witness Witness} to account for an observation about the non-null + * scrutinee conforming to a type. + * + * @return whether this {@link Witness Witness} was updated (iff the observation adds any new + * information) + */ + public boolean trackIO(ResolvedJavaType observed, GuardingNode anchor) { + assert repOK(); + try { + boolean gotMorePreciseType = refinesSeenType(observed); + if (!atInstanceOf() || gotMorePreciseType) { + transition(LEVEL.IO, anchor); + return true; + } + return gotMorePreciseType; + } finally { + assert repOK(); + } + } + + /** + * Shallow cloning is enough because what's reachable from {@link Witness} is primitive or used + * read-only when merging states. + * */ + @Override + public Witness clone() { + return new Witness(this); + } + + /** + * @return null for a clueless method, non-null otherwise. + * */ + GuardingNode guard() { + return gn; + } + + /** + * Merges another state into this one, by mutating this object, the other is left as is. + * */ + public void merge(Witness that, MergeNode merge) { + assert this.repOK(); + assert that.repOK(); + + if (clueless()) { + return; + } + + // umbrella type over the observations from both witnesses + ResolvedJavaType newSeen = (seen == null || that.seen == null) ? null : FlowUtil.widen(seen, that.seen); + + // preserve guarding node only if matches other, otherwise settle on `merge` + final GuardingNode resultGuard = guard() == that.guard() ? guard() : merge; + + /* + * guarantee on (both conformance and non-nullness) required from each input in order for + * the result to be able to offer such guarantee + */ + final boolean resultIO = atInstanceOf() && that.atInstanceOf(); + /* failing that, attempt to rescue type-conformance */ + final boolean resultCC = !resultIO && (!cluelessAboutType() && !that.cluelessAboutType()); + /* if all else fails, attempt to rescue non-nullness */ + final boolean resultNN = !resultIO && !resultCC && (isNonNull() && that.isNonNull()); + + seen = newSeen; + level = resultIO ? LEVEL.IO : resultCC ? LEVEL.CC : resultNN ? LEVEL.NN : LEVEL.CLUELESS; + gn = resultGuard; + + assert repOK(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(cluelessAboutType() ? "seen=?" : "seen=" + seen); + sb.append(";"); + sb.append("gn=" + gn); + return sb.toString(); + } + +}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,283 +0,0 @@ -/* - * 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 - * 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.phases; - -import com.oracle.graal.options.*; - -/** - * This class encapsulates options that control the behavior of the Graal compiler. - */ -// @formatter:off -public final class GraalOptions { - - @Option(help = "Use baseline compiler configuration") - public static final OptionValue<Boolean> UseBaselineCompiler = new OptionValue<>(false); - @Option(help = "Enable use of compiler intrinsics") - public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true); - @Option(help = "Enable inlining of monomorphic calls") - static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true); - @Option(help = "Enable inlining of polymorphic calls") - static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true); - @Option(help = "Enable inlining of megamorphic calls") - static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D); - @Option(help = "") - public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(20000); - @Option(help = "") - public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(5); - - // inlining settings - @Option(help = "") - public static final OptionValue<Float> BoostInliningForEscapeAnalysis = new OptionValue<>(2f); - @Option(help = "") - public static final OptionValue<Float> RelevanceCapForInlining = new OptionValue<>(1f); - @Option(help = "") - public static final OptionValue<Float> CapInheritedRelevance = new OptionValue<>(1f); - @Option(help = "") - public static final OptionValue<Boolean> IterativeInlining = new OptionValue<>(false); - - @Option(help = "") - public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10); - @Option(help = "") - public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300); - @Option(help = "") - public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300); - @Option(help = "") - public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0); - @Option(help = "") - public static final OptionValue<Boolean> InlineEverything = new OptionValue<>(false); - - // escape analysis settings - @Option(help = "") - public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2); - @Option(help = "") - public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null); - @Option(help = "") - public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32); - @Option(help = "") - public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false); - - @Option(help = "") - public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5); - @Option(help = "") - public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1); - - // profiling information - @Option(help = "") - public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); - - // graph caching - @Option(help = "") - public static final OptionValue<Boolean> CacheGraphs = new OptionValue<>(true); - - //loop transform settings TODO (gd) tune - @Option(help = "") - public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Integer> FullUnrollMaxNodes = new OptionValue<>(300); - @Option(help = "") - public static final OptionValue<Integer> ExactFullUnrollMaxNodes = new OptionValue<>(1200); - @Option(help = "") - public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f); - @Option(help = "") - public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3); - @Option(help = "") - public static final OptionValue<Integer> LoopUnswitchMaxIncrease = new OptionValue<>(50); - @Option(help = "") - public static final OptionValue<Integer> LoopUnswitchUncertaintyBoost = new OptionValue<>(5); - @Option(help = "") - public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true); - - // debugging settings - @Option(help = "") - public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false); - - @Option(help = "") - public static final OptionValue<String> PrintFilter = new OptionValue<>(null); - - // Debug settings: - @Option(help = "") - public static final OptionValue<Boolean> BootstrapReplacements = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Integer> GCDebugStartCycle = new OptionValue<>(-1); - // Ideal graph visualizer output settings - @Option(help = "Dump IdealGraphVisualizer output in binary format") - public static final OptionValue<Boolean> PrintBinaryGraphs = new OptionValue<>(true); - @Option(help = "Output probabilities for fixed nodes during binary graph dumping") - public static final OptionValue<Boolean> PrintGraphProbabilities = new OptionValue<>(false); - @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.") - public static final OptionValue<Boolean> PrintCFG = new OptionValue<>(false); - @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.") - public static final OptionValue<Boolean> PrintBackendCFG = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> PrintIdealGraphFile = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<String> PrintIdealGraphAddress = new OptionValue<>("127.0.0.1"); - @Option(help = "") - public static final OptionValue<Integer> PrintIdealGraphPort = new OptionValue<>(4444); - @Option(help = "") - public static final OptionValue<Integer> PrintBinaryGraphPort = new OptionValue<>(4445); - - // Other printing settings - @Option(help = "") - public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false); - @Option(help = "Print profiling information when parsing a method's bytecode") - public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> PrintCodeBytes = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> PrintBailout = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> TraceEscapeAnalysis = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false); - @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required") - public static final OptionValue<String> DecompileAfterPhase = new OptionValue<>(null); - - // HotSpot command line options - @Option(help = "") - public static final OptionValue<Boolean> HotSpotPrintCompilation = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> HotSpotCIPrintCompilerName = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false); - - // Register allocator debugging - @Option(help = "") - public static final OptionValue<String> RegisterPressure = new OptionValue<>(null); - - // Code generator settings - @Option(help = "") - public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true); - @Option(help = "") - static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true); - @Option(help = "") - static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true); - @Option(help = "") - static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true); - @Option(help = "") - static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> GenAssertionCode = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> AlignCallsForPatching = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true); - - @Option(help = "") - public static final OptionValue<Boolean> MemoryAwareScheduling = new OptionValue<>(true); - - // Translating tableswitch instructions - @Option(help = "") - public static final OptionValue<Integer> MinimumJumpTableSize = new OptionValue<>(5); - @Option(help = "") - public static final OptionValue<Integer> RangeTestsSwitchDensity = new OptionValue<>(5); - @Option(help = "") - public static final OptionValue<Double> MinTableSwitchDensity = new OptionValue<>(0.5); - - // Ahead of time compilation - @Option(help = "Try to avoid emitting code where patching is required") - public static final OptionValue<Boolean> ImmutableCode = new OptionValue<>(false); - - @Option(help = "") - public static final OptionValue<Boolean> CallArrayCopy = new OptionValue<>(true); - - // Runtime settings - @Option(help = "") - public static final OptionValue<Boolean> SupportJsrBytecodes = new OptionValue<>(true); - - @Option(help = "") - public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptCanonicalizer = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptDeoptimizationGrouping = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptLivenessAnalysis = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true); - @Option(help = "Allow backend to emit arithmetic and compares directly against memory.") - public static final OptionValue<Boolean> OptFoldMemory = new OptionValue<>(true); - - - /** - * Counts the various paths taken through snippets. - */ - @Option(help = "") - public static final OptionValue<Boolean> SnippetCounters = new OptionValue<>(false); -}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; public final class OptimisticOptimizations {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.phases.graph; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class InferStamps {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.phases.schedule; import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.nodes.cfg.ControlFlowGraph.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; @@ -986,13 +986,21 @@ stateAfter = ((StateSplit) i).stateAfter(); } + if (i instanceof LoopExitNode) { + for (ProxyNode proxy : ((LoopExitNode) i).proxies()) { + addToLatestSorting(b, proxy, sortedInstructions, visited, reads, beforeLastLocation); + } + } + for (Node input : i.inputs()) { if (input instanceof FrameState) { if (input != stateAfter) { addUnscheduledToLatestSorting(b, (FrameState) input, sortedInstructions, visited, reads, beforeLastLocation); } } else { - addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation); + if (!(i instanceof ProxyNode && input instanceof LoopExitNode)) { + addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation); + } } }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Mon Apr 28 10:31:17 2014 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; import com.oracle.graal.phases.schedule.*; @@ -60,8 +61,8 @@ } else { for (Node input : node.inputs()) { if (!visited.isMarked(input)) { - if (input instanceof FrameState && node instanceof StateSplit && input == ((StateSplit) node).stateAfter()) { - // nothing to do - after frame states are known, allowed cycles + if (input instanceof FrameState) { + // nothing to do - frame states are known, allowed cycles } else { assert false : "unexpected cycle detected at input " + node + " -> " + input; } @@ -157,11 +158,15 @@ FrameState pendingStateAfter = null; for (final ScheduledNode node : list) { FrameState stateAfter = node instanceof StateSplit ? ((StateSplit) node).stateAfter() : null; + if (node instanceof InfopointNode) { + stateAfter = ((InfopointNode) node).getState(); + } if (pendingStateAfter != null && node instanceof FixedNode) { pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() { public void apply(Node usage, Node nonVirtualNode) { - assert currentState.isMarked(nonVirtualNode) : nonVirtualNode + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list; + assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage + + " before " + node + " in block " + block + " \n" + list; } }); pendingStateAfter = null; @@ -181,15 +186,23 @@ } } } else if (node instanceof LoopExitNode) { - // the contents of the loop are only accessible via proxies at the exit - currentState.clearAll(); - currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin())); + if (!graph.isAfterFloatingReadPhase()) { + // loop contents are only accessible via proxies at the exit + currentState.clearAll(); + currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin())); + } // Loop proxies aren't scheduled, so they need to be added explicitly currentState.markAll(((LoopExitNode) node).proxies()); } else { for (Node input : node.inputs()) { if (input != stateAfter) { - assert currentState.isMarked(input) : input + " not available at " + node + " in block " + block + "\n" + list; + if (input instanceof FrameState) { + ((FrameState) input).applyToNonVirtual((usage, nonVirtual) -> { + assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list; + }); + } else { + assert currentState.isMarked(input) || input instanceof VirtualObjectNode : input + " not available at " + node + " in block " + block + "\n" + list; + } } } }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Providers.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Providers.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,13 +24,14 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.spi.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.tiers.*; /** * A set of providers, some of which may not be present (i.e., null). */ -public class Providers { +public class Providers implements CodeGenProviders { private final MetaAccessProvider metaAccess; private final CodeCacheProvider codeCache;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.phases.verify; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.type.*; @@ -45,7 +46,7 @@ private boolean isAssignableType(ValueNode node, MetaAccessProvider metaAccess) { if (node.stamp() instanceof ObjectStamp) { ResolvedJavaType valueType = metaAccess.lookupJavaType(klass); - ResolvedJavaType nodeType = ObjectStamp.typeOrNull(node); + ResolvedJavaType nodeType = StampTool.typeOrNull(node); if (nodeType != null && valueType.isAssignableFrom(nodeType)) { return true;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.printer; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.nio.*; @@ -297,13 +297,13 @@ Collection<Position> directInputPositions = nodeClass.getFirstLevelInputPositions(); writeShort((char) directInputPositions.size()); for (Position pos : directInputPositions) { - writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1); + writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); } Collection<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); writeShort((char) directSuccessorPositions.size()); for (Position pos : directSuccessorPositions) { - writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1); + writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); } } else if (object instanceof ResolvedJavaMethod) { @@ -433,7 +433,7 @@ private void writeEdges(Node node, Collection<Position> positions) throws IOException { NodeClass nodeClass = node.getNodeClass(); for (Position pos : positions) { - if (pos.subIndex == NodeClass.NOT_ITERABLE) { + if (pos.getSubIndex() == NodeClass.NOT_ITERABLE) { Node edge = nodeClass.get(node, pos); writeNodeRef(edge); } else {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Mon Apr 28 10:31:17 2014 +0200 @@ -380,12 +380,12 @@ continue; } - if (pos.index != lastIndex) { + if (pos.getIndex() != lastIndex) { if (lastIndex != -1) { out.print(suffix); } out.print(prefix).print(node.getNodeClass().getName(pos)).print(": "); - lastIndex = pos.index; + lastIndex = pos.getIndex(); } out.print(nodeToString(node.getNodeClass().get(node, pos))).print(" "); }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.printer; import static com.oracle.graal.compiler.GraalDebugConfig.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.util.*;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.printer; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.util.concurrent.atomic.*;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.printer; import static com.oracle.graal.compiler.GraalDebugConfig.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.net.*;
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,10 +24,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.spi.*; /**
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,10 +23,11 @@ package com.oracle.graal.replacements.amd64; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @@ -37,7 +38,7 @@ @ServiceProvider(ReplacementsProvider.class) public class AMD64Substitutions implements ReplacementsProvider { - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, Replacements replacements, TargetDescription target) { + public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { if (Intrinsify.getValue()) { replacements.registerSubstitutions(ArraysSubstitutions.class); replacements.registerSubstitutions(StringSubstitutions.class);
--- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,14 +24,15 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.hsail.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * This node implements HSAIL intrinsics for specific {@link Math} routines.
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,11 @@ */ package com.oracle.graal.replacements.test; +import org.junit.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.test.*; /** * Tests the implementation of checkcast, allowing profiling information to be manually specified. @@ -41,7 +42,7 @@ } } - @LongTest + @Test public void test1() { test("asNumber", profile(), 111); test("asNumber", profile(Integer.class), 111); @@ -51,7 +52,7 @@ test("asNumberExt", profile(Long.class, Short.class), 111); } - @LongTest + @Test public void test2() { test("asString", profile(), "111"); test("asString", profile(String.class), "111"); @@ -67,27 +68,27 @@ test("asStringExt", profile(String.class), "111"); } - @LongTest + @Test public void test3() { test("asNumber", profile(), "111"); } - @LongTest + @Test public void test4() { test("asString", profile(String.class), 111); } - @LongTest + @Test public void test5() { test("asNumberExt", profile(), "111"); } - @LongTest + @Test public void test6() { test("asStringExt", profile(String.class), 111); } - @LongTest + @Test public void test7() { Throwable throwable = new Exception(); test("asThrowable", profile(), throwable); @@ -95,12 +96,12 @@ test("asThrowable", profile(Exception.class, Error.class), throwable); } - @LongTest + @Test public void test8() { test("arrayStore", new Object[100], "111"); } - @LongTest + @Test public void test801() { test("arrayFill", new Object[100], "111"); } @@ -197,7 +198,7 @@ return (Cloneable) o; } - @LongTest + @Test public void test9() { Object o = new Depth13(); test("asDepth12", profile(), o); @@ -205,7 +206,7 @@ test("asDepth12", profile(Depth13.class, Depth14.class), o); } - @LongTest + @Test public void test10() { Object o = new Depth13[3][]; test("asDepth12Arr", o);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,10 @@ */ package com.oracle.graal.replacements.test; +import org.junit.*; + import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.test.*; /** * Tests for {@link InstanceOfDynamicNode}. @@ -35,7 +36,7 @@ return value; } - @LongTest + @Test public void test100() { final Object nul = null; test("isStringDynamic", nul); @@ -43,7 +44,7 @@ test("isStringDynamic", Object.class); } - @LongTest + @Test public void test101() { final Object nul = null; test("isStringIntDynamic", nul); @@ -51,7 +52,7 @@ test("isStringIntDynamic", Object.class); } - @LongTest + @Test public void test103() { test("isInstanceDynamic", String.class, null); test("isInstanceDynamic", String.class, "object"); @@ -61,7 +62,7 @@ test("isInstanceDynamic", int.class, Object.class); } - @LongTest + @Test public void test104() { test("isInstanceIntDynamic", String.class, null); test("isInstanceIntDynamic", String.class, "object");
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,6 +24,8 @@ import java.util.*; +import org.junit.*; + import com.oracle.graal.api.code.CompilationResult.Call; import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.code.CompilationResult.Site; @@ -34,7 +36,6 @@ import com.oracle.graal.replacements.test.CheckCastTest.Depth12; import com.oracle.graal.replacements.test.CheckCastTest.Depth13; import com.oracle.graal.replacements.test.CheckCastTest.Depth14; -import com.oracle.graal.test.*; /** * Tests the implementation of instanceof, allowing profiling information to be manually specified. @@ -54,7 +55,7 @@ } } - @LongTest + @Test public void test1() { test("isString", profile(), "object"); test("isString", profile(String.class), "object"); @@ -63,7 +64,7 @@ test("isString", profile(String.class), Object.class); } - @LongTest + @Test public void test2() { test("isStringInt", profile(), "object"); test("isStringInt", profile(String.class), "object"); @@ -72,7 +73,7 @@ test("isStringInt", profile(String.class), Object.class); } - @LongTest + @Test public void test201() { test("isStringIntComplex", profile(), "object"); test("isStringIntComplex", profile(String.class), "object"); @@ -81,7 +82,7 @@ test("isStringIntComplex", profile(String.class), Object.class); } - @LongTest + @Test public void test3() { Throwable throwable = new Exception(); test("isThrowable", profile(), throwable); @@ -93,7 +94,7 @@ test("isThrowable", profile(Exception.class, Error.class), Object.class); } - @LongTest + @Test public void test301() { onlyFirstIsException(new Exception(), new Error()); test("onlyFirstIsException", profile(), new Exception(), new Error()); @@ -102,7 +103,7 @@ test("onlyFirstIsException", profile(), new Error(), new Error()); } - @LongTest + @Test public void test4() { Throwable throwable = new Exception(); test("isThrowableInt", profile(), throwable); @@ -114,7 +115,7 @@ test("isThrowableInt", profile(Exception.class, Error.class), Object.class); } - @LongTest + @Test public void test5() { Map<?, ?> map = new HashMap<>(); test("isMap", profile(), map); @@ -127,7 +128,7 @@ test("isMap", profile(String.class, HashMap.class), Object.class); } - @LongTest + @Test public void test6() { Map<?, ?> map = new HashMap<>(); test("isMapInt", profile(), map); @@ -139,7 +140,7 @@ test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class); } - @LongTest + @Test public void test7() { Object o = new Depth13(); test("isDepth12", profile(), o); @@ -153,7 +154,7 @@ test("isDepth12", profile(String.class, HashMap.class), o); } - @LongTest + @Test public void test8() { Object o = new Depth13(); test("isDepth12Int", profile(), o); @@ -259,7 +260,7 @@ } } - @LongTest + @Test public void test9() { MyCall callAt63 = new MyCall(63); MyMark markAt63 = new MyMark(63); @@ -276,11 +277,10 @@ return s1.offset - s2.offset; } - @LongTest + @Test public void test10() { - Mark[] noMarks = {}; Call callAt63 = new Call(null, 63, 5, true, null); - Mark markAt63 = new Mark(63, "1", noMarks); + Mark markAt63 = new Mark(63, "1"); test("compareSites", callAt63, callAt63); test("compareSites", callAt63, markAt63); test("compareSites", markAt63, callAt63); @@ -301,7 +301,7 @@ * The test exists in this source file as the transformation was originally motivated by the * need to remove use of special JumpNodes in the {@code InstanceOfSnippets}. */ - @LongTest + @Test public void testRemoveIntermediateMaterialization() { List<String> list = Arrays.asList("1", "2", "3", "4"); test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no"); @@ -356,7 +356,7 @@ return o instanceof D[]; } - @LongTest + @Test public void testArray() { Object aArray = new A[10]; test("isArrayOfA", aArray);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,7 +25,6 @@ import org.junit.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.test.*; /** * Tests the implementation of {@code [A]NEWARRAY}. @@ -58,7 +57,7 @@ } } - @LongTest + @Test public void test1() { for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) { test("new" + type + "Array7");
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,7 +27,6 @@ import org.junit.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.test.*; /** * Tests the implementation of {@code NEW}. @@ -57,12 +56,12 @@ } } - @LongTest + @Test public void test1() { test("newObject"); } - @LongTest + @Test public void test2() { test("newObjectTwice"); } @@ -71,37 +70,37 @@ return new Object(); } - @LongTest + @Test public void test3() { test("newObjectLoop", 100); } - @LongTest + @Test public void test4() { test("newBigObject"); } - @LongTest + @Test public void test5() { test("newSomeObject"); } - @LongTest + @Test public void test6() { test("newEmptyString"); } - @LongTest + @Test public void test7() { test("newString", "value"); } - @LongTest + @Test public void test8() { test("newHashMap", 31); } - @LongTest + @Test public void test9() { test("newRegression", true); }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -25,12 +25,13 @@ import java.lang.reflect.*; import java.util.*; +import org.junit.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.test.*; /** * Tests the lowering of the MULTIANEWARRAY instruction. @@ -86,7 +87,7 @@ Class<?> bottomClass; int[] dimensions; - @LongTest + @Test public void test1() { for (Class<?> clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) { bottomClass = clazz; @@ -117,7 +118,7 @@ return new Object[10][9][8]; } - @LongTest + @Test public void test2() { test("newMultiArrayException"); }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -127,7 +127,7 @@ JavaWriteNode write = (JavaWriteNode) graph.start().next(); Assert.assertEquals(graph.getParameter(2), write.value()); Assert.assertEquals(graph.getParameter(0), write.object()); - Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); + Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci); IndexedLocationNode location = (IndexedLocationNode) write.location(); Assert.assertEquals(kind, location.getValueKind());
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -139,7 +139,7 @@ JavaWriteNode write = (JavaWriteNode) cast.next(); Assert.assertEquals(graph.getParameter(2), write.value()); - Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); + Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci); Assert.assertEquals(cast, write.object()); Assert.assertEquals(graph.getParameter(0), cast.getInput());
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 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,16 +22,10 @@ */ package com.oracle.graal.replacements.test; -import static com.oracle.graal.graph.UnsafeAccess.*; -import static com.oracle.graal.replacements.UnsafeSubstitutions.*; - import java.lang.reflect.*; -import java.util.concurrent.atomic.*; import org.junit.*; -import sun.misc.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; @@ -44,287 +38,6 @@ */ public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest { - static long off(Object o, String name) { - try { - return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name)); - } catch (Exception e) { - Assert.fail(e.toString()); - return 0L; - } - } - - static class Foo { - - boolean z; - byte b; - short s; - char c; - int i; - long l; - float f; - double d; - Object o; - - void testGet(Field field, long offset, String getName, Object value) throws Exception { - field.set(this, value); - Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class); - Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class); - Object expected = m1.invoke(unsafe, this, offset); - Object actual = m2.invoke(null, unsafe, this, offset); - Assert.assertEquals(expected, actual); - } - - void testDirect(Field field, long offset, String type, Object value) throws Exception { - if (type.equals("Boolean") || type.equals("Object")) { - // No direct memory access for these types - return; - } - - long address = unsafe.allocateMemory(offset + 16); - - String getName = "get" + type; - String putName = "put" + type; - Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType()); - Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class); - - Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); - Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class); - - m1.invoke(unsafe, address + offset, value); - Object expected = m2.invoke(unsafe, address + offset); - - m3.invoke(null, unsafe, address + offset, value); - Object actual = m4.invoke(null, unsafe, address + offset); - - unsafe.freeMemory(address); - Assert.assertEquals(expected, actual); - } - - void testPut(Field field, long offset, String putName, Object value) throws Exception { - Object initialValue = field.get(new Foo()); - field.set(this, initialValue); - - try { - Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); - Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType()); - m1.invoke(unsafe, this, offset, value); - Object expected = field.get(this); - m2.invoke(null, unsafe, this, offset, value); - Object actual = field.get(this); - Assert.assertEquals(expected, actual); - } catch (NoSuchMethodException e) { - if (!putName.startsWith("putOrdered")) { - throw e; - } - } - } - - void test(String fieldName, String typeSuffix, Object value) { - try { - Field field = Foo.class.getDeclaredField(fieldName); - long offset = unsafe.objectFieldOffset(field); - testGet(field, offset, "get" + typeSuffix, value); - testGet(field, offset, "get" + typeSuffix + "Volatile", value); - testPut(field, offset, "put" + typeSuffix, value); - testPut(field, offset, "put" + typeSuffix + "Volatile", value); - testPut(field, offset, "putOrdered" + typeSuffix, value); - testDirect(field, offset, typeSuffix, value); - } catch (Exception e) { - throw new AssertionError(e); - } - } - } - - @Test - public void testUnsafeSubstitutions() throws Exception { - test("unsafeCompareAndSwapInt"); - test("unsafeCompareAndSwapLong"); - test("unsafeCompareAndSwapObject"); - - test("unsafeGetBoolean"); - test("unsafeGetByte"); - test("unsafeGetShort"); - test("unsafeGetChar"); - test("unsafeGetInt"); - test("unsafeGetLong"); - test("unsafeGetFloat"); - test("unsafeGetDouble"); - test("unsafeGetObject"); - - test("unsafePutBoolean"); - test("unsafePutByte"); - test("unsafePutShort"); - test("unsafePutChar"); - test("unsafePutInt"); - test("unsafePutFloat"); - test("unsafePutDouble"); - test("unsafePutObject"); - - test("unsafeDirectMemoryRead"); - test("unsafeDirectMemoryWrite"); - - AtomicInteger a1 = new AtomicInteger(42); - AtomicInteger a2 = new AtomicInteger(42); - assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53)); - assertEquals(a1.get(), a2.get()); - - AtomicLong l1 = new AtomicLong(42); - AtomicLong l2 = new AtomicLong(42); - assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53)); - assertEquals(l1.get(), l2.get()); - - AtomicReference<String> o1 = new AtomicReference<>("42"); - AtomicReference<String> o2 = new AtomicReference<>("42"); - assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53")); - assertEquals(o1.get(), o2.get()); - - Foo f1 = new Foo(); - f1.test("z", "Boolean", Boolean.TRUE); - f1.test("b", "Byte", Byte.MIN_VALUE); - f1.test("s", "Short", Short.MAX_VALUE); - f1.test("c", "Char", '!'); - f1.test("i", "Int", 1010010); - f1.test("f", "Float", -34.5F); - f1.test("l", "Long", 99999L); - f1.test("d", "Double", 1234.5678D); - f1.test("o", "Object", "object"); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapInt(obj, offset, 0, 1); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapLong(obj, offset, 0, 1); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapObject(obj, offset, null, new Object()); - } - - @SuppressWarnings("all") - public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) { - return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) { - return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) { - return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) { - return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) { - return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) { - return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) { - return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) { - return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) { - return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) { - unsafe.putBoolean(obj, offset, value); - unsafe.putBooleanVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) { - unsafe.putByte(obj, offset, value); - unsafe.putByteVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) { - unsafe.putShort(obj, offset, value); - unsafe.putShortVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) { - unsafe.putChar(obj, offset, value); - unsafe.putCharVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) { - unsafe.putInt(obj, offset, value); - unsafe.putIntVolatile(obj, offset, value); - unsafe.putOrderedInt(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) { - unsafe.putLong(obj, offset, value); - unsafe.putLongVolatile(obj, offset, value); - unsafe.putOrderedLong(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) { - unsafe.putFloat(obj, offset, value); - unsafe.putFloatVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) { - unsafe.putDouble(obj, offset, value); - unsafe.putDoubleVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) { - unsafe.putObject(obj, offset, value); - unsafe.putObjectVolatile(obj, offset, value); - unsafe.putOrderedObject(obj, offset, value); - } - - @SuppressWarnings("all") - public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) { - // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist - return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address); - } - - @SuppressWarnings("all") - public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) { - // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist - unsafe.putByte(address, value); - unsafe.putShort(address, value); - unsafe.putChar(address, (char) value); - unsafe.putInt(address, value); - unsafe.putLong(address, value); - unsafe.putFloat(address, value); - unsafe.putDouble(address, value); - } - @Test public void testMathSubstitutions() { assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class); // Java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,451 @@ +/* + * 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.replacements.test; + +import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import static com.oracle.graal.replacements.UnsafeSubstitutions.*; + +import java.lang.reflect.*; +import java.util.concurrent.atomic.*; + +import org.junit.*; + +import sun.misc.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.replacements.*; + +/** + * Tests the VM independent {@link UnsafeSubstitutions}. + */ +public class UnsafeSubstitutionsTest extends MethodSubstitutionTest { + + private static Object executeVarargsSafe(InstalledCode code, Object... args) { + try { + return code.executeVarargs(args); + } catch (InvalidInstalledCodeException e) { + throw new RuntimeException(e); + } + } + + private static Object invokeSafe(Method method, Object receiver, Object... args) { + method.setAccessible(true); + try { + return method.invoke(receiver, args); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public void testSubstitution(String testMethodName, Class<?> holder, String methodName, Class<?>[] parameterTypes, Object receiver, Object[] args1, Object[] args2) { + Method originalMethod = getMethod(holder, methodName, parameterTypes); + Method testMethod = getMethod(testMethodName); + + // Force compilation + InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod)); + assert code != null; + + // Verify that the original method and the substitution produce the same value + { + Object expected = invokeSafe(originalMethod, receiver, args1); + Object actual = invokeSafe(testMethod, null, args2); + assertEquals(expected, actual); + } + + // Verify that the generated code and the original produce the same value + { + Object expected = invokeSafe(originalMethod, receiver, args1); + Object actual = executeVarargsSafe(code, args2); + assertEquals(expected, actual); + } + } + + static long off(Object o, String name) { + try { + return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name)); + } catch (Exception e) { + Assert.fail(e.toString()); + return 0L; + } + } + + static class Foo { + + boolean z; + byte b; + short s; + char c; + int i; + long l; + float f; + double d; + Object o; + + void testGet(Field field, long offset, String getName, Object value) throws Exception { + field.set(this, value); + Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class); + Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class); + Object expected = m1.invoke(unsafe, this, offset); + Object actual = m2.invoke(null, unsafe, this, offset); + Assert.assertEquals(expected, actual); + } + + void testDirect(Field field, long offset, String type, Object value) throws Exception { + if (type.equals("Boolean") || type.equals("Object")) { + // No direct memory access for these types + return; + } + + long address = unsafe.allocateMemory(offset + 16); + + String getName = "get" + type; + String putName = "put" + type; + Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType()); + Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class); + + Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); + Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class); + + m1.invoke(unsafe, address + offset, value); + Object expected = m2.invoke(unsafe, address + offset); + + m3.invoke(null, unsafe, address + offset, value); + Object actual = m4.invoke(null, unsafe, address + offset); + + unsafe.freeMemory(address); + Assert.assertEquals(expected, actual); + } + + void testPut(Field field, long offset, String putName, Object value) throws Exception { + Object initialValue = field.get(new Foo()); + field.set(this, initialValue); + + try { + Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); + Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType()); + m1.invoke(unsafe, this, offset, value); + Object expected = field.get(this); + m2.invoke(null, unsafe, this, offset, value); + Object actual = field.get(this); + Assert.assertEquals(expected, actual); + } catch (NoSuchMethodException e) { + if (!putName.startsWith("putOrdered")) { + throw e; + } + } + } + + void test(String fieldName, String typeSuffix, Object value) { + try { + Field field = Foo.class.getDeclaredField(fieldName); + long offset = unsafe.objectFieldOffset(field); + testGet(field, offset, "get" + typeSuffix, value); + testGet(field, offset, "get" + typeSuffix + "Volatile", value); + testPut(field, offset, "put" + typeSuffix, value); + testPut(field, offset, "put" + typeSuffix + "Volatile", value); + testPut(field, offset, "putOrdered" + typeSuffix, value); + testDirect(field, offset, typeSuffix, value); + } catch (Exception e) { + throw new AssertionError(e); + } + } + } + + @Test + public void testUnsafeSubstitutions() throws Exception { + test("unsafeCompareAndSwapInt"); + test("unsafeCompareAndSwapLong"); + test("unsafeCompareAndSwapObject"); + + test("unsafeGetBoolean"); + test("unsafeGetByte"); + test("unsafeGetShort"); + test("unsafeGetChar"); + test("unsafeGetInt"); + test("unsafeGetLong"); + test("unsafeGetFloat"); + test("unsafeGetDouble"); + test("unsafeGetObject"); + + test("unsafePutBoolean"); + test("unsafePutByte"); + test("unsafePutShort"); + test("unsafePutChar"); + test("unsafePutInt"); + test("unsafePutFloat"); + test("unsafePutDouble"); + test("unsafePutObject"); + + test("unsafeDirectMemoryRead"); + test("unsafeDirectMemoryWrite"); + + AtomicInteger a1 = new AtomicInteger(42); + AtomicInteger a2 = new AtomicInteger(42); + assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53)); + assertEquals(a1.get(), a2.get()); + + AtomicLong l1 = new AtomicLong(42); + AtomicLong l2 = new AtomicLong(42); + assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53)); + assertEquals(l1.get(), l2.get()); + + AtomicReference<String> o1 = new AtomicReference<>("42"); + AtomicReference<String> o2 = new AtomicReference<>("42"); + assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53")); + assertEquals(o1.get(), o2.get()); + + Foo f1 = new Foo(); + f1.test("z", "Boolean", Boolean.TRUE); + f1.test("b", "Byte", Byte.MIN_VALUE); + f1.test("s", "Short", Short.MAX_VALUE); + f1.test("c", "Char", '!'); + f1.test("i", "Int", 1010010); + f1.test("f", "Float", -34.5F); + f1.test("l", "Long", 99999L); + f1.test("d", "Double", 1234.5678D); + f1.test("o", "Object", "object"); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapInt(obj, offset, 0, 1); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapLong(obj, offset, 0, 1); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapObject(obj, offset, null, new Object()); + } + + @SuppressWarnings("all") + public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) { + return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) { + return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) { + return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) { + return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) { + return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) { + return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) { + return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) { + return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) { + return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) { + unsafe.putBoolean(obj, offset, value); + unsafe.putBooleanVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) { + unsafe.putByte(obj, offset, value); + unsafe.putByteVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) { + unsafe.putShort(obj, offset, value); + unsafe.putShortVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) { + unsafe.putChar(obj, offset, value); + unsafe.putCharVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) { + unsafe.putInt(obj, offset, value); + unsafe.putIntVolatile(obj, offset, value); + unsafe.putOrderedInt(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) { + unsafe.putLong(obj, offset, value); + unsafe.putLongVolatile(obj, offset, value); + unsafe.putOrderedLong(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) { + unsafe.putFloat(obj, offset, value); + unsafe.putFloatVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) { + unsafe.putDouble(obj, offset, value); + unsafe.putDoubleVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) { + unsafe.putObject(obj, offset, value); + unsafe.putObjectVolatile(obj, offset, value); + unsafe.putOrderedObject(obj, offset, value); + } + + @SuppressWarnings("all") + public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) { + // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist + return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address); + } + + @SuppressWarnings("all") + public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) { + // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist + unsafe.putByte(address, value); + unsafe.putShort(address, value); + unsafe.putChar(address, (char) value); + unsafe.putInt(address, value); + unsafe.putLong(address, value); + unsafe.putFloat(address, value); + unsafe.putDouble(address, value); + } + + @Test + public void testGetAndAddInt() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "i"); + Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, int.class}; + for (int delta = Integer.MAX_VALUE - 10; delta < Integer.MAX_VALUE; delta++) { + Object[] args1 = new Object[]{f1, offset, delta}; + Object[] args2 = new Object[]{f2, offset, delta}; + testSubstitution("getAndAddInt", Unsafe.class, "getAndAddInt", parameterTypes, unsafe, args1, args2); + } + } + + public static int getAndAddInt(Object obj, long offset, int delta) { + return unsafe.getAndAddInt(obj, offset, delta); + } + + @Test + public void testGetAndAddLong() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "l"); + Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, long.class}; + for (long delta = Long.MAX_VALUE - 10; delta < Long.MAX_VALUE; delta++) { + Object[] args1 = new Object[]{f1, offset, delta}; + Object[] args2 = new Object[]{f2, offset, delta}; + testSubstitution("getAndAddLong", Unsafe.class, "getAndAddLong", parameterTypes, unsafe, args1, args2); + } + } + + public static long getAndAddLong(Object obj, long offset, long delta) { + return unsafe.getAndAddLong(obj, offset, delta); + } + + @Test + public void testGetAndSetInt() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "i"); + Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, int.class}; + for (int delta = Integer.MAX_VALUE - 10; delta < Integer.MAX_VALUE; delta++) { + Object[] args1 = new Object[]{f1, offset, delta}; + Object[] args2 = new Object[]{f2, offset, delta}; + testSubstitution("getAndSetInt", Unsafe.class, "getAndSetInt", parameterTypes, unsafe, args1, args2); + } + } + + public static int getAndSetInt(Object obj, long offset, int newValue) { + return unsafe.getAndSetInt(obj, offset, newValue); + } + + @Test + public void testGetAndSetLong() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "l"); + Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, long.class}; + for (long newValue = Long.MAX_VALUE - 10; newValue < Long.MAX_VALUE; newValue++) { + Object[] args1 = new Object[]{f1, offset, newValue}; + Object[] args2 = new Object[]{f2, offset, newValue}; + testSubstitution("getAndSetLong", Unsafe.class, "getAndSetLong", parameterTypes, unsafe, args1, args2); + } + } + + public static long getAndSetLong(Object obj, long offset, long newValue) { + return unsafe.getAndSetLong(obj, offset, newValue); + } + + @Test + public void testGetAndSetObject() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "o"); + Class<?>[] parameterTypes = new Class<?>[]{Object.class, long.class, Object.class}; + for (long i = 0; i < 10; i++) { + Object o = new Object(); + Object[] args1 = new Object[]{f1, offset, o}; + Object[] args2 = new Object[]{f2, offset, o}; + testSubstitution("getAndSetObject", Unsafe.class, "getAndSetObject", parameterTypes, unsafe, args1, args2); + System.gc(); + } + } + + public static Object getAndSetObject(Object obj, long offset, Object newValue) { + return unsafe.getAndSetObject(obj, offset, newValue); + } + +}
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,6 +24,8 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; @@ -31,7 +33,6 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing; import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; -import com.oracle.graal.test.*; import com.oracle.graal.word.*; /** @@ -53,7 +54,7 @@ return installer.makeGraph(resolvedMethod, null, resolvedMethod, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); } - @LongTest + @Test public void construction() { long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; @@ -65,7 +66,7 @@ } } - @LongTest + @Test public void testArithmetic() { long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; @@ -102,7 +103,7 @@ } } - @LongTest + @Test public void testCompare() { long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE}; for (long word1 : words) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,22 +22,21 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.Snippet.Fold; @@ -57,7 +56,7 @@ @Override public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - if (Modifier.isNative(method.getModifiers())) { + if (method.isNative()) { return false; } if (method.getAnnotation(Fold.class) != null) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @@ -33,12 +34,12 @@ import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; /** - * This phase ensures that there's a single {@linkplain FrameState#AFTER_BCI collapsed frame state} - * per path. + * This phase ensures that there's a single {@linkplain BytecodeFrame#AFTER_BCI collapsed frame + * state} per path. * * Removes other frame states from {@linkplain StateSplit#hasSideEffect() non-side-effecting} nodes - * in the graph, and replaces them with {@linkplain FrameState#INVALID_FRAMESTATE_BCI invalid frame - * states}. + * in the graph, and replaces them with {@linkplain BytecodeFrame#INVALID_FRAMESTATE_BCI invalid + * frame states}. * * The invalid frame states ensure that no deoptimization to a snippet frame state will happen. */ @@ -176,7 +177,7 @@ if (!unwindSideEffects.contains(returnSideEffect) && !maskedSideEffects.contains(returnSideEffect)) { StateSplit split = (StateSplit) returnSideEffect; if (split.stateAfter() != null) { - split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI))); + split.setStateAfter(graph.add(new FrameState(BytecodeFrame.AFTER_BCI))); } } } @@ -185,7 +186,7 @@ if (!returnSideEffects.contains(unwindSideEffect) && !maskedSideEffects.contains(unwindSideEffect)) { StateSplit split = (StateSplit) unwindSideEffect; if (split.stateAfter() != null) { - split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_EXCEPTION_BCI))); + split.setStateAfter(graph.add(new FrameState(BytecodeFrame.AFTER_EXCEPTION_BCI))); } } } @@ -214,7 +215,7 @@ } private static FrameState createInvalidFrameState(FixedNode node) { - return node.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI)); + return node.graph().add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); } } }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,11 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; @@ -35,7 +36,7 @@ @ServiceProvider(ReplacementsProvider.class) public class GraalMethodSubstitutions implements ReplacementsProvider { - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) { + public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { for (Class<?> clazz : BoxingSubstitutions.getClasses()) { replacements.registerSubstitutions(clazz); }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Apr 28 10:31:17 2014 +0200 @@ -96,7 +96,7 @@ } public InvokeNode createInvoke(Class<?> declaringClass, String name, ValueNode... args) { - return createInvoke(declaringClass, name, InvokeKind.Static, null, FrameState.UNKNOWN_BCI, args); + return createInvoke(declaringClass, name, InvokeKind.Static, null, BytecodeFrame.UNKNOWN_BCI, args); } /** @@ -125,7 +125,7 @@ * arguments. */ public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, HIRFrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { - assert Modifier.isStatic(method.getModifiers()) == (invokeKind == InvokeKind.Static); + assert method.isStatic() == (invokeKind == InvokeKind.Static); Signature signature = method.getSignature(); JavaType returnType = signature.getReturnType(null); assert checkArgs(method, args); @@ -157,7 +157,7 @@ */ public boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) { Signature signature = method.getSignature(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); if (signature.getParameterCount(!isStatic) != args.length) { throw new AssertionError(graph + ": wrong number of arguments to " + method); }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -42,7 +42,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.util.*; @@ -82,7 +81,7 @@ NodeIntrinsic intrinsic = getIntrinsic(target); if (intrinsic != null) { assert target.getAnnotation(Fold.class) == null; - assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target; + assert target.isStatic() : "node intrinsic must be static: " + target; ResolvedJavaType[] parameterTypes = resolveJavaTypes(signatureToTypes(target), declaringClass);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.lang.reflect.*; import java.util.*; @@ -96,7 +96,7 @@ @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry) { assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); - assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native"; + assert !method.isAbstract() && !method.isNative() : "Snippet must not be abstract or native"; StructuredGraph graph = UseSnippetGraphCache ? graphs.get(method) : null; if (graph == null) { @@ -532,7 +532,7 @@ } private static boolean isInlinable(final ResolvedJavaMethod method) { - return !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()); + return !method.isAbstract() && !method.isNative(); } private static String originalName(Method substituteMethod, String methodSubstitution) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.replacements; import java.lang.annotation.*; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.replacements.nodes.*; @@ -89,7 +87,7 @@ @Override public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - if (Modifier.isNative(method.getModifiers())) { + if (method.isNative()) { return false; } if (method.getAnnotation(Fold.class) != null) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,7 +24,7 @@ //JaCoCo Exclude -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.io.*; import java.util.*; @@ -32,15 +32,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.word.*; /** * A counter that can be safely {@linkplain #inc() incremented} from within a snippet for gathering * snippet specific metrics. */ public class SnippetCounter implements Comparable<SnippetCounter> { - private static final LocationIdentity SNIPPET_COUNTER_LOCATION = new NamedLocationIdentity("SnippetCounter"); - /** * A group of related counters. */ @@ -107,7 +105,7 @@ /** * Creates a counter. - * + * * @param group the group to which the counter belongs. If this is null, the newly created * counter is disabled and {@linkplain #inc() incrementing} is a no-op. * @param name the name of the counter @@ -130,12 +128,20 @@ } /** + * We do not want to use the {@link LocationIdentity} of the {@link #value} field, so that the + * usage in snippets is always possible. If a method accesses the counter via the field and the + * snippet, the result might not be correct though. + */ + protected static final LocationIdentity SNIPPET_COUNTER_LOCATION = new NamedLocationIdentity("SnippetCounter"); + + /** * Increments the value of this counter. This method can be safely used in a snippet if it is * invoked on a compile-time constant {@link SnippetCounter} object. */ public void inc() { if (group != null) { - DirectObjectStoreNode.storeLong(this, countOffset(), 0, value + 1, SNIPPET_COUNTER_LOCATION); + long loadedValue = ObjectAccess.readLong(this, countOffset(), SNIPPET_COUNTER_LOCATION); + ObjectAccess.writeLong(this, countOffset(), loadedValue + 1, SNIPPET_COUNTER_LOCATION); } }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,9 +23,11 @@ package com.oracle.graal.replacements; import static com.oracle.graal.api.meta.LocationIdentity.*; + import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.debug.Debug.*; import static java.util.FormattableFlags.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.lang.reflect.*; @@ -40,8 +42,8 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; @@ -49,7 +51,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.FloatingReadPhase.MemoryMapImpl; @@ -103,7 +104,7 @@ this.method = method; instantiationCounter = Debug.metric("SnippetInstantiationCount[%s]", method); instantiationTimer = Debug.timer("SnippetInstantiationTime[%s]", method); - assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); + assert method.isStatic() : "snippet method must be static: " + MetaUtil.format("%H.%n", method); int count = method.getSignature().getParameterCount(false); constantParameters = new boolean[count]; varargsParameters = new boolean[count]; @@ -966,7 +967,15 @@ * if no FloatingReadNode is reading from this location, the kill to this location is fine. */ for (FloatingReadNode frn : replacee.graph().getNodes(FloatingReadNode.class)) { - assert !(kills.contains(frn.location().getLocationIdentity())) : frn + " reads from " + frn.location().getLocationIdentity() + " but " + replacee + " does not kill this location"; + LocationIdentity locationIdentity = frn.location().getLocationIdentity(); + if (SnippetCounters.getValue()) { + // accesses to snippet counters are artificially introduced and violate the memory + // semantics. + if (locationIdentity == SnippetCounter.SNIPPET_COUNTER_LOCATION) { + continue; + } + } + assert !kills.contains(locationIdentity) : frn + " reads from location \"" + locationIdentity + "\" but " + replacee + " does not kill this location"; } return true; }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.lang.reflect.*;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java Mon Apr 28 10:31:17 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 @@ -42,17 +42,17 @@ @MethodSubstitution(isStatic = false) public static boolean compareAndSwapObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object expected, Object x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Object); + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Object, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) public static boolean compareAndSwapInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int expected, int x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Int); + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Int, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) public static boolean compareAndSwapLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long expected, long x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Long); + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Long, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -399,4 +399,47 @@ } return DynamicNewInstanceNode.allocateInstance(clazz, true); } + + /** + * Guard for {@link Unsafe#getAndSetInt} method family. + */ + public static class GetAndSetGuard implements SubstitutionGuard { + public boolean execute() { + // FIXME should return whether the current compilation target supports these + String arch = System.getProperty("os.arch"); + switch (arch) { + case "amd64": + case "x86_64": + return true; + default: + return false; + } + } + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static int getAndAddInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int delta) { + return AtomicReadAndAddNode.getAndAddInt(o, offset, delta, LocationIdentity.ANY_LOCATION); + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static long getAndAddLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long delta) { + return AtomicReadAndAddNode.getAndAddLong(o, offset, delta, LocationIdentity.ANY_LOCATION); + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static int getAndSetInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int newValue) { + return AtomicReadAndWriteNode.getAndSetInt(o, offset, newValue, Kind.Int, LocationIdentity.ANY_LOCATION); + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static long getAndSetLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long newValue) { + return AtomicReadAndWriteNode.getAndSetLong(o, offset, newValue, Kind.Long, LocationIdentity.ANY_LOCATION); + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static Object getAndSetObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object newValue) { + return AtomicReadAndWriteNode.getAndSetObject(o, offset, newValue, Kind.Object, LocationIdentity.ANY_LOCATION); + } + }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,20 +23,18 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; /** * Compares two arrays with the same length. */ -public class ArrayEqualsNode extends FixedWithNextNode implements LIRGenLowerable, Canonicalizable, Virtualizable { +public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable { /** {@link Kind} of the arrays to compare. */ private final Kind kind; @@ -131,7 +129,7 @@ public static native boolean equals(double[] array1, double[] array2, int length); @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(Kind.Int); gen.emitArrayEquals(kind, result, gen.operand(array1), gen.operand(array2), gen.operand(length)); gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,16 +23,15 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class BitCountNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class BitCountNode extends FloatingNode implements LIRLowerable, Canonicalizable { @Input private ValueNode value; @@ -65,7 +64,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(Kind.Int); gen.emitBitCount(result, gen.operand(value)); gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,16 +23,15 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class BitScanForwardNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class BitScanForwardNode extends FloatingNode implements LIRLowerable, Canonicalizable { @Input private ValueNode value; @@ -72,7 +71,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(Kind.Int); gen.emitBitScanForward(result, gen.operand(value)); gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,16 +23,15 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class BitScanReverseNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class BitScanReverseNode extends FloatingNode implements LIRLowerable, Canonicalizable { @Input private ValueNode value; @@ -79,7 +78,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(Kind.Int); gen.getLIRGeneratorTool().emitBitScanReverse(result, gen.operand(value)); gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,13 +22,13 @@ */ package com.oracle.graal.replacements.nodes; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,13 +22,13 @@ */ package com.oracle.graal.replacements.nodes; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,9 +24,9 @@ import java.util.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.Snippet.VarargsParameter; /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,7 @@ */ package com.oracle.graal.replacements.nodes; -import static java.lang.reflect.Modifier.*; - +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; @@ -89,7 +88,7 @@ StructuredGraph methodSubstitution = tool.getReplacements().getMethodSubstitution(getTargetMethod()); if (methodSubstitution != null) { methodSubstitution = methodSubstitution.copy(); - if (stateAfter() == null || stateAfter().bci == FrameState.AFTER_BCI) { + if (stateAfter() == null || stateAfter().bci == BytecodeFrame.AFTER_BCI) { /* * handles the case of a MacroNode inside a snippet used for another MacroNode * lowering @@ -136,7 +135,7 @@ if (replacementGraph != null) { // Pull out the receiver null check so that a replaced // receiver can be lowered if necessary - if (!isStatic(targetMethod.getModifiers())) { + if (!targetMethod.isStatic()) { ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); if (nonNullReceiver instanceof Lowerable) { ((Lowerable) nonNullReceiver).lower(tool); @@ -173,7 +172,7 @@ if (!call.targetMethod().equals(getTargetMethod())) { throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName()); } - assert invoke.stateAfter().bci == FrameState.AFTER_BCI; + assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI; // Here we need to fix the bci of the invoke InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci())); newInvoke.setStateAfter(invoke.stateAfter());
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,12 +24,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; 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 MathIntrinsicNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.replacements.nodes; +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.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) public class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,10 +24,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Access the value of a specific register.
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,16 +23,15 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class ReverseBytesNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class ReverseBytesNode extends FloatingNode implements LIRLowerable, Canonicalizable { @Input private ValueNode value; @@ -66,9 +65,9 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(value.getKind()); - gen.getLIRGenerator().emitByteSwap(result, gen.operand(value)); + gen.getLIRGeneratorTool().emitByteSwap(result, gen.operand(value)); gen.setResult(this, result); } }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,10 +24,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Changes the value of a specific register.
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Mon Apr 28 10:31:17 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -35,28 +35,28 @@ */ public class SPARC extends Architecture { - // @formatter:off - public static final RegisterCategory CPU = new RegisterCategory("CPU"); public static final RegisterCategory FPU = new RegisterCategory("FPU"); // General purpose registers - public static final Register r0 = new Register(0, 0, "g0", CPU); - public static final Register r1 = new Register(1, 1, "g1", CPU); - public static final Register r2 = new Register(2, 2, "g2", CPU); - public static final Register r3 = new Register(3, 3, "g3", CPU); - public static final Register r4 = new Register(4, 4, "g4", CPU); - public static final Register r5 = new Register(5, 5, "g5", CPU); - public static final Register r6 = new Register(6, 6, "g6", CPU); - public static final Register r7 = new Register(7, 7, "g7", CPU); - public static final Register r8 = new Register(8, 8, "o0", CPU); - public static final Register r9 = new Register(9, 9, "o1", CPU); + public static final Register r0 = new Register(0, 0, "g0", CPU); + public static final Register r1 = new Register(1, 1, "g1", CPU); + public static final Register r2 = new Register(2, 2, "g2", CPU); + public static final Register r3 = new Register(3, 3, "g3", CPU); + public static final Register r4 = new Register(4, 4, "g4", CPU); + public static final Register r5 = new Register(5, 5, "g5", CPU); + public static final Register r6 = new Register(6, 6, "g6", CPU); + public static final Register r7 = new Register(7, 7, "g7", CPU); + + public static final Register r8 = new Register(8, 8, "o0", CPU); + public static final Register r9 = new Register(9, 9, "o1", CPU); public static final Register r10 = new Register(10, 10, "o2", CPU); public static final Register r11 = new Register(11, 11, "o3", CPU); public static final Register r12 = new Register(12, 12, "o4", CPU); public static final Register r13 = new Register(13, 13, "o5", CPU); public static final Register r14 = new Register(14, 14, "o6", CPU); public static final Register r15 = new Register(15, 15, "o7", CPU); + public static final Register r16 = new Register(16, 16, "l0", CPU); public static final Register r17 = new Register(17, 17, "l1", CPU); public static final Register r18 = new Register(18, 18, "l2", CPU); @@ -65,6 +65,7 @@ public static final Register r21 = new Register(21, 21, "l5", CPU); public static final Register r22 = new Register(22, 22, "l6", CPU); public static final Register r23 = new Register(23, 23, "l7", CPU); + public static final Register r24 = new Register(24, 24, "i0", CPU); public static final Register r25 = new Register(25, 25, "i1", CPU); public static final Register r26 = new Register(26, 26, "i2", CPU); @@ -113,12 +114,14 @@ public static final Register sp = o6; public static final Register fp = i6; + // @formatter:off public static final Register[] cpuRegisters = { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30, r31 }; + // @formatter:on // Floating point registers public static final Register f0 = new Register(32, 0, "f0", FPU); @@ -130,6 +133,43 @@ public static final Register f6 = new Register(38, 6, "f6", FPU); public static final Register f7 = new Register(39, 7, "f7", FPU); + public static final Register f8 = new Register(40, 8, "f8", FPU); + public static final Register f9 = new Register(41, 9, "f9", FPU); + public static final Register f10 = new Register(42, 10, "f10", FPU); + public static final Register f11 = new Register(43, 11, "f11", FPU); + public static final Register f12 = new Register(44, 12, "f12", FPU); + public static final Register f13 = new Register(45, 13, "f13", FPU); + public static final Register f14 = new Register(46, 14, "f14", FPU); + public static final Register f15 = new Register(47, 15, "f15", FPU); + + public static final Register f16 = new Register(48, 16, "f16", FPU); + public static final Register f17 = new Register(49, 17, "f17", FPU); + public static final Register f18 = new Register(50, 18, "f18", FPU); + public static final Register f19 = new Register(51, 19, "f19", FPU); + public static final Register f20 = new Register(52, 20, "f20", FPU); + public static final Register f21 = new Register(53, 21, "f21", FPU); + public static final Register f22 = new Register(54, 22, "f22", FPU); + public static final Register f23 = new Register(55, 23, "f23", FPU); + + public static final Register f24 = new Register(56, 24, "f24", FPU); + public static final Register f25 = new Register(57, 25, "f25", FPU); + public static final Register f26 = new Register(58, 26, "f26", FPU); + public static final Register f27 = new Register(59, 27, "f27", FPU); + public static final Register f28 = new Register(60, 28, "f28", FPU); + public static final Register f29 = new Register(61, 29, "f29", FPU); + public static final Register f30 = new Register(62, 30, "f30", FPU); + public static final Register f31 = new Register(63, 31, "f31", FPU); + + // @formatter:off + public static final Register[] fpuRegisters = { + f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, f14, f15, + f16, f17, f18, f19, f20, f21, f22, f23, + f24, f25, f26, f27, f28, f29, f30, f31 + }; + // @formatter:on + + // @formatter:off public static final Register[] allRegisters = { // CPU r0, r1, r2, r3, r4, r5, r6, r7, @@ -138,9 +178,16 @@ r24, r25, r26, r27, r28, r29, r30, r31, // FPU f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, f14, f15, + f16, f17, f18, f19, f20, f21, f22, f23, + f24, f25, f26, f27, f28, f29, f30, f31 }; + // @formatter:on - // @formatter:on + /** + * Stack bias for stack and frame pointer loads. + */ + public static final int STACK_BIAS = 0x7ff; public SPARC() { super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + 1, 8);
--- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalLongUnitTest.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.test; - -import java.util.*; - -import org.junit.*; -import org.junit.runners.*; -import org.junit.runners.model.*; - -public class GraalLongUnitTest extends BlockJUnit4ClassRunner { - - public GraalLongUnitTest(Class<?> klass) throws InitializationError { - super(klass); - } - - @Override - protected List<FrameworkMethod> computeTestMethods() { - List<FrameworkMethod> methods = new ArrayList<>(5); - methods.addAll(getTestClass().getAnnotatedMethods(Test.class)); - methods.addAll(getTestClass().getAnnotatedMethods(LongTest.class)); - return methods; - } -}
--- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -26,14 +26,12 @@ import java.util.*; import org.junit.*; -import org.junit.runner.*; /** * Base class for Graal tests. * <p> * This contains common utility methods that are used in multiple test projects. */ -@RunWith(GraalLongUnitTest.class) public class GraalTest { protected Method getMethod(String methodName) {
--- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/LongTest.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.test; - -import java.lang.annotation.*; - -/* copy of org.junit.Test */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface LongTest { - - static final class None extends Throwable { - - private static final long serialVersionUID = 1L; - - private None() { - } - } - - Class<? extends Throwable> expected() default None.class; - - long timeout() default 0L; -}
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java Mon Apr 28 10:31:17 2014 +0200 @@ -88,13 +88,12 @@ public abstract CallTarget getTargetCallTarget(); - public DirectCallNode getCallNode() { + public Node getCallNode() { Object receiver = stackFrame.getLocal(getNotifyIndex()); - if (receiver instanceof DirectCallNode) { - return (DirectCallNode) receiver; - } else { - return null; + if (receiver instanceof DirectCallNode || receiver instanceof IndirectCallNode) { + return (Node) receiver; } + return null; } /**
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Mon Apr 28 10:31:17 2014 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.asm.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.meta.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Apr 28 10:31:17 2014 +0200 @@ -247,16 +247,16 @@ logInliningDecision(result); } - private void performInlining(TruffleInliningResult result) { - if (inliningPerformed) { + private static void performInlining(TruffleInliningResult result) { + if (result.getCallTarget().inliningPerformed) { return; } - inliningPerformed = true; + result.getCallTarget().inliningPerformed = true; for (TruffleInliningProfile profile : result) { profile.getCallNode().inline(); TruffleInliningResult recursiveResult = profile.getRecursiveResult(); if (recursiveResult != null) { - recursiveResult.getCallTarget().performInlining(recursiveResult); + performInlining(recursiveResult); } } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Mon Apr 28 10:31:17 2014 +0200 @@ -171,7 +171,7 @@ } if (node instanceof DirectCallNode) { DirectCallNode callNode = (DirectCallNode) node; - if (callNode.isInliningForced()) { + if (callNode.isInlined()) { callNode.getCurrentRootNode().accept(this); } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,10 +22,9 @@ */ package com.oracle.graal.truffle; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.truffle.TruffleCompilerOptions.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -35,8 +34,8 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.spi.*; import com.oracle.graal.loop.*; @@ -44,7 +43,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; @@ -69,14 +67,12 @@ private final CanonicalizerPhase canonicalizer; private Set<Constant> constantReceivers; private final TruffleCache truffleCache; - private final ResolvedJavaType frameType; public PartialEvaluator(Providers providers, TruffleCache truffleCache) { this.providers = providers; CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(providers.getMetaAccess(), providers.getConstantReflection()); this.canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue(), customCanonicalizer); this.truffleCache = truffleCache; - this.frameType = providers.getMetaAccess().lookupJavaType(FrameWithoutBoxing.class); } public StructuredGraph createGraph(final OptimizedCallTarget callTarget, final Assumptions assumptions) { @@ -90,7 +86,7 @@ constantReceivers = new HashSet<>(); } - final StructuredGraph graph = truffleCache.createRootGraph(); + final StructuredGraph graph = truffleCache.createRootGraph(callTarget.toString()); assert graph != null : "no graph for root method"; try (Scope s = Debug.scope("CreateGraph", graph); Indent indent = Debug.logAndIndent("createGraph %s", graph.method())) { @@ -127,7 +123,16 @@ if (TraceTruffleCompilationHistogram.getValue() && constantReceivers != null) { DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes"); for (Constant c : constantReceivers) { - histogram.add(providers.getMetaAccess().lookupJavaType(c).getName()); + String javaName = MetaUtil.toJavaName(providers.getMetaAccess().lookupJavaType(c), false); + + // The DSL uses nested classes with redundant names - only show the inner class + int index = javaName.indexOf('$'); + if (index != -1) { + javaName = javaName.substring(index + 1); + } + + histogram.add(javaName); + } new DebugHistogramAsciiPrinter(TTY.out().out()).print(histogram); } @@ -182,7 +187,7 @@ for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class)) { InvokeKind kind = methodCallTargetNode.invokeKind(); try (Indent id1 = Debug.logAndIndent("try inlining %s, kind = %s", methodCallTargetNode.targetMethod(), kind)) { - if (kind == InvokeKind.Static || (kind == InvokeKind.Special && (methodCallTargetNode.receiver().isConstant() || isFrame(methodCallTargetNode.receiver())))) { + if (kind == InvokeKind.Static || kind == InvokeKind.Special) { if ((TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) && kind == InvokeKind.Special && methodCallTargetNode.receiver().isConstant()) { constantReceivers.add(methodCallTargetNode.receiver().asConstant()); } @@ -196,7 +201,7 @@ } StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); - if (inlineGraph == null && !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().canBeInlined()) { + if (inlineGraph == null && !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().canBeInlined()) { inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, false); } @@ -214,7 +219,6 @@ expansionLogger.postExpand(inlined); } if (Debug.isDumpEnabled()) { - Debug.log("dump enabled"); int nodeCountAfter = graph.getNodeCount(); Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter); } @@ -237,10 +241,6 @@ } } - private boolean isFrame(ValueNode receiver) { - return receiver instanceof NewFrameNode || Objects.equals(ObjectStamp.typeOrNull(receiver.stamp()), frameType); - } - private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList<ValueNode> arguments, final Assumptions assumptions, final PhaseContext phaseContext, boolean ignoreSlowPath) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.truffle; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node; import com.oracle.graal.nodes.*; @@ -47,7 +45,7 @@ if (node instanceof LoadFieldNode) { LoadFieldNode loadFieldNode = (LoadFieldNode) node; if (!loadFieldNode.isStatic() && loadFieldNode.object().isConstant() && !loadFieldNode.object().isNullConstant()) { - if (Modifier.isFinal(loadFieldNode.field().getModifiers()) || (loadFieldNode.getKind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || + if (loadFieldNode.field().isFinal() || (loadFieldNode.getKind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || loadFieldNode.field().getAnnotation(CompilerDirectives.CompilationFinal.class) != null) { Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant()); assert verifyFieldValue(loadFieldNode.field(), constant);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Mon Apr 28 10:31:17 2014 +0200 @@ -33,7 +33,7 @@ /** * Creates the graph for the root method, i.e. {@link OptimizedCallTarget#callBoundary}. */ - StructuredGraph createRootGraph(); + StructuredGraph createRootGraph(String name); /** * Returns a cached graph for a method with given arguments.
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,9 +22,8 @@ */ package com.oracle.graal.truffle; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; -import java.lang.reflect.*; import java.util.*; import java.util.Map.Entry; @@ -81,8 +80,8 @@ } } - public StructuredGraph createRootGraph() { - StructuredGraph graph = new StructuredGraph(callBoundaryMethod); + public StructuredGraph createRootGraph(String name) { + StructuredGraph graph = new StructuredGraph(name, callBoundaryMethod); new GraphBuilderPhase.Instance(providers.getMetaAccess(), configForRootGraph, TruffleCompilerImpl.Optimizations).apply(graph); return graph; } @@ -251,7 +250,7 @@ if (methodCallTargetNode.targetMethod().isConstructor()) { ResolvedJavaType runtimeException = providers.getMetaAccess().lookupJavaType(RuntimeException.class); ResolvedJavaType controlFlowException = providers.getMetaAccess().lookupJavaType(ControlFlowException.class); - ResolvedJavaType exceptionType = Objects.requireNonNull(ObjectStamp.typeOrNull(methodCallTargetNode.receiver().stamp())); + ResolvedJavaType exceptionType = Objects.requireNonNull(StampTool.typeOrNull(methodCallTargetNode.receiver().stamp())); if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass()) && !controlFlowException.isAssignableFrom(exceptionType)) { DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); FixedNode invokeNode = methodCallTargetNode.invoke().asNode(); @@ -265,7 +264,7 @@ private boolean shouldInline(final MethodCallTargetNode methodCallTargetNode) { boolean result = (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && methodCallTargetNode.targetMethod().canBeInlined() && - !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && + !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null && !methodCallTargetNode.targetMethod().getDeclaringClass().equals(stringBuilderClass); return result;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.truffle; import java.io.*; -import java.lang.reflect.*; import java.util.*; import java.util.Map.Entry; @@ -51,7 +50,7 @@ int sourceMethodBci = callTarget.invoke().bci(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); ResolvedJavaType targetReceiverType = null; - if (!Modifier.isStatic(sourceMethod.getModifiers()) && callTarget.receiver().isConstant()) { + if (!sourceMethod.isStatic() && callTarget.receiver().isConstant()) { targetReceiverType = providers.getMetaAccess().lookupJavaType(callTarget.arguments().first().asConstant()); }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Mon Apr 28 10:31:17 2014 +0200 @@ -117,7 +117,7 @@ } private static double calculateFrequency(OptimizedCallTarget target, OptimizedDirectCallNode ocn) { - return (double) Math.max(1, target.getCompilationProfile().getCallCount()) / Math.max(1, ocn.getCallCount()); + return (double) Math.max(1, ocn.getCallCount()) / (double) Math.max(1, target.getCompilationProfile().getCallCount()); } private final static class ProfileScoreComparator implements Comparator<TruffleInliningProfile> {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -59,7 +59,7 @@ } private static Stamp createStamp(ValueNode array, Kind kind) { - ResolvedJavaType type = ObjectStamp.typeOrNull(array); + ResolvedJavaType type = StampTool.typeOrNull(array); if (kind == Kind.Object && type != null) { return StampFactory.declared(type.getComponentType()); } else {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.truffle.nodes.arithmetic; 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.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,12 +23,12 @@ package com.oracle.graal.truffle.nodes.arithmetic; 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.*; import com.oracle.truffle.api.*; /**
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.truffle.nodes.arithmetic; 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.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,12 +22,11 @@ */ package com.oracle.graal.truffle.nodes.frame; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class ForceMaterializeNode extends FixedWithNextNode implements LIRGenLowerable { +public class ForceMaterializeNode extends FixedWithNextNode implements LIRLowerable { @Input private ValueNode object; @@ -36,7 +35,7 @@ this.object = object; } - public void generate(NodeLIRBuilder generator) { + public void generate(NodeLIRBuilderTool generator) { // nothing to do }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -34,7 +34,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.truffle.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,13 +24,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; +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.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.truffle.nodes.*; import com.oracle.truffle.api.*; @@ -89,7 +89,7 @@ public void lower(LoweringTool tool) { CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph())); LocationIdentity locationIdentity; - if (location.asConstant().isNull()) { + if (!location.isConstant() || location.asConstant().isNull()) { locationIdentity = LocationIdentity.ANY_LOCATION; } else { locationIdentity = ObjectLocationIdentity.create(location.asConstant());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.truffle.nodes.asserts.*; import com.oracle.truffle.api.*;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Mon Apr 28 10:31:17 2014 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.truffle.substitutions; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.nodes.frame.*; import com.oracle.truffle.api.frame.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.virtual.phases.ea; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.debug.Debug.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationBlockState.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationBlockState.java Mon Apr 28 10:31:17 2014 +0200 @@ -34,10 +34,10 @@ static class ReadCacheEntry { - public final ResolvedJavaField identity; + public final LocationIdentity identity; public final ValueNode object; - public ReadCacheEntry(ResolvedJavaField identity, ValueNode object) { + public ReadCacheEntry(LocationIdentity identity, ValueNode object) { this.identity = identity; this.object = object; } @@ -95,7 +95,7 @@ return super.equivalentTo(other); } - public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value, PartialEscapeClosure<?> closure) { + public void addReadCache(ValueNode object, LocationIdentity identity, ValueNode value, PartialEscapeClosure<?> closure) { ValueNode cacheObject; ObjectState obj = closure.getObjectState(this, object); if (obj != null) { @@ -107,7 +107,7 @@ readCache.put(new ReadCacheEntry(identity, cacheObject), value); } - public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity, PartialEscapeClosure<?> closure) { + public ValueNode getReadCache(ValueNode object, LocationIdentity identity, PartialEscapeClosure<?> closure) { ValueNode cacheObject; ObjectState obj = closure.getObjectState(this, object); if (obj != null) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Mon Apr 28 10:31:17 2014 +0200 @@ -83,6 +83,17 @@ } else { processIdentity(state, ANY_LOCATION); } + } else if (node instanceof ArrayLengthNode) { + ArrayLengthNode length = (ArrayLengthNode) node; + ValueNode array = GraphUtil.unproxify(length.array()); + ValueNode cachedValue = state.getReadCache(array, ARRAY_LENGTH_LOCATION, this); + if (cachedValue != null) { + effects.replaceAtUsages(length, cachedValue); + addScalarAlias(length, cachedValue); + deleted = true; + } else { + state.addReadCache(array, ARRAY_LENGTH_LOCATION, length, this); + } } else if (node instanceof MemoryCheckpoint.Single) { METRIC_MEMORYCHECKPOINT.increment(); LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); @@ -183,7 +194,7 @@ } } - private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List<PEReadEliminationBlockState> states) { + private void mergeReadCachePhi(PhiNode phi, LocationIdentity identity, List<PEReadEliminationBlockState> states) { ValueNode[] values = new ValueNode[phi.valueCount()]; for (int i = 0; i < phi.valueCount(); i++) { ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity, PEReadEliminationClosure.this);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Apr 28 10:31:17 2014 +0200 @@ -36,7 +36,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.util.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.virtual.phases.ea.PartialEscapePhase.Options.*; import java.util.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*;
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.word; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.lang.annotation.*;
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -27,12 +27,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Location node that can be used inside a snippet without having the elements (including the
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Mon Apr 28 10:31:17 2014 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.phases.*; /**
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -144,7 +144,7 @@ * own and not in the stamp, {@link #changeToWord} does not perform all necessary changes. */ protected void rewriteAccessIndexed(StructuredGraph graph, AccessIndexedNode node) { - ResolvedJavaType arrayType = ObjectStamp.typeOrNull(node.array()); + ResolvedJavaType arrayType = StampTool.typeOrNull(node.array()); /* * There are cases where the array does not have a known type yet, i.e., the type is null. * In that case we assume it is not a word type. @@ -234,7 +234,7 @@ case WRITE: case INITIALIZE: { assert arguments.size() == 3 || arguments.size() == 4; - Kind writeKind = asKind(targetMethod.getSignature().getParameterType(Modifier.isStatic(targetMethod.getModifiers()) ? 2 : 1, targetMethod.getDeclaringClass())); + Kind writeKind = asKind(targetMethod.getSignature().getParameterType(targetMethod.isStatic() ? 2 : 1, targetMethod.getDeclaringClass())); LocationNode location; if (arguments.size() == 3) { location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION); @@ -403,7 +403,7 @@ } protected boolean isWord(ValueNode node) { - return isWord(ObjectStamp.typeOrNull(node)); + return isWord(StampTool.typeOrNull(node)); } protected boolean isWord(ResolvedJavaType type) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Mon Apr 28 10:31:17 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.word.phases; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.*; @@ -110,7 +108,7 @@ if (method.getAnnotation(NodeIntrinsic.class) == null) { Invoke invoke = (Invoke) callTarget.usages().first(); NodeInputList<ValueNode> arguments = callTarget.arguments(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); int argc = 0; if (!isStatic) { ValueNode receiver = arguments.get(argc);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/OnAdoptTest.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,130 @@ +/* + * 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.truffle.api.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * <h3>Inserting Extra Nodes into the AST Transparently</h3> + * + * <p> + * The {@link Node} class provides a callback that is invoked whenever a node is adopted in an AST + * by insertion or replacement. Node classes can override the {@code onAdopt()} method to run extra + * functionality upon adoption. + * </p> + * + * <p> + * This test demonstrates how node instances of a specific class can be automatically wrapped in + * extra nodes when they are inserted into the AST. + * </p> + */ +public class OnAdoptTest { + + static class Root extends RootNode { + + @Child private Base child1; + @Child private Base child2; + + public Root(Base child1, Base child2) { + super(null); + this.child1 = child1; + this.child2 = child2; + } + + @Override + public Object execute(VirtualFrame frame) { + return child1.executeInt(frame) + child2.executeInt(frame); + } + + } + + abstract static class Base extends Node { + public abstract int executeInt(VirtualFrame frame); + } + + static class Wrapper extends Base { + + @Child private Base wrappee; + + public Wrapper(Base wrappee) { + this.wrappee = wrappee; + } + + @Override + public int executeInt(VirtualFrame frame) { + return 1 + wrappee.executeInt(frame); + } + + } + + abstract static class GenBase extends Base { + + private final int k; + + public GenBase(int k) { + this.k = k; + } + + @Override + public int executeInt(VirtualFrame frame) { + return k; + } + + } + + static class Gen extends GenBase { + public Gen(int k) { + super(k); + } + } + + static class GenWrapped extends GenBase { + + public GenWrapped(int k) { + super(k); + } + + @Override + protected void onAdopt() { + Wrapper w = new Wrapper(this); + this.replace(w); + } + + } + + @Test + public void testOnInsert() { + TruffleRuntime runtime = Truffle.getRuntime(); + Base b1 = new Gen(11); + Base b2 = new GenWrapped(11); + Root r = new Root(b1, b2); + CallTarget ct = runtime.createCallTarget(r); + Object result = ct.call(); + Assert.assertEquals(23, result); + } + +}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Mon Apr 28 10:31:17 2014 +0200 @@ -24,11 +24,12 @@ */ package com.oracle.truffle.api; -import com.oracle.truffle.api.debug.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.source.*; /** - * Information about the runtime context of a Truffle program. + * Access to information and basic services in the runtime context for a Truffle-implemented guest + * language. * <p> * <strong>Disclaimer:</strong> this interface is under development and will change. */ @@ -46,8 +47,20 @@ SourceManager getSourceManager(); /** - * Gets access to debugging services. Returns an inert instance if no services installed. + * Gets access to AST instrumentation services. + */ + Instrumentation instrumentation(); + + /** + * Access to information visualization services for the specific language. */ - DebugContext getDebugContext(); + Visualizer visualizer(); + /** + * Add instrumentation to subsequently constructed Truffle ASTs for the guest language; every + * one added will have the opportunity to add instrumentation. + * + * @throws IllegalArgumentException if prober not usable for the guest language. + */ + void addNodeProber(ASTNodeProber nodeProber); }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java Mon Apr 28 10:31:17 2014 +0200 @@ -34,12 +34,21 @@ /** * Returns the name of this resource holding a guest language program. An example would be the * name of a guest language source code file. - * + * * @return the name of the guest language program */ String getName(); /** + * Returns a short version of the name of the resource holding a guest language program (as + * described in @getName). For example, this could be just the name of the file, rather than a + * full path. + * + * @return the short name of the guest language program + */ + String getShortName(); + + /** * The normalized, canonical name of the file. */ String getPath();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Mon Apr 28 10:31:17 2014 +0200 @@ -31,21 +31,21 @@ /** * Returns the object representing the source program that contains this section. - * + * * @return the source object */ Source getSource(); /** * Returns 1-based line number of the first character in this source section (inclusive). - * + * * @return the starting line number */ int getStartLine(); /** * Returns the 1-based column number of the first character in this source section (inclusive). - * + * * @return the starting column number */ int getStartColumn(); @@ -55,7 +55,7 @@ * <p> * The complete text of the source that contains this section can be retrieved via * {@link Source#getCode()}. - * + * * @return the starting character index */ int getCharIndex(); @@ -65,7 +65,7 @@ * <p> * The complete text of the source that contains this section can be retrieved via * {@link Source#getCode()}. - * + * * @return the number of characters in the section */ int getCharLength(); @@ -73,42 +73,54 @@ /** * Returns the index of the text position immediately following the last character in the * section. - * + * * @return the end position of the section */ int getCharEndIndex(); /** * Returns the identifier of this source section that is used for printing the section. - * + * * @return the identifier of the section */ String getIdentifier(); /** * Returns text of the code represented by this source section. - * + * * @return the code as a String object */ String getCode(); /** + * Returns a short description of the source section, using just the file name, rather than its + * full path. + * + * @return a short description of the source section + */ + String getShortDescription(); + + /** * Singleton instance with no content. */ SourceSection NULL = new NullSourceSection() { + @Override public Source getSource() { return null; } + @Override public int getStartLine() { return 0; } + @Override public int getStartColumn() { return 0; } + @Override public int getCharIndex() { return 0; } @@ -118,18 +130,26 @@ return 0; } + @Override public int getCharEndIndex() { return 0; } + @Override public String getIdentifier() { return null; } + @Override public String getCode() { return null; } + @Override + public String getShortDescription() { + return "short"; + } + }; }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ASTPrinter.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2013, 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. 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.debug; - -import java.io.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * Language-agnostic access to AST-based debugging support. - * <p> - * <strong>WARNING:</strong> this interface is under development and will change substantially. - */ -public interface ASTPrinter { - - /** - * Prints a textual AST display, one line per node, with nesting. - * - * @param p - * @param node the root node of the display. - * @param maxDepth the maximum number of levels to print below the root - * @param markNode a node to mark with a textual arrow prefix, if present. - */ - void printTree(PrintWriter p, Node node, int maxDepth, Node markNode); - - /** - * Creates a textual AST display, one line per node, with nesting. - * - * @param node the root node of the display. - * @param maxDepth the maximum number of levels to print below the root - * @param markNode a node to mark with a textual arrow prefix, if present. - */ - String printTreeToString(Node node, int maxDepth, Node markNode); - - /** - * Creates a textual AST display, one line per node, with nesting. - * - * @param node the root node of the display. - * @param maxDepth the maximum number of levels to print below the root - */ - String printTreeToString(Node node, int maxDepth); - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugContext.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * 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. 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.debug; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.instrument.*; - -/** - * Access to the suite of facilities available when debugging is enabled. - */ -public interface DebugContext { - - /** - * Access to the Truffle execution context being debugged. - */ - ExecutionContext getContext(); - - /** - * Access to the appropriate implementation of AST node instrumentation. - */ - NodeInstrumenter getNodeInstrumenter(); - - /** - * Access to the management of breakpoints, notifications, etc. - */ - DebugManager getDebugManager(); - - /** - * Gets a printer for Truffle ASTs helpful for debugging guest language implementations. - */ - ASTPrinter getASTPrinter(); - - /** - * Converts a value in the guest language to a display string. - */ - String displayValue(Object value); - - /** - * Converts a slot identifier in the guest language to a display string. - */ - String displayIdentifier(FrameSlot slot); - - /** - * Invokes appropriate debugging action when Truffle execution halts. - */ - void executionHalted(Node node, MaterializedFrame frame); - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugManager.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2013, 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. 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.debug; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.instrument.*; -import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain; - -/** - * Language-agnostic access to AST-based debugging support. - * <p> - * <strong>Disclaimer:</strong> this interface is under development and will change. - */ -public interface DebugManager { - - /** - * Informs the {@link DebugManager} that the Guest Language runtime is starting to load a - * source. Care should be taken to ensure that under any circumstance there is always a - * following call to {@link #notifyFinishedLoading(Source)} with the same argument. - */ - void notifyStartLoading(Source source); - - /** - * Informs the {@link DebugManager} that the Guest Language runtime has finished loading a - * source. Care should be taken to ensure that under any circumstance there is always a prior - * call to {@link #notifyStartLoading(Source)} with the same argument. - */ - void notifyFinishedLoading(Source source); - - /** - * Return a reference to the (canonical) instrumentation site associated with a particular - * source code location; this site will have effect on any Truffle/AST implementation - * corresponding to the source location, even if the AST is copied multiple times. - */ - ProbeChain getProbeChain(SourceSection sourceSection); - - /** - * Informs the {@link DebugManager} that Truffle execution has halted; execution will resume - * when this method returns. - * - * @param astNode a guest language AST node that represents the current execution site, assumed - * not to be any kind of {@link InstrumentationNode}, - * @param frame execution frame at the site where execution suspended - */ - void haltedAt(Node astNode, MaterializedFrame frame); - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DefaultDebugManager.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * 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. 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.debug; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain; -import com.oracle.truffle.api.source.*; - -/** - * A minimal, language-agnostic implementation that tracks loaded sources, and keeps maps describing - * what locations in the source have instrumentation available. This implementation will do nothing - * unless there are calls to it during AST construction, notably {@link #notifyStartLoading(Source)} - * and {@link #notifyFinishedLoading(Source)} <em>and</em> there are at least some AST nodes being - * instrumented. - */ -public class DefaultDebugManager implements DebugManager { - - private final Set<Source> loadedSources = new HashSet<>(); - - private Source beingLoaded = null; - - /** - * Map: SourceSection ==> probe chain associated with that source section in an AST. - */ - private final Map<SourceSection, ProbeChain> srcToProbeChain = new HashMap<>(); - - /** - * Map: Source lines ==> probe chains associated with source sections starting on the line. - */ - private final Map<SourceLineLocation, Set<ProbeChain>> lineToProbeChains = new HashMap<>(); - - private final ExecutionContext context; - - public DefaultDebugManager(ExecutionContext context) { - this.context = context; - } - - /** - * Gets the {@linkplain ProbeChain probe} associated with a particular {@link SourceSection - * source location}, creating a new one if needed. There should only be one probe associated - * with each {@linkplain SourceSection source location}. - */ - public ProbeChain getProbeChain(SourceSection sourceSection) { - assert sourceSection != null; - assert sourceSection.getSource().equals(beingLoaded); - - ProbeChain probeChain = srcToProbeChain.get(sourceSection); - - if (probeChain != null) { - return probeChain; - } - probeChain = new ProbeChain(context, sourceSection, null); - - // Register new ProbeChain by unique SourceSection - srcToProbeChain.put(sourceSection, probeChain); - - // Register new ProbeChain by source line, there may be more than one - // Create line location for map key - final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine()); - - Set<ProbeChain> probeChains = lineToProbeChains.get(lineLocation); - if (probeChains == null) { - probeChains = new HashSet<>(); - lineToProbeChains.put(lineLocation, probeChains); - } - probeChains.add(probeChain); - - return probeChain; - } - - public void notifyStartLoading(Source source) { - assert beingLoaded == null; - beingLoaded = source; - } - - public void notifyFinishedLoading(Source source) { - assert source == beingLoaded; - loadedSources.add(source); - beingLoaded = null; - } - - public void haltedAt(Node astNode, MaterializedFrame frame) { - } - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * 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. 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.debug; - -import com.oracle.truffle.api.nodes.*; - -/** - * Controls breaking out of an execution context, such as a shell or eval. - */ -public final class KillException extends ControlFlowException { - - private static final long serialVersionUID = 3163641880088766957L; -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * 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. 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.debug; - -import com.oracle.truffle.api.nodes.*; - -/** - * Controls breaking out of all executions and ending Truffle execution. - */ -public final class QuitException extends ControlFlowException { - - private static final long serialVersionUID = -4301115629772778413L; -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java Mon Apr 28 10:31:17 2014 +0200 @@ -40,9 +40,7 @@ boolean isVirtualFrame(); - DirectCallNode getCallNode(); + Node getCallNode(); CallTarget getCallTarget(); - - CallTarget getTargetCallTarget(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractExecutionContext.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,91 @@ +/* + * 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. 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.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.instrument.impl.*; +import com.oracle.truffle.api.source.*; + +public abstract class AbstractExecutionContext implements ExecutionContext { + + private final SourceManager sourceManager = new SourceManager(); + private final Instrumentation instrumentation; + private Visualizer visualizer = new DefaultVisualizer(); + protected ASTProber astProber = null; + + protected AbstractExecutionContext() { + this.instrumentation = InstrumentationFactory.create(this); + } + + public final SourceManager getSourceManager() { + return sourceManager; + } + + public final Instrumentation instrumentation() { + return instrumentation; + } + + public Visualizer visualizer() { + return visualizer; + } + + public void addNodeProber(ASTNodeProber nodeProber) { + if (astProber == null) { + throw new IllegalStateException("No ASTProber installed in context"); + } + astProber.addNodeProber(nodeProber); + } + + /** + * Assign guest language-specific visualization support for tools. This must be assigned outside + * the implementation context to avoid build circularities. + */ + public void setVisualizer(Visualizer visualizer) { + this.visualizer = visualizer; + } + + /** + * Assigns a guest language-specific manager for using {@link ASTNodeProber}s added by tools to + * instrument ASTs with {@link Probe}s at specified nodes. This must be assigned outside the + * implementation context to avoid build circularities. It must also be set before any + * instrumentation probe implementations are assigned. + */ + public void setASTProber(ASTProber astProber) { + this.astProber = astProber; + } + + /** + * Gets a guest language-specific {@link ASTNodeProber} that will apply all that have been + * added; {@code null} if no instrumentation in AST. + */ + public ASTNodeProber getCombinedNodeProber() { + return astProber == null ? null : astProber.getCombinedNodeProber(); + } + + public abstract void setInstrumentEventListener(InstrumentEventListener listener); + + public abstract InstrumentEventListener getInstrumentEventListener(); +}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java Mon Apr 28 10:31:17 2014 +0200 @@ -53,7 +53,7 @@ * a character index. The (row,column) coordinates of a newline character should never appear in * a text section. * <p> - * + * * @param source object representing the complete source program that contains this section * @param identifier an identifier used when printing the section * @param startLine the 1-based number of the start line of the section @@ -102,6 +102,10 @@ return getSource().getCode().substring(charIndex, charIndex + charLength); } + public final String getShortDescription() { + return String.format("%s:%d", source.getShortName(), startLine); + } + @Override public String toString() { return String.format("%s:%d", source.getName(), startLine);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,63 @@ +/* + * 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. 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.instrument; + +import com.oracle.truffle.api.nodes.*; + +/** + * Implementation of a policy for <em>instrumenting</em> inserting a {@link Probe} at a Truffle AST + * node. + * <p> + * Note that this interface is guest language agnostic, but current extensions are + * language-specific. This will be revisited. + * <p> + * <strong>Disclaimer:</strong> experimental interface under development. Really! + */ +public interface ASTNodeProber { + + /** + * Optionally applies <em>instrumentation</em> at a Truffle AST node, depending on guest + * language characteristics and use-case policy. + * <ul> + * <li>if no instrumentation is to be applied, returns the AST node unmodified;</li> + * <li>if an AST node is to be instrumented, then returns a newly created {@link Wrapper} that + * <em>decorates</em> the AST node and notifies an associated {@link Probe} of all + * {@link ExecutionEvents} at the wrapped AST node.</li> + * <li>if the argument is itself a {@link Wrapper}, i.e. if the AST node at this site has + * already been wrapped, then the wrapper is returned (with the possible addition of a + * {@linkplain PhylumTag tag}).</li> + * </ul> + * + * @param astNode an AST node to which instrumentation might be applied + * @param tag an optional category directing how the node, if instrumented, should be perceived + * by tool users + * @param args additional arguments for instrumentation specific to a particular guest language + * @return if no instrumentation should be applied or if the node is a {@link Wrapper} then the + * unmodified node; otherwise a newly created {@link Wrapper} (whose child + * {@code astNode}) with an associated {@link Probe} . + */ + + Node probeAs(Node astNode, PhylumTag tag, Object... args); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, 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. 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.instrument; + +import java.io.*; + +import com.oracle.truffle.api.nodes.*; + +/** + * Language-agnostic access to AST-based debugging support. + * <p> + * <strong>WARNING:</strong> this interface is under development and will change substantially. + */ +public interface ASTPrinter { + + /** + * Prints a textual AST display, one line per node, with nesting. + * + * @param p + * @param node the root node of the display. + * @param maxDepth the maximum number of levels to print below the root + * @param markNode a node to mark with a textual arrow prefix, if present. + */ + void printTree(PrintWriter p, Node node, int maxDepth, Node markNode); + + /** + * Creates a textual AST display, one line per node, with nesting. + * + * @param node the root node of the display. + * @param maxDepth the maximum number of levels to print below the root + * @param markNode a node to mark with a textual arrow prefix, if present. + */ + String printTreeToString(Node node, int maxDepth, Node markNode); + + /** + * Creates a textual AST display, one line per node, with nesting. + * + * @param node the root node of the display. + * @param maxDepth the maximum number of levels to print below the root + */ + String printTreeToString(Node node, int maxDepth); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, 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. 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.instrument; + +/** + * Implementation of a policy for <em>instrumenting</em> Truffle ASTs with {@link Probe}s at + * particular nodes by inserting node {@link Wrapper}s. + * <p> + * <strong>Disclaimer:</strong> experimental interface under development. + */ +public interface ASTProber { + + // TODO (mlvdv) This is a provisional interface, more of a marker really + // TODO (mlvdv) AST probing should eventually be done with visitors. + + void addNodeProber(ASTNodeProber nodeProber); + + /** + * Gets a prober that applies all added {@link ASTNodeProber}s. + */ + ASTNodeProber getCombinedNodeProber(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2013, 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. 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.instrument; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Normal events during program execution at Truffle AST nodes that are reported via a {@link Probe} + * associated with the node, and made available to the probe's attached {@link Instrument}s. + * <p> + * <strong>Disclaimer:</strong> experimental interface under development. + */ +public interface ExecutionEvents { + + /** + * Notifies that an AST node's execute method has just been entered. Callers should assure that + * a matching call to {@link #leave(Node, VirtualFrame, Object)} always follows. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame being passed to the execute method + */ + void enter(Node astNode, VirtualFrame frame); + + /** + * Notifies that an AST Node's void-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + */ + void leave(Node astNode, VirtualFrame frame); + + /** + * Notifies that an AST Node's boolean-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, boolean result); + + /** + * Notifies that an AST Node's byte-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, byte result); + + /** + * Notifies that an AST Node's short-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, short result); + + /** + * Notifies that an AST Node's integer-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, int result); + + /** + * Notifies that an AST Node's long-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, long result); + + /** + * Notifies that an AST Node's float-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, float result); + + /** + * Notifies that an AST Node's double-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, double result); + + /** + * Notifies that an AST Node's char-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, char result); + + /** + * Notifies that an AST Node's object-valued execute method is about to exit. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, Object result); + + /** + * Notifies that an AST Node's execute method is about to leave under exceptional conditions, + * returning no value. + * <p> + * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param e the exception associated with the unusual return + */ + void leaveExceptional(Node astNode, VirtualFrame frame, Exception e); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,40 @@ +/* + * 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. 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.instrument; + +/** + * A receiver of Truffle AST {@link ExecutionEvents}, propagated from a {@link Probe} to which the + * instrument is attached. + * <p> + * <strong>Disclaimer:</strong> experimental interface under development. + */ +public interface Instrument extends ExecutionEvents { + + /** + * @return the {@link Probe} to which this instrument is attached. + */ + Probe getProbe(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentEventListener.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 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. 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.instrument; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A client of the instrumentation framework that requests event notifications from the language + * engine. + */ +public interface InstrumentEventListener { + + /** + * The guest language runtime is starting to load a source. Care should be taken to ensure that + * under any circumstance there is always a following call to {@link #loadEnding(Source)} with + * the same argument. + */ + void loadStarting(Source source); + + /** + * The guest language runtime has finished loading a source. Care should be taken to ensure that + * under any circumstance there is always a prior call to {@link #loadStarting(Source)} with the + * same argument. + */ + void loadEnding(Source source); + + /** + * A guest language call is about to be executed. + */ + void callEntering(Node astNode, String name); + + /** + * A guest language call has just completed. + */ + void callReturned(Node astNode, String name); + + /** + * An opportunity for instrumentation to interact with Truffle AST execution halted at some + * node. + */ + void haltedAt(Node astNode, MaterializedFrame frame); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentation.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,66 @@ +/* + * 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. 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.instrument; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; + +public interface Instrumentation { + + /** + * Adds a new specification for how to instrument ASTs. + */ + void addNodeProber(ASTNodeProber nodeProber); + + /** + * Registers a tool interested in being notified about the insertion of a newly created + * {@link Probe} into a Truffle AST. + */ + void addProbeListener(ProbeListener listener); + + /** + * Return the (possibly newly created) {@link Probe} uniquely associated with a particular + * source code location. A newly created probe carries no tags. + * + * @param eventListener an optional listener for certain instrumentation-related events + * @return a probe uniquely associated with an extent of guest language source code. + */ + Probe getProbe(SourceSection sourceSection, InstrumentEventListener eventListener); + + /** + * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty + * collection if no probes found. + */ + Collection<Probe> findProbesTaggedAs(PhylumTag tag); + + /** + * Returns all existing probes with first character on a specified line; empty collection if no + * probes found. + */ + Collection<Probe> findProbesByLine(SourceLineLocation lineLocation); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationFactory.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,36 @@ +/* + * 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. 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.instrument; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.impl.*; + +public class InstrumentationFactory { + + public static Instrumentation create(ExecutionContext context) { + return new InstrumentationImpl(context); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,35 @@ +/* + * 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. 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.instrument; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls breaking out of an execution context, such as a shell or eval. + */ +public final class KillException extends ControlFlowException { + + private static final long serialVersionUID = 3163641880088766957L; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTag.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,70 @@ +/* + * 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. 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.instrument; + +/** + * Program element "tags" that define user-visible behavior for debugging and other simple tools. + * These categories (<em>phyla</em>) should correspond to program structures that are meaningful to + * a guest language programmer. + * <p> + * An untagged Truffle node should be understood as an artifact of the guest language implementation + * and should not be visible to the user of a guest language programming tool. Nodes may also have + * more than one tag, for example a variable assignment that is also a statement. Finally, the + * assignment of tags to nodes could depending on the use-case of whatever tool is using them. + * <p> + * This is a somewhat language-agnostic set of phyla, suitable for conventional imperative + * languages, and is being developed incrementally. + * <p> + * The need for alternative sets of tags is likely to arise, perhaps for other families of languages + * (for example for mostly expression-oriented languages) or even for specific languages. + * <p> + * These are listed alphabetically so that listing from some collection classes will come out in + * that order. + * <p> + * <strong>Disclaimer:</strong> experimental interface under development. + */ +public enum PhylumTag { + + /** + * Marker for a variable assignment. + */ + ASSIGNMENT, + + /** + * Marker for a call site. + */ + CALL, + + /** + * Marker for a location where a guest language exception is about to be thrown. + */ + THROW, + + /** + * Marker for a location where ordinary "stepping" should halt. + */ + STATEMENT; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTagged.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,47 @@ +/* + * 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. 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.instrument; + +import java.util.*; + +/** + * Information about a guest language program element that can be marked as belonging to 0 or more + * {@linkplain PhylumTag tags}. + * <p> + * <strong>Disclaimer:</strong> experimental interface under development. + */ +public interface PhylumTagged { + + /** + * Is this node tagged as belonging to a particular category of language constructs? + */ + boolean isTaggedAs(PhylumTag tag); + + /** + * In which categories has this node been tagged (<em>empty set</em> if none). + */ + Set<PhylumTag> getPhylumTags(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,148 @@ +/* + * 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. 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.instrument; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A collector of {@link ExecutionEvents} at a specific site (node) in a Truffle AST (generated by a + * {@link Wrapper} inserted into the AST) for the purpose of <em>instrumentation</em>. For probes + * associated with programmer-facing tools, there should be no more than one probe associated with a + * particular piece of source code syntax (i.e. a {@link SourceSection}). + * <p> + * Any {@linkplain PhylumTag tags} associated with a particular piece of source code syntax are + * managed by the probe. + * <p> + * When ASTs are copied, it is presumed that the probe for a site is shared by all AST nodes + * representing that site. + * <p> + * A probe holds zero or more {@link Instrument}s, which can be added and removed dynamically. + * Events reported to a probe are propagated to every attached instrument; the order is undefined. + * <p> + * Probe methods must be amenable to Truffle/Graal inlining on the assumption that the collection of + * attached instruments seldom changes. The assumption is invalidated when instruments are added or + * removed, but some instruments may change their internal state in such a way that the assumption + * should also be invalidated. + * <p> + * <strong>Disclaimer:</strong> experimental interface under development. + */ +public interface Probe extends PhylumTagged { + + /** + * The source location with which this probe is (presumably uniquely) associated. + */ + SourceSection getSourceLocation(); + + /** + * Mark this probe as being associated with an AST node in some category useful for debugging + * and other tools. + */ + void tagAs(PhylumTag tag); + + /** + * Adds an instrument to this probe. + */ + void addInstrument(Instrument newInstrument); + + /** + * Removes an instrument from this probe. + */ + void removeInstrument(Instrument oldInstrument); + + /** + * Change <em>stepping mode</em>, which is used in association with nodes tagged as + * {@linkplain PhylumTag#STATEMENT statements}. + */ + void setStepping(boolean stepping); + + /** + * Value of <em>stepping mode</em>, which is used in association with nodes tagged as + * {@linkplain PhylumTag#STATEMENT statements}. + */ + boolean isStepping(); + + /** + * @see ExecutionEvents#enter(Node, VirtualFrame) + */ + void notifyEnter(Node astNode, VirtualFrame frame); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame) + */ + void notifyLeave(Node astNode, VirtualFrame frame); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, boolean) + */ + void notifyLeave(Node astNode, VirtualFrame frame, boolean result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, byte) + */ + void notifyLeave(Node astNode, VirtualFrame frame, byte result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, short) + */ + void notifyLeave(Node astNode, VirtualFrame frame, short result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, int) + */ + void notifyLeave(Node astNode, VirtualFrame frame, int result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, long) + */ + void notifyLeave(Node astNode, VirtualFrame frame, long result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, char) + */ + void notifyLeave(Node astNode, VirtualFrame frame, char result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, float) + */ + void notifyLeave(Node astNode, VirtualFrame frame, float result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, double) + */ + void notifyLeave(Node astNode, VirtualFrame frame, double result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, Object) + */ + void notifyLeave(Node astNode, VirtualFrame frame, Object result); + + /** + * @see ExecutionEvents#leaveExceptional(Node, VirtualFrame, Exception) + */ + void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,46 @@ +/* + * 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. 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.instrument; + +import com.oracle.truffle.api.*; + +/** + * Client for receiving events relate to {@link Probe} management. Does not report AST copying. + */ +public interface ProbeListener { + + /** + * Notifies that a newly created (untagged) {@link Probe} has been inserted into a Truffle AST. + * There will be no notification when an existing {@link Probe} is shared by an AST copy. + */ + void newProbeInserted(SourceSection location, Probe probe); + + /** + * Notifies that a (fully constructed) {@link Probe} has been tagged. A subsequent marking with + * the same tag is idempotent and generates no notification. + */ + void probeTaggedAs(Probe probe, PhylumTag tag); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,35 @@ +/* + * 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. 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.instrument; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls breaking out of all executions and ending Truffle execution. + */ +public final class QuitException extends ControlFlowException { + + private static final long serialVersionUID = -4301115629772778413L; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,50 @@ +/* + * 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. 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.instrument; + +import com.oracle.truffle.api.frame.*; + +/** + * Visualization services for guest language and Truffle information. + */ +public interface Visualizer { + + /** + * Gets a printer for Truffle ASTs, possibly specialized to be helpful for a specific guest + * language implementation. + */ + ASTPrinter getASTPrinter(); + + /** + * Converts a value in the guest language to a display string. + */ + String displayValue(Object value); + + /** + * Converts a slot identifier in the guest language to a display string. + */ + String displayIdentifier(FrameSlot slot); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Wrapper.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013, 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. 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.instrument; + +import com.oracle.truffle.api.nodes.*; + +/** + * A node that can be inserted into a Truffle AST in order to attach <em>instrumentation</em> at a + * particular node. + * <p> + * A wrapper <em>decorates</em> an AST node (its <em>child</em>) by acting as a transparent + * <em>proxy</em> for the child with respect to Truffle execution semantics. + * <p> + * A wrapper is also expected to notify its associated {@link Probe} when certain + * {@link ExecutionEvents} occur at the wrapper during program execution. + * <p> + * The wrapper's {@link Probe} is shared by every copy of the wrapper made when the AST is copied. + * <p> + * Wrappers methods must be amenable to Truffle/Graal inlining. + * <p> + * <strong>Disclaimer:</strong> experimental interface under development. + */ +public interface Wrapper extends PhylumTagged { + + /** + * Gets the AST node being instrumented, which should never be an instance of {@link Wrapper}. + */ + Node getChild(); + + /** + * Gets the {@link Probe} to which events occurring at this wrapper's child are propagated. + */ + Probe getProbe(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,168 @@ +/* + * 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. 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.instrument.impl; + +import java.io.*; +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeClass; +import com.oracle.truffle.api.nodes.NodeUtil.NodeField; +import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind; + +/** + * A language-agnostic for printing out various pieces of a Truffle AST. + */ +public class DefaultASTPrinter implements ASTPrinter { + + public DefaultASTPrinter() { + } + + public void printTree(PrintWriter p, Node node, int maxDepth, Node markNode) { + printTree(p, node, maxDepth, markNode, 1); + p.println(); + p.flush(); + } + + public String printTreeToString(Node node, int maxDepth, Node markNode) { + StringWriter out = new StringWriter(); + printTree(new PrintWriter(out), node, maxDepth, markNode); + return out.toString(); + } + + public String printTreeToString(Node node, int maxDepth) { + return printTreeToString(node, maxDepth, null); + } + + private static void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) { + if (node == null) { + p.print("null"); + return; + } + + p.print(nodeName(node)); + + String sep = ""; + p.print("("); + + final SourceSection src = node.getSourceSection(); + if (src != null) { + if (!(src instanceof NullSourceSection)) { + p.print(src.getSource().getName() + ":" + src.getStartLine()); + } + } + if (node instanceof PhylumTagged) { + final PhylumTagged taggedNode = (PhylumTagged) node; + String prefix = ""; + for (PhylumTag tag : taggedNode.getPhylumTags()) { + p.print(prefix); + prefix = ","; + p.print(tag.toString()); + } + + } + + ArrayList<NodeField> childFields = new ArrayList<>(); + + for (NodeField field : NodeClass.get(node.getClass()).getFields()) { + if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) { + childFields.add(field); + } else if (field.getKind() == NodeFieldKind.DATA) { + // p.print(sep); + // sep = ", "; + // + // final String fieldName = field.getName(); + // switch (fieldName) { + // + // } + // p.print(fieldName); + // p.print(" = "); + // p.print(field.loadValue(node)); + } + } + p.print(")"); + + if (level <= maxDepth) { + + if (childFields.size() != 0) { + p.print(" {"); + for (NodeField field : childFields) { + + Object value = field.loadValue(node); + if (value == null) { + printNewLine(p, level); + p.print(field.getName()); + p.print(" = null "); + } else if (field.getKind() == NodeFieldKind.CHILD) { + final Node valueNode = (Node) value; + printNewLine(p, level, valueNode == markNode); + p.print(field.getName()); + p.print(" = "); + printTree(p, valueNode, maxDepth, markNode, level + 1); + } else if (field.getKind() == NodeFieldKind.CHILDREN) { + printNewLine(p, level); + p.print(field.getName()); + Node[] children = (Node[]) value; + p.print(" = ["); + sep = ""; + for (Node child : children) { + p.print(sep); + sep = ", "; + printTree(p, child, maxDepth, markNode, level + 1); + } + p.print("]"); + } else { + printNewLine(p, level); + p.print(field.getName()); + } + } + printNewLine(p, level - 1); + p.print("}"); + } + } + } + + private static void printNewLine(PrintWriter p, int level, boolean mark) { + p.println(); + for (int i = 0; i < level; i++) { + if (mark && i == 0) { + p.print(" -->"); + } else { + p.print(" "); + } + } + } + + private static void printNewLine(PrintWriter p, int level) { + printNewLine(p, level, false); + } + + private static String nodeName(Node node) { + return node.getClass().getSimpleName(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultInstrument.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013, 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. 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.instrument.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * An {@link Instrument} that implements all {@link ExecutionEvents} notifications with empty + * methods. + */ +public class DefaultInstrument extends InstrumentationNodeImpl implements Instrument { + + protected DefaultInstrument() { + } + + public void enter(Node astNode, VirtualFrame frame) { + } + + public void leave(Node astNode, VirtualFrame frame) { + } + + public void leave(Node astNode, VirtualFrame frame, boolean result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, byte result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, short result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, int result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, long result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, char result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, float result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, double result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, Object result) { + } + + public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,50 @@ +/* + * 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. 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.instrument.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; + +public class DefaultVisualizer implements Visualizer { + + private final ASTPrinter astPrinter; + + public DefaultVisualizer() { + this.astPrinter = new DefaultASTPrinter(); + } + + public ASTPrinter getASTPrinter() { + return astPrinter; + } + + public String displayValue(Object value) { + return value.toString(); + } + + public String displayIdentifier(FrameSlot slot) { + return slot.getIdentifier().toString(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationImpl.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2013, 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. 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.instrument.impl; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.source.*; + +/** + * @author mlvdv + * + */ +public final class InstrumentationImpl implements Instrumentation { + + private final ExecutionContext context; + + // TODO (mlvdv) maps should really use weak references. + + /** + * Map: SourceSection ==> probe associated with that source section in an AST. + */ + private final Map<SourceSection, Probe> srcToProbe = new HashMap<>(); + + /** + * Map: Source line ==> probes associated with source sections starting on the line. + */ + private final Map<SourceLineLocation, Collection<Probe>> lineToProbes = new HashMap<>(); + + private final List<ProbeListener> probeListeners = new ArrayList<>(); + + public InstrumentationImpl(ExecutionContext context) { + this.context = context; + } + + public void addNodeProber(ASTNodeProber nodeProber) { + context.addNodeProber(nodeProber); + } + + public void addProbeListener(ProbeListener listener) { + assert listener != null; + probeListeners.add(listener); + } + + /** + * Return the (possibly newly created) {@link Probe} uniquely associated with a particular + * source code location. A newly created probe carries no tags. + * + * @param eventListener an optional listener for certain instrumentation-related events + * @return a probe uniquely associated with an extent of guest language source code. + */ + public Probe getProbe(SourceSection sourceSection, InstrumentEventListener eventListener) { + assert sourceSection != null; + + Probe probe = srcToProbe.get(sourceSection); + + if (probe != null) { + return probe; + } + probe = InstrumentationNodeImpl.createProbe(this, sourceSection, eventListener); + + // Register new probe by unique SourceSection + srcToProbe.put(sourceSection, probe); + + // Register new probe by source line, there may be more than one + // Create line location for map key + final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine()); + + Collection<Probe> probes = lineToProbes.get(lineLocation); + if (probes == null) { + probes = new ArrayList<>(2); + lineToProbes.put(lineLocation, probes); + } + probes.add(probe); + + for (ProbeListener listener : probeListeners) { + listener.newProbeInserted(sourceSection, probe); + } + + return probe; + } + + /** + * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty + * collection if no probes found. + */ + public Collection<Probe> findProbesTaggedAs(PhylumTag tag) { + if (tag == null) { + return new ArrayList<>(srcToProbe.values()); + } + final List<Probe> probes = new ArrayList<>(); + for (Probe probe : srcToProbe.values()) { + if (probe.isTaggedAs(tag)) { + probes.add(probe); + } + } + return probes; + } + + /** + * Returns all existing probes with first character on a specified line; empty collection if no + * probes found. + */ + public Collection<Probe> findProbesByLine(SourceLineLocation lineLocation) { + final Collection<Probe> probes = lineToProbes.get(lineLocation); + if (probes == null) { + return Collections.emptyList(); + } + return new ArrayList<>(probes); + } + + /** + * Receives (from the {@link Probe} implementation) and distributes notification that a + * {@link Probe} has acquired a new {@linkplain PhylumTag tag}. + */ + void newTagAdded(Probe probe, PhylumTag tag) { + for (ProbeListener listener : probeListeners) { + listener.probeTaggedAs(probe, tag); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNodeImpl.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2013, 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. 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.instrument.impl; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments. + * <p> + * Coordinates propagation of Truffle AST {@link ExecutionEvents}. + */ +public abstract class InstrumentationNodeImpl extends Node implements ExecutionEvents { + + // TODO (mlvdv) This is a pretty awkward design. + + /** + * Creates a new {@link Probe}, presumed to be unique to a particular {@linkplain SourceSection} + * extent of guest language source code. + * + * @param eventListener an optional listener for certain instrumentation-related events. + * @return a new probe + */ + static Probe createProbe(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) { + return new ProbeImpl(instrumentation, sourceSection, eventListener); + } + + /** + * Next in chain. + */ + @Child protected InstrumentationNodeImpl next; + + protected InstrumentationNodeImpl() { + } + + /** + * @return the instance of {@link Probe} to which this instrument is attached. + */ + public Probe getProbe() { + final InstrumentationNodeImpl parent = (InstrumentationNodeImpl) getParent(); + return parent == null ? null : parent.getProbe(); + } + + /** + * Add a probe to the end of this probe chain. + */ + void internalAddInstrument(InstrumentationNodeImpl newInstrument) { + if (next == null) { + this.next = insert(newInstrument); + } else { + next.internalAddInstrument(newInstrument); + } + } + + void internalRemoveInstrument(InstrumentationNodeImpl oldInstrument) { + if (next == null) { + throw new RuntimeException("Couldn't find probe to remove: " + oldInstrument); + } else if (next == oldInstrument) { + if (oldInstrument.next == null) { + this.next = null; + } else { + this.next = insert(oldInstrument.next); + oldInstrument.next = null; + } + } else { + next.internalRemoveInstrument(oldInstrument); + } + } + + /** + * Reports to the instance of {@link Probe} holding this instrument that some essential state + * has changed that requires deoptimization. + */ + @CompilerDirectives.SlowPath + protected void notifyProbeChanged(InstrumentationNodeImpl instrument) { + final ProbeImpl probe = (ProbeImpl) getProbe(); + probe.notifyProbeChanged(instrument); + } + + private void internalEnter(Node astNode, VirtualFrame frame) { + enter(astNode, frame); + if (next != null) { + next.internalEnter(astNode, frame); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame) { + leave(astNode, frame); + if (next != null) { + next.internalLeave(astNode, frame); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, boolean result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, byte result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, short result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, int result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, long result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, char result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, float result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, double result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, Object result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + leaveExceptional(astNode, frame, null); + if (next != null) { + next.internalLeaveExceptional(astNode, frame, e); + } + } + + /** + * Holder of a chain of {@linkplain InstrumentationNodeImpl instruments}: manages the + * {@link Assumption} that none of the instruments have changed since last checked. + * <p> + * An instance is intended to be shared by every clone of the AST node with which it is + * originally attached, so it holds no parent pointer. + * <p> + * May be categorized by one or more {@linkplain PhylumTag tags}, signifying information useful + * for instrumentation about its AST location(s). + */ + private static final class ProbeImpl extends InstrumentationNodeImpl implements Probe { + + final InstrumentationImpl instrumentation; + + final InstrumentEventListener eventListener; + + @CompilerDirectives.CompilationFinal private Assumption probeUnchanged; + + /** + * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line + * will cause a halt. + */ + @CompilerDirectives.CompilationFinal private boolean stepping; + + /** + * Source information about the AST node to which this instrumentation is attached. + */ + private final SourceSection probedSourceSection; + + private final Set<PhylumTag> tags = EnumSet.noneOf(PhylumTag.class); + + private ProbeImpl(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) { + this.instrumentation = instrumentation; + this.probedSourceSection = sourceSection; + this.eventListener = eventListener == null ? NullInstrumentEventListener.INSTANCE : eventListener; + this.probeUnchanged = Truffle.getRuntime().createAssumption(); + this.next = null; + } + + @Override + public Probe getProbe() { + return this; + } + + @Override + protected void notifyProbeChanged(InstrumentationNodeImpl instrument) { + probeUnchanged.invalidate(); + probeUnchanged = Truffle.getRuntime().createAssumption(); + } + + public SourceSection getSourceLocation() { + return probedSourceSection; + } + + public void tagAs(PhylumTag tag) { + assert tag != null; + if (!tags.contains(tag)) { + tags.add(tag); + instrumentation.newTagAdded(this, tag); + } + } + + public boolean isTaggedAs(PhylumTag tag) { + assert tag != null; + return tags.contains(tag); + } + + public Set<PhylumTag> getPhylumTags() { + return tags; + } + + public void setStepping(boolean stepping) { + if (this.stepping != stepping) { + this.stepping = stepping; + probeUnchanged.invalidate(); + probeUnchanged = Truffle.getRuntime().createAssumption(); + } + } + + public boolean isStepping() { + return stepping; + } + + @CompilerDirectives.SlowPath + public void addInstrument(Instrument instrument) { + probeUnchanged.invalidate(); + final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument; + super.internalAddInstrument(instrumentImpl); + probeUnchanged = Truffle.getRuntime().createAssumption(); + } + + @CompilerDirectives.SlowPath + public void removeInstrument(Instrument instrument) { + probeUnchanged.invalidate(); + final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument; + super.internalRemoveInstrument(instrumentImpl); + probeUnchanged = Truffle.getRuntime().createAssumption(); + } + + public void notifyEnter(Node astNode, VirtualFrame frame) { + if (stepping || next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + if (stepping) { + eventListener.haltedAt(astNode, frame.materialize()); + } + if (next != null) { + next.internalEnter(astNode, frame); + } + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, byte result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, short result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, int result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, long result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, char result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, float result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, double result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, Object result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeaveExceptional(astNode, frame, e); + } + } + + public void enter(Node astNode, VirtualFrame frame) { + } + + public void leave(Node astNode, VirtualFrame frame) { + } + + public void leave(Node astNode, VirtualFrame frame, boolean result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, byte result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, short result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, int result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, long result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, char result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, float result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, double result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, Object result) { + } + + public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/NullInstrumentEventListener.java Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013, 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. 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.instrument.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Minimal, mostly no-op implementation of instrumentation services. + */ +public final class NullInstrumentEventListener implements InstrumentEventListener { + + public static final InstrumentEventListener INSTANCE = new NullInstrumentEventListener(); + + private NullInstrumentEventListener() { + } + + public void callEntering(Node astNode, String name) { + } + + public void callReturned(Node astNode, String name) { + } + + public void haltedAt(Node astNode, MaterializedFrame frame) { + } + + public void loadStarting(Source source) { + } + + public void loadEnding(Source source) { + } + +}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Apr 28 10:31:17 2014 +0200 @@ -191,8 +191,12 @@ if (newChild == this) { throw new IllegalStateException("The parent of a node can never be the node itself."); } + boolean isInserted = newChild.parent == null; newChild.parent = this; newChild.adoptHelper(); + if (isInserted) { + newChild.onAdopt(); + } } private void adoptHelper() { @@ -209,8 +213,12 @@ if (newChild == this) { throw new IllegalStateException("The parent of a node can never be the node itself."); } + boolean isInserted = newChild.parent == null; newChild.parent = this; newChild.adoptUnadoptedHelper(); + if (isInserted) { + newChild.onAdopt(); + } } private void adoptUnadoptedHelper() { @@ -332,7 +340,6 @@ } private void traceRewrite(Node newNode, CharSequence reason) { - if (TruffleOptions.TraceRewritesFilterFromCost != null) { if (filterByKind(this, TruffleOptions.TraceRewritesFilterFromCost)) { return; @@ -352,8 +359,21 @@ return; } + final SourceSection reportedSourceSection = getEncapsulatingSourceSection(); + PrintStream out = System.out; - out.printf("[truffle] rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason); + out.printf("[truffle] rewrite %-50s |From %-40s |To %-40s |Reason %s%s%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason != null && reason.length() > 0 ? reason + : "unknown", reportedSourceSection != null ? " at " + reportedSourceSection.getShortDescription() : ""); + } + + /** + * Subclasses of {@link Node} can implement this method to execute extra functionality when a + * node is effectively inserted into the AST. The {@code onAdopt} callback is called after the + * node has been effectively inserted, and it is guaranteed to be called only once for any given + * node. + */ + protected void onAdopt() { + // empty default } private static String formatNodeInfo(Node node) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/DefaultNodeInstrumenter.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * 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. 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.nodes.instrument; - -import com.oracle.truffle.api.nodes.*; - -/** - * A no-op node instrumenter; always returns the node unproxied and unmodified. - */ -public class DefaultNodeInstrumenter implements NodeInstrumenter { - - public Node instrumentAs(Node node, NodePhylum phylum, Object... args) { - return node; - } - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationNode.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.nodes.instrument; - -/** - * Marker interface for all Truffle <strong>instrumentation nodes</strong>: nodes that are do not - * appear in Truffle ASTs as part of a language's execution semantics. - * <p> - * In documentation related to instrumentation nodes, these are distinguished by referring to all - * other nodes (i.e. ones that <em>do</em> implement language semantics) as <em>AST nodes</em>. - */ -public interface InstrumentationNode { - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeEvents.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.nodes.instrument; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -/** - * Marker interface for all Truffle <strong>instrumentation nodes</strong>: nodes that are do not - * appear in Truffle ASTs as part of a language's execution semantics. - * <p> - * In documentation related to instrumentation nodes, these are distinguished by referring to all - * other nodes (i.e. ones that <em>do</em> implement language semantics) as <em>AST nodes</em>. - */ -public interface InstrumentationProbeEvents { - - /** - * Notifies a probe that receiver that an AST node's execute method has just been entered. - * Callers should assure that a matching call to {@link #leave(Node, VirtualFrame, Object)} - * always follows. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame being passed to the execute method - */ - void enter(Node astNode, VirtualFrame frame); - - /** - * Notifies a probe that an AST Node's void-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - */ - void leave(Node astNode, VirtualFrame frame); - - /** - * Notifies a probe that an AST Node's boolean-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, boolean result); - - /** - * Notifies a probe that an AST Node's byte-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, byte result); - - /** - * Notifies a probe that an AST Node's short-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, short result); - - /** - * Notifies a probe that an AST Node's integer-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, int result); - - /** - * Notifies a probe that an AST Node's long-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, long result); - - /** - * Notifies a probe that an AST Node's float-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, float result); - - /** - * Notifies a probe that an AST Node's double-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, double result); - - /** - * Notifies a probe that an AST Node's char-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, char result); - - /** - * Notifies a probe that an AST Node's object-valued execute method is about to exit. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, Object result); - - /** - * Notifies a probe that an AST Node's execute method is about to leave under exceptional - * conditions, returning no value. - * <p> - * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param e the exception associated with the unusual return - */ - void leaveExceptional(Node astNode, VirtualFrame frame, Exception e); - - /** - * Notifies a probe that an AST node is about to be replaced with another. - * - * @param oldAstNode the AST node currently in the tree - * @param newAstNode the AST replacement node - * @param reason explanation for the replacement - */ - void replace(Node oldAstNode, Node newAstNode, String reason); - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,500 +0,0 @@ -/* - * Copyright (c) 2013, 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. 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.nodes.instrument; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -/** - * A <strong>probe</strong>: a Truffle instrumentation node that holds code to perform some action - * when notified (via a {@linkplain InstrumentationProxyNode proxy node} in the AST) of a - * {@linkplain InstrumentationProbeEvents probe event} taking place at the AST node. - * <p> - * Probes are only active when attached to a {@linkplain ProbeChain "probe chain"} that is referred - * to by one or more {@linkplain InstrumentationProxyNode proxy nodes} in an AST. - */ -public abstract class InstrumentationProbeNode extends Node implements InstrumentationNode, InstrumentationProbeEvents { - - /** - * Next in chain. - */ - @Child protected InstrumentationProbeNode next; - - protected InstrumentationProbeNode() { - } - - protected int countProbes() { - return next == null ? 0 : next.countProbes() + 1; - } - - protected boolean isStepping() { - final InstrumentationProbeNode parent = (InstrumentationProbeNode) getParent(); - return parent.isStepping(); - } - - /** - * Add a probe to the end of this probe chain. - */ - protected void internalAppendProbe(InstrumentationProbeNode newProbeNode) { - if (next == null) { - this.next = insert(newProbeNode); - } else { - next.internalAppendProbe(newProbeNode); - } - } - - protected void internalRemoveProbe(InstrumentationProbeNode oldProbeNode) { - if (next == null) { - throw new RuntimeException("Couldn't find probe to remove: " + oldProbeNode); - } else if (next == oldProbeNode) { - if (oldProbeNode.next == null) { - this.next = null; - } else { - this.next = insert(oldProbeNode.next); - oldProbeNode.next = null; - } - } else { - next.internalRemoveProbe(oldProbeNode); - } - } - - /** - * Passes up the chain notification that a probe has changed its execution state in a way that - * invalidates fast path code. Assumes that there is an instance of {@link ProbeChain} at the - * head of the chain. - */ - @CompilerDirectives.SlowPath - protected void notifyProbeChanged(InstrumentationProbeNode probeNode) { - final InstrumentationProbeNode parent = (InstrumentationProbeNode) getParent(); - parent.notifyProbeChanged(probeNode); - } - - // TODO (mlvdv) making the internal*() methods public is a workaround for a bug/limitation in - // the Truffle compiler; they are intended to be private. - - public void internalEnter(Node astNode, VirtualFrame frame) { - enter(astNode, frame); - if (next != null) { - next.internalEnter(astNode, frame); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame) { - leave(astNode, frame); - if (next != null) { - next.internalLeave(astNode, frame); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, boolean result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, byte result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, short result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, int result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, long result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, char result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, float result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, double result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, Object result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { - leaveExceptional(astNode, frame, null); - if (next != null) { - next.internalLeaveExceptional(astNode, frame, e); - } - } - - public void internalReplace(Node oldAstNode, Node newAstNode, String reason) { - replace(oldAstNode, newAstNode, reason); - if (next != null) { - next.internalReplace(oldAstNode, newAstNode, reason); - } - } - - /** - * A probe implementation that implements all of {@link InstrumentationProbeEvents} with empty - * methods; concrete subclasses can override only the methods for which something is to be done. - */ - public static class DefaultProbeNode extends InstrumentationProbeNode { - - private final ExecutionContext executionContext; - - protected DefaultProbeNode(ExecutionContext context) { - this.executionContext = context; - } - - public ExecutionContext getContext() { - return executionContext; - } - - public void enter(Node astNode, VirtualFrame frame) { - } - - public void leave(Node astNode, VirtualFrame frame) { - } - - public void leave(Node astNode, VirtualFrame frame, boolean result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, byte result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, short result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, int result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, long result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, char result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, float result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, double result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, Object result) { - } - - public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { - } - - public void replace(Node oldAstNode, Node newAstNode, String reason) { - } - - } - - /** - * Holder of a chain of {@linkplain InstrumentationProbeNode probes}: manages the - * {@link Assumption} that the chain has not changed since checked checked. - * <p> - * May be categorized by one or more {@linkplain NodePhylum node phyla}, signifying information - * useful for instrumentation about its AST location(s). - */ - public static final class ProbeChain extends DefaultProbeNode implements PhylumMarked { - - @CompilerDirectives.CompilationFinal private Assumption probeUnchanged; - - /** - * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line - * will cause a halt. - */ - @CompilerDirectives.CompilationFinal private boolean stepping; - - /** - * Source information about the node to which this probe chain is attached; it isn't - * otherwise available. A probe chain is shared by every copy made during runtime, so there - * is no parent pointer. - */ - private final SourceSection probedSourceSection; - - private final Set<NodePhylum> phyla = EnumSet.noneOf(NodePhylum.class); - - private final String description; // for debugging - - /** - * Creates a new, empty chain of {@linkplain InstrumentationProbeNode probes}, to which - * probes can be added/removed, and all of which will be notified of - * {@linkplain InstrumentationProbeEvents events} when the chain is notified. - */ - public ProbeChain(ExecutionContext context, SourceSection sourceSection, String description) { - super(context); - this.probeUnchanged = Truffle.getRuntime().createAssumption(); - this.probedSourceSection = sourceSection; - this.description = description; - this.next = null; - } - - public int probeCount() { - return countProbes(); - } - - public String getDescription() { - return description; - } - - public SourceSection getProbedSourceSection() { - return probedSourceSection; - } - - /** - * Mark this probe chain as being associated with an AST node in some category useful for - * debugging and other tools. - */ - public void markAs(NodePhylum phylum) { - assert phylum != null; - phyla.add(phylum); - } - - /** - * Is this probe chain as being associated with an AST node in some category useful for - * debugging and other tools. - */ - public boolean isMarkedAs(NodePhylum phylum) { - assert phylum != null; - return phyla.contains(phylum); - } - - /** - * In which categories is the AST (with which this probe is associated) marked? - */ - public Set<NodePhylum> getPhylumMarks() { - return phyla; - } - - /** - * Change <em>stepping mode</em> for statements. - */ - public void setStepping(boolean stepping) { - if (this.stepping != stepping) { - this.stepping = stepping; - probeUnchanged.invalidate(); - probeUnchanged = Truffle.getRuntime().createAssumption(); - } - } - - @Override - protected boolean isStepping() { - return stepping; - } - - @Override - protected int countProbes() { - // The head of the chain does not itself hold a probe - return next == null ? 0 : next.countProbes(); - } - - @Override - protected void notifyProbeChanged(InstrumentationProbeNode probeNode) { - probeUnchanged.invalidate(); - probeUnchanged = Truffle.getRuntime().createAssumption(); - } - - @CompilerDirectives.SlowPath - public void appendProbe(InstrumentationProbeNode newProbeNode) { - probeUnchanged.invalidate(); - super.internalAppendProbe(newProbeNode); - probeUnchanged = Truffle.getRuntime().createAssumption(); - } - - @CompilerDirectives.SlowPath - public void removeProbe(InstrumentationProbeNode oldProbeNode) { - probeUnchanged.invalidate(); - super.internalRemoveProbe(oldProbeNode); - probeUnchanged = Truffle.getRuntime().createAssumption(); - } - - public void notifyEnter(Node astNode, VirtualFrame frame) { - if (stepping || next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - if (stepping) { - getContext().getDebugContext().getDebugManager().haltedAt(astNode, frame.materialize()); - } - if (next != null) { - next.internalEnter(astNode, frame); - } - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, byte result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, short result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, int result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, long result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, char result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, float result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, double result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, Object result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeaveExceptional(astNode, frame, e); - } - } - - public void notifyReplace(Node oldAstNode, Node newAstNode, String reason) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalReplace(oldAstNode, newAstNode, reason); - } - } - - } - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProxyNode.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013, 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. 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.nodes.instrument; - -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain; - -/** - * Interface implemented by language-specific Truffle <strong>proxy nodes</strong>: nodes that do - * not participate in the language's execution semantics, but which are inserted into an AST so that - * tools (e.g. tracers, analyzers, debuggers) can be notified of AST interpretation events and - * possibly intervene. - * <p> - * Language-specific proxy nodes call notification methods on an attached {@linkplain ProbeChain - * probe chain} which passes along {@linkplain InstrumentationProbeEvents events} to any - * {@linkplain InstrumentationProbeNode probes} that might have been attached. - */ -public interface InstrumentationProxyNode extends InstrumentationNode, PhylumMarked { - - /** - * Gets the non-instrumentation node being proxied. - */ - Node getChild(); - - /** - * Gets the chain of probes to which events at this node are delegated. Note that a chain of - * probes may be used by more than one proxy. - */ - ProbeChain getProbeChain(); - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodeInstrumenter.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * 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. 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.nodes.instrument; - -import com.oracle.truffle.api.nodes.*; - -/** - * Implements the instrumentation of a Truffle AST node and returning either: - * <ul> - * <li>the node itself, or</li> - * <li>a newly created {@linkplain InstrumentationProxyNode proxy node} that holds the instrumented - * node as its {@linkplain com.oracle.truffle.api.nodes.Node.Child child}.</li> - * </ul> - */ -public interface NodeInstrumenter { - - /** - * Wraps a {@linkplain InstrumentationProxyNode proxy node} around a node (if not already - * wrapped), marks the location with a {@linkplain NodePhylum phylum (category)} for user - * interaction, and passes along any characteristics of the particular node that are important - * for instrumentation (e.g. the function/method name at a call). - */ - Node instrumentAs(Node node, NodePhylum phylum, Object... args); -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodePhylum.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * 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. 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.nodes.instrument; - -/** - * Categories of {@link InstrumentationProxyNode}s to be used for defining user-visible debugging - * and other simple tool behavior. These categories (<em>phyla</em>) should correspond to program - * structures that are meaningful to a programmer using the guest language. A Truffle node without a - * proxy carrying some phylum should be treated as an artifact of the guest language implementation - * and should never be visible to the user of a guest language programming tool. - * <p> - * Note that phyla are not intended to represent a partition of user-visible node categories, as the - * relative categorization of nodes can change with the particular programming tasks at hand. - * <p> - * This is a somewhat language-agnostic set of phyla, suitable for conventional imperative - * languages, and is being developed incrementally. - * <p> - * The need for alternative sets of phyla is likely to arise, perhaps for other families of - * languages (for example for mostly expression-oriented languages) or even for specific languages. - * <p> - * These are listed alphabetically so that listing from some collection classes will come out in - * that order. - * <p> - * <strong>Disclaimer:</strong> this interface is under development and will change. - */ -public enum NodePhylum { - - /** - * Marker for a proxy at a variable assignment. - */ - ASSIGNMENT, - - /** - * Marker for a proxy at a call site. - */ - CALL, - - /** - * Marker for a proxy at which ordinary "stepping" should halt. - */ - STATEMENT; - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/PhylumMarked.java Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * 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. 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.nodes.instrument; - -import java.util.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * A kind of {@link Node} that can be marked as belong to 0 or more {@linkplain NodePhylum phyla}. - */ -public interface PhylumMarked { - - /** - * Is this proxy tagged as belonging to a particular category of language constructs? - */ - boolean isMarkedAs(NodePhylum phylum); - - /** - * In which categories is this node tagged (<em>empty set</em> if none). - */ - Set<NodePhylum> getPhylumMarks(); - -}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceManager.java Fri Apr 18 15:41:13 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceManager.java Mon Apr 28 10:31:17 2014 +0200 @@ -70,7 +70,7 @@ /** * Gets the canonical representation of a source file, whose contents will be read lazily and * then cached. - * + * * @param reset forces any existing {@link Source} cache to be cleared, forcing a re-read */ public Source get(String fileName, boolean reset) { @@ -227,6 +227,11 @@ } @Override + public String getShortName() { + return name; + } + + @Override public String getCode() { return code; } @@ -292,6 +297,11 @@ } @Override + public String getShortName() { + return file.getName(); + } + + @Override public String getCode() { if (code == null || timeStamp != file.lastModified()) { try {
--- a/mx/mx_graal.py Fri Apr 18 15:41:13 2014 +0200 +++ b/mx/mx_graal.py Mon Apr 28 10:31:17 2014 +0200 @@ -35,6 +35,7 @@ import sanitycheck import itertools import json, textwrap +import fnmatch # This works because when mx loads this file, it makes sure __file__ gets an absolute path _graal_home = dirname(dirname(__file__)) @@ -861,7 +862,7 @@ projectscp = mx.classpath(projs) if whitelist: - classes = list(set(classes) & set(whitelist)) + classes = [c for c in classes if any((glob.match(c) for glob in whitelist))] if len(classes) != 0: f_testfile = open(testfile, 'w') @@ -905,10 +906,8 @@ _unittestHelpSuffix = """ Unittest options: - --short-only run short testcases only - --long-only run long testcases only - --baseline-whitelist run only testcases which are known to - work with the baseline compiler + --whitelist run only testcases which are included + in the given whitelist To avoid conflicts with VM options '--' can be used as delimiter. @@ -945,10 +944,7 @@ formatter_class=RawDescriptionHelpFormatter, epilog=_unittestHelpSuffix, ) - group = parser.add_mutually_exclusive_group() - group.add_argument('--short-only', action='store_true', help='run short testcases only') - group.add_argument('--long-only', action='store_true', help='run long testcases only') - parser.add_argument('--baseline-whitelist', action='store_true', help='run baseline testcases only') + parser.add_argument('--whitelist', help='run testcases specified in whitelist only', metavar='<path>') ut_args = [] delimiter = False @@ -968,33 +964,19 @@ parsed_args, args = parser.parse_known_args(ut_args) whitelist = None - if parsed_args.baseline_whitelist: - baseline_whitelist_file = 'test/baseline_whitelist.txt' + if parsed_args.whitelist: try: - with open(join(_graal_home, baseline_whitelist_file)) as fp: - whitelist = [l.rstrip() for l in fp.readlines()] + with open(join(_graal_home, parsed_args.whitelist)) as fp: + whitelist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')] except IOError: - mx.log('warning: could not read baseline whitelist: ' + baseline_whitelist_file) + mx.log('warning: could not read whitelist: ' + parsed_args.whitelist) - if parsed_args.long_only: - annotations = ['@LongTest', '@Parameters'] - elif parsed_args.short_only: - annotations = ['@Test'] - else: - annotations = ['@Test', '@LongTest', '@Parameters'] - - _unittest(args, annotations, whitelist=whitelist) + _unittest(args, ['@Test', '@Parameters'], whitelist=whitelist) def shortunittest(args): - """alias for 'unittest --short-only'{0}""" - - args.insert(0, '--short-only') - unittest(args) + """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'{0}""" -def longunittest(args): - """alias for 'unittest --long-only'{0}""" - - args.insert(0, '--long-only') + args = ['--whitelist', 'test/whitelist_shortunittest.txt'] + args unittest(args) def buildvms(args): @@ -1104,6 +1086,11 @@ unittest([]) tasks.append(t.stop()) + with VM('server', 'product'): # hosted mode + t = Task('UnitTests-BaselineCompiler:hosted-product') + unittest(['--whitelist', 'test/whitelist_baseline.txt', '-G:+UseBaselineCompiler']) + tasks.append(t.stop()) + for vmbuild in ['fastdebug', 'product']: for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild) + sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): t = Task(str(test) + ':' + vmbuild) @@ -1305,10 +1292,10 @@ else: executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer') - archive = join(libpath, 'c1visualizer.zip') - if not exists(executable): + archive = join(libpath, 'c1visualizer_2014-04-22.zip') + if not exists(executable) or not exists(archive): if not exists(archive): - mx.download(archive, ['https://java.net/downloads/c1visualizer/c1visualizer.zip']) + mx.download(archive, ['https://java.net/downloads/c1visualizer/c1visualizer_2014-04-22.zip']) zf = zipfile.ZipFile(archive, 'r') zf.extractall(libpath) @@ -1402,19 +1389,133 @@ with open(resultFile, 'w') as f: f.write(json.dumps(results)) -def jmh(args): - """run the JMH_BENCHMARKS +def _get_jmh_path(): + path = mx.get_env('JMH_BENCHMARKS', None) + if not path: + probe = join(dirname(_graal_home), 'java-benchmarks') + if exists(probe): + path = probe + + if not path: + mx.abort("Please set the JMH_BENCHMARKS environment variable to point to the java-benchmarks workspace") + if not exists(path): + mx.abort("The directory denoted by the JMH_BENCHMARKS environment variable does not exist: " + path) + return path + +def makejmhdeps(args): + """creates and installs Maven dependencies required by the JMH benchmarks + + The dependencies are specified by files named pom.mxdeps in the + JMH directory tree. Each such file contains a list of dependencies + defined in JSON format. For example: + + '[{"artifactId" : "compiler.test", "groupId" : "com.oracle.graal", "deps" : ["com.oracle.graal.compiler.test"]}]' + + will result in a dependency being installed in the local Maven repository + that can be referenced in a pom.xml file as follows: - The benchmarks are running with the default VM. - You can override this with an explicit option. - For example: + <dependency> + <groupId>com.oracle.graal</groupId> + <artifactId>compiler.test</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency>""" + + parser = ArgumentParser(prog='mx makejmhdeps') + parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='<path>') + parser.add_argument('-p', '--permissive', action='store_true', help='issue note instead of error if a Maven dependency cannot be built due to missing projects/libraries') + args = parser.parse_args(args) + + def makejmhdep(artifactId, groupId, deps): + graalSuite = mx.suite("graal") + path = artifactId + '.jar' + if args.permissive: + for name in deps: + if not mx.project(name, fatalIfMissing=False): + if not mx.library(name, fatalIfMissing=False): + mx.log('Skipping ' + groupId + '.' + artifactId + '.jar as ' + name + ' cannot be resolved') + return + d = mx.Distribution(graalSuite, name=artifactId, path=path, sourcesPath=path, deps=deps, excludedLibs=[]) + d.make_archive() + cmd = ['mvn', 'install:install-file', '-DgroupId=' + groupId, '-DartifactId=' + artifactId, + '-Dversion=1.0-SNAPSHOT', '-Dpackaging=jar', '-Dfile=' + d.path] + if not mx._opts.verbose: + cmd.append('-q') + if args.settings: + cmd = cmd + ['-s', args.settings] + mx.run(cmd) + os.unlink(d.path) - mx jmh -server ... + jmhPath = _get_jmh_path() + for root, _, filenames in os.walk(jmhPath): + for f in [join(root, n) for n in filenames if n == 'pom.mxdeps']: + mx.logv('[processing ' + f + ']') + try: + with open(f) as fp: + for d in json.load(fp): + artifactId = d['artifactId'] + groupId = d['groupId'] + deps = d['deps'] + makejmhdep(artifactId, groupId, deps) + except ValueError as e: + mx.abort('Error parsing {}:\n{}'.format(f, e)) + +def buildjmh(args): + """build the JMH benchmarks""" + + parser = ArgumentParser(prog='mx buildjmh') + parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='<path>') + parser.add_argument('-c', action='store_true', dest='clean', help='clean before building') + args = parser.parse_args(args) + + jmhPath = _get_jmh_path() + mx.log('JMH benchmarks: ' + jmhPath) + + # Ensure the mx injected dependencies are up to date + makejmhdeps(['-p'] + (['-s', args.settings] if args.settings else [])) - Will force the benchmarks to be run with the server VM. -""" + timestamp = mx.TimeStampFile(join(_graal_home, 'mx', 'jmh', jmhPath.replace(os.sep, '_') + '.timestamp')) + mustBuild = args.clean + if not mustBuild: + try: + hgfiles = [join(jmhPath, f) for f in subprocess.check_output(['hg', '-R', jmhPath, 'locate']).split('\n')] + mustBuild = timestamp.isOlderThan(hgfiles) + except: + # not a Mercurial repository or hg commands are not available. + mustBuild = True - # TODO: add option for `mvn clean package' + if mustBuild: + buildOutput = [] + def _redirect(x): + if mx._opts.verbose: + mx.log(x[:-1]) + else: + buildOutput.append(x) + env = os.environ.copy() + env['JAVA_HOME'] = _jdk(vmToCheck='server') + env['MAVEN_OPTS'] = '-server' + mx.log("Building benchmarks...") + cmd = ['mvn'] + if args.settings: + cmd = cmd + ['-s', args.settings] + if args.clean: + cmd.append('clean') + cmd.append('package') + retcode = mx.run(cmd, cwd=jmhPath, out=_redirect, env=env, nonZeroIsFatal=False) + if retcode != 0: + mx.log(''.join(buildOutput)) + mx.abort(retcode) + timestamp.touch() + else: + mx.logv('[all Mercurial controlled files in ' + jmhPath + ' are older than ' + timestamp.path + ' - skipping build]') + +def jmh(args): + """run the JMH benchmarks + + This command respects the standard --vm and --vmbuild options + for choosing which VM to run the benchmarks with.""" + if '-h' in args: + mx.help_(['jmh']) + mx.abort(1) vmArgs, benchmarksAndJsons = _extract_VM_args(args) @@ -1432,64 +1533,10 @@ else: jmhArgs[n] = v except ValueError as e: - mx.abort('error parsing JSON input: {}"\n{}'.format(j, e)) - - jmhPath = mx.get_env('JMH_BENCHMARKS', None) - if not jmhPath: - probe = join(dirname(_graal_home), 'java-benchmarks') - if exists(probe): - jmhPath = probe - - if not jmhPath: - mx.abort("Please set the JMH_BENCHMARKS environment variable to point to the java-benchmarks workspace") - if not exists(jmhPath): - mx.abort("The directory denoted by the JMH_BENCHMARKS environment variable does not exist: " + jmhPath) - mx.log('Using benchmarks in ' + jmhPath) - - timestamp = mx.TimeStampFile(join(_graal_home, 'mx', 'jmh', jmhPath.replace(os.sep, '_') + '.timestamp')) - buildJmh = False - jmhTree = [] - for root, dirnames, filenames in os.walk(jmhPath): - if root == jmhPath: - for n in ['.hg', '.metadata']: - if n in dirnames: - dirnames.remove(n) - jmhTree.append(os.path.relpath(root, jmhPath) + ':') - jmhTree = jmhTree + filenames - jmhTree.append('') + mx.abort('error parsing JSON input: {}\n{}'.format(j, e)) - files = [join(root, f) for f in filenames] - if timestamp.isOlderThan(files): - buildJmh = True - - if not buildJmh: - with open(timestamp.path) as fp: - oldJmhTree = fp.read().split('\n') - if oldJmhTree != jmhTree: - import difflib - diff = difflib.unified_diff(oldJmhTree, jmhTree) - mx.log("Need to rebuild JMH due to change in JMH directory tree indicated by this diff:") - mx.log('\n'.join(diff)) - buildJmh = True - - if buildJmh: - buildOutput = [] - def _redirect(x): - if mx._opts.verbose: - mx.log(x[:-1]) - else: - buildOutput.append(x) - env = os.environ.copy() - env['JAVA_HOME'] = _jdk(vmToCheck='server') - env['MAVEN_OPTS'] = '-server' - mx.log("Building benchmarks...") - retcode = mx.run(['mvn', 'package'], cwd=jmhPath, out=_redirect, env=env, nonZeroIsFatal=False) - if retcode != 0: - mx.log(''.join(buildOutput)) - mx.abort(retcode) - timestamp.touch() - with open(timestamp.path, 'w') as fp: - fp.write('\n'.join(jmhTree)) + jmhPath = _get_jmh_path() + mx.log('Using benchmarks in ' + jmhPath) matchedSuites = set() numBench = [0] @@ -1503,8 +1550,7 @@ microJar = os.path.join(absoluteMicro, "target", "microbenchmarks.jar") if not exists(microJar): - mx.logv('JMH: ignored ' + absoluteMicro + " because it doesn't contain the expected jar file ('" + microJar + "')") - continue + mx.abort('Missing ' + microJar + ' - please run "mx buildjmh"') if benchmarks: def _addBenchmark(x): if x.startswith("Benchmark:"): @@ -1544,7 +1590,6 @@ javaArgs.append(str(v)) mx.run_java(javaArgs + regex, addDefaultArgs=False, cwd=jmhPath) - def specjvm2008(args): """run one or more SPECjvm2008 benchmarks""" @@ -1665,14 +1710,14 @@ """make truffle.jar""" # Test with the built classes - _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@LongTest', '@Parameters']) + _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@Parameters']) # We use the DSL processor as the starting point for the classpath - this # therefore includes the DSL processor, the DSL and the API. packagejar(mx.classpath("com.oracle.truffle.dsl.processor").split(os.pathsep), "truffle.jar", None, "com.oracle.truffle.dsl.processor.TruffleProcessor") # Test with the JAR - _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@LongTest', '@Parameters'], "truffle.jar:") + _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@Parameters'], "truffle.jar:") def isGraalEnabled(vm): @@ -1874,6 +1919,7 @@ def mx_init(suite): commands = { 'build': [build, ''], + 'buildjmh': [buildjmh, '[-options]'], 'buildvars': [buildvars, ''], 'buildvms': [buildvms, '[-options]'], 'c1visualizer' : [c1visualizer, ''], @@ -1894,7 +1940,7 @@ 'gate' : [gate, '[-options]'], 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], 'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix], - 'longunittest' : [longunittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix], + 'makejmhdeps' : [makejmhdeps, ''], 'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix], 'jacocoreport' : [jacocoreport, '[output directory]'], 'site' : [site, '[-options]'],
--- a/mx/projects Fri Apr 18 15:41:13 2014 +0200 +++ b/mx/projects Mon Apr 28 10:31:17 2014 +0200 @@ -42,15 +42,15 @@ library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar library@DACAPO_SCALA@sha1=59b64c974662b5cf9dbd3cf9045d293853dd7a51 -library@OKRA@path=lib/okra-1.8.jar -library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.8.jar -library@OKRA@sourcePath=lib/okra-1.8-src.jar -library@OKRA@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-src.jar +library@OKRA@path=lib/okra-1.9.jar +library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.9.jar +library@OKRA@sourcePath=lib/okra-1.9-src.jar +library@OKRA@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-src.jar -library@OKRA_WITH_SIM@path=lib/okra-1.8-with-sim.jar -library@OKRA_WITH_SIM@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim.jar -library@OKRA_WITH_SIM@sourcePath=lib/okra-1.8-with-sim-src.jar -library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim-src.jar +library@OKRA_WITH_SIM@path=lib/okra-1.9-with-sim.jar +library@OKRA_WITH_SIM@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim.jar +library@OKRA_WITH_SIM@sourcePath=lib/okra-1.9-with-sim-src.jar +library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim-src.jar library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-8f0db117e64e.jar @@ -283,7 +283,7 @@ # graal.lir project@com.oracle.graal.lir@subDir=graal project@com.oracle.graal.lir@sourceDirs=src -project@com.oracle.graal.lir@dependencies=com.oracle.graal.nodes,com.oracle.graal.asm +project@com.oracle.graal.lir@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.asm project@com.oracle.graal.lir@checkstyle=com.oracle.graal.graph project@com.oracle.graal.lir@javaCompliance=1.8 project@com.oracle.graal.lir@workingSets=Graal,LIR @@ -373,7 +373,7 @@ # graal.nodes project@com.oracle.graal.nodes@subDir=graal project@com.oracle.graal.nodes@sourceDirs=src -project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements +project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements,com.oracle.graal.lir project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph project@com.oracle.graal.nodes@javaCompliance=1.8 project@com.oracle.graal.nodes@annotationProcessors=com.oracle.graal.replacements.verifier @@ -390,7 +390,7 @@ # graal.phases project@com.oracle.graal.phases@subDir=graal project@com.oracle.graal.phases@sourceDirs=src -project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes,com.oracle.graal.options +project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes project@com.oracle.graal.phases@checkstyle=com.oracle.graal.graph project@com.oracle.graal.phases@javaCompliance=1.8 project@com.oracle.graal.phases@workingSets=Graal,Phases @@ -422,10 +422,11 @@ # graal.compiler project@com.oracle.graal.compiler@subDir=graal project@com.oracle.graal.compiler@sourceDirs=src -project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir +project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler@javaCompliance=1.8 project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor +project@com.oracle.graal.compiler@annotationProcessorForDependents=true project@com.oracle.graal.compiler@workingSets=Graal # graal.compiler.amd64 @@ -502,7 +503,7 @@ # graal.compiler.common project@com.oracle.graal.compiler.common@subDir=graal project@com.oracle.graal.compiler.common@sourceDirs=src -project@com.oracle.graal.compiler.common@dependencies=com.oracle.graal.api.code +project@com.oracle.graal.compiler.common@dependencies=com.oracle.graal.api.code,com.oracle.graal.options project@com.oracle.graal.compiler.common@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.common@javaCompliance=1.8 project@com.oracle.graal.compiler.common@workingSets=Graal,Java
--- a/mxtool/mx.py Fri Apr 18 15:41:13 2014 +0200 +++ b/mxtool/mx.py Mon Apr 28 10:31:17 2014 +0200 @@ -1800,11 +1800,13 @@ parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)') parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects') parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects') - parser.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not') - parser.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='<path>') parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors') parser.add_argument('--jdt-show-task-tags', action='store_true', help='show task tags as Eclipse batch compiler warnings') - parser.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>') + compilerSelect = parser.add_mutually_exclusive_group() + compilerSelect.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='<path>') + compilerSelect.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='<path>') + compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not') + if suppliedParser: parser.add_argument('remainder', nargs=REMAINDER, metavar='...') @@ -1886,12 +1888,11 @@ cp = classpath(p.name, includeSelf=True) sourceDirs = p.source_dirs() - mustBuild = args.force - if not mustBuild: + buildReason = 'forced build' if args.force else None + if not buildReason: for dep in p.all_deps([], False): if dep.name in built: - mustBuild = True - + buildReason = dep.name + ' rebuilt' jasminAvailable = None javafilelist = [] @@ -1940,20 +1941,19 @@ if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)): shutil.copyfile(src, dst) - if not mustBuild: + if not buildReason: for javafile in javafiles: classfile = TimeStampFile(outputDir + javafile[len(sourceDir):-len('java')] + 'class') if not classfile.exists() or classfile.isOlderThan(javafile): - mustBuild = True + buildReason = 'class file(s) out of date' break aps = p.annotation_processors() apsOutOfDate = p.update_current_annotation_processors_file() if apsOutOfDate: - logv('[annotation processors for {0} changed]'.format(p.name)) - mustBuild = True - - if not mustBuild: + buildReason = 'annotation processor(s) changed' + + if not buildReason: logv('[all class files for {0} are up to date - skipping]'.format(p.name)) continue @@ -1985,10 +1985,14 @@ toBeDeleted = [argfileName] try: + + def logCompilation(p, compiler, reason): + log('Compiling Java sources for {} with {}... [{}]'.format(p.name, compiler, reason)) + if not jdtJar: mainJava = java() if not args.error_prone: - log('Compiling Java sources for {0} with javac...'.format(p.name)) + logCompilation(p, 'javac', buildReason) javacCmd = [mainJava.javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()] if jdk.debug_port is not None: javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)] @@ -1999,7 +2003,7 @@ javacCmd.append('-XDignore.symbol.file') run(javacCmd) else: - log('Compiling Java sources for {0} with javac (with error-prone)...'.format(p.name)) + logCompilation(p, 'javac (with error-prone)', buildReason) javaArgs = ['-Xmx1g'] javacArgs = ['-g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()] javacArgs += processorArgs @@ -2008,7 +2012,7 @@ javacArgs.append('-XDignore.symbol.file') run_java(javaArgs + ['-cp', os.pathsep.join([mainJava.toolsjar, args.error_prone]), 'com.google.errorprone.ErrorProneCompiler'] + javacArgs) else: - log('Compiling Java sources for {0} with JDT...'.format(p.name)) + logCompilation(p, 'JDT', buildReason) jdtVmArgs = ['-Xmx1g', '-jar', jdtJar] @@ -2058,6 +2062,39 @@ return args return None +def _chunk_files_for_command_line(files, limit=None, pathFunction=None): + """ + Returns a generator for splitting up a list of files into chunks such that the + size of the space separated file paths in a chunk is less than a given limit. + This is used to work around system command line length limits. + """ + chunkSize = 0 + chunkStart = 0 + if limit is None: + commandLinePrefixAllowance = 3000 + if get_os() == 'windows': + # The CreateProcess function on Windows limits the length of a command line to + # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx) + limit = 32768 - commandLinePrefixAllowance + else: + # Using just SC_ARG_MAX without extra downwards adjustment + # results in "[Errno 7] Argument list too long" on MacOS. + syslimit = os.sysconf('SC_ARG_MAX') - 20000 + limit = syslimit - commandLinePrefixAllowance + for i in range(len(files)): + path = files[i] if pathFunction is None else pathFunction(files[i]) + size = len(path) + 1 + if chunkSize + size < limit: + chunkSize += size + else: + assert i > chunkStart + yield files[chunkStart:i] + chunkStart = i + chunkSize = 0 + if chunkStart == 0: + assert chunkSize < limit + yield files + def eclipseformat(args): """run the Eclipse Code Formatter on the Java sources @@ -2160,18 +2197,19 @@ if res is not batch: res.javafiles = res.javafiles + batch.javafiles - print "we have: " + str(len(batches)) + " batches" + log("we have: " + str(len(batches)) + " batches") for batch in batches.itervalues(): - run([args.eclipse_exe, - '-nosplash', - '-application', - 'org.eclipse.jdt.core.JavaCodeFormatter', - '-vm', java(batch.javaCompliance).java, - '-config', batch.path] - + [f.path for f in batch.javafiles]) - for fi in batch.javafiles: - if fi.update(batch.removeTrailingWhitespace): - modified.append(fi) + for chunk in _chunk_files_for_command_line(batch.javafiles, pathFunction=lambda f: f.path): + run([args.eclipse_exe, + '-nosplash', + '-application', + 'org.eclipse.jdt.core.JavaCodeFormatter', + '-vm', java(batch.javaCompliance).java, + '-config', batch.path] + + [f.path for f in chunk]) + for fi in chunk: + if fi.update(batch.removeTrailingWhitespace): + modified.append(fi) log('{0} files were modified'.format(len(modified))) @@ -2503,26 +2541,9 @@ log('Running Checkstyle on {0} using {1}...'.format(sourceDir, config)) try: - - # Checkstyle is unable to read the filenames to process from a file, and the - # CreateProcess function on Windows limits the length of a command line to - # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx) - # so calling Checkstyle must be done in batches. - while len(javafilelist) != 0: - i = 0 - size = 0 - while i < len(javafilelist): - s = len(javafilelist[i]) + 1 - if size + s < 30000: - size += s - i += 1 - else: - break - - batch = javafilelist[:i] - javafilelist = javafilelist[i:] + for chunk in _chunk_files_for_command_line(javafilelist): try: - run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + batch, nonZeroIsFatal=False) + run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + chunk, nonZeroIsFatal=False) finally: if exists(auditfileName): errors = [] @@ -3826,7 +3847,7 @@ def ideinit(args, refreshOnly=False, buildProcessorJars=True): - """(re)generate Eclipse and NetBeans project configurations""" + """(re)generate Eclipse, NetBeans and Intellij project configurations""" eclipseinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars) netbeansinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars) intellijinit(args, refreshOnly=refreshOnly) @@ -4328,6 +4349,7 @@ parser = ArgumentParser(prog='exportlibs') parser.add_argument('-b', '--base', action='store', help='base name of archive (default: libs)', default='libs', metavar='<path>') + parser.add_argument('-a', '--include-all', action='store_true', help="include all defined libaries") parser.add_argument('--arc', action='store', choices=['tgz', 'tbz2', 'tar', 'zip'], default='tgz', help='the type of the archive to create') parser.add_argument('--no-sha1', action='store_false', dest='sha1', help='do not create SHA1 signature of archive') parser.add_argument('--no-md5', action='store_false', dest='md5', help='do not create MD5 signature of archive') @@ -4348,9 +4370,44 @@ else: logv('[already added ' + path + ']') - for lib in _libs.itervalues(): - if len(lib.urls) != 0 or args.include_system_libs: - add(lib.get_path(resolve=True), lib.path) + libsToExport = set() + if args.include_all: + for lib in _libs.itervalues(): + libsToExport.add(lib) + else: + def isValidLibrary(dep): + if dep in _libs.iterkeys(): + lib = _libs[dep] + if len(lib.urls) != 0 or args.include_system_libs: + return lib + return None + + # iterate over all project dependencies and find used libraries + for p in _projects.itervalues(): + for dep in p.deps: + r = isValidLibrary(dep) + if r: + libsToExport.add(r) + + # a library can have other libraries as dependency + size = 0 + while size != len(libsToExport): + size = len(libsToExport) + for lib in libsToExport.copy(): + for dep in lib.deps: + r = isValidLibrary(dep) + if r: + libsToExport.add(r) + + for lib in libsToExport: + add(lib.get_path(resolve=True), lib.path) + if lib.sha1: + add(lib.get_path(resolve=True) + ".sha1", lib.path + ".sha1") + if lib.sourcePath: + add(lib.get_source_path(resolve=True), lib.sourcePath) + if lib.sourceSha1: + add(lib.get_source_path(resolve=True) + ".sha1", lib.sourcePath + ".sha1") + if args.extras: for e in args.extras: if os.path.isdir(e):
--- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Apr 18 15:41:13 2014 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Apr 28 10:31:17 2014 +0200 @@ -676,8 +676,11 @@ oop hotspot_method = BytecodePosition::method(frame); Method* method = getMethodFromHotSpotMethod(hotspot_method); jint bci = BytecodePosition::bci(frame); + if (bci == BytecodeFrame::BEFORE_BCI()) { + bci = SynchronizationEntryBCI; + } bool reexecute; - if (bci == -1 || bci == -2){ + if (bci == SynchronizationEntryBCI){ reexecute = false; } else { Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci));
--- a/src/share/vm/graal/graalGlobals.hpp Fri Apr 18 15:41:13 2014 +0200 +++ b/src/share/vm/graal/graalGlobals.hpp Mon Apr 28 10:31:17 2014 +0200 @@ -52,6 +52,9 @@ COMPILERGRAAL_PRESENT(product(bool, BootstrapGraal, true, \ "Bootstrap Graal before running Java main method")) \ \ + product(bool, ForceGraalInitialization, false, \ + "Force VM to initialize the Compiler although not used") \ + \ product(intx, TraceGraal, 0, \ "Trace level for Graal") \ \
--- a/src/share/vm/graal/graalJavaAccess.cpp Fri Apr 18 15:41:13 2014 +0200 +++ b/src/share/vm/graal/graalJavaAccess.cpp Mon Apr 28 10:31:17 2014 +0200 @@ -59,10 +59,11 @@ #define FLOAT_FIELD(klass, name) FIELD(klass, name, "F", false) #define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false) #define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true) +#define STATIC_INT_FIELD(klass, name) FIELD(klass, name, "I", true) void graal_compute_offsets() { - COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD) + COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD) guarantee(InstalledCode::_address_offset == sizeof(oopDesc), "codeBlob must be first field!"); } @@ -72,7 +73,7 @@ #define FIELD2(klass, name) int klass::_##name##_offset = 0; #define FIELD3(klass, name, sig) FIELD2(klass, name) -COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3) +COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD2)
--- a/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 18 15:41:13 2014 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Mon Apr 28 10:31:17 2014 +0200 @@ -47,7 +47,7 @@ * */ -#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field) \ +#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field, static_int_field) \ start_class(HotSpotResolvedObjectType) \ oop_field(HotSpotResolvedObjectType, javaClass, "Ljava/lang/Class;") \ end_class \ @@ -196,6 +196,7 @@ int_field(BytecodeFrame, numLocks) \ boolean_field(BytecodeFrame, rethrowException) \ boolean_field(BytecodeFrame, duringCall) \ + static_int_field(BytecodeFrame, BEFORE_BCI) \ end_class \ start_class(BytecodePosition) \ oop_field(BytecodePosition, caller, "Lcom/oracle/graal/api/code/BytecodePosition;") \ @@ -313,7 +314,19 @@ oop_store((oop*)addr, x); \ } \ } -COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD) +#define STATIC_INT_FIELD(klassName, name) \ + static int _##name##_offset; \ + static int name() { \ + InstanceKlass* ik = InstanceKlass::cast(klassName::klass()); \ + address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \ + return *((jint *)addr); \ + } \ + static void set_##name(int x) { \ + InstanceKlass* ik = InstanceKlass::cast(klassName::klass()); \ + address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \ + *((jint *)addr) = x; \ + } +COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD) #undef START_CLASS #undef END_CLASS #undef FIELD @@ -324,6 +337,7 @@ #undef FLOAT_FIELD #undef OOP_FIELD #undef STATIC_OOP_FIELD +#undef STATIC_INT_FIELD void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field);
--- a/src/share/vm/prims/jni.cpp Fri Apr 18 15:41:13 2014 +0200 +++ b/src/share/vm/prims/jni.cpp Mon Apr 28 10:31:17 2014 +0200 @@ -5176,6 +5176,9 @@ #ifdef GRAAL // GraalCompiler needs to have been created in compileBroker.cpp GraalCompiler* graal_compiler = GraalCompiler::instance(); + if (ForceGraalInitialization && graal_compiler == NULL) { + graal_compiler = new GraalCompiler(); + } if (graal_compiler != NULL) { graal_compiler->initialize(); } else {
--- a/src/share/vm/runtime/gpu.cpp Fri Apr 18 15:41:13 2014 +0200 +++ b/src/share/vm/runtime/gpu.cpp Mon Apr 28 10:31:17 2014 +0200 @@ -32,10 +32,10 @@ void Gpu::initialized_gpu(Gpu* gpu) { // GPUs are always initialized on the same thread so no need for locking guarantee(_initialized_gpus_count < MAX_GPUS, "oob"); + _initialized_gpus[_initialized_gpus_count++] = gpu; if (TraceGPUInteraction) { - tty->print_cr("[GPU] registered initialization of %s (total initialized: %d)", gpu->name(), _initialized_gpus); + tty->print_cr("[GPU] registered initialization of %s (total initialized: %d)", gpu->name(), _initialized_gpus_count); } - _initialized_gpus[_initialized_gpus_count++] = gpu; } void Gpu::safepoint_event(SafepointEvent event) {
--- a/src/share/vm/runtime/thread.cpp Fri Apr 18 15:41:13 2014 +0200 +++ b/src/share/vm/runtime/thread.cpp Mon Apr 28 10:31:17 2014 +0200 @@ -1680,9 +1680,11 @@ if (_thread_stat != NULL) delete _thread_stat; #ifdef GRAAL - if (GraalCounterSize > 0 && graal_counters_include(threadObj())) { - for (int i = 0; i < GraalCounterSize; i++) { - _graal_old_thread_counters[i] += _graal_counters[i]; + if (GraalCounterSize > 0) { + if (graal_counters_include(threadObj())) { + for (int i = 0; i < GraalCounterSize; i++) { + _graal_old_thread_counters[i] += _graal_counters[i]; + } } FREE_C_HEAP_ARRAY(jlong, _graal_counters, mtInternal); }
--- a/test/baseline_whitelist.txt Fri Apr 18 15:41:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -com.oracle.graal.jtt.loop.Loop03 -com.oracle.graal.jtt.loop.Loop04 -com.oracle.graal.jtt.loop.Loop08 -com.oracle.graal.jtt.loop.Loop11 -com.oracle.graal.jtt.bytecode.BC_iadd -com.oracle.graal.jtt.bytecode.BC_iadd2 -com.oracle.graal.jtt.bytecode.BC_iadd3 -com.oracle.graal.jtt.bytecode.BC_ifeq_2 -com.oracle.graal.jtt.bytecode.BC_ifeq_3 -com.oracle.graal.jtt.bytecode.BC_ifeq -com.oracle.graal.jtt.bytecode.BC_aload_3 -com.oracle.graal.jtt.bytecode.BC_aload_2 -com.oracle.graal.jtt.bytecode.BC_aload_1 -com.oracle.graal.jtt.bytecode.BC_aload_0 -com.oracle.graal.jtt.bytecode.BC_areturn -com.oracle.graal.jtt.bytecode.BC_freturn -com.oracle.graal.jtt.bytecode.BC_iconst -com.oracle.graal.jtt.bytecode.BC_ireturn -com.oracle.graal.jtt.bytecode.BC_lreturn
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/whitelist_baseline.txt Mon Apr 28 10:31:17 2014 +0200 @@ -0,0 +1,19 @@ +# com.oracle.graal.jtt.loop.Loop03 +# com.oracle.graal.jtt.loop.Loop04 +# com.oracle.graal.jtt.loop.Loop08 +# com.oracle.graal.jtt.loop.Loop11 +com.oracle.graal.jtt.bytecode.BC_iadd +com.oracle.graal.jtt.bytecode.BC_iadd2 +com.oracle.graal.jtt.bytecode.BC_iadd3 +com.oracle.graal.jtt.bytecode.BC_ifeq_2 +com.oracle.graal.jtt.bytecode.BC_ifeq_3 +com.oracle.graal.jtt.bytecode.BC_ifeq +com.oracle.graal.jtt.bytecode.BC_aload_3 +com.oracle.graal.jtt.bytecode.BC_aload_2 +com.oracle.graal.jtt.bytecode.BC_aload_1 +com.oracle.graal.jtt.bytecode.BC_aload_0 +com.oracle.graal.jtt.bytecode.BC_areturn +com.oracle.graal.jtt.bytecode.BC_freturn +com.oracle.graal.jtt.bytecode.BC_iconst +com.oracle.graal.jtt.bytecode.BC_ireturn +com.oracle.graal.jtt.bytecode.BC_lreturn