# HG changeset patch # User Stefan Anzinger # Date 1406741979 25200 # Node ID e7b7a5be4d21fa6be87e230888617d391932d9ec # Parent f1fba319d4e30fcbe6941b77acd2b6bb7c047d28# Parent faaea970b95100560f57af7e0f82f32a91f1af0e Merge diff -r f1fba319d4e3 -r e7b7a5be4d21 CHANGELOG.md --- a/CHANGELOG.md Wed Jul 30 09:36:32 2014 -0700 +++ b/CHANGELOG.md Wed Jul 30 10:39:39 2014 -0700 @@ -10,6 +10,7 @@ * Enabled use of separate class loader (via -XX:+UseGraalClassLoader) for classes loaded from graal.jar to hide them from application classes. ### Truffle +* Change API for stack walking to a visitor: `TruffleRuntime#iterateFrames` replaces `TruffleRuntime#getStackTrace` * New flag -G:+TraceTruffleCompilationCallTree to print the tree of inlined calls before compilation. * `truffle.jar`: strip out build-time only dependency into a seperated JAR file (`truffle-dsl-processor.jar`) * New flag -G:+TraceTruffleCompilationAST to print the AST before compilation. diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java --- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Wed Jul 30 10:39:39 2014 -0700 @@ -138,7 +138,7 @@ private final EnumSet features; public AMD64(EnumSet features) { - super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT, 8); + super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8); this.features = features; assert features.contains(CPUFeature.SSE2) : "minimum config for x64"; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodePosition.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodePosition.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodePosition.java Wed Jul 30 10:39:39 2014 -0700 @@ -32,7 +32,7 @@ * system to reconstruct a source-level stack trace for exceptions and to create * {@linkplain BytecodeFrame frames} for deoptimization. */ -public abstract class BytecodePosition implements Serializable { +public class BytecodePosition implements Serializable { private static final long serialVersionUID = 8633885274526033515L; @@ -42,7 +42,7 @@ /** * Constructs a new object representing a given parent/caller, a given method, and a given BCI. - * + * * @param caller the parent position * @param method the method * @param bci a BCI within the method @@ -56,7 +56,7 @@ /** * Converts this code position to a string representation. - * + * * @return a string representation of this code position */ @Override diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Wed Jul 30 10:39:39 2014 -0700 @@ -620,9 +620,24 @@ */ public void addInfopoint(Infopoint infopoint) { // The infopoints list must always be sorted - if (!infopoints.isEmpty() && infopoints.get(infopoints.size() - 1).pcOffset >= infopoint.pcOffset) { - // This re-sorting should be very rare - Collections.sort(infopoints); + if (!infopoints.isEmpty()) { + Infopoint previousInfopoint = infopoints.get(infopoints.size() - 1); + if (previousInfopoint.pcOffset > infopoint.pcOffset) { + // This re-sorting should be very rare + Collections.sort(infopoints); + previousInfopoint = infopoints.get(infopoints.size() - 1); + } + if (previousInfopoint.pcOffset == infopoint.pcOffset) { + if (infopoint.reason.canBeOmited()) { + return; + } + if (previousInfopoint.reason.canBeOmited()) { + Infopoint removed = infopoints.remove(infopoints.size() - 1); + assert removed == previousInfopoint; + } else { + throw new RuntimeException("Infopoints that can not be omited should have distinct PCs"); + } + } } infopoints.add(infopoint); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java Wed Jul 30 10:39:39 2014 -0700 @@ -26,13 +26,21 @@ * A reason for infopoint insertion. */ public enum InfopointReason { + UNKNOWN(false), + SAFEPOINT(false), + CALL(false), + IMPLICIT_EXCEPTION(false), + METHOD_START(true), + METHOD_END(true), + LINE_NUMBER(true); - UNKNOWN, - SAFEPOINT, - CALL, - IMPLICIT_EXCEPTION, - METHOD_START, - METHOD_END, - LINE_NUMBER; + private InfopointReason(boolean canBeOmited) { + this.canBeOmited = canBeOmited; + } + private final boolean canBeOmited; + + public boolean canBeOmited() { + return canBeOmited; + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java Wed Jul 30 10:39:39 2014 -0700 @@ -140,22 +140,30 @@ for (int i = 0; i < values.length; i++) { ResolvedJavaField field = fields[fieldIndex++]; Kind valKind = values[i].getKind().getStackKind(); - if ((valKind == Kind.Double || valKind == Kind.Long) && field.getKind() == Kind.Int) { - assert fields[fieldIndex].getKind() == Kind.Int; - fieldIndex++; + if (field.getKind() == Kind.Object) { + assert values[i].getLIRKind().isReference(0) : field + ": " + valKind + " != " + field.getKind(); } else { - assert valKind == field.getKind().getStackKind() : field + ": " + valKind + " != " + field.getKind().getStackKind(); + if ((valKind == Kind.Double || valKind == Kind.Long) && field.getKind() == Kind.Int) { + assert fields[fieldIndex].getKind() == Kind.Int; + fieldIndex++; + } else { + assert valKind == field.getKind().getStackKind() : field + ": " + valKind + " != " + field.getKind(); + } } } assert fields.length == fieldIndex : type + ": fields=" + Arrays.toString(fields) + ", field values=" + Arrays.toString(values); } else { Kind componentKind = type.getComponentType().getKind().getStackKind(); - for (int i = 0; i < values.length; i++) { - assert values[i].getKind().getStackKind() == componentKind || componentKind.getBitCount() >= values[i].getKind().getStackKind().getBitCount() : values[i].getKind() + " != " + - componentKind; + if (componentKind == Kind.Object) { + for (int i = 0; i < values.length; i++) { + assert values[i].getLIRKind().isReference(0) : values[i].getKind() + " != " + componentKind; + } + } else { + for (int i = 0; i < values.length; i++) { + assert values[i].getKind() == componentKind || componentKind.getBitCount() >= values[i].getKind().getBitCount() : values[i].getKind() + " != " + componentKind; + } } } - } return true; } @@ -187,7 +195,11 @@ return false; } for (int i = 0; i < values.length; i++) { - if (!Objects.equals(values[i], l.values[i])) { + /* + * Virtual objects can form cycles. Calling equals() could therefore lead to + * infinite recursion. + */ + if (!same(values[i], l.values[i])) { return false; } } @@ -195,4 +207,8 @@ } return false; } + + private static boolean same(Object o1, Object o2) { + return o1 == o2; + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/InspectedFrame.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/InspectedFrame.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/InspectedFrame.java Wed Jul 30 10:39:39 2014 -0700 @@ -60,4 +60,10 @@ * @return the current method */ ResolvedJavaMethod getMethod(); + + /** + * Checks if the current method is equal to the given method. This is semantically equivalent to + * {@code method.equals(getMethod())}, but can be implemented more efficiently. + */ + boolean isMethod(ResolvedJavaMethod method); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/InspectedFrameVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/InspectedFrameVisitor.java Wed Jul 30 10:39:39 2014 -0700 @@ -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.api.code.stack; + +/** + * Callback interface for {@link StackIntrospection#iterateFrames}. Implementations of + * {@link #visitFrame} return null to indicate that frame iteration should continue and the next + * caller frame should be visited; and return any non-null value to indicate that frame iteration + * should stop. + */ +public interface InspectedFrameVisitor { + + T visitFrame(InspectedFrame frame); +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java Wed Jul 30 10:39:39 2014 -0700 @@ -27,13 +27,19 @@ public interface StackIntrospection { /** - * Accesses the current stack, returning a collection of {@link InspectedFrame}s that can be - * used to inspect the stack frames' contents. + * Accesses the current stack, providing {@link InspectedFrame}s to the visitor that can be used + * to inspect the stack frames' contents. Iteration continues as long as + * {@link InspectedFrameVisitor#visitFrame}, which is invoked for every {@link InspectedFrame}, + * returns null. Any non-null result of the visitor indicates that frame iteration should stop. * * @param initialMethods if this is non-{@code null}, then the stack trace will start at these * methods * @param matchingMethods if this is non-{@code null}, then only matching stack frames are * returned + * @param initialSkip the number of matching methods to skip (including the initial method) + * @param visitor the visitor that is called for every matching method + * @return the last result returned by the visitor (which is non-null to indicate that iteration + * should stop), or null if the whole stack was iterated. */ - Iterable getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip); + T iterateFrames(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip, InspectedFrameVisitor visitor); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Wed Jul 30 10:39:39 2014 -0700 @@ -41,4 +41,5 @@ RuntimeConstraint, LoopLimitCheck, Aliasing, + TransferToInterpreter, } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -52,7 +52,7 @@ protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { AllocatableValue targetAddress = AMD64.rax.asValue(); gen.emitMove(targetAddress, operand(callTarget.computedAddress())); - append(new AMD64Call.IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState)); + append(new AMD64Call.IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, targetAddress, callState)); } @Override @@ -350,10 +350,10 @@ @MatchRule("(If (IntegerEquals=compare value Read=access))") @MatchRule("(If (IntegerLessThan=compare value Read=access))") - @MatchRule("(If (IntegerBelowThan=compare value Read=access))") + @MatchRule("(If (IntegerBelow=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 (IntegerBelow=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))") @@ -473,11 +473,6 @@ } @Override - public void visitInfopointNode(InfopointNode i) { - append(new InfopointOp(stateFor(i.getState()), i.reason)); - } - - @Override public AMD64LIRGenerator getLIRGeneratorTool() { return (AMD64LIRGenerator) gen; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Wed Jul 30 10:39:39 2014 -0700 @@ -150,6 +150,8 @@ public static final OptionValue PrintIdealGraphPort = new OptionValue<>(4444); @Option(help = "") public static final OptionValue PrintBinaryGraphPort = new OptionValue<>(4445); + @Option(help = "") + public static final OptionValue PrintIdealGraphSchedule = new OptionValue<>(false); // Other printing settings @Option(help = "") diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/Condition.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/Condition.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/Condition.java Wed Jul 30 10:39:39 2014 -0700 @@ -337,128 +337,130 @@ * false */ public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) { - switch (lt.getKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: { - int x = lt.asInt(); - int y = rt.asInt(); - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - case AE: - return UnsignedMath.aboveOrEqual(x, y); - case BE: - return UnsignedMath.belowOrEqual(x, y); - case AT: - return UnsignedMath.aboveThan(x, y); - case BT: - return UnsignedMath.belowThan(x, y); - default: - throw new GraalInternalError("expected condition: %s", this); - } - } - case Long: { - long x = lt.asLong(); - long y = rt.asLong(); - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - case AE: - return UnsignedMath.aboveOrEqual(x, y); - case BE: - return UnsignedMath.belowOrEqual(x, y); - case AT: - return UnsignedMath.aboveThan(x, y); - case BT: - return UnsignedMath.belowThan(x, y); - default: - throw new GraalInternalError("expected condition: %s", this); - } - } - case Object: { - Boolean equal = constantReflection.constantEquals(lt, rt); - if (equal != null) { + if (lt instanceof PrimitiveConstant) { + switch (lt.getKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: { + int x = lt.asInt(); + int y = rt.asInt(); switch (this) { case EQ: - return equal.booleanValue(); + return x == y; case NE: - return !equal.booleanValue(); + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalInternalError("expected condition: %s", this); + } + } + case Long: { + long x = lt.asLong(); + long y = rt.asLong(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); default: throw new GraalInternalError("expected condition: %s", this); } } - } - case Float: { - float x = lt.asFloat(); - float y = rt.asFloat(); - if (Float.isNaN(x) || Float.isNaN(y)) { - return unorderedIsTrue; + case Float: { + float x = lt.asFloat(); + float y = rt.asFloat(); + if (Float.isNaN(x) || Float.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalInternalError("expected condition: %s", this); + } } - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - default: - throw new GraalInternalError("expected condition: %s", this); + case Double: { + double x = lt.asDouble(); + double y = rt.asDouble(); + if (Double.isNaN(x) || Double.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalInternalError("expected condition: %s", this); + } } + default: + throw new GraalInternalError("expected value kind %s while folding condition: %s", lt.getKind(), this); } - case Double: { - double x = lt.asDouble(); - double y = rt.asDouble(); - if (Double.isNaN(x) || Double.isNaN(y)) { - return unorderedIsTrue; - } - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - default: - throw new GraalInternalError("expected condition: %s", this); - } + } else { + Boolean equal = constantReflection.constantEquals(lt, rt); + if (equal == null) { + throw new GraalInternalError("could not fold %s %s %s", lt, this, rt); } - default: - throw new GraalInternalError("expected value kind %s while folding condition: %s", lt.getKind(), this); + switch (this) { + case EQ: + return equal.booleanValue(); + case NE: + return !equal.booleanValue(); + default: + throw new GraalInternalError("expected condition: %s", this); + } } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Wed Jul 30 10:39:39 2014 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.compiler.common.type; +import java.util.function.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.spi.*; @@ -134,6 +136,16 @@ return str.toString(); } + private static double meetBounds(double a, double b, DoubleBinaryOperator op) { + if (Double.isNaN(a)) { + return b; + } else if (Double.isNaN(b)) { + return a; + } else { + return op.applyAsDouble(a, b); + } + } + @Override public Stamp meet(Stamp otherStamp) { if (otherStamp == this) { @@ -144,12 +156,12 @@ } FloatStamp other = (FloatStamp) otherStamp; assert getBits() == other.getBits(); - double meetUpperBound = Math.max(upperBound, other.upperBound); - double meetLowerBound = Math.min(lowerBound, other.lowerBound); + double meetUpperBound = meetBounds(upperBound, other.upperBound, Math::max); + double meetLowerBound = meetBounds(lowerBound, other.lowerBound, Math::min); boolean meetNonNaN = nonNaN && other.nonNaN; - if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) { + if (Double.compare(meetLowerBound, lowerBound) == 0 && Double.compare(meetUpperBound, upperBound) == 0 && meetNonNaN == nonNaN) { return this; - } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) { + } else if (Double.compare(meetLowerBound, other.lowerBound) == 0 && Double.compare(meetUpperBound, other.upperBound) == 0 && meetNonNaN == other.nonNaN) { return other; } else { return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN); @@ -169,9 +181,9 @@ 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) { + if (Double.compare(joinLowerBound, lowerBound) == 0 && Double.compare(joinUpperBound, upperBound) == 0 && joinNonNaN == nonNaN) { return this; - } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) { + } else if (Double.compare(joinLowerBound, other.lowerBound) == 0 && Double.compare(joinUpperBound, other.upperBound) == 0 && joinNonNaN == other.nonNaN) { return other; } else { return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN); @@ -227,7 +239,7 @@ @Override public Constant asConstant() { - if (nonNaN && lowerBound == upperBound) { + if (nonNaN && Double.compare(lowerBound, upperBound) == 0) { switch (getBits()) { case 32: return Constant.forFloat((float) lowerBound); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java Wed Jul 30 10:39:39 2014 -0700 @@ -32,7 +32,7 @@ } @Override - protected AbstractObjectStamp copyWith(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { + protected ObjectStamp copyWith(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { return new ObjectStamp(type, exactType, nonNull, alwaysNull); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java Wed Jul 30 10:39:39 2014 -0700 @@ -248,6 +248,10 @@ } public static Stamp exact(ResolvedJavaType type) { - return new ObjectStamp(type, true, false, false); + if (ObjectStamp.isConcreteType(type)) { + return new ObjectStamp(type, true, false, false); + } else { + return illegal(Kind.Object); + } } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -47,22 +47,16 @@ @Override protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw GraalInternalError.unimplemented(callTarget.target().format("direct call to %H.%n(%p)")); + throw GraalInternalError.unimplemented(callTarget.targetMethod().format("direct call to %H.%n(%p)")); } @Override protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw GraalInternalError.unimplemented(callTarget.target().format("direct call to %H.%n(%p)")); + throw GraalInternalError.unimplemented(callTarget.targetMethod().format("direct call to %H.%n(%p)")); } @Override public void visitBreakpointNode(BreakpointNode node) { throw GraalInternalError.unimplemented(); } - - @Override - public void visitInfopointNode(InfopointNode i) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); - } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -123,9 +123,4 @@ // append(new PTXSafepointOp(info, runtime().config, this)); Debug.log("visitSafePointNode unimplemented"); } - - @Override - public void visitInfopointNode(InfopointNode i) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.visitInfopointNode()"); - } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -26,7 +26,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.lir.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.nodes.*; @@ -56,9 +55,4 @@ Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false), node.arguments()); append(new SPARCBreakpointOp(parameters)); } - - @Override - public void visitInfopointNode(InfopointNode i) { - append(new InfopointOp(stateFor(i.getState()), i.reason)); - } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -30,6 +30,7 @@ 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.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -27,12 +27,13 @@ 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.CallTargetNode.InvokeKind; 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.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -693,7 +693,7 @@ * Parses a Java method in debug mode to produce a graph with extra infopoints. */ protected StructuredGraph parseDebug(Method m) { - return parse0(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerInfopointDefault())); + return parse0(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault())); } private StructuredGraph parse0(Method m, PhaseSuite graphBuilderSuite) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -76,14 +76,14 @@ final Method method = getMethod("testMethod"); final StructuredGraph graph = parseDebug(method); int graphLineSPs = 0; - for (InfopointNode ipn : graph.getNodes().filter(InfopointNode.class)) { - if (ipn.reason == InfopointReason.LINE_NUMBER) { + for (FullInfopointNode ipn : graph.getNodes().filter(FullInfopointNode.class)) { + if (ipn.getReason() == InfopointReason.LINE_NUMBER) { ++graphLineSPs; } } assertTrue(graphLineSPs > 0); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerInfopointDefault()); + PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()); final CompilationResult cr = compileGraph(graph, null, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), getSpeculationLog(), getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); int lineSPs = 0; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -232,7 +232,7 @@ try (Scope s = Debug.scope("InliningTest", new DebugDumpScope(snippet))) { Method method = getMethod(snippet); StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method); - PhaseSuite graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerInfopointDefault()) : getDefaultGraphBuilderSuite(); + PhaseSuite graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()) : getDefaultGraphBuilderSuite(); Assumptions assumptions = new Assumptions(true); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, graphBuilderSuite, OptimisticOptimizations.ALL); Debug.dump(graph, "Graph"); @@ -277,10 +277,10 @@ private static int[] countMethodInfopoints(StructuredGraph graph) { int start = 0; int end = 0; - for (InfopointNode ipn : graph.getNodes().filter(InfopointNode.class)) { - if (ipn.reason == InfopointReason.METHOD_START) { + for (FullInfopointNode ipn : graph.getNodes().filter(FullInfopointNode.class)) { + if (ipn.getReason() == InfopointReason.METHOD_START) { ++start; - } else if (ipn.reason == InfopointReason.METHOD_END) { + } else if (ipn.getReason() == InfopointReason.METHOD_END) { ++end; } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -89,11 +89,11 @@ assert currentField != null; int pos = 0; for (int i = 0; i < vobj.entryCount(); i++) { - if (!currentField.fieldValues().get(i).isConstant() || currentField.fieldValues().get(i).asConstant().getKind() != Kind.Illegal) { - values[pos++] = toValue(currentField.fieldValues().get(i)); + if (!currentField.values().get(i).isConstant() || currentField.values().get(i).asConstant().getKind() != Kind.Illegal) { + values[pos++] = toValue(currentField.values().get(i)); } else { - assert currentField.fieldValues().get(i - 1).getKind() == Kind.Double || currentField.fieldValues().get(i - 1).getKind() == Kind.Long : vobj + " " + i + " " + - currentField.fieldValues().get(i - 1); + assert currentField.values().get(i - 1).getKind() == Kind.Double || currentField.values().get(i - 1).getKind() == Kind.Long : vobj + " " + i + " " + + currentField.values().get(i - 1); } } if (pos != vobj.entryCount()) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -74,7 +74,7 @@ @MatchableNode(nodeClass = FloatLessThanNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = FloatMulNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = IntegerAddNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = IntegerBelowThanNode.class, inputs = {"x", "y"}, commutative = true) +@MatchableNode(nodeClass = IntegerBelowNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = IntegerEqualsNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = IntegerLessThanNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = IntegerMulNode.class, inputs = {"x", "y"}, commutative = true) @@ -602,6 +602,16 @@ } @Override + public void visitFullInfopointNode(FullInfopointNode i) { + append(new FullInfopointOp(stateFor(i.getState()), i.getReason())); + } + + @Override + public void visitSimpleInfopointNode(SimpleInfopointNode i) { + append(new SimpleInfopointOp(i.getReason(), i.getPosition())); + } + + @Override public LIRGeneratorTool getLIRGeneratorTool() { return gen; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java Wed Jul 30 10:39:39 2014 -0700 @@ -68,35 +68,41 @@ private static final DebugMetric MatchResult_ALREADY_USED = Debug.metric("MatchResult_ALREADY_USED"); static final Result OK = new Result(MatchResultCode.OK, null, null); + private static final Result CACHED_WRONG_CLASS = new Result(MatchResultCode.WRONG_CLASS, null, null); + private static final Result CACHED_NAMED_VALUE_MISMATCH = new Result(MatchResultCode.NAMED_VALUE_MISMATCH, null, null); + private static final Result CACHED_TOO_MANY_USERS = new Result(MatchResultCode.TOO_MANY_USERS, null, null); + private static final Result CACHED_NOT_IN_BLOCK = new Result(MatchResultCode.NOT_IN_BLOCK, null, null); + private static final Result CACHED_NOT_SAFE = new Result(MatchResultCode.NOT_SAFE, null, null); + private static final Result CACHED_ALREADY_USED = new Result(MatchResultCode.ALREADY_USED, null, null); static Result WRONG_CLASS(ValueNode node, MatchPattern matcher) { MatchResult_WRONG_CLASS.increment(); - return new Result(MatchResultCode.WRONG_CLASS, node, matcher); + return Debug.isEnabled() ? new Result(MatchResultCode.WRONG_CLASS, node, matcher) : CACHED_WRONG_CLASS; } static Result NAMED_VALUE_MISMATCH(ValueNode node, MatchPattern matcher) { MatchResult_NAMED_VALUE_MISMATCH.increment(); - return new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher); + return Debug.isEnabled() ? new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher) : CACHED_NAMED_VALUE_MISMATCH; } static Result TOO_MANY_USERS(ValueNode node, MatchPattern matcher) { MatchResult_TOO_MANY_USERS.increment(); - return new Result(MatchResultCode.TOO_MANY_USERS, node, matcher); + return Debug.isEnabled() ? new Result(MatchResultCode.TOO_MANY_USERS, node, matcher) : CACHED_TOO_MANY_USERS; } static Result NOT_IN_BLOCK(ScheduledNode node, MatchPattern matcher) { MatchResult_NOT_IN_BLOCK.increment(); - return new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher); + return Debug.isEnabled() ? new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher) : CACHED_NOT_IN_BLOCK; } static Result NOT_SAFE(ScheduledNode node, MatchPattern matcher) { MatchResult_NOT_SAFE.increment(); - return new Result(MatchResultCode.NOT_SAFE, node, matcher); + return Debug.isEnabled() ? new Result(MatchResultCode.NOT_SAFE, node, matcher) : CACHED_NOT_SAFE; } static Result ALREADY_USED(ValueNode node, MatchPattern matcher) { MatchResult_ALREADY_USED.increment(); - return new Result(MatchResultCode.ALREADY_USED, node, matcher); + return Debug.isEnabled() ? new Result(MatchResultCode.ALREADY_USED, node, matcher) : CACHED_ALREADY_USED; } @Override @@ -104,7 +110,11 @@ if (code == MatchResultCode.OK) { return "OK"; } - return code + " " + node.toString(Verbosity.Id) + "|" + node.getClass().getSimpleName() + " " + matcher; + if (node == null) { + return code.toString(); + } else { + return code + " " + node.toString(Verbosity.Id) + "|" + node.getClass().getSimpleName() + " " + matcher; + } } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Wed Jul 30 10:39:39 2014 -0700 @@ -70,7 +70,7 @@ } } - appendPhase(new CleanTypeProfileProxyPhase()); + appendPhase(new CleanTypeProfileProxyPhase(canonicalizer)); if (FullUnroll.getValue()) { appendPhase(new LoopFullUnrollPhase(canonicalizer)); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Wed Jul 30 10:39:39 2014 -0700 @@ -54,6 +54,13 @@ appendPhase(new ExpandLogicPhase()); + /* Cleanup IsNull checks resulting from MID_TIER/LOW_TIER lowering and ExpandLogic phase. */ + if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) { + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer)); + /* Canonicalizer may create some new ShortCircuitOrNodes so clean them up. */ + appendPhase(new ExpandLogicPhase()); + } + appendPhase(new UseTrappingNullChecksPhase()); appendPhase(new DeadCodeEliminationPhase()); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Jul 30 10:39:39 2014 -0700 @@ -578,7 +578,7 @@ } } if (oldInput != null && oldInput.recordsUsages() && oldInput.usages().isEmpty()) { - maybeNotifyZeroInputs(oldInput); + maybeNotifyZeroUsages(oldInput); } } } @@ -707,7 +707,7 @@ } } - private void maybeNotifyZeroInputs(Node node) { + private void maybeNotifyZeroUsages(Node node) { if (graph != null) { assert !graph.isFrozen(); NodeEventListener listener = graph.nodeEventListener; @@ -753,7 +753,7 @@ if (input.recordsUsages()) { removeThisFromUsages(input); if (input.usages().isEmpty()) { - maybeNotifyZeroInputs(input); + maybeNotifyZeroUsages(input); } } } @@ -806,12 +806,18 @@ } public final Node copyWithInputs() { - Node newNode = clone(graph); + return copyWithInputs(true); + } + + public final Node copyWithInputs(boolean addToGraph) { + Node newNode = clone(addToGraph ? graph : null); NodeClass clazz = getNodeClass(); clazz.copyInputs(this, newNode); - for (Node input : inputs()) { - if (input.recordsUsages()) { - input.addUsage(newNode); + if (addToGraph) { + for (Node input : inputs()) { + if (input.recordsUsages()) { + input.addUsage(newNode); + } } } return newNode; @@ -834,7 +840,7 @@ final Node clone(Graph into, boolean clearInputsAndSuccessors) { NodeClass nodeClass = getNodeClass(); - if (nodeClass.valueNumberable() && nodeClass.isLeafNode()) { + if (into != null && nodeClass.valueNumberable() && nodeClass.isLeafNode()) { Node otherNode = into.findNodeInCache(this); if (otherNode != null) { return otherNode; @@ -854,13 +860,15 @@ newNode.graph = into; newNode.typeCacheNext = null; newNode.id = INITIAL_ID; - into.register(newNode); + if (into != null) { + into.register(newNode); + } newNode.usage0 = null; newNode.usage1 = null; newNode.extraUsages = NO_NODES; newNode.predecessor = null; - if (nodeClass.valueNumberable() && nodeClass.isLeafNode()) { + if (into != null && nodeClass.valueNumberable() && nodeClass.isLeafNode()) { into.putNodeIntoCache(newNode); } newNode.afterClone(this); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Jul 30 10:39:39 2014 -0700 @@ -397,7 +397,7 @@ node.getNodeClass().set(node, this, value); } - void initialize(Node node, Node value) { + public void initialize(Node node, Node value) { node.getNodeClass().initializePosition(node, this, value); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -48,9 +48,9 @@ import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 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. @@ -148,12 +148,12 @@ protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) { - append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); + append(new AMD64HotspotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind)); } else { assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; - HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); + HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method."; - append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); + append(new AMD64HotspotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind)); } } @@ -164,7 +164,7 @@ gen.emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); AllocatableValue targetAddress = AMD64.rax.asValue(); gen.emitMove(targetAddress, operand(callTarget.computedAddress())); - append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); + append(new AMD64IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); } else { super.emitIndirectCall(callTarget, result, parameters, temps, callState); } @@ -192,11 +192,11 @@ } @Override - public void visitInfopointNode(InfopointNode i) { + public void visitFullInfopointNode(FullInfopointNode i) { if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { Debug.log("Ignoring InfopointNode for AFTER_BCI"); } else { - super.visitInfopointNode(i); + super.visitFullInfopointNode(i); } } @@ -243,12 +243,12 @@ @MatchRule("(If (IntegerEquals=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (IntegerLessThan=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") - @MatchRule("(If (IntegerBelowThan=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") + @MatchRule("(If (IntegerBelow=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (FloatEquals=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (FloatLessThan=compare value (FloatingRead=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (IntegerEquals=compare value (Read=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (IntegerLessThan=compare value (Read=access (Compression=compress object) ConstantLocation=location)))") - @MatchRule("(If (IntegerBelowThan=compare value (Read=access (Compression=compress object) ConstantLocation=location)))") + @MatchRule("(If (IntegerBelow=compare value (Read=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (FloatEquals=compare value (Read=access (Compression=compress object) ConstantLocation=location)))") @MatchRule("(If (FloatLessThan=compare value (Read=access (Compression=compress object) ConstantLocation=location)))") public ComplexMatchResult ifCompareCompressedMemory(IfNode root, CompareNode compare, CompressionNode compress, ValueNode value, ConstantLocationNode location, Access access) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Wed Jul 30 10:39:39 2014 -0700 @@ -28,7 +28,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; /** * A direct call that complies with the conventions for such calls in HotSpot. It doesn't use an diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Wed Jul 30 10:39:39 2014 -0700 @@ -22,8 +22,6 @@ */ package com.oracle.graal.hotspot.amd64; -import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*; - import com.oracle.graal.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; @@ -32,7 +30,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; /** * A direct call that complies with the conventions for such calls in HotSpot. In particular, for @@ -53,7 +51,7 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. - MarkId.recordMark(crb, invokeKind == Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE); + MarkId.recordMark(crb, invokeKind == InvokeKind.Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE); // This must be emitted exactly like this to ensure it's patchable masm.movq(AMD64.rax, HotSpotGraalRuntime.runtime().getConfig().nonOopBits); super.emitCode(crb, masm); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Wed Jul 30 10:39:39 2014 -0700 @@ -238,10 +238,12 @@ @Override protected void run(StructuredGraph graph) { int argCount = 0; + Stamp nonNull = StampFactory.objectNonNull(); for (ParameterNode param : graph.getNodes(ParameterNode.class)) { argCount++; if (argCount < numArgs && param.stamp() instanceof ObjectStamp) { - param.setStamp(StampFactory.declaredNonNull(((ObjectStamp) param.stamp()).type())); + ObjectStamp paramStamp = (ObjectStamp) param.stamp(); + param.setStamp(paramStamp.join(nonNull)); } } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -40,7 +40,7 @@ import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements HotSpotNodeLIRBuilder { @@ -97,12 +97,12 @@ protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) { - append(new SPARCHotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); + append(new SPARCHotspotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind)); } else { assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; - HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); + HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method."; - append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); + append(new SPARCHotspotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind)); } } @@ -112,7 +112,7 @@ gen.emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); AllocatableValue targetAddress = g3.asValue(); gen.emitMove(targetAddress, operand(callTarget.computedAddress())); - append(new SPARCIndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); + append(new SPARCIndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); } @Override @@ -142,12 +142,11 @@ } @Override - public void visitInfopointNode(InfopointNode i) { + public void visitFullInfopointNode(FullInfopointNode i) { if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { Debug.log("Ignoring InfopointNode for AFTER_BCI"); } else { - super.visitInfopointNode(i); + super.visitFullInfopointNode(i); } } - } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java Wed Jul 30 10:39:39 2014 -0700 @@ -28,7 +28,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; /** * A direct call that complies with the conventions for such calls in HotSpot. It doesn't use an diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Wed Jul 30 10:39:39 2014 -0700 @@ -22,19 +22,18 @@ */ package com.oracle.graal.hotspot.sparc; -import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*; import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; /** * A direct call that complies with the conventions for such calls in HotSpot. In particular, for @@ -55,7 +54,7 @@ public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. - MarkId.recordMark(crb, invokeKind == Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE); + MarkId.recordMark(crb, invokeKind == InvokeKind.Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE); Register scratchRegister = g5; new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, scratchRegister, true).emit(masm); super.emitCode(crb, masm); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ArrayCopyIntrinsificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ArrayCopyIntrinsificationTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ArrayCopyIntrinsificationTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -52,7 +52,7 @@ Invoke invoke = (Invoke) node; Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode); LoweredCallTargetNode directCall = (LoweredCallTargetNode) invoke.callTarget(); - JavaMethod callee = directCall.target(); + JavaMethod callee = directCall.targetMethod(); Assert.assertTrue(callee.getName().equals("")); Assert.assertTrue(getMetaAccess().lookupJavaType(ArrayIndexOutOfBoundsException.class).equals(callee.getDeclaringClass()) || getMetaAccess().lookupJavaType(NullPointerException.class).equals(callee.getDeclaringClass())); @@ -64,7 +64,7 @@ if (node instanceof Invoke) { Invoke invoke = (Invoke) node; LoweredCallTargetNode directCall = (LoweredCallTargetNode) invoke.callTarget(); - JavaMethod callee = directCall.target(); + JavaMethod callee = directCall.targetMethod(); if (callee.getDeclaringClass().equals(getMetaAccess().lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) { found = true; } else { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/BytecodeVerificationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/BytecodeVerificationTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,122 @@ +/* + * 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.test; + +import java.io.*; + +import jdk.internal.org.objectweb.asm.*; + +import org.junit.*; + +import com.oracle.graal.compiler.test.*; + +/** + * Tests that the Graal API can only be used to access verified bytecode. + */ +public class BytecodeVerificationTest extends GraalCompilerTest { + + @Test(expected = VerifyError.class) + public void test() throws Exception { + BadClassLoader loader = new BadClassLoader(); + String className = BytecodeVerificationTest.class.getName() + "$BadClass"; + Class c = loader.findClass(className); + + // Should fail with a verification error as long as -XX:-BytecodeVerificationRemote is not + // specified on the command line + getMetaAccess().lookupJavaMethod(c.getDeclaredMethod("getValue")).getCode(); + } + + /** + * Class that will be rewritten during loading to be unverifiable. + */ + public static class BadClass { + + public static String value; + + public static String getValue() { + // Re-written to "return 5;" + return value; + } + } + + /** + * Rewrites {@link BadClass#getValue()} to: + * + *
+     * public static String getValue() {
+     *     return 5;
+     * }
+     * 
+ */ + private static class BadClassRewriter extends ClassVisitor { + + public BadClassRewriter(ClassWriter cw) { + super(Opcodes.ASM5, cw); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, d, signature, exceptions); + if (name.equals("getValue")) { + return new MethodVisitor(Opcodes.ASM5, mv) { + @Override + public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) { + if (opcode == Opcodes.GETSTATIC) { + visitInsn(Opcodes.ICONST_5); + } else { + super.visitFieldInsn(opcode, owner, name, fieldDesc); + } + } + }; + } + return mv; + } + } + + /** + * Class loader used for loading {@link BadClass}. Using a separate class loader ensure the + * class is treated as "remote" so that it will be subject to verification by default. + */ + private static class BadClassLoader extends ClassLoader { + + @Override + protected Class findClass(final String name) throws ClassNotFoundException { + byte[] classData = null; + try { + InputStream is = BytecodeVerificationTest.class.getResourceAsStream("/" + name.replace('.', '/') + ".class"); + classData = new byte[is.available()]; + new DataInputStream(is).readFully(classData); + } catch (IOException e) { + Assert.fail("can't access class: " + name); + } + + ClassReader cr = new ClassReader(classData); + ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); + + BadClassRewriter rewriter = new BadClassRewriter(cw); + cr.accept(rewriter, ClassReader.SKIP_FRAMES); + classData = cw.toByteArray(); + return defineClass(null, classData, 0, classData.length); + } + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/GraalClassLoaderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/GraalClassLoaderTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,58 @@ +/* + * 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.test; + +import org.junit.*; + +import sun.management.*; + +import com.oracle.graal.api.runtime.*; +import com.sun.management.*; + +/** + * Tests that the Graal API is inaccessible when -XX:+UseGraalClassLoader is specified. Execute as + * follows to show class loader based isolation: + * + *
+ * mx unittest -XX:+UseGraalClassLoader GraalClassLoaderTest
+ * 
+ */ +public class GraalClassLoaderTest { + + @Test + public void test() throws Exception { + if (System.getProperty("java.vm.version").contains("graal")) { + HotSpotDiagnosticMXBean diag = ManagementFactoryHelper.getDiagnosticMXBean(); + VMOption option = diag.getVMOption("UseGraalClassLoader"); + if (option.getValue().equals("true")) { + try { + Graal.getRuntime(); + Assert.fail(); + } catch (NoClassDefFoundError e) { + // expected + } + } + } + } + +} \ No newline at end of file diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Jul 30 10:39:39 2014 -0700 @@ -52,6 +52,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderConfiguration.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -133,7 +134,11 @@ if (HotSpotGraalRuntime.runtime().getCompilerToVM().shouldDebugNonSafepoints()) { // need to tweak the graph builder config - suite.findPhase(GraphBuilderPhase.class).set(new GraphBuilderPhase(GraphBuilderConfiguration.getInfopointDefault())); + suite = suite.copy(); + GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) suite.findPhase(GraphBuilderPhase.class).previous(); + GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); + GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig.withDebugInfoMode(DebugInfoMode.Simple)); + suite.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); } boolean osrCompilation = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Wed Jul 30 10:39:39 2014 -0700 @@ -519,38 +519,20 @@ } } - public Iterable getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip) { + @Override + public T iterateFrames(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip, InspectedFrameVisitor visitor) { final long[] initialMetaMethods = toMeta(initialMethods); final long[] matchingMetaMethods = toMeta(matchingMethods); - class StackFrameIterator implements Iterator { - private HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, initialMetaMethods, initialSkip); - // we don't want to read ahead if hasNext isn't called - private boolean advanced = true; - - public boolean hasNext() { - update(); - return current != null; + HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, initialMetaMethods, initialSkip); + while (current != null) { + T result = visitor.visitFrame(current); + if (result != null) { + return result; } - - public InspectedFrame next() { - update(); - advanced = false; - return current; - } - - private void update() { - if (!advanced) { - current = compilerToVm.getNextStackFrame(current, matchingMetaMethods, 0); - advanced = true; - } - } + current = compilerToVm.getNextStackFrame(current, matchingMetaMethods, 0); } - return new Iterable() { - public Iterator iterator() { - return new StackFrameIterator(); - } - }; + return null; } private static long[] toMeta(ResolvedJavaMethod[] methods) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotStackFrameReference.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotStackFrameReference.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotStackFrameReference.java Wed Jul 30 10:39:39 2014 -0700 @@ -51,26 +51,37 @@ return frameNumber; } + @Override public Object getLocal(int index) { return locals[index]; } + @Override public boolean isVirtual(int index) { return localIsVirtual == null ? false : localIsVirtual[index]; } + @Override public void materializeVirtualObjects(boolean invalidateCode) { compilerToVM.materializeVirtualObjects(this, invalidateCode); } + @Override public int getBytecodeIndex() { return bci; } + @Override public ResolvedJavaMethod getMethod() { return HotSpotResolvedJavaMethod.fromMetaspace(metaspaceMethod); } + @Override + public boolean isMethod(ResolvedJavaMethod method) { + return metaspaceMethod == ((HotSpotResolvedJavaMethod) method).getMetaspaceMethod(); + } + + @Override public boolean hasVirtualObjects() { return localIsVirtual != null; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Jul 30 10:39:39 2014 -0700 @@ -848,6 +848,8 @@ @HotSpotVMType(name = "vtableEntry", get = HotSpotVMType.Type.SIZE) @Stable public int vtableEntrySize; @HotSpotVMField(name = "vtableEntry::_method", type = "Method*", get = HotSpotVMField.Type.OFFSET) @Stable public int vtableEntryMethodOffset; @HotSpotVMValue(expression = "InstanceKlass::vtable_start_offset() * HeapWordSize") @Stable public int instanceKlassVtableStartOffset; + @HotSpotVMValue(expression = "InstanceKlass::vtable_length_offset() * HeapWordSize") @Stable public int instanceKlassVtableLengthOffset; + @HotSpotVMValue(expression = "Universe::base_vtable_size() / vtableEntry::size()") @Stable public int baseVtableLength; /** * The offset of the array length word in an array object's header. @@ -1014,6 +1016,7 @@ @HotSpotVMField(name = "ThreadShadow::_pending_exception", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingExceptionOffset; @HotSpotVMField(name = "ThreadShadow::_pending_deoptimization", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingDeoptimizationOffset; @HotSpotVMField(name = "ThreadShadow::_pending_failed_speculation", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingFailedSpeculationOffset; + @HotSpotVMField(name = "ThreadShadow::_pending_transfer_to_interpreter", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingTransferToInterpreterOffset; @HotSpotVMFlag(name = "UseHSAILDeoptimization") @Stable public boolean useHSAILDeoptimization; @HotSpotVMFlag(name = "UseHSAILSafepoints") @Stable public boolean useHSAILSafepoints; @@ -1460,6 +1463,7 @@ @HotSpotVMConstant(name = "Deoptimization::Reason_constraint") @Stable public int deoptReasonConstraint; @HotSpotVMConstant(name = "Deoptimization::Reason_loop_limit_check") @Stable public int deoptReasonLoopLimitCheck; @HotSpotVMConstant(name = "Deoptimization::Reason_aliasing") @Stable public int deoptReasonAliasing; + @HotSpotVMConstant(name = "Deoptimization::Reason_transfer_to_interpreter") @Stable public int deoptReasonTransferToInterpreter; @HotSpotVMConstant(name = "Deoptimization::Reason_LIMIT") @Stable public int deoptReasonOSROffset; @HotSpotVMConstant(name = "Deoptimization::Action_none") @Stable public int deoptActionNone; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Jul 30 10:39:39 2014 -0700 @@ -32,6 +32,7 @@ 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.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; @@ -342,7 +343,7 @@ if (Options.TimedDynamicCounters.getValue() > 0) { Thread thread = new Thread() { long lastTime = System.nanoTime(); - PrintStream out = System.out; + PrintStream out = TTY.cachedOut; @Override public void run() { @@ -369,7 +370,7 @@ public static void shutdown(CompilerToVM compilerToVM, long compilerStartTime) { if (Options.GenericDynamicCounters.getValue()) { - dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d, compilerToVM.collectCounters(), 100); + dump(TTY.cachedOut, (System.nanoTime() - compilerStartTime) / 1000000000d, compilerToVM.collectCounters(), 100); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Wed Jul 30 10:39:39 2014 -0700 @@ -40,12 +40,12 @@ import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.extended.*; 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.replacements.*; @@ -202,7 +202,7 @@ StampFactory.forKind(wordKind), BarrierType.NONE)); loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), - CallingConvention.Type.JavaCall)); + CallingConvention.Type.JavaCall, callTarget.invokeKind())); graph.addBeforeFixed(invoke.asNode(), metaspaceMethod); graph.addAfterFixed(metaspaceMethod, compiledEntry); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Wed Jul 30 10:39:39 2014 -0700 @@ -230,6 +230,8 @@ return config.deoptReasonLoopLimitCheck; case Aliasing: return config.deoptReasonAliasing; + case TransferToInterpreter: + return config.deoptReasonTransferToInterpreter; default: throw GraalInternalError.shouldNotReachHere(); } @@ -282,6 +284,9 @@ if (reason == config.deoptReasonAliasing) { return DeoptimizationReason.Aliasing; } + if (reason == config.deoptReasonTransferToInterpreter) { + return DeoptimizationReason.TransferToInterpreter; + } throw GraalInternalError.shouldNotReachHere(Integer.toHexString(reason)); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Wed Jul 30 10:39:39 2014 -0700 @@ -488,11 +488,24 @@ long totalCount = 0; int entries = 0; - for (int i = 0; i < typeProfileWidth; i++) { + outer: for (int i = 0; i < typeProfileWidth; i++) { long receiverKlass = data.readWord(position, getTypeOffset(i)); if (receiverKlass != 0) { - types[entries] = HotSpotResolvedObjectType.fromMetaspaceKlass(receiverKlass); + ResolvedJavaType klass = HotSpotResolvedObjectType.fromMetaspaceKlass(receiverKlass); long count = data.readUnsignedInt(position, getTypeCountOffset(i)); + /* + * Because of races in the profile collection machinery it's possible for a + * class to appear multiple times so merge them to make the profile look + * rational. + */ + for (int j = 0; j < entries; j++) { + if (types[j].equals(klass)) { + totalCount += count; + counts[j] += count; + continue outer; + } + } + types[entries] = klass; totalCount += count; counts[entries] = count; entries++; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Wed Jul 30 10:39:39 2014 -0700 @@ -612,21 +612,26 @@ public int vtableEntryOffset(ResolvedJavaType resolved) { guarantee(isInVirtualMethodTable(resolved), "%s does not have a vtable entry", this); HotSpotVMConfig config = runtime().getConfig(); - final int vtableIndex = getVtableIndex(resolved); + final int vtableIndex = getVtableIndex((HotSpotResolvedObjectType) resolved); return config.instanceKlassVtableStartOffset + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset; } @Override public boolean isInVirtualMethodTable(ResolvedJavaType resolved) { - return getVtableIndex(resolved) >= 0; + if (resolved instanceof HotSpotResolvedObjectType) { + HotSpotResolvedObjectType hotspotResolved = (HotSpotResolvedObjectType) resolved; + int vtableIndex = getVtableIndex(hotspotResolved); + return vtableIndex >= 0 && vtableIndex < hotspotResolved.getVtableLength(); + } + return false; } - private int getVtableIndex(ResolvedJavaType resolved) { + private int getVtableIndex(HotSpotResolvedObjectType resolved) { if (!holder.isLinked()) { return runtime().getConfig().invalidVtableIndex; } if (holder.isInterface()) { - if (resolved.isArray() || resolved.isInterface()) { + if (resolved.isInterface()) { return runtime().getConfig().invalidVtableIndex; } return getVtableIndexForInterface(resolved); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Jul 30 10:39:39 2014 -0700 @@ -436,6 +436,17 @@ return method; } + public int getVtableLength() { + HotSpotVMConfig config = runtime().getConfig(); + if (isInterface() || isArray()) { + /* Everything has the core vtable of java.lang.Object */ + return config.baseVtableLength; + } + int result = unsafe.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize); + assert result >= config.baseVtableLength : unsafe.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) + " " + config.vtableEntrySize; + return result; + } + /** * Gets the mask used to filter out HotSpot internal flags for fields when a {@link Field} * object is created. This is the value of {@code JVM_RECOGNIZED_FIELD_MODIFIERS} in @@ -712,13 +723,13 @@ } /** - * Determines if this type is resolved in the context of a given accessing class. This is a - * conservative check based on this type's class loader being identical to - * {@code accessingClass}'s loader. This type may still be the correct resolved type in the - * context of {@code accessingClass} if its loader is an ancestor of {@code accessingClass}'s - * loader. + * Performs a fast-path check that this type is resolved in the context of a given accessing + * class. A negative result does not mean this type is not resolved with respect to + * {@code accessingClass}. That can only be determined by + * {@linkplain HotSpotGraalRuntime#lookupType(String, HotSpotResolvedObjectType, boolean) + * re-resolving} the type. */ - public boolean isResolvedWithRespectTo(ResolvedJavaType accessingClass) { + public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) { assert accessingClass != null; ResolvedJavaType elementType = getElementalType(); if (elementType.isPrimitive()) { @@ -738,7 +749,7 @@ @Override public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { - if (isResolvedWithRespectTo(requireNonNull(accessingClass))) { + if (isDefinitelyResolvedWithRespectTo(requireNonNull(accessingClass))) { return this; } HotSpotResolvedObjectType accessingType = (HotSpotResolvedObjectType) accessingClass; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Wed Jul 30 10:39:39 2014 -0700 @@ -134,7 +134,7 @@ } if (type instanceof HotSpotResolvedObjectType) { - return ((HotSpotResolvedObjectType) type).isResolvedWithRespectTo(accessingClass); + return ((HotSpotResolvedObjectType) type).isDefinitelyResolvedWithRespectTo(accessingClass); } return true; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -56,7 +56,7 @@ ParameterNode arg0 = g.unique(new ParameterNode(0, StampFactory.forKind(Kind.Object))); ParameterNode arg1 = g.unique(new ParameterNode(1, StampFactory.forKind(Kind.Object))); ParameterNode arg2 = g.unique(new ParameterNode(2, StampFactory.forKind(Kind.Object))); - FrameState frameState = g.add(new FrameState(method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList(), + FrameState frameState = g.add(new FrameState(null, method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList(), new ArrayList())); g.start().setStateAfter(frameState); List parameters = new ArrayList<>(); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -56,6 +56,11 @@ this.encoding = encoding; } + @Override + public boolean inferStamp() { + return updateStamp(mkStamp(op, getValue().stamp(), encoding)); + } + public static CompressionNode compress(ValueNode input, CompressEncoding encoding) { return input.graph().unique(new CompressionNode(CompressionOp.Compress, input, encoding)); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -28,18 +28,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; public class HotSpotDirectCallTargetNode extends DirectCallTargetNode { - - private final InvokeKind invokeKind; - public HotSpotDirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, Type callType, InvokeKind invokeKind) { - super(arguments, returnStamp, signature, target, callType); - this.invokeKind = invokeKind; - } - - public InvokeKind invokeKind() { - return invokeKind; + super(arguments, returnStamp, signature, target, callType, invokeKind); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -34,8 +34,8 @@ @Input private ValueNode metaspaceMethod; public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, - Type callType) { - super(computedAddress, arguments, returnStamp, signature, target, callType); + Type callType, InvokeKind invokeKind) { + super(computedAddress, arguments, returnStamp, signature, target, callType, invokeKind); this.metaspaceMethod = metaspaceMethod; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -35,8 +35,8 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Wed Jul 30 10:39:39 2014 -0700 @@ -40,10 +40,10 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.extended.*; 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.options.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java --- a/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConfigProcessor.java Wed Jul 30 10:39:39 2014 -0700 @@ -26,6 +26,7 @@ import java.lang.annotation.*; import java.util.*; import java.util.Map.Entry; +import java.util.function.*; import javax.annotation.processing.*; import javax.lang.model.*; @@ -142,7 +143,6 @@ "void VMStructs::initHotSpotVMConfig(oop vmconfig_oop) {", " InstanceKlass* vmconfig_klass = InstanceKlass::cast(vmconfig_oop->klass());", "", - " for (JavaFieldStream fs(vmconfig_klass); !fs.done(); fs.next()) {", }; //@formatter:on @@ -158,7 +158,29 @@ out.println(line); } - out.println(); + Map expectedValues = new HashMap<>(); + for (VMConfigField value : annotations.values()) { + if (!value.optional) { + String key = value.define != null ? value.define : ""; + if (expectedValues.get(key) == null) { + expectedValues.put(key, 1); + } else { + expectedValues.put(key, expectedValues.get(key) + 1); + } + } + } + + out.printf(" int expected = %s;%n", expectedValues.get("")); + for (Entry entry : expectedValues.entrySet()) { + if (entry.getKey().equals("")) { + continue; + } + out.printf("#if %s%n", entry.getKey()); + out.printf(" expected += %s;%n", entry.getValue()); + out.printf("#endif%n"); + } + out.println(" int assigned = 0;"); + out.println(" for (JavaFieldStream fs(vmconfig_klass); !fs.done(); fs.next()) {"); Set fieldTypes = new HashSet<>(); for (VMConfigField key : annotations.values()) { @@ -194,6 +216,7 @@ out.println(" } // if"); } out.println(" } // for"); + out.println(" guarantee(assigned == expected, \"Didn't find all fields during init of HotSpotVMConfig. Maybe recompile?\");"); out.println("}"); } } @@ -215,21 +238,84 @@ } } - class VMConfigField { + static class VMConfigField { + final String setter; + final String define; + private boolean optional; final VariableElement field; - final Annotation annotation; + + public VMConfigField(VariableElement field, HotSpotVMField value) { + this.field = field; + define = archDefines(value.archs()); + String type = field.asType().toString(); + String name = value.name(); + int i = name.lastIndexOf("::"); + switch (value.get()) { + case OFFSET: + setter = String.format("set_%s(\"%s\", offset_of(%s, %s));", type, field.getSimpleName(), name.substring(0, i), name.substring(i + 2)); + break; + case ADDRESS: + setter = String.format("set_address(\"%s\", &%s);", field.getSimpleName(), name); + break; + case VALUE: + setter = String.format("set_%s(\"%s\", (%s) (intptr_t) %s);", type, field.getSimpleName(), type, name); + break; + default: + throw new GraalInternalError("unexpected type: " + value.get()); + } + } + + public VMConfigField(VariableElement field, HotSpotVMType value) { + this.field = field; + define = null; // ((HotSpotVMType) annotation).archs(); + String type = field.asType().toString(); + setter = String.format("set_%s(\"%s\", sizeof(%s));", type, field.getSimpleName(), value.name()); + } - public VMConfigField(VariableElement field, Annotation value) { - super(); + public VMConfigField(VariableElement field, HotSpotVMValue value) { this.field = field; - this.annotation = value; + String[] defines = value.defines(); + int length = defines.length; + if (length != 0) { + for (int i = 0; i < length; i++) { + defines[i] = "defined(" + defines[i] + ")"; + } + define = String.join(" || ", defines); + } else { + define = null; // ((HotSpotVMValue) annotation).archs(); + } + String type = field.asType().toString(); + if (value.get() == HotSpotVMValue.Type.ADDRESS) { + setter = String.format("set_address(\"%s\", %s);", field.getSimpleName(), value.expression()); + } else { + setter = String.format("set_%s(\"%s\", %s);", type, field.getSimpleName(), value.expression()); + } + } + + public VMConfigField(VariableElement field, HotSpotVMConstant value) { + this.field = field; + define = archDefines(value.archs()); + String type = field.asType().toString(); + setter = String.format("set_%s(\"%s\", %s);", type, field.getSimpleName(), value.name()); + } + + public VMConfigField(VariableElement field, HotSpotVMFlag value) { + this.field = field; + define = archDefines(value.archs()); + optional = value.optional(); + String type = field.asType().toString(); + if (value.optional()) { + setter = String.format("set_optional_%s_flag(\"%s\", \"%s\");", type, field.getSimpleName(), value.name()); + } else { + setter = String.format("set_%s(\"%s\", %s);", type, field.getSimpleName(), value.name()); + } } public String getType() { return field.asType().toString(); } - private String archDefine(String arch) { + private static String archDefine(String arch) { switch (arch) { case "amd64": return "defined(AMD64)"; @@ -242,8 +328,8 @@ } } - private String archDefines(String[] archs) { - if (archs.length == 0) { + private static String archDefines(String[] archs) { + if (archs == null || archs.length == 0) { return null; } if (archs.length == 1) { @@ -254,102 +340,16 @@ for (String arch : archs) { defs[i++] = archDefine(arch); } - return String.join(" ||", defs); + return String.join(" || ", defs); } public void emit(PrintWriter out) { - if (annotation instanceof HotSpotVMField) { - emitField(out, (HotSpotVMField) annotation); - } else if (annotation instanceof HotSpotVMType) { - emitType(out, (HotSpotVMType) annotation); - } else if (annotation instanceof HotSpotVMFlag) { - emitFlag(out, (HotSpotVMFlag) annotation); - } else if (annotation instanceof HotSpotVMConstant) { - emitConstant(out, (HotSpotVMConstant) annotation); - } else if (annotation instanceof HotSpotVMValue) { - emitValue(out, (HotSpotVMValue) annotation); - } else { - throw new InternalError(annotation.toString()); - } - - } - - private void emitField(PrintWriter out, HotSpotVMField value) { - String type = field.asType().toString(); - String define = archDefines(value.archs()); if (define != null) { out.printf("#if %s\n", define); } - - String name = value.name(); - int i = name.lastIndexOf("::"); - switch (value.get()) { - case OFFSET: - out.printf(" set_%s(\"%s\", offset_of(%s, %s));\n", type, field.getSimpleName(), name.substring(0, i), name.substring(i + 2)); - break; - case ADDRESS: - out.printf(" set_address(\"%s\", &%s);\n", field.getSimpleName(), name); - break; - case VALUE: - out.printf(" set_%s(\"%s\", (%s) (intptr_t) %s);\n", type, field.getSimpleName(), type, name); - break; - } - if (define != null) { - out.printf("#endif\n"); - } - } - - private void emitType(PrintWriter out, HotSpotVMType value) { - String type = field.asType().toString(); - out.printf(" set_%s(\"%s\", sizeof(%s));\n", type, field.getSimpleName(), value.name()); - } - - private void emitValue(PrintWriter out, HotSpotVMValue value) { - String type = field.asType().toString(); - int length = value.defines().length; - if (length != 0) { - out.printf("#if "); - for (int i = 0; i < length; i++) { - out.printf("defined(%s)", value.defines()[i]); - if (i + 1 < length) { - out.printf(" || "); - } - } - out.println(); - } - if (value.get() == HotSpotVMValue.Type.ADDRESS) { - out.printf(" set_address(\"%s\", %s);\n", field.getSimpleName(), value.expression()); - } else { - out.printf(" set_%s(\"%s\", %s);\n", type, field.getSimpleName(), value.expression()); - } - if (length != 0) { - out.println("#endif"); - } - } - - private void emitConstant(PrintWriter out, HotSpotVMConstant value) { - String define = archDefines(value.archs()); - if (define != null) { - out.printf("#if %s\n", define); - } - String type = field.asType().toString(); - out.printf(" set_%s(\"%s\", %s);\n", type, field.getSimpleName(), value.name()); - if (define != null) { - out.printf("#endif\n"); - } - } - - private void emitFlag(PrintWriter out, HotSpotVMFlag value) { - String type = field.asType().toString(); - - String define = archDefines(value.archs()); - if (define != null) { - out.printf("#if %s\n", define); - } - if (value.optional()) { - out.printf(" set_optional_%s_flag(\"%s\", \"%s\");\n", type, field.getSimpleName(), value.name()); - } else { - out.printf(" set_%s(\"%s\", %s);\n", type, field.getSimpleName(), value.name()); + out.printf(" %s%n", setter); + if (!optional) { + out.printf(" assigned++;%n"); } if (define != null) { out.printf("#endif\n"); @@ -358,7 +358,9 @@ } - private void collectAnnotations(RoundEnvironment roundEnv, Map annotationMap, Class annotationClass) { + @SuppressWarnings("unchecked") + private void collectAnnotations(RoundEnvironment roundEnv, Map annotationMap, Class annotationClass, + BiFunction builder) { for (Element element : roundEnv.getElementsAnnotatedWith(annotationClass)) { Annotation constant = element.getAnnotation(annotationClass); if (element.getKind() != ElementKind.FIELD) { @@ -377,7 +379,7 @@ errorMessage(element, "Multiple types encountered. Only HotSpotVMConfig is supported"); } } - annotationMap.put(element.getSimpleName().toString(), new VMConfigField((VariableElement) element, constant)); + annotationMap.put(element.getSimpleName().toString(), builder.apply((VariableElement) element, (T) constant)); } } @@ -399,11 +401,11 @@ // First collect all the annotations. Map annotationMap = new HashMap<>(); - collectAnnotations(roundEnv, annotationMap, HotSpotVMConstant.class); - collectAnnotations(roundEnv, annotationMap, HotSpotVMFlag.class); - collectAnnotations(roundEnv, annotationMap, HotSpotVMField.class); - collectAnnotations(roundEnv, annotationMap, HotSpotVMType.class); - collectAnnotations(roundEnv, annotationMap, HotSpotVMValue.class); + collectAnnotations(roundEnv, annotationMap, HotSpotVMConstant.class, (e, v) -> new VMConfigField(e, v)); + collectAnnotations(roundEnv, annotationMap, HotSpotVMFlag.class, (e, v) -> new VMConfigField(e, v)); + collectAnnotations(roundEnv, annotationMap, HotSpotVMField.class, (e, v) -> new VMConfigField(e, v)); + collectAnnotations(roundEnv, annotationMap, HotSpotVMType.class, (e, v) -> new VMConfigField(e, v)); + collectAnnotations(roundEnv, annotationMap, HotSpotVMValue.class, (e, v) -> new VMConfigField(e, v)); if (annotationMap.isEmpty()) { return true; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java Wed Jul 30 10:39:39 2014 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.java; +import static com.oracle.graal.nodes.cfg.ControlFlowGraph.*; + import java.util.*; import java.util.stream.*; @@ -30,7 +32,6 @@ public class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.NodeIteratorClosure { - private static final double EPSILON = Double.MIN_NORMAL; private static final ComputeLoopFrequenciesClosure INSTANCE = new ComputeLoopFrequenciesClosure(); private ComputeLoopFrequenciesClosure() { @@ -62,8 +63,8 @@ double exitProbability = exitStates.values().stream().mapToDouble(d -> d).sum(); assert exitProbability <= 1D && exitProbability >= 0D; - if (exitProbability < EPSILON) { - exitProbability = EPSILON; + if (exitProbability < MIN_PROBABILITY) { + exitProbability = MIN_PROBABILITY; } double loopFrequency = 1D / exitProbability; loop.setLoopFrequency(loopFrequency); @@ -75,14 +76,14 @@ } /** - * Multiplies a and b and saturates the result to 1/{@link Double#MIN_NORMAL}. + * Multiplies a and b and saturates the result to 1/{@link #MIN_PROBABILITY}. * - * @return a times b saturated to 1/{@link Double#MIN_NORMAL} + * @return a times b saturated to 1/{@link #MIN_PROBABILITY} */ public static double multiplySaturate(double a, double b) { double r = a * b; - if (r > 1 / Double.MIN_NORMAL) { - return 1 / Double.MIN_NORMAL; + if (r > 1 / MIN_PROBABILITY) { + return 1 / MIN_PROBABILITY; } return r; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Wed Jul 30 10:39:39 2014 -0700 @@ -22,34 +22,57 @@ */ package com.oracle.graal.java; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; public class GraphBuilderConfiguration { + private static final ResolvedJavaType[] EMPTY = new ResolvedJavaType[]{}; private final boolean eagerResolving; private final boolean omitAllExceptionEdges; - private ResolvedJavaType[] skippedExceptionTypes; + private final ResolvedJavaType[] skippedExceptionTypes; + private final DebugInfoMode debugInfoMode; - /** - * When the graph builder is in eager infopoint mode, it inserts {@link InfopointNode}s in - * places where no safepoints would be inserted: inlining boundaries, and line number switches. - * This is relevant when code is to be generated for native, machine-code level debugging. - */ - private boolean eagerInfopointMode; + public static enum DebugInfoMode { + SafePointsOnly, + /** + * This mode inserts {@link FullInfopointNode}s in places where no safepoints would be + * inserted: inlining boundaries, and line number switches. + *

+ * In this mode the infopoint only have a location (method and bytecode index) and no + * values. + *

+ * This is useful to have better program counter to bci mapping and has no influence on the + * generated code. However it can increase the amount of metadata and does not allow access + * to accessing values at runtime. + */ + Simple, + /** + * In this mode, infopoints are generated in the same locations as in {@link #Simple} mode + * but the infopoints have access to the runtime values. + *

+ * This is relevant when code is to be generated for native, machine-code level debugging + * but can have a limit the amount of optimisation applied to the code. + */ + Full, + } - protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, boolean eagerInfopointMode) { + protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes) { this.eagerResolving = eagerResolving; this.omitAllExceptionEdges = omitAllExceptionEdges; - this.eagerInfopointMode = eagerInfopointMode; - } - - public void setSkippedExceptionTypes(ResolvedJavaType[] skippedExceptionTypes) { + this.debugInfoMode = debugInfoMode; this.skippedExceptionTypes = skippedExceptionTypes; } - public void setEagerInfopointMode(boolean eagerInfopointMode) { - this.eagerInfopointMode = eagerInfopointMode; + public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) { + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes); + } + + public GraphBuilderConfiguration withDebugInfoMode(DebugInfoMode newDebugInfoMode) { + ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length); + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newDebugInfoMode, newSkippedExceptionTypes); } public ResolvedJavaType[] getSkippedExceptionTypes() { @@ -64,28 +87,28 @@ return omitAllExceptionEdges; } - public boolean eagerInfopointMode() { - return eagerInfopointMode; + public boolean insertNonSafepointDebugInfo() { + return debugInfoMode.ordinal() >= DebugInfoMode.Simple.ordinal(); + } + + public boolean insertFullDebugInfo() { + return debugInfoMode.ordinal() >= DebugInfoMode.Full.ordinal(); } public static GraphBuilderConfiguration getDefault() { - return new GraphBuilderConfiguration(false, false, false); - } - - public static GraphBuilderConfiguration getInfopointDefault() { - return new GraphBuilderConfiguration(false, false, true); + return new GraphBuilderConfiguration(false, false, DebugInfoMode.SafePointsOnly, EMPTY); } public static GraphBuilderConfiguration getEagerDefault() { - return new GraphBuilderConfiguration(true, false, false); + return new GraphBuilderConfiguration(true, false, DebugInfoMode.SafePointsOnly, EMPTY); } public static GraphBuilderConfiguration getSnippetDefault() { - return new GraphBuilderConfiguration(true, true, false); + return new GraphBuilderConfiguration(true, true, DebugInfoMode.SafePointsOnly, EMPTY); } - public static GraphBuilderConfiguration getEagerInfopointDefault() { - return new GraphBuilderConfiguration(true, false, true); + public static GraphBuilderConfiguration getFullDebugDefault() { + return new GraphBuilderConfiguration(true, false, DebugInfoMode.Full, EMPTY); } /** diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -44,10 +44,10 @@ import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.java.BciBlockMapping.LocalLiveness; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; @@ -69,6 +69,10 @@ new Instance(context.getMetaAccess(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph); } + public GraphBuilderConfiguration getGraphBuilderConfig() { + return graphBuilderConfig; + } + public static class Instance extends Phase { private LineNumberTable lnt; @@ -139,7 +143,7 @@ @Override protected void run(StructuredGraph graph) { ResolvedJavaMethod method = graph.method(); - if (graphBuilderConfig.eagerInfopointMode()) { + if (graphBuilderConfig.insertNonSafepointDebugInfo()) { lnt = method.getLineNumberTable(); previousLineNumber = -1; } @@ -232,11 +236,12 @@ lastInstr = genMonitorEnter(methodSynchronizedObject); } frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true); - ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); + assert bci() == 0; + ((StateSplit) lastInstr).setStateAfter(frameState.create(bci())); finishPrepare(lastInstr); - if (graphBuilderConfig.eagerInfopointMode()) { - InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START, frameState.create(0))); + if (graphBuilderConfig.insertNonSafepointDebugInfo()) { + InfopointNode ipn = currentGraph.add(createInfoPointNode(InfopointReason.METHOD_START)); lastInstr.setNext(ipn); lastInstr = ipn; } @@ -661,7 +666,7 @@ protected void emitBoundsCheck(ValueNode index, ValueNode length) { BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); - append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.99)); + append(new IfNode(currentGraph.unique(new IntegerBelowNode(index, length)), trueSucc, falseSucc, 0.99)); lastInstr = trueSucc; BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); @@ -835,8 +840,8 @@ protected void genReturn(ValueNode x) { frameState.setRethrowException(false); frameState.clearStack(); - if (graphBuilderConfig.eagerInfopointMode()) { - append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci()))); + if (graphBuilderConfig.insertNonSafepointDebugInfo()) { + append(createInfoPointNode(InfopointReason.METHOD_END)); } synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x); @@ -1290,10 +1295,10 @@ BytecodesParsed.add(block.endBci - bci); while (bci < endBCI) { - if (graphBuilderConfig.eagerInfopointMode() && lnt != null) { + if (graphBuilderConfig.insertNonSafepointDebugInfo() && lnt != null) { currentLineNumber = lnt.getLineNumber(bci); if (currentLineNumber != previousLineNumber) { - append(new InfopointNode(InfopointReason.LINE_NUMBER, frameState.create(bci))); + append(createInfoPointNode(InfopointReason.LINE_NUMBER)); previousLineNumber = currentLineNumber; } } @@ -1356,6 +1361,14 @@ return instr; } + private InfopointNode createInfoPointNode(InfopointReason reason) { + if (graphBuilderConfig.insertFullDebugInfo()) { + return new FullInfopointNode(reason, frameState.create(bci())); + } else { + return new SimpleInfopointNode(reason, new BytecodePosition(null, method, bci())); + } + } + private void traceState() { if (traceLevel >= TRACELEVEL_STATE && Debug.isLogEnabled()) { Debug.log(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method)); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java Wed Jul 30 10:39:39 2014 -0700 @@ -29,8 +29,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw; -import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx; import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.asm.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FullInfopointOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FullInfopointOp.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,47 @@ +/* + * 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; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits an infopoint (only mark the position). + */ +@Opcode("INFOPOINT") +public class FullInfopointOp extends LIRInstruction { + + @State protected LIRFrameState state; + + private final InfopointReason reason; + + public FullInfopointOp(LIRFrameState state, InfopointReason reason) { + this.state = state; + this.reason = reason; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + crb.recordInfopoint(crb.asm.position(), state, reason); + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java Wed Jul 30 09:36:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +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.lir; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.lir.asm.*; - -/** - * Emits an infopoint (only mark the position). - */ -@Opcode("INFOPOINT") -public class InfopointOp extends LIRInstruction { - - @State protected LIRFrameState state; - - private final InfopointReason reason; - - public InfopointOp(LIRFrameState state, InfopointReason reason) { - this.state = state; - this.reason = reason; - } - - @Override - public void emitCode(CompilationResultBuilder crb) { - crb.recordInfopoint(crb.asm.position(), state, reason); - } -} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,42 @@ +/* + * 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; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.lir.asm.*; + +@Opcode("SIMPLE_INFOPOINT") +public class SimpleInfopointOp extends LIRInstruction { + private final InfopointReason reason; + private final BytecodePosition position; + + public SimpleInfopointOp(InfopointReason reason, BytecodePosition position) { + this.reason = reason; + this.position = position; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + crb.recordInfopoint(crb.asm.position(), new DebugInfo(position, null), reason); + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Wed Jul 30 10:39:39 2014 -0700 @@ -146,6 +146,10 @@ public void recordInfopoint(int pos, LIRFrameState info, InfopointReason reason) { // infopoints always need debug info DebugInfo debugInfo = info.debugInfo(); + recordInfopoint(pos, debugInfo, reason); + } + + public void recordInfopoint(int pos, DebugInfo debugInfo, InfopointReason reason) { compilationResult.recordInfopoint(pos, debugInfo, reason); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java Wed Jul 30 10:39:39 2014 -0700 @@ -51,7 +51,7 @@ AbstractEndNode forwardEnd = loopBegin.forwardEnd(); for (PhiNode phi : loopBegin.phis()) { ValueNode backValue = phi.singleBackValue(); - if (backValue == PhiNode.NO_VALUE) { + if (backValue == PhiNode.MULTIPLE_VALUES) { continue; } ValueNode stride = addSub(backValue, phi); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Wed Jul 30 10:39:39 2014 -0700 @@ -173,7 +173,7 @@ } LogicNode ifTest = ifNode.condition(); if (!(ifTest instanceof IntegerLessThanNode)) { - if (ifTest instanceof IntegerBelowThanNode) { + if (ifTest instanceof IntegerBelowNode) { Debug.log("Ignored potential Counted loop at %s with |<|", loopBegin); } return false; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Wed Jul 30 10:39:39 2014 -0700 @@ -332,7 +332,7 @@ * VirtualState nodes contained in the old exit's state may be shared by other * dominated VirtualStates. Those dominated virtual states need to see the * proxy->phi update that are applied below. - * + * * We now update the original fragment's nodes accordingly: */ originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node)); @@ -345,7 +345,7 @@ } boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode; - for (final ProxyNode vpn : loopEarlyExit.proxies().snapshot()) { + for (ProxyNode vpn : loopEarlyExit.proxies().snapshot()) { if (vpn.usages().isEmpty()) { continue; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Wed Jul 30 10:39:39 2014 -0700 @@ -24,6 +24,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; +import java.util.*; import java.util.function.*; import com.oracle.graal.debug.*; @@ -63,25 +64,27 @@ return loop.loopBegin().unswitches() <= LoopMaxUnswitch.getValue(); } - public static boolean shouldUnswitch(LoopEx loop, ControlSplitNode controlSplit) { - Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator(); - BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null; + public static boolean shouldUnswitch(LoopEx loop, List controlSplits) { int loopTotal = loop.size(); int inBranchTotal = 0; double maxProbability = 0; - for (Node successor : controlSplit.successors()) { - BeginNode branch = (BeginNode) successor; - // this may count twice because of fall-through in switches - inBranchTotal += loop.nodesInLoopFrom(branch, postDom).count(); - double probability = controlSplit.probability(branch); - if (probability > maxProbability) { - maxProbability = probability; + for (ControlSplitNode controlSplit : controlSplits) { + Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator(); + BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null; + for (Node successor : controlSplit.successors()) { + BeginNode branch = (BeginNode) successor; + // this may count twice because of fall-through in switches + inBranchTotal += loop.nodesInLoopFrom(branch, postDom).count(); + double probability = controlSplit.probability(branch); + if (probability > maxProbability) { + maxProbability = probability; + } } } int netDiff = loopTotal - (inBranchTotal); double uncertainty = 1 - maxProbability; int maxDiff = LoopUnswitchMaxIncrease.getValue() + (int) (LoopUnswitchUncertaintyBoost.getValue() * loop.loopBegin().loopFrequency() * uncertainty); - Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of branches", loop, controlSplit, netDiff, maxDiff, (double) (inBranchTotal) / loopTotal * 100); + Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of branches", loop, controlSplits, netDiff, maxDiff, (double) (inBranchTotal) / loopTotal * 100); return netDiff <= maxDiff; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Wed Jul 30 10:39:39 2014 -0700 @@ -24,6 +24,8 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; @@ -71,30 +73,53 @@ } } - public static void unswitch(LoopEx loop, ControlSplitNode controlSplitNode) { + public static void unswitch(LoopEx loop, List controlSplitNodeSet) { + ControlSplitNode firstNode = controlSplitNodeSet.iterator().next(); LoopFragmentWhole originalLoop = loop.whole(); + StructuredGraph graph = firstNode.graph(); + // create new control split out of loop - ControlSplitNode newControlSplit = (ControlSplitNode) controlSplitNode.copyWithInputs(); + ControlSplitNode newControlSplit = (ControlSplitNode) firstNode.copyWithInputs(); originalLoop.entryPoint().replaceAtPredecessor(newControlSplit); - NodeClassIterator successors = controlSplitNode.successors().iterator(); + /* + * The code below assumes that all of the control split nodes have the same successor + * structure, which should have been enforced by findUnswitchable. + */ + NodeClassIterator successors = firstNode.successors().iterator(); assert successors.hasNext(); // original loop is used as first successor Position firstPosition = successors.nextPosition(); - NodeClass controlSplitClass = controlSplitNode.getNodeClass(); - controlSplitClass.set(newControlSplit, firstPosition, BeginNode.begin(originalLoop.entryPoint())); + NodeClass controlSplitClass = firstNode.getNodeClass(); + BeginNode originalLoopBegin = BeginNode.begin(originalLoop.entryPoint()); + controlSplitClass.set(newControlSplit, firstPosition, originalLoopBegin); - StructuredGraph graph = controlSplitNode.graph(); while (successors.hasNext()) { Position position = successors.nextPosition(); - // create a new loop duplicate, connect it and simplify it + // create a new loop duplicate and connect it. LoopFragmentWhole duplicateLoop = originalLoop.duplicate(); - controlSplitClass.set(newControlSplit, position, BeginNode.begin(duplicateLoop.entryPoint())); - ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode); - graph.removeSplitPropagate(duplicatedControlSplit, (BeginNode) controlSplitClass.get(duplicatedControlSplit, position)); + BeginNode newBegin = BeginNode.begin(duplicateLoop.entryPoint()); + controlSplitClass.set(newControlSplit, position, newBegin); + + // For each cloned ControlSplitNode, simplify the proper path + for (ControlSplitNode controlSplitNode : controlSplitNodeSet) { + ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode); + if (duplicatedControlSplit.isAlive()) { + BeginNode survivingSuccessor = (BeginNode) controlSplitClass.get(duplicatedControlSplit, position); + survivingSuccessor.replaceAtUsages(InputType.Guard, newBegin); + graph.removeSplitPropagate(duplicatedControlSplit, survivingSuccessor); + } + } } // original loop is simplified last to avoid deleting controlSplitNode too early - graph.removeSplitPropagate(controlSplitNode, (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition)); + for (ControlSplitNode controlSplitNode : controlSplitNodeSet) { + if (controlSplitNode.isAlive()) { + BeginNode survivingSuccessor = (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition); + survivingSuccessor.replaceAtUsages(InputType.Guard, originalLoopBegin); + graph.removeSplitPropagate(controlSplitNode, survivingSuccessor); + } + } + // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms) } @@ -119,17 +144,36 @@ } } - public static ControlSplitNode findUnswitchable(LoopEx loop) { + public static List findUnswitchable(LoopEx loop) { + List controls = null; + ValueNode invariantValue = null; for (IfNode ifNode : loop.whole().nodes().filter(IfNode.class)) { if (loop.isOutsideLoop(ifNode.condition())) { - return ifNode; + if (controls == null) { + invariantValue = ifNode.condition(); + controls = new ArrayList<>(); + controls.add(ifNode); + } else if (ifNode.condition() == invariantValue) { + controls.add(ifNode); + } } } - for (SwitchNode switchNode : loop.whole().nodes().filter(SwitchNode.class)) { - if (switchNode.successors().count() > 1 && loop.isOutsideLoop(switchNode.value())) { - return switchNode; + if (controls == null) { + SwitchNode firstSwitch = null; + for (SwitchNode switchNode : loop.whole().nodes().filter(SwitchNode.class)) { + if (switchNode.successors().count() > 1 && loop.isOutsideLoop(switchNode.value())) { + if (controls == null) { + firstSwitch = switchNode; + invariantValue = switchNode.value(); + controls = new ArrayList<>(); + controls.add(switchNode); + } else if (switchNode.value() == invariantValue && firstSwitch.equalKeys(switchNode)) { + // Only collect switches which test the same values in the same order + controls.add(switchNode); + } + } } } - return null; + return controls; } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -24,6 +24,8 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; +import java.util.*; + import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.NodeClass.NodeClassIterator; @@ -34,6 +36,7 @@ public class LoopTransformLowPhase extends Phase { private static final DebugMetric UNSWITCHED = Debug.metric("Unswitched"); + private static final DebugMetric UNSWITCH_CANDIDATES = Debug.metric("UnswitchCandidates"); @Override protected void run(StructuredGraph graph) { @@ -56,16 +59,18 @@ final LoopsData dataUnswitch = new LoopsData(graph); for (LoopEx loop : dataUnswitch.loops()) { if (LoopPolicies.shouldTryUnswitch(loop)) { - ControlSplitNode controlSplit = LoopTransformations.findUnswitchable(loop); - if (controlSplit != null && LoopPolicies.shouldUnswitch(loop, controlSplit)) { - if (Debug.isLogEnabled()) { - logUnswitch(loop, controlSplit); + List controlSplits = LoopTransformations.findUnswitchable(loop); + if (controlSplits != null) { + UNSWITCH_CANDIDATES.increment(); + if (LoopPolicies.shouldUnswitch(loop, controlSplits)) { + if (Debug.isLogEnabled()) { + logUnswitch(loop, controlSplits); + } + LoopTransformations.unswitch(loop, controlSplits); + UNSWITCHED.increment(); + unswitched = true; + break; } - LoopTransformations.unswitch(loop, controlSplit); - UNSWITCHED.increment(); - Debug.dump(graph, "After unswitch %s", loop); - unswitched = true; - break; } } } @@ -74,17 +79,20 @@ } } - private static void logUnswitch(LoopEx loop, ControlSplitNode controlSplit) { + private static void logUnswitch(LoopEx loop, List controlSplits) { StringBuilder sb = new StringBuilder("Unswitching "); - sb.append(loop).append(" at ").append(controlSplit).append(" ["); - NodeClassIterator it = controlSplit.successors().iterator(); - while (it.hasNext()) { - sb.append(controlSplit.probability((BeginNode) it.next())); - if (it.hasNext()) { - sb.append(", "); + sb.append(loop).append(" at "); + for (ControlSplitNode controlSplit : controlSplits) { + sb.append(controlSplit).append(" ["); + NodeClassIterator it = controlSplit.successors().iterator(); + while (it.hasNext()) { + sb.append(controlSplit.probability((BeginNode) it.next())); + if (it.hasNext()) { + sb.append(", "); + } } + sb.append("]"); } - sb.append("]"); Debug.log("%s", sb); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -38,16 +38,6 @@ 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; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -24,22 +24,39 @@ 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.spi.*; @NodeInfo(allowedUsageTypes = {InputType.Extension}) public abstract class CallTargetNode extends ValueNode implements LIRLowerable { + public enum InvokeKind { + Interface, + Special, + Static, + Virtual; + + public boolean hasReceiver() { + return this != Static; + } + } @Input private final NodeInputList arguments; + private ResolvedJavaMethod targetMethod; + private InvokeKind invokeKind; - public CallTargetNode(ValueNode[] arguments) { + public CallTargetNode(ValueNode[] arguments, ResolvedJavaMethod targetMethod, InvokeKind invokeKind) { super(StampFactory.forVoid()); + this.targetMethod = targetMethod; + this.invokeKind = invokeKind; this.arguments = new NodeInputList<>(this, arguments); } - public CallTargetNode(List arguments) { + public CallTargetNode(List arguments, ResolvedJavaMethod targetMethod, InvokeKind invokeKind) { super(StampFactory.forVoid()); + this.targetMethod = targetMethod; + this.invokeKind = invokeKind; this.arguments = new NodeInputList<>(this, arguments); } @@ -58,4 +75,25 @@ public void generate(NodeLIRBuilderTool gen) { // nop } + + public void setTargetMethod(ResolvedJavaMethod method) { + targetMethod = method; + } + + /** + * Gets the target method for this invocation instruction. + * + * @return the target method + */ + public ResolvedJavaMethod targetMethod() { + return targetMethod; + } + + public InvokeKind invokeKind() { + return invokeKind; + } + + public void setInvokeKind(InvokeKind kind) { + this.invokeKind = kind; + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -36,6 +36,4 @@ } public abstract double probability(BeginNode successor); - - public abstract void setProbability(BeginNode successor, double value); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -30,12 +30,12 @@ public class DirectCallTargetNode extends LoweredCallTargetNode { - public DirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType) { - super(arguments, returnStamp, signature, target, callType); + public DirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { + super(arguments, returnStamp, signature, target, callType, invokeKind); } @Override public String targetName() { - return target().format("Direct#%h.%n"); + return targetMethod().format("Direct#%h.%n"); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Jul 30 10:39:39 2014 -0700 @@ -86,9 +86,10 @@ * @param monitorIds one MonitorIdNode for each locked object * @param virtualObjectMappings a description of the current state for every virtual object */ - public FrameState(ResolvedJavaMethod method, int bci, List values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall, List monitorIds, - List virtualObjectMappings) { + public FrameState(FrameState outerFrameState, ResolvedJavaMethod method, int bci, List values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall, + List monitorIds, List virtualObjectMappings) { assert stackSize >= 0; + this.outerFrameState = outerFrameState; this.method = method; this.bci = bci; this.localsSize = localsSize; @@ -109,13 +110,13 @@ * @param bci marker bci, needs to be < 0 */ public FrameState(int bci) { - this(null, bci, Collections. emptyList(), 0, 0, false, false, Collections. emptyList(), Collections. emptyList()); + this(null, null, bci, Collections. emptyList(), 0, 0, false, false, Collections. emptyList(), Collections. emptyList()); 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 stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, boolean duringCall) { - this(method, bci, createValues(locals, stack, locks), locals.length, stack.size(), rethrowException, duringCall, Arrays.asList(monitorIds), Collections. emptyList()); + this(null, method, bci, createValues(locals, stack, locks), locals.length, stack.size(), rethrowException, duringCall, Arrays.asList(monitorIds), Collections. emptyList()); } private static List createValues(ValueNode[] locals, List stack, ValueNode[] locks) { @@ -139,6 +140,10 @@ return values; } + public NodeInputList monitorIds() { + return monitorIds; + } + public FrameState outerFrameState() { return outerFrameState; } @@ -187,9 +192,7 @@ * Gets a copy of this frame state. */ public FrameState duplicate(int newBci) { - FrameState other = graph().add(new FrameState(method, newBci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings)); - other.setOuterFrameState(outerFrameState()); - return other; + return graph().add(new FrameState(outerFrameState(), method, newBci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, virtualObjectMappings)); } /** @@ -213,9 +216,7 @@ for (EscapeObjectState state : virtualObjectMappings) { newVirtualMappings.add(state.duplicateWithVirtualState()); } - FrameState other = graph().add(new FrameState(method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, newVirtualMappings)); - other.setOuterFrameState(newOuterFrameState); - return other; + return graph().add(new FrameState(newOuterFrameState, method, bci, values, localsSize, stackSize, rethrowException, duringCall, monitorIds, newVirtualMappings)); } /** @@ -255,9 +256,7 @@ int newStackSize = copy.size() - localsSize; copy.addAll(values.subList(localsSize + stackSize, values.size())); - FrameState other = graph().add(new FrameState(newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings)); - other.setOuterFrameState(outerFrameState()); - return other; + return graph().add(new FrameState(outerFrameState(), newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings)); } /** diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FullInfopointNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,54 @@ +/* + * 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; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Nodes of this type are inserted into the graph to denote points of interest to debugging. + */ +public class FullInfopointNode extends InfopointNode implements LIRLowerable, NodeWithState { + @Input(InputType.State) private FrameState state; + + public FullInfopointNode(InfopointReason reason, FrameState state) { + super(reason); + this.state = state; + } + + @Override + public void generate(NodeLIRBuilderTool generator) { + generator.visitFullInfopointNode(this); + } + + public FrameState getState() { + return state; + } + + @Override + public boolean verify() { + return state != null && super.verify(); + } + +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -32,10 +32,16 @@ @NodeInfo(nameTemplate = "GuardPhi({i#values})", allowedUsageTypes = {InputType.Guard}) public class GuardPhiNode extends PhiNode implements GuardingNode { - @OptionalInput(InputType.Guard) final NodeInputList values = new NodeInputList<>(this); + @OptionalInput(InputType.Guard) final NodeInputList values; public GuardPhiNode(MergeNode merge) { super(StampFactory.forVoid(), merge); + this.values = new NodeInputList<>(this); + } + + public GuardPhiNode(MergeNode merge, ValueNode[] values) { + super(StampFactory.forVoid(), merge); + this.values = new NodeInputList<>(this, values); } @Override diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -121,12 +121,6 @@ } @Override - public void setProbability(BeginNode successor, double value) { - assert successor == trueSuccessor || successor == falseSuccessor; - setTrueSuccessorProbability(successor == trueSuccessor ? value : 1 - value); - } - - @Override public void generate(NodeLIRBuilderTool gen) { gen.emitIf(this); } @@ -265,14 +259,14 @@ IntegerLessThanNode lessThan2 = (IntegerLessThanNode) ifNode2.condition(); BeginNode falseSucc = ifNode2.falseSuccessor(); BeginNode trueSucc = ifNode2.trueSuccessor(); - IntegerBelowThanNode below = null; + IntegerBelowNode below = null; /* * Convert x >= 0 && x < positive which is represented as !(x < 0) && x < * into an unsigned compare. */ if (lessThan2.getX() == lessThan.getX() && lessThan2.getY().stamp() instanceof IntegerStamp && ((IntegerStamp) lessThan2.getY().stamp()).isPositive() && sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) { - below = graph().unique(new IntegerBelowThanNode(lessThan2.getX(), lessThan2.getY())); + below = graph().unique(new IntegerBelowNode(lessThan2.getX(), lessThan2.getY())); // swap direction BeginNode tmp = falseSucc; falseSucc = trueSucc; @@ -287,7 +281,7 @@ Constant positive = lessThan2.getX().asConstant(); if (positive != null && positive.asLong() > 0 && positive.asLong() < positive.getKind().getMaxValue()) { ConstantNode newLimit = ConstantNode.forIntegerKind(positive.getKind(), positive.asLong() + 1, graph()); - below = graph().unique(new IntegerBelowThanNode(lessThan.getX(), newLimit)); + below = graph().unique(new IntegerBelowNode(lessThan.getX(), newLimit)); } } if (below != null) { @@ -485,24 +479,32 @@ AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next(); MergeNode merge = trueEnd.merge(); if (merge == falseEnd.merge() && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) { - Iterator phis = merge.phis().iterator(); - if (!phis.hasNext()) { + PhiNode singlePhi = null; + int distinct = 0; + for (PhiNode phi : merge.phis()) { + ValueNode trueValue = phi.valueAt(trueEnd); + ValueNode falseValue = phi.valueAt(falseEnd); + if (trueValue != falseValue) { + distinct++; + singlePhi = phi; + } + } + if (distinct == 0) { + /* + * Multiple phis but merging same values for true and false, so simply delete + * the path + */ tool.addToWorkList(condition()); removeThroughFalseBranch(tool); return true; - } else { - PhiNode singlePhi = phis.next(); - if (!phis.hasNext()) { - // one phi at the merge of an otherwise empty if construct: try to convert - // into a MaterializeNode - ValueNode trueValue = singlePhi.valueAt(trueEnd); - ValueNode falseValue = singlePhi.valueAt(falseEnd); - ConditionalNode conditional = canonicalizeConditionalCascade(trueValue, falseValue); - if (conditional != null) { - singlePhi.setValueAt(trueEnd, conditional); - removeThroughFalseBranch(tool); - return true; - } + } else if (distinct == 1) { + ValueNode trueValue = singlePhi.valueAt(trueEnd); + ValueNode falseValue = singlePhi.valueAt(falseEnd); + ConditionalNode conditional = canonicalizeConditionalCascade(trueValue, falseValue); + if (conditional != null) { + singlePhi.setValueAt(trueEnd, conditional); + removeThroughFalseBranch(tool); + return true; } } } @@ -512,14 +514,18 @@ ReturnNode falseEnd = (ReturnNode) falseSuccessor().next(); ValueNode trueValue = trueEnd.result(); ValueNode falseValue = falseEnd.result(); - ConditionalNode conditional = null; + ValueNode value = null; if (trueValue != null) { - conditional = canonicalizeConditionalCascade(trueValue, falseValue); - if (conditional == null) { - return false; + if (trueValue == falseValue) { + value = trueValue; + } else { + value = canonicalizeConditionalCascade(trueValue, falseValue); + if (value == null) { + return false; + } } } - ReturnNode newReturn = graph().add(new ReturnNode(conditional)); + ReturnNode newReturn = graph().add(new ReturnNode(value)); replaceAtPredecessor(newReturn); GraphUtil.killCFG(this); return true; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -32,8 +32,9 @@ @Input private ValueNode computedAddress; - public IndirectCallTargetNode(ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType) { - super(arguments, returnStamp, signature, target, callType); + public IndirectCallTargetNode(ValueNode computedAddress, List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, + InvokeKind invokeKind) { + super(arguments, returnStamp, signature, target, callType, invokeKind); this.computedAddress = computedAddress; } @@ -43,6 +44,6 @@ @Override public String targetName() { - return target().format("Indirect#%h.%n"); + return targetMethod().format("Indirect#%h.%n"); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,35 +24,16 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.spi.*; -/** - * Nodes of this type are inserted into the graph to denote points of interest to debugging. - */ -public class InfopointNode extends FixedWithNextNode implements LIRLowerable, NodeWithState { +public abstract class InfopointNode extends FixedWithNextNode { + private final InfopointReason reason; - public final InfopointReason reason; - @Input(InputType.State) private FrameState state; - - public InfopointNode(InfopointReason reason, FrameState state) { + public InfopointNode(InfopointReason reason) { super(StampFactory.forVoid()); this.reason = reason; - this.state = state; - } - - @Override - public void generate(NodeLIRBuilderTool generator) { - generator.visitInfopointNode(this); } - public FrameState getState() { - return state; + public InfopointReason getReason() { + return reason; } - - @Override - public boolean verify() { - return state != null && super.verify(); - } - } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Wed Jul 30 10:39:39 2014 -0700 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.CallTargetNode.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -89,6 +90,7 @@ } default ValueNode getReceiver() { + assert getInvokeKind().hasReceiver(); return callTarget().arguments().get(0); } @@ -99,4 +101,8 @@ } return receiverType; } + + default InvokeKind getInvokeKind() { + return callTarget().invokeKind(); + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -201,12 +201,6 @@ } @Override - public void setProbability(BeginNode successor, double value) { - assert successor == next || successor == exceptionEdge; - this.exceptionProbability = successor == next ? 1 - value : value; - } - - @Override public boolean canDeoptimize() { return true; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -32,14 +32,12 @@ private final Stamp returnStamp; private final JavaType[] signature; - private final ResolvedJavaMethod target; private final CallingConvention.Type callType; - public LoweredCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType) { - super(arguments); + public LoweredCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType, InvokeKind invokeKind) { + super(arguments, target, invokeKind); this.returnStamp = returnStamp; this.signature = signature; - this.target = target; this.callType = callType; } @@ -52,10 +50,6 @@ return signature; } - public ResolvedJavaMethod target() { - return target; - } - public CallingConvention.Type callType() { return callType; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -33,12 +33,19 @@ @NodeInfo(nameTemplate = "MemoryPhi({i#values}) {p#locationIdentity/s}", allowedUsageTypes = {InputType.Memory}) public class MemoryPhiNode extends PhiNode implements MemoryNode { - @Input(InputType.Memory) final NodeInputList values = new NodeInputList<>(this); + @Input(InputType.Memory) final NodeInputList values; private final LocationIdentity locationIdentity; public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity) { super(StampFactory.forVoid(), merge); this.locationIdentity = locationIdentity; + this.values = new NodeInputList<>(this); + } + + public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) { + super(StampFactory.forVoid(), merge); + this.locationIdentity = locationIdentity; + this.values = new NodeInputList<>(this, values); } public LocationIdentity getLocationIdentity() { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -137,10 +137,15 @@ values().remove(index); } - public static final ValueNode NO_VALUE = new ValueNode(null) { + public static final ValueNode MULTIPLE_VALUES = new ValueNode(null) { // empty dummy class }; + /** + * If all inputs are the same value, this value is returned, otherwise {@link #MULTIPLE_VALUES}. + * Note that {@code null} is a valid return value, since {@link GuardPhiNode}s can have + * {@code null} inputs. + */ public ValueNode singleValue() { Iterator iterator = values().iterator(); ValueNode singleValue = iterator.next(); @@ -148,13 +153,18 @@ ValueNode value = iterator.next(); if (value != this) { if (value != singleValue) { - return NO_VALUE; + return MULTIPLE_VALUES; } } } return singleValue; } + /** + * If all inputs (but the first one) are the same value, this value is returned, otherwise + * {@link #MULTIPLE_VALUES}. Note that {@code null} is a valid return value, since + * {@link GuardPhiNode}s can have {@code null} inputs. + */ public ValueNode singleBackValue() { assert merge() instanceof LoopBeginNode; Iterator iterator = values().iterator(); @@ -162,7 +172,7 @@ ValueNode singleValue = iterator.next(); while (iterator.hasNext()) { if (iterator.next() != singleValue) { - return NO_VALUE; + return MULTIPLE_VALUES; } } return singleValue; @@ -172,7 +182,7 @@ public void simplify(SimplifierTool tool) { ValueNode singleValue = singleValue(); - if (singleValue != NO_VALUE) { + if (singleValue != MULTIPLE_VALUES) { for (Node node : usages().snapshot()) { if (node instanceof ProxyNode && ((ProxyNode) node).proxyPoint() instanceof LoopExitNode && ((LoopExitNode) ((ProxyNode) node).proxyPoint()).loopBegin() == merge) { tool.addToWorkList(node.usages()); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.spi.*; + +public class SimpleInfopointNode extends InfopointNode implements LIRLowerable, IterableNodeType { + private BytecodePosition position; + + public SimpleInfopointNode(InfopointReason reason, BytecodePosition position) { + super(reason); + this.position = position; + } + + @Override + public void generate(NodeLIRBuilderTool generator) { + generator.visitSimpleInfopointNode(this); + } + + public BytecodePosition getPosition() { + return position; + } + + public void addCaller(BytecodePosition caller) { + this.position = relink(this.position, caller); + } + + private static BytecodePosition relink(BytecodePosition position, BytecodePosition link) { + if (position.getCaller() == null) { + return new BytecodePosition(link, position.getMethod(), position.getBCI()); + } else { + return new BytecodePosition(relink(position.getCaller(), link), position.getMethod(), position.getBCI()); + } + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -166,7 +166,7 @@ } else { assert condition == Condition.BT; assert x.getKind().isNumericInteger(); - comparison = new IntegerBelowThanNode(x, y); + comparison = new IntegerBelowNode(x, y); } return comparison; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -50,7 +50,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { if (forX.isConstant() && forY.isConstant()) { - return ConstantNode.forPrimitive(evalConst(getX().asConstant(), getY().asConstant())); + return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); } return this; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,87 @@ +/* + * 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.calc; + +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.util.*; + +@NodeInfo(shortName = "|<|") +public final class IntegerBelowNode 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 + */ + public IntegerBelowNode(ValueNode x, ValueNode y) { + super(x, y); + assert x.stamp() instanceof IntegerStamp; + assert y.stamp() instanceof IntegerStamp; + } + + @Override + public Condition condition() { + return Condition.BT; + } + + @Override + public boolean unorderedIsTrue() { + return false; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode result = super.canonical(tool, forX, forY); + if (result != this) { + return result; + } + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return LogicConstantNode.contradiction(); + } 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 LogicConstantNode.tautology(); + } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { + return LogicConstantNode.contradiction(); + } + } + } + if (forX.isConstant() && forX.asConstant().asLong() == 0) { + // 0 |<| y is the same as 0 != y + return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY)); + } + return this; + } + + @Override + protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { + return new IntegerBelowNode(newX, newY); + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Wed Jul 30 09:36:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +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.calc; - -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.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 - */ - public IntegerBelowThanNode(ValueNode x, ValueNode y) { - super(x, y); - assert x.stamp() instanceof IntegerStamp; - assert y.stamp() instanceof IntegerStamp; - } - - @Override - public Condition condition() { - return Condition.BT; - } - - @Override - public boolean unorderedIsTrue() { - return false; - } - - @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode result = super.canonical(tool, forX, forY); - if (result != this) { - return result; - } - if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return LogicConstantNode.contradiction(); - } 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 LogicConstantNode.tautology(); - } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { - return LogicConstantNode.contradiction(); - } - } - } - if (forX.isConstant() && forX.asConstant().asLong() == 0) { - // 0 |<| y is the same as 0 != y - return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY)); - } - return this; - } - - @Override - protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { - return new IntegerBelowThanNode(newX, newY); - } -} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -91,7 +91,7 @@ } if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) { - return new IntegerBelowThanNode(forX, forY); + return new IntegerBelowNode(forX, forY); } } return this; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -29,6 +29,7 @@ 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 { @@ -38,6 +39,11 @@ } @Override + public boolean inferStamp() { + return updateStamp(StampTool.rightShift(getX().stamp(), getY().stamp())); + } + + @Override public Constant evalConst(Constant... inputs) { assert inputs.length == 2; if (getKind() == Kind.Int) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Wed Jul 30 10:39:39 2014 -0700 @@ -31,6 +31,12 @@ import com.oracle.graal.nodes.*; public class ControlFlowGraph implements AbstractControlFlowGraph { + /** + * Don't allow probability values to be become too small as this makes frequency calculations + * large enough that they can overflow the range of a double. This commonly happens with + * infinite loops within infinite loops. + */ + public static final double MIN_PROBABILITY = 0.000001; public final StructuredGraph graph; @@ -221,8 +227,8 @@ } } } - if (probability > 1. / Double.MIN_NORMAL) { - probability = 1. / Double.MIN_NORMAL; + if (probability > 1. / MIN_PROBABILITY) { + probability = 1. / MIN_PROBABILITY; } block.setPredecessors(predecessors); block.setProbability(probability); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -73,6 +73,12 @@ this.initialization = initialization; } + public AbstractWriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) { + super(object, location, StampFactory.forVoid(), guard, barrierType, false, null); + this.value = value; + this.initialization = initialization; + } + @Override public boolean isAllowedUsageType(InputType type) { return (type == InputType.Guard && getNullCheck()) ? true : super.isAllowedUsageType(type); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -42,7 +42,7 @@ /** * Constructs a integer switch instruction. The keyProbabilities and keySuccessors array contain * key.length + 1 entries, the last entry describes the default (fall through) case. - * + * * @param value the instruction producing the value being switched on * @param successors the list of successors * @param keys the sorted list of keys @@ -68,7 +68,7 @@ /** * Constructs a integer switch instruction. The keyProbabilities and keySuccessors array contain * key.length + 1 entries, the last entry describes the default (fall through) case. - * + * * @param value the instruction producing the value being switched on * @param successorCount the number of successors * @param keys the sorted list of keys @@ -86,7 +86,7 @@ /** * Gets the key at the specified index. - * + * * @param i the index * @return the key at that index */ @@ -101,6 +101,15 @@ } @Override + public boolean equalKeys(SwitchNode switchNode) { + if (!(switchNode instanceof IntegerSwitchNode)) { + return false; + } + IntegerSwitchNode other = (IntegerSwitchNode) switchNode; + return Arrays.equals(keys, other.keys); + } + + @Override public void generate(NodeLIRBuilderTool gen) { gen.emitSwitch(this); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -33,7 +33,7 @@ * Loads an object's {@linkplain Representation#ObjectHub hub}. The object is not null-checked by * this operation. */ -public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable.Unary, Virtualizable { +public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable { @Input private ValueNode value; @@ -62,10 +62,10 @@ } @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) { + public ValueNode canonical(CanonicalizerTool tool) { MetaAccessProvider metaAccess = tool.getMetaAccess(); - if (metaAccess != null && forObject.stamp() instanceof ObjectStamp) { - ObjectStamp stamp = (ObjectStamp) forObject.stamp(); + if (metaAccess != null && getValue().stamp() instanceof ObjectStamp) { + ObjectStamp stamp = (ObjectStamp) getValue().stamp(); ResolvedJavaType exactType; if (stamp.isExactType()) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -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 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import java.util.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; @@ -37,12 +35,14 @@ @Successor private final NodeSuccessorList successors; @Input private ValueNode value; - private double[] keyProbabilities; - private int[] keySuccessors; + + // do not change the contents of these arrays: + private final double[] keyProbabilities; + private final int[] keySuccessors; /** * Constructs a new Switch. - * + * * @param value the instruction that provides the value to be switched over * @param successors the list of successors of this switch */ @@ -87,33 +87,6 @@ return sum; } - @Override - public void setProbability(BeginNode successor, double value) { - double changeInProbability = 0; - int nonZeroProbabilityCases = 0; - for (int i = 0; i < keySuccessors.length; i++) { - if (successors.get(keySuccessors[i]) == successor) { - changeInProbability += keyProbabilities[i] - value; - keyProbabilities[i] = value; - } else if (keyProbabilities[i] > 0) { - nonZeroProbabilityCases++; - } - } - - if (nonZeroProbabilityCases > 0) { - double changePerEntry = changeInProbability / nonZeroProbabilityCases; - if (changePerEntry != 0) { - for (int i = 0; i < keyProbabilities.length; i++) { - if (keyProbabilities[i] > 0) { - keyProbabilities[i] = keyProbabilities[i] + changePerEntry; - } - } - } - } - - assertProbabilities(); - } - public ValueNode value() { return value; } @@ -131,6 +104,11 @@ public abstract Constant keyAt(int i); /** + * Returns true if the switch has the same keys in the same order as this switch. + */ + public abstract boolean equalKeys(SwitchNode switchNode); + + /** * Returns the index of the successor belonging to the key at the specified index. */ public int keySuccessorIndex(int i) { @@ -172,7 +150,7 @@ /** * Gets the successor corresponding to the default (fall through) case. - * + * * @return the default successor */ public BeginNode defaultSuccessor() { @@ -181,11 +159,4 @@ } return defaultSuccessorIndex() == -1 ? null : successors.get(defaultSuccessorIndex()); } - - @Override - public void afterClone(Node other) { - SwitchNode oldSwitch = (SwitchNode) other; - keyProbabilities = Arrays.copyOf(oldSwitch.keyProbabilities, oldSwitch.keyProbabilities.length); - keySuccessors = Arrays.copyOf(oldSwitch.keySuccessors, oldSwitch.keySuccessors.length); - } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -42,6 +42,10 @@ super(object, value, location, barrierType, initialization); } + public WriteNode(ValueNode object, ValueNode value, ValueNode location, BarrierType barrierType, GuardingNode guard, boolean initialization) { + super(object, value, location, barrierType, guard, initialization); + } + @Override public void generate(NodeLIRBuilderTool gen) { Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -54,7 +54,7 @@ */ LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) predecessor()).getLocationIdentity(); BeginNode entry = graph().add(new KillingBeginNode(locationsKilledByInvoke)); - LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(StampFactory.declaredNonNull(tool.getMetaAccess().lookupJavaType(Throwable.class)))); + LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp())); loadException.setStateAfter(stateAfter()); replaceAtUsages(InputType.Value, loadException); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -30,47 +30,14 @@ import com.oracle.graal.nodes.type.*; public class MethodCallTargetNode extends CallTargetNode implements IterableNodeType, Canonicalizable { - - public enum InvokeKind { - Interface, - Special, - Static, - Virtual - } - private final JavaType returnType; - private ResolvedJavaMethod targetMethod; - private InvokeKind invokeKind; /** * @param arguments */ public MethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType) { - super(arguments); - this.invokeKind = invokeKind; + super(arguments, targetMethod, invokeKind); this.returnType = returnType; - this.targetMethod = targetMethod; - } - - /** - * Gets the target method for this invocation instruction. - * - * @return the target method - */ - public ResolvedJavaMethod targetMethod() { - return targetMethod; - } - - public InvokeKind invokeKind() { - return invokeKind; - } - - public void setInvokeKind(InvokeKind kind) { - this.invokeKind = kind; - } - - public void setTargetMethod(ResolvedJavaMethod method) { - targetMethod = method; } /** @@ -106,13 +73,13 @@ for (Node n : usages()) { assertTrue(n instanceof Invoke, "call target can only be used from an invoke (%s)", n); } - if (invokeKind == InvokeKind.Special || invokeKind == InvokeKind.Static) { - assertFalse(targetMethod.isAbstract(), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod); + if (invokeKind() == InvokeKind.Special || invokeKind() == InvokeKind.Static) { + assertFalse(targetMethod().isAbstract(), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod()); } - if (invokeKind == InvokeKind.Static) { - assertTrue(targetMethod.isStatic(), "static calls are only allowed for static methods (%s)", targetMethod); + if (invokeKind() == InvokeKind.Static) { + assertTrue(targetMethod().isStatic(), "static calls are only allowed for static methods (%s)", targetMethod()); } else { - assertFalse(targetMethod.isStatic(), "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(); } @@ -128,12 +95,12 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) { + if (invokeKind() == InvokeKind.Interface || invokeKind() == InvokeKind.Virtual) { // attempt to devirtualize the call // check for trivial cases (e.g. final methods, nonvirtual methods) - if (targetMethod.canBeStaticallyBound()) { - invokeKind = InvokeKind.Special; + if (targetMethod().canBeStaticallyBound()) { + setInvokeKind(InvokeKind.Special); return this; } @@ -145,29 +112,29 @@ * either the holder class is exact, or the receiver object has an exact type, or * it's an array type */ - ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod, invoke().getContextType()); + ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod(), invoke().getContextType()); if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) { - invokeKind = InvokeKind.Special; - targetMethod = resolvedMethod; + setInvokeKind(InvokeKind.Special); + setTargetMethod(resolvedMethod); return this; } if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); if (uniqueConcreteType != null) { - ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveMethod(targetMethod, invoke().getContextType()); + ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveMethod(targetMethod(), invoke().getContextType()); if (methodFromUniqueType != null) { tool.assumptions().recordConcreteSubtype(type, uniqueConcreteType); - invokeKind = InvokeKind.Special; - targetMethod = methodFromUniqueType; + setInvokeKind(InvokeKind.Special); + setTargetMethod(methodFromUniqueType); return this; } } - ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod); + ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod()); if (uniqueConcreteMethod != null) { - tool.assumptions().recordConcreteMethod(targetMethod, type, uniqueConcreteMethod); - invokeKind = InvokeKind.Special; - targetMethod = uniqueConcreteMethod; + tool.assumptions().recordConcreteMethod(targetMethod(), type, uniqueConcreteMethod); + setInvokeKind(InvokeKind.Special); + setTargetMethod(uniqueConcreteMethod); return this; } } @@ -178,7 +145,7 @@ @Override public Stamp returnStamp() { - Kind returnKind = targetMethod.getSignature().getReturnKind(); + Kind returnKind = targetMethod().getSignature().getReturnKind(); if (returnKind == Kind.Object && returnType instanceof ResolvedJavaType) { return StampFactory.declared((ResolvedJavaType) returnType); } else { @@ -200,7 +167,7 @@ public static MethodCallTargetNode find(StructuredGraph graph, ResolvedJavaMethod method) { for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.class)) { - if (target.targetMethod.equals(method)) { + if (target.targetMethod().equals(method)) { return target; } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -44,7 +44,7 @@ /** * Constructs a type switch instruction. The keyProbabilities array contain key.length + 1 * entries. The last entry in every array describes the default case. - * + * * @param value the instruction producing the value being switched on, the object hub * @param successors the list of successors * @param keys the list of types @@ -57,6 +57,21 @@ assert keySuccessors.length == keyProbabilities.length; this.keys = keys; assert assertValues(); + assert assertKeys(); + } + + /** + * Don't allow duplicate keys + */ + private boolean assertKeys() { + for (int i = 0; i < keys.length; i++) { + for (int j = 0; j < keys.length; j++) { + if (i == j) + continue; + assert !keys[i].equals(keys[j]); + } + } + return true; } @Override @@ -87,6 +102,15 @@ return keys[index].getEncoding(Representation.ObjectHub); } + @Override + public boolean equalKeys(SwitchNode switchNode) { + if (!(switchNode instanceof TypeSwitchNode)) { + return false; + } + TypeSwitchNode other = (TypeSwitchNode) switchNode; + return Arrays.equals(keys, other.keys); + } + public ResolvedJavaType typeAt(int index) { return keys[index]; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java Wed Jul 30 10:39:39 2014 -0700 @@ -60,7 +60,9 @@ void visitBreakpointNode(BreakpointNode i); - void visitInfopointNode(InfopointNode i); + void visitFullInfopointNode(FullInfopointNode i); + + void visitSimpleInfopointNode(SimpleInfopointNode i); LIRGeneratorTool getLIRGeneratorTool(); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Wed Jul 30 10:39:39 2014 -0700 @@ -252,6 +252,29 @@ return stampForMask(stamp1.getBits(), newDownMask, newUpMask); } + public static Stamp rightShift(Stamp value, Stamp shift) { + if (value instanceof IntegerStamp && shift instanceof IntegerStamp) { + return rightShift((IntegerStamp) value, (IntegerStamp) shift); + } + return value.illegal(); + } + + public static Stamp rightShift(IntegerStamp value, IntegerStamp shift) { + int bits = value.getBits(); + if (shift.lowerBound() == shift.upperBound()) { + int extraBits = 64 - bits; + long shiftMask = bits > 32 ? 0x3FL : 0x1FL; + long shiftCount = shift.lowerBound() & shiftMask; + long defaultMask = IntegerStamp.defaultMask(bits); + // shifting back and forth performs sign extension + long downMask = (value.downMask() << extraBits) >> (shiftCount + extraBits) & defaultMask; + long upMask = (value.upMask() << extraBits) >> (shiftCount + extraBits) & defaultMask; + return new IntegerStamp(bits, value.lowerBound() >> shiftCount, value.upperBound() >> shiftCount, downMask, upMask); + } + long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); + return stampForMask(bits, 0, mask); + } + public static Stamp unsignedRightShift(Stamp value, Stamp shift) { if (value instanceof IntegerStamp && shift instanceof IntegerStamp) { return unsignedRightShift((IntegerStamp) value, (IntegerStamp) shift); @@ -264,19 +287,12 @@ if (shift.lowerBound() == shift.upperBound()) { long shiftMask = bits > 32 ? 0x3FL : 0x1FL; long shiftCount = shift.lowerBound() & shiftMask; - if (shiftCount != 0) { - long lowerBound; - long upperBound; - long downMask = value.downMask() >>> shiftCount; - long upMask = value.upMask() >>> shiftCount; - if (value.lowerBound() < 0) { - lowerBound = downMask; - upperBound = upMask; - } else { - lowerBound = value.lowerBound() >>> shiftCount; - upperBound = value.upperBound() >>> shiftCount; - } - return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask); + long downMask = value.downMask() >>> shiftCount; + long upMask = value.upMask() >>> shiftCount; + if (value.lowerBound() < 0) { + return new IntegerStamp(bits, downMask, upMask, downMask, upMask); + } else { + return new IntegerStamp(bits, value.lowerBound() >>> shiftCount, value.upperBound() >>> shiftCount, downMask, upMask); } } long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Wed Jul 30 10:39:39 2014 -0700 @@ -174,7 +174,7 @@ } ValueNode singleValue = phiNode.singleValue(); - if (singleValue != PhiNode.NO_VALUE) { + if (singleValue != PhiNode.MULTIPLE_VALUES) { Collection phiUsages = phiNode.usages().filter(PhiNode.class).snapshot(); Collection proxyUsages = phiNode.usages().filter(ProxyNode.class).snapshot(); phiNode.graph().replaceFloating(phiNode, singleValue); @@ -343,7 +343,7 @@ v = ((ValueProxy) v).getOriginalNode(); } else if (v instanceof PhiNode) { v = ((PhiNode) v).singleValue(); - if (v == PhiNode.NO_VALUE) { + if (v == PhiNode.MULTIPLE_VALUES) { v = null; } } else { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -49,9 +49,15 @@ private final boolean canonicalizeReads; private final CustomCanonicalizer customCanonicalizer; - public interface CustomCanonicalizer { + public static abstract class CustomCanonicalizer { - Node canonicalize(Node node); + public Node canonicalize(Node node) { + return node; + } + + @SuppressWarnings("unused") + public void simplify(Node node, SimplifierTool tool) { + } } public CanonicalizerPhase(boolean canonicalizeReads) { @@ -88,19 +94,19 @@ * @param workingSet the initial working set of nodes on which the canonicalizer works, should * be an auto-grow node bitmap */ - public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet) { + public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet) { applyIncremental(graph, context, workingSet, true); } - public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, boolean dumpGraph) { + public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, boolean dumpGraph) { new Instance(context, canonicalizeReads, workingSet, customCanonicalizer).apply(graph, dumpGraph); } - public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, Mark newNodesMark) { + public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, Mark newNodesMark) { applyIncremental(graph, context, workingSet, newNodesMark, true); } - public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, Mark newNodesMark, boolean dumpGraph) { + public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, Mark newNodesMark, boolean dumpGraph) { new Instance(context, canonicalizeReads, workingSet, newNodesMark, customCanonicalizer).apply(graph, dumpGraph); } @@ -109,7 +115,7 @@ private final Mark newNodesMark; private final PhaseContext context; private final CustomCanonicalizer customCanonicalizer; - private final Iterable initWorkingSet; + private final Iterable initWorkingSet; private final boolean canonicalizeReads; private NodeWorkList workList; @@ -119,7 +125,7 @@ this(context, canonicalizeReads, null, null, customCanonicalizer); } - private Instance(PhaseContext context, boolean canonicalizeReads, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { + private Instance(PhaseContext context, boolean canonicalizeReads, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { this(context, canonicalizeReads, workingSet, null, customCanonicalizer); } @@ -127,7 +133,7 @@ this(context, canonicalizeReads, null, newNodesMark, customCanonicalizer); } - private Instance(PhaseContext context, boolean canonicalizeReads, Iterable workingSet, Mark newNodesMark, CustomCanonicalizer customCanonicalizer) { + private Instance(PhaseContext context, boolean canonicalizeReads, Iterable workingSet, Mark newNodesMark, CustomCanonicalizer customCanonicalizer) { super("Canonicalizer"); this.newNodesMark = newNodesMark; this.context = context; @@ -225,6 +231,9 @@ if (!result && customCanonicalizer != null) { Node canonical = customCanonicalizer.canonicalize(node); result = performReplacement(node, canonical); + if (!result) { + customCanonicalizer.simplify(node, tool); + } } return result; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CleanTypeProfileProxyPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -22,15 +22,30 @@ */ package com.oracle.graal.phases.common; +import com.oracle.graal.graph.Graph.NodeEventScope; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.util.*; +import com.oracle.graal.phases.tiers.*; -public class CleanTypeProfileProxyPhase extends Phase { +public class CleanTypeProfileProxyPhase extends BasePhase { + + private CanonicalizerPhase canonicalizer; + + public CleanTypeProfileProxyPhase(CanonicalizerPhase canonicalizer) { + this.canonicalizer = canonicalizer; + } @Override - protected void run(StructuredGraph graph) { - for (TypeProfileProxyNode proxy : graph.getNodes(TypeProfileProxyNode.class)) { - graph.replaceFloating(proxy, proxy.getValue()); + protected void run(StructuredGraph graph, PhaseContext context) { + HashSetNodeEventListener listener = new HashSetNodeEventListener(); + try (NodeEventScope s = graph.trackNodeEvents(listener)) { + for (TypeProfileProxyNode proxy : graph.getNodes(TypeProfileProxyNode.class)) { + graph.replaceFloating(proxy, proxy.getValue()); + } + } + if (!listener.getNodes().isEmpty()) { + canonicalizer.applyIncremental(graph, context, listener.getNodes()); } assert graph.getNodes(TypeProfileProxyNode.class).count() == 0; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -32,10 +32,10 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; 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.*; @@ -446,12 +446,12 @@ } private GuardedStamp computeGuardedStamp(GuardNode guard) { - if (guard.condition() instanceof IntegerBelowThanNode) { + if (guard.condition() instanceof IntegerBelowNode) { if (guard.negated()) { // Not sure how to reason about negated guards return null; } - IntegerBelowThanNode below = (IntegerBelowThanNode) guard.condition(); + IntegerBelowNode below = (IntegerBelowNode) guard.condition(); if (below.getX().getKind() == Kind.Int && below.getX().isConstant() && !below.getY().isConstant()) { Stamp stamp = StampTool.unsignedCompare(below.getX().stamp(), below.getY().stamp()); if (stamp != null) { @@ -520,8 +520,8 @@ } GuardNode existingGuard = null; - if (guard.condition() instanceof IntegerBelowThanNode) { - IntegerBelowThanNode below = (IntegerBelowThanNode) guard.condition(); + if (guard.condition() instanceof IntegerBelowNode) { + IntegerBelowNode below = (IntegerBelowNode) guard.condition(); IntegerStamp xStamp = (IntegerStamp) below.getX().stamp(); IntegerStamp yStamp = (IntegerStamp) below.getY().stamp(); GuardedStamp cstamp = state.valueConstraints.get(below.getX()); @@ -769,7 +769,7 @@ } if (replacement != null) { - if (!(replacementAnchor instanceof BeginNode)) { + if (replacementAnchor != null && !(replacementAnchor instanceof BeginNode)) { ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor)); graph.addBeforeFixed(ifNode, anchor); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -47,6 +47,7 @@ * */ public class ConvertDeoptimizeToGuardPhase extends Phase { + private SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false); private static BeginNode findBeginNode(FixedNode startNode) { return GraphUtil.predecessorIterable(startNode).filter(BeginNode.class).first(); @@ -58,10 +59,9 @@ if (graph.getNodes(DeoptimizeNode.class).isEmpty()) { return; } - SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false); for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) { assert d.isAlive(); - visitDeoptBegin(BeginNode.prevBegin(d), d.action(), d.reason(), graph, simplifierTool); + visitDeoptBegin(BeginNode.prevBegin(d), d.action(), d.reason(), graph); } for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.class)) { @@ -94,7 +94,7 @@ } if (xs[i].getKind() != Kind.Object && ys[i].getKind() != Kind.Object && compare.condition().foldCondition(xs[i], ys[i], null, compare.unorderedIsTrue()) == fixedGuard.isNegated()) { - visitDeoptBegin(BeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), graph, simplifierTool); + visitDeoptBegin(BeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), graph); } } } @@ -104,7 +104,7 @@ new DeadCodeEliminationPhase().apply(graph); } - private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph, SimplifierTool simplifierTool) { + private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) { if (deoptBegin instanceof MergeNode) { MergeNode mergeNode = (MergeNode) deoptBegin; Debug.log("Visiting %s", mergeNode); @@ -112,11 +112,11 @@ while (mergeNode.isAlive()) { AbstractEndNode end = mergeNode.forwardEnds().first(); BeginNode newBeginNode = findBeginNode(end); - visitDeoptBegin(newBeginNode, deoptAction, deoptReason, graph, simplifierTool); + visitDeoptBegin(newBeginNode, deoptAction, deoptReason, graph); } assert next.isAlive(); BeginNode newBeginNode = findBeginNode(next); - visitDeoptBegin(newBeginNode, deoptAction, deoptReason, graph, simplifierTool); + visitDeoptBegin(newBeginNode, deoptAction, deoptReason, graph); return; } else if (deoptBegin.predecessor() instanceof IfNode) { IfNode ifNode = (IfNode) deoptBegin.predecessor(); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -209,7 +209,7 @@ } - private static class CollectMemoryCheckpointsClosure extends NodeIteratorClosure> { + public static class CollectMemoryCheckpointsClosure extends NodeIteratorClosure> { private final Map> modifiedInLoops; @@ -261,7 +261,7 @@ } - private static class FloatingReadClosure extends NodeIteratorClosure { + public static class FloatingReadClosure extends NodeIteratorClosure { private final Map> modifiedInLoops; private boolean createFloatingReads; @@ -372,7 +372,7 @@ Map phis = new HashMap<>(); if (updateExistingPhis) { - for (MemoryPhiNode phi : loop.phis().filter(MemoryPhiNode.class)) { + for (MemoryPhiNode phi : loop.phis().filter(MemoryPhiNode.class).snapshot()) { if (modifiedLocations.contains(phi.getLocationIdentity())) { phi.values().clear(); phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(phi.getLocationIdentity()))); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -89,7 +89,8 @@ @Override protected FrameState merge(MergeNode merge, List states) { - return merge.stateAfter() != null ? merge.stateAfter() : singleFrameState(merge, states); + FrameState singleFrameState = singleFrameState(states); + return singleFrameState == null ? merge.stateAfter() : singleFrameState; } @Override @@ -123,7 +124,7 @@ return true; } - private static FrameState singleFrameState(@SuppressWarnings("unused") MergeNode merge, List states) { + private static FrameState singleFrameState(List states) { FrameState singleState = states.get(0); for (int i = 1; i < states.size(); ++i) { if (states.get(i) != singleState) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -34,9 +34,11 @@ @Override protected void run(StructuredGraph graph) { + Stamp nonNull = StampFactory.objectNonNull(); for (ParameterNode param : graph.getNodes(ParameterNode.class)) { if (param.stamp() instanceof ObjectStamp) { - param.setStamp(StampFactory.declaredNonNull(((ObjectStamp) param.stamp()).type())); + ObjectStamp paramStamp = (ObjectStamp) param.stamp(); + param.setStamp(paramStamp.join(nonNull)); } } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Wed Jul 30 10:39:39 2014 -0700 @@ -306,8 +306,8 @@ * */ private MethodCallTargetNode deverbosifyInputsCopyOnWrite(MethodCallTargetNode parent) { - final MethodCallTargetNode.InvokeKind ik = parent.invokeKind(); - final boolean shouldTryDevirt = (ik == MethodCallTargetNode.InvokeKind.Interface || ik == MethodCallTargetNode.InvokeKind.Virtual); + final CallTargetNode.InvokeKind ik = parent.invokeKind(); + final boolean shouldTryDevirt = (ik == CallTargetNode.InvokeKind.Interface || ik == CallTargetNode.InvokeKind.Virtual); boolean shouldDowncastReceiver = shouldTryDevirt; MethodCallTargetNode changed = null; for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) { @@ -546,10 +546,9 @@ * MethodCallTargetNode} as described above may enable two optimizations: *

    *
  • - * devirtualization of an - * {@link com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind#Interface} or - * {@link com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind#Virtual} callsite - * (devirtualization made possible after narrowing the type of the receiver)
  • + * devirtualization of an {@link com.oracle.graal.nodes.CallTargetNode.InvokeKind#Interface} or + * {@link com.oracle.graal.nodes.CallTargetNode.InvokeKind#Virtual} callsite (devirtualization + * made possible after narrowing the type of the receiver) *
  • * (future work) actual-argument-aware inlining, ie, to specialize callees on the types of * arguments other than the receiver (examples: multi-methods, the inlining problem, lambdas as @@ -572,7 +571,7 @@ } 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) { + if (callTarget.invokeKind() != CallTargetNode.InvokeKind.Interface && callTarget.invokeKind() != CallTargetNode.InvokeKind.Virtual) { return; } ValueNode receiver = callTarget.receiver(); @@ -600,7 +599,7 @@ } if (method.canBeStaticallyBound() || Modifier.isFinal(type.getModifiers())) { metricMethodResolved.increment(); - callTarget.setInvokeKind(MethodCallTargetNode.InvokeKind.Special); + callTarget.setInvokeKind(CallTargetNode.InvokeKind.Special); callTarget.setTargetMethod(method); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Wed Jul 30 10:39:39 2014 -0700 @@ -39,10 +39,10 @@ import com.oracle.graal.graph.Graph.DuplicationReplacement; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; 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.*; @@ -314,8 +314,9 @@ } } + processSimpleInfopoints(invoke, inlineGraph, duplicates); if (stateAfter != null) { - processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge); + processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge, returnNodes.size() > 1); int callerLockDepth = stateAfter.nestedLockDepth(); if (callerLockDepth != 0) { for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.class)) { @@ -353,7 +354,25 @@ return duplicates; } - protected static void processFrameStates(Invoke invoke, StructuredGraph inlineGraph, Map duplicates, FrameState stateAtExceptionEdge) { + private static void processSimpleInfopoints(Invoke invoke, StructuredGraph inlineGraph, Map duplicates) { + if (inlineGraph.getNodes(SimpleInfopointNode.class).isEmpty()) { + return; + } + BytecodePosition pos = new BytecodePosition(toBytecodePosition(invoke.stateAfter()), invoke.asNode().graph().method(), invoke.bci()); + for (SimpleInfopointNode original : inlineGraph.getNodes(SimpleInfopointNode.class)) { + SimpleInfopointNode duplicate = (SimpleInfopointNode) duplicates.get(original); + duplicate.addCaller(pos); + } + } + + private static BytecodePosition toBytecodePosition(FrameState fs) { + if (fs == null) { + return null; + } + return new BytecodePosition(toBytecodePosition(fs.outerFrameState()), fs.method(), fs.bci); + } + + protected static void processFrameStates(Invoke invoke, StructuredGraph inlineGraph, Map duplicates, FrameState stateAtExceptionEdge, boolean alwaysDuplicateStateAfter) { FrameState stateAtReturn = invoke.stateAfter(); FrameState outerFrameState = null; Kind invokeReturnKind = invoke.asNode().getKind(); @@ -366,7 +385,7 @@ * return value (top of stack) */ FrameState stateAfterReturn = stateAtReturn; - if (invokeReturnKind != Kind.Void && frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0)) { + if (invokeReturnKind != Kind.Void && (alwaysDuplicateStateAfter || frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0))) { stateAfterReturn = stateAtReturn.duplicateModified(invokeReturnKind, frameState.stackAt(0)); } frameState.replaceAndDelete(stateAfterReturn); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AssumptionInlineInfo.java Wed Jul 30 10:39:39 2014 -0700 @@ -27,12 +27,12 @@ import com.oracle.graal.api.code.Assumptions; import com.oracle.graal.api.meta.MetaAccessProvider; import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.util.Providers; import com.oracle.graal.api.code.Assumptions.Assumption; import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; /** * Represents an inlining opportunity where the current class hierarchy leads to a monomorphic diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Wed Jul 30 10:39:39 2014 -0700 @@ -34,10 +34,10 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; @@ -78,6 +78,15 @@ this.methodProbabilities = computeMethodProbabilities(); this.maximumMethodProbability = maximumMethodProbability(); assert maximumMethodProbability > 0; + assert assertUniqueTypes(ptypes); + } + + private static boolean assertUniqueTypes(ArrayList ptypes) { + Set set = new HashSet<>(); + for (ProfiledType ptype : ptypes) { + set.add(ptype.getType()); + } + return set.size() == ptypes.size(); } private double[] computeMethodProbabilities() { @@ -383,15 +392,22 @@ ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()]; double[] keyProbabilities = new double[ptypes.size() + 1]; int[] keySuccessors = new int[ptypes.size() + 1]; + double totalProbability = notRecordedTypeProbability; for (int i = 0; i < ptypes.size(); i++) { keys[i] = ptypes.get(i).getType(); keyProbabilities[i] = ptypes.get(i).getProbability(); + totalProbability += keyProbabilities[i]; keySuccessors[i] = invokeIsOnlySuccessor ? 0 : typesToConcretes.get(i); assert keySuccessors[i] < successors.length - 1 : "last successor is the unknownTypeSux"; } keyProbabilities[keyProbabilities.length - 1] = notRecordedTypeProbability; keySuccessors[keySuccessors.length - 1] = successors.length - 1; + // Normalize the probabilities. + for (int i = 0; i < keyProbabilities.length; i++) { + keyProbabilities[i] /= totalProbability; + } + TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors)); FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor(); pred.setNext(typeSwitch); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Wed Jul 30 10:39:39 2014 -0700 @@ -29,12 +29,12 @@ import com.oracle.graal.compiler.common.calc.Condition; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.CompareNode; import com.oracle.graal.nodes.extended.LoadHubNode; import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.common.inlining.info.elem.Inlineable; import com.oracle.graal.phases.util.Providers; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; /** * Represents an inlining opportunity for which profiling information suggests a monomorphic diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Wed Jul 30 10:39:39 2014 -0700 @@ -166,11 +166,11 @@ MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); - if (callTarget.invokeKind() == MethodCallTargetNode.InvokeKind.Special || targetMethod.canBeStaticallyBound()) { + if (callTarget.invokeKind() == CallTargetNode.InvokeKind.Special || targetMethod.canBeStaticallyBound()) { return getExactInlineInfo(invoke, targetMethod); } - assert callTarget.invokeKind() == MethodCallTargetNode.InvokeKind.Virtual || callTarget.invokeKind() == MethodCallTargetNode.InvokeKind.Interface; + assert callTarget.invokeKind() == CallTargetNode.InvokeKind.Virtual || callTarget.invokeKind() == CallTargetNode.InvokeKind.Interface; ResolvedJavaType holder = targetMethod.getDeclaringClass(); if (!(callTarget.receiver().stamp() instanceof ObjectStamp)) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -112,7 +112,8 @@ } protected CharSequence createName() { - String s = BasePhase.this.getClass().getSimpleName(); + String className = BasePhase.this.getClass().getName(); + String s = className.substring(className.lastIndexOf(".") + 1); // strip the package name if (s.endsWith("Phase")) { s = s.substring(0, s.length() - "Phase".length()); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Wed Jul 30 10:39:39 2014 -0700 @@ -114,6 +114,7 @@ ControlSplitNode split = (ControlSplitNode) current.predecessor(); probability = split.probability((BeginNode) current) * applyAsDouble(split); } + assert !Double.isNaN(probability) && !Double.isInfinite(probability) : current + " " + probability; cache.put(current, probability); return probability; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Wed Jul 30 10:39:39 2014 -0700 @@ -160,8 +160,8 @@ 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 (node instanceof FullInfopointNode) { + stateAfter = ((FullInfopointNode) node).getState(); } if (pendingStateAfter != null && node instanceof FixedNode) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Wed Jul 30 10:39:39 2014 -0700 @@ -129,10 +129,12 @@ private void writeGraph(Graph graph, SchedulePhase predefinedSchedule) throws IOException { SchedulePhase schedule = predefinedSchedule; if (schedule == null) { - try { - schedule = new SchedulePhase(); - schedule.apply((StructuredGraph) graph); - } catch (Throwable t) { + if (PrintIdealGraphSchedule.getValue()) { + try { + schedule = new SchedulePhase(); + schedule.apply((StructuredGraph) graph); + } catch (Throwable t) { + } } } ControlFlowGraph cfg = schedule == null ? null : schedule.getCFG(); @@ -410,7 +412,11 @@ NodeClass nodeClass = node.getNodeClass(); node.getDebugProperties(props); if (probabilities != null && node instanceof FixedNode) { - props.put("probability", probabilities.applyAsDouble((FixedNode) node)); + try { + props.put("probability", probabilities.applyAsDouble((FixedNode) node)); + } catch (Throwable t) { + props.put("probability", t); + } } writeInt(getNodeId(node)); writePoolObject(nodeClass); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Wed Jul 30 10:39:39 2014 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.printer; +import static com.oracle.graal.compiler.common.GraalOptions.*; + import java.io.*; import java.util.*; import java.util.Map.Entry; @@ -87,10 +89,12 @@ Set noBlockNodes = new HashSet<>(); SchedulePhase schedule = predefinedSchedule; if (schedule == null && tryToSchedule) { - try { - schedule = new SchedulePhase(); - schedule.apply((StructuredGraph) graph); - } catch (Throwable t) { + if (PrintIdealGraphSchedule.getValue()) { + try { + schedule = new SchedulePhase(); + schedule.apply((StructuredGraph) graph); + } catch (Throwable t) { + } } } ControlFlowGraph cfg = schedule == null ? null : schedule.getCFG(); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -33,6 +33,7 @@ import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.replacements.nodes.*; public class BitOpNodesTest extends GraalCompilerTest { @@ -186,8 +187,11 @@ @Test public void testScanReverseInt() { - ValueNode result = parseAndInline("scanReverseIntSnippet"); - Assert.assertEquals(StampFactory.forInteger(Kind.Int, 16, 20), result.stamp()); + /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */ + ValueNode result = parseAndInline("scanReverseIntSnippet", BitScanReverseNode.class); + if (result != null) { + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 16, 20), result.stamp()); + } } public static int scanReverseLongConstantSnippet() { @@ -208,8 +212,11 @@ @Test public void testScanReverseLong() { - ValueNode result = parseAndInline("scanReverseLongSnippet"); - Assert.assertEquals(StampFactory.forInteger(Kind.Int, 48, 64), result.stamp()); + /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */ + ValueNode result = parseAndInline("scanReverseLongSnippet", BitScanReverseNode.class); + if (result != null) { + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 48, 64), result.stamp()); + } } public static int scanReverseLongEmptySnippet(long v) { @@ -220,11 +227,26 @@ @Test public void testScanReverseLongEmpty() { - ValueNode result = parseAndInline("scanReverseLongEmptySnippet"); - Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 64), result.stamp()); + /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */ + ValueNode result = parseAndInline("scanReverseLongEmptySnippet", BitScanReverseNode.class); + if (result != null) { + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 64), result.stamp()); + } } private ValueNode parseAndInline(String name) { + return parseAndInline(name, null); + } + + /** + * Parse and optimize {@code name}. If {@code expectedClass} is non-null and a node of that type + * isn't found simply return null. Otherwise return the node returned by the graph. + * + * @param name + * @param expectedClass + * @return the returned value or null if {@code expectedClass} is not found in the graph. + */ + private ValueNode parseAndInline(String name, Class expectedClass) { StructuredGraph graph = parse(name); HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); @@ -232,6 +254,11 @@ new InliningPhase(canonicalizer).apply(graph, context); canonicalizer.apply(graph, context); Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); + if (expectedClass != null) { + if (graph.getNodes().filter(expectedClass).count() == 0) { + return null; + } + } return graph.getNodes(ReturnNode.class).first().result(); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Wed Jul 30 10:39:39 2014 -0700 @@ -646,7 +646,7 @@ } } - return tool.createGuard(n, graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); + return tool.createGuard(n, graph.unique(new IntegerBelowNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); } protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Wed Jul 30 10:39:39 2014 -0700 @@ -31,9 +31,9 @@ import com.oracle.graal.graph.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; import com.oracle.graal.phases.util.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java Wed Jul 30 10:39:39 2014 -0700 @@ -39,7 +39,7 @@ if (i == 0) { return 32; } - return 31 - BitScanReverseNode.scan(i); + return 31 - BitScanReverseNode.unsafeScan(i); } @MethodSubstitution @@ -47,7 +47,7 @@ if (i == 0) { return 32; } - return BitScanForwardNode.scan(i); + return BitScanForwardNode.unsafeScan(i); } @MethodSubstitution diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java Wed Jul 30 10:39:39 2014 -0700 @@ -39,7 +39,7 @@ if (i == 0) { return 64; } - return 63 - BitScanReverseNode.scan(i); + return 63 - BitScanReverseNode.unsafeScan(i); } @MethodSubstitution @@ -47,7 +47,7 @@ if (i == 0) { return 64; } - return BitScanForwardNode.scan(i); + return BitScanForwardNode.unsafeScan(i); } @MethodSubstitution diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Jul 30 10:39:39 2014 -0700 @@ -45,8 +45,8 @@ import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPhase.Instance; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 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.*; import com.oracle.graal.phases.common.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -63,27 +63,53 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (forValue.isConstant()) { Constant c = forValue.asConstant(); - return ConstantNode.forInt(forValue.getKind() == Kind.Int ? scan(c.asInt()) : scan(c.asLong())); + if (c.asLong() != 0) { + return ConstantNode.forInt(forValue.getKind() == Kind.Int ? scan(c.asInt()) : scan(c.asLong())); + } } return this; } - @NodeIntrinsic + /** + * Utility method with defined return value for 0. + * + * @param v + * @return number of trailing zeros or -1 if {@code v} == 0. + */ public static int scan(long v) { if (v == 0) { return -1; } - int index = 0; - while (((1L << index) & v) == 0) { - ++index; - } - return index; + return Long.numberOfTrailingZeros(v); + } + + /** + * Utility method with defined return value for 0. + * + * @param v + * @return number of trailing zeros or -1 if {@code v} == 0. + */ + public static int scan(int v) { + return scan(0xffffffffL & v); } + /** + * Raw intrinsic for bsf instruction. + * + * @param v + * @return number of trailing zeros or an undefined value if {@code v} == 0. + */ @NodeIntrinsic - public static int scan(int v) { - return scan(v & 0xFFFFFFFFL); - } + public static native int unsafeScan(long v); + + /** + * Raw intrinsic for bsf instruction. + * + * @param v + * @return number of trailing zeros or an undefined value if {@code v} == 0. + */ + @NodeIntrinsic + public static native int unsafeScan(int v); @Override public void generate(NodeLIRBuilderTool gen) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -61,34 +61,50 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (forValue.isConstant()) { Constant c = forValue.asConstant(); - return ConstantNode.forInt(forValue.getKind() == Kind.Int ? scan(c.asInt()) : scan(c.asLong())); + if (c.asLong() != 0) { + return ConstantNode.forInt(forValue.getKind() == Kind.Int ? scan(c.asInt()) : scan(c.asLong())); + } } return this; } - @NodeIntrinsic - public static int scan(int v) { - if (v == 0) { - return -1; - } - int index = 31; - while (((1 << index) & v) == 0) { - --index; - } - return index; + /** + * Utility method with defined return value for 0. + * + * @param v + * @return index of first set bit or -1 if {@code v} == 0. + */ + public static int scan(long v) { + return 63 - Long.numberOfLeadingZeros(v); } + /** + * Utility method with defined return value for 0. + * + * @param v + * @return index of first set bit or -1 if {@code v} == 0. + */ + public static int scan(int v) { + return 31 - Integer.numberOfLeadingZeros(v); + } + + /** + * Raw intrinsic for bsr instruction. + * + * @param v + * @return index of first set bit or an undefined value if {@code v} == 0. + */ @NodeIntrinsic - public static int scan(long v) { - if (v == 0) { - return -1; - } - int index = 63; - while (((1L << index) & v) == 0) { - --index; - } - return index; - } + public static native int unsafeScan(int v); + + /** + * Raw intrinsic for bsr instruction. + * + * @param v + * @return index of first set bit or an undefined value if {@code v} == 0. + */ + @NodeIntrinsic + public static native int unsafeScan(long v); @Override public void generate(NodeLIRBuilderTool gen) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -31,9 +31,9 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; 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.common.inlining.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Wed Jul 30 10:39:39 2014 -0700 @@ -29,6 +29,7 @@ import java.util.*; import java.util.concurrent.*; +import java.util.stream.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; @@ -41,6 +42,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; @@ -52,6 +54,7 @@ import com.oracle.graal.printer.*; import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.*; +import com.oracle.graal.word.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.SlowPath; import com.oracle.truffle.api.frame.*; @@ -245,33 +248,31 @@ } @SlowPath - public Iterable getStackTrace() { + @Override + public T iterateFrames(FrameInstanceVisitor visitor) { initStackIntrospection(); - final Iterator frames = stackIntrospection.getStackTrace(anyFrameMethod, anyFrameMethod, 1).iterator(); - class FrameIterator implements Iterator { - public boolean hasNext() { - return frames.hasNext(); - } + InspectedFrameVisitor inspectedFrameVisitor = new InspectedFrameVisitor() { + private boolean skipNext = false; - public FrameInstance next() { - InspectedFrame frame = frames.next(); - if (frame.getMethod().equals(callNodeMethod[0])) { - assert frames.hasNext(); - InspectedFrame calltarget2 = frames.next(); - assert calltarget2.getMethod().equals(callTargetMethod[0]); - return new HotSpotFrameInstance.CallNodeFrame(frame); + public T visitFrame(InspectedFrame frame) { + if (skipNext) { + assert frame.isMethod(callTargetMethod[0]); + skipNext = false; + return null; + } + + if (frame.isMethod(callNodeMethod[0])) { + skipNext = true; + return visitor.visitFrame(new HotSpotFrameInstance.CallNodeFrame(frame)); } else { - assert frame.getMethod().equals(callTargetMethod[0]); - return new HotSpotFrameInstance.CallTargetFrame(frame, false); + assert frame.isMethod(callTargetMethod[0]); + return visitor.visitFrame(new HotSpotFrameInstance.CallTargetFrame(frame, false)); } - } - } - return new Iterable() { - public Iterator iterator() { - return new FrameIterator(); + } }; + return stackIntrospection.iterateFrames(anyFrameMethod, anyFrameMethod, 1, inspectedFrameVisitor); } private void initStackIntrospection() { @@ -280,15 +281,17 @@ } } + @Override + public FrameInstance getCallerFrame() { + return iterateFrames(frame -> frame); + } + @SlowPath + @Override public FrameInstance getCurrentFrame() { initStackIntrospection(); - Iterator frames = stackIntrospection.getStackTrace(callTargetMethod, callTargetMethod, 0).iterator(); - if (frames.hasNext()) { - return new HotSpotFrameInstance.CallTargetFrame(frames.next(), true); - } else { - return null; - } + + return stackIntrospection.iterateFrames(callTargetMethod, callTargetMethod, 0, frame -> new HotSpotFrameInstance.CallTargetFrame(frame, true)); } public void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous) { @@ -342,4 +345,25 @@ public void reinstallStubs() { installOptimizedCallTargetCallMethod(); } + + public void notifyTransferToInterpreter() { + CompilerAsserts.neverPartOfCompilation(); + if (TraceTruffleTransferToInterpreter.getValue()) { + Word thread = CurrentJavaThreadNode.get(HotSpotGraalRuntime.runtime().getTarget().wordKind); + boolean deoptimized = thread.readByte(HotSpotGraalRuntime.runtime().getConfig().pendingTransferToInterpreterOffset) != 0; + if (deoptimized) { + thread.writeByte(HotSpotGraalRuntime.runtime().getConfig().pendingTransferToInterpreterOffset, (byte) 0); + + logTransferToInterpreter(); + } + } + } + + private static void logTransferToInterpreter() { + final int skip = 2; + final int limit = 20; + StackTraceElement[] stackTrace = new Throwable().getStackTrace(); + String suffix = stackTrace.length > skip + limit ? "\n ..." : ""; + TTY.out().out().println(Arrays.stream(stackTrace).skip(skip).limit(limit).map(StackTraceElement::toString).collect(Collectors.joining("\n ", "", suffix))); + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -164,7 +164,7 @@ canonicalizer.apply(graph, context); // Additional inlining. - PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getEagerInfopointDefault()); + PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()); graphBuilderSuite.appendPhase(canonicalizer); graphBuilderSuite.appendPhase(new DeadCodeEliminationPhase()); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Wed Jul 30 10:39:39 2014 -0700 @@ -195,7 +195,6 @@ private Object callBoundary(Object[] args) { if (CompilerDirectives.inInterpreter()) { // We are called and we are still in Truffle interpreter mode. - CompilerDirectives.transferToInterpreter(); interpreterCall(); } else { // We come here from compiled code (i.e., we have been inlined). diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Jul 30 10:39:39 2014 -0700 @@ -39,8 +39,8 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 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.util.*; import com.oracle.graal.nodes.virtual.*; @@ -122,20 +122,7 @@ new VerifyFrameDoesNotEscapePhase().apply(graph, false); if (TraceTruffleCompilationHistogram.getValue() && constantReceivers != null) { - DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes"); - for (Constant c : constantReceivers) { - String javaName = providers.getMetaAccess().lookupJavaType(c).toJavaName(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); + createHistogram(); } canonicalizer.apply(graph, baseContext); @@ -176,6 +163,23 @@ return graph; } + private void createHistogram() { + DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes"); + for (Constant c : constantReceivers) { + String javaName = providers.getMetaAccess().lookupJavaType(c).toJavaName(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); + } + private void expandTree(StructuredGraph graph, Assumptions assumptions) { PhaseContext phaseContext = new PhaseContext(providers, assumptions); TruffleExpansionLogger expansionLogger = null; @@ -207,26 +211,7 @@ } if (inlineGraph != null) { - try (Indent indent = Debug.logAndIndent("inline graph %s", methodCallTargetNode.targetMethod())) { - - int nodeCountBefore = graph.getNodeCount(); - if (TraceTruffleExpansion.getValue()) { - expansionLogger.preExpand(methodCallTargetNode, inlineGraph); - } - List canonicalizedNodes = methodCallTargetNode.invoke().asNode().usages().snapshot(); - Map inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false, canonicalizedNodes); - if (TraceTruffleExpansion.getValue()) { - expansionLogger.postExpand(inlined); - } - if (Debug.isDumpEnabled()) { - int nodeCountAfter = graph.getNodeCount(); - Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter); - } - AbstractInlineInfo.getInlinedParameterUsages(canonicalizedNodes, inlineGraph, inlined); - canonicalizer.applyIncremental(graph, phaseContext, canonicalizedNodes); - - changed = true; - } + changed = expandTreeInline(graph, phaseContext, expansionLogger, methodCallTargetNode, inlineGraph); } } } @@ -242,6 +227,28 @@ } } + private boolean expandTreeInline(StructuredGraph graph, PhaseContext phaseContext, TruffleExpansionLogger expansionLogger, MethodCallTargetNode methodCallTargetNode, StructuredGraph inlineGraph) { + try (Indent indent = Debug.logAndIndent("inline graph %s", methodCallTargetNode.targetMethod())) { + int nodeCountBefore = graph.getNodeCount(); + if (TraceTruffleExpansion.getValue()) { + expansionLogger.preExpand(methodCallTargetNode, inlineGraph); + } + List canonicalizedNodes = methodCallTargetNode.invoke().asNode().usages().snapshot(); + Map inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false, canonicalizedNodes); + if (TraceTruffleExpansion.getValue()) { + expansionLogger.postExpand(inlined); + } + if (Debug.isDumpEnabled()) { + int nodeCountAfter = graph.getNodeCount(); + Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter); + } + AbstractInlineInfo.getInlinedParameterUsages(canonicalizedNodes, inlineGraph, inlined); + canonicalizer.applyIncremental(graph, phaseContext, canonicalizedNodes); + + return true; + } + } + private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList arguments, final Assumptions assumptions, final PhaseContext phaseContext, boolean ignoreSlowPath) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Wed Jul 30 10:39:39 2014 -0700 @@ -30,7 +30,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.Node.Child; -final class PartialEvaluatorCanonicalizer implements CanonicalizerPhase.CustomCanonicalizer { +final class PartialEvaluatorCanonicalizer extends CanonicalizerPhase.CustomCanonicalizer { private final MetaAccessProvider metaAccess; private final ConstantReflectionProvider constantReflection; @@ -43,27 +43,35 @@ @Override public Node canonicalize(Node node) { if (node instanceof LoadFieldNode) { - LoadFieldNode loadFieldNode = (LoadFieldNode) node; - if (!loadFieldNode.isStatic() && loadFieldNode.object().isConstant() && !loadFieldNode.object().isNullConstant()) { - 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); - return ConstantNode.forConstant(constant, metaAccess); - } - } + return canonicalizeLoadField((LoadFieldNode) node); } else if (node instanceof LoadIndexedNode) { - LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node; - if (loadIndexedNode.array().isConstant() && loadIndexedNode.index().isConstant()) { - int index = loadIndexedNode.index().asConstant().asInt(); + return canonicalizeLoadIndex((LoadIndexedNode) node); + } + return node; + } - Constant constant = constantReflection.readArrayElement(loadIndexedNode.array().asConstant(), index); - if (constant != null) { - return ConstantNode.forConstant(constant, metaAccess); - } + private Node canonicalizeLoadField(LoadFieldNode loadFieldNode) { + if (!loadFieldNode.isStatic() && loadFieldNode.object().isConstant() && !loadFieldNode.object().isNullConstant()) { + 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); + return ConstantNode.forConstant(constant, metaAccess); } } - return node; + return loadFieldNode; + } + + private Node canonicalizeLoadIndex(LoadIndexedNode loadIndexedNode) { + if (loadIndexedNode.array().isConstant() && loadIndexedNode.index().isConstant()) { + int index = loadIndexedNode.index().asConstant().asInt(); + + Constant constant = constantReflection.readArrayElement(loadIndexedNode.array().asConstant(), index); + if (constant != null) { + return ConstantNode.forConstant(constant, metaAccess); + } + } + return loadIndexedNode; } private boolean verifyFieldValue(ResolvedJavaField field, Constant constant) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Wed Jul 30 10:39:39 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; 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.graph.Graph.Mark; @@ -37,8 +38,8 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; @@ -97,7 +98,6 @@ return graph; } - @SuppressWarnings("unused") public StructuredGraph lookup(final ResolvedJavaMethod method, final NodeInputList arguments, final Assumptions assumptions, final CanonicalizerPhase finalCanonicalizer, boolean ignoreSlowPath) { @@ -124,24 +124,7 @@ } if (lastUsed.values().size() >= TruffleCompilerOptions.TruffleMaxCompilationCacheSize.getValue()) { - List lastUsedList = new ArrayList<>(); - for (long l : lastUsed.values()) { - lastUsedList.add(l); - } - Collections.sort(lastUsedList); - long mid = lastUsedList.get(lastUsedList.size() / 2); - - List> toRemoveList = new ArrayList<>(); - for (Entry, Long> entry : lastUsed.entrySet()) { - if (entry.getValue() < mid) { - toRemoveList.add(entry.getKey()); - } - } - - for (List entry : toRemoveList) { - cache.remove(entry); - lastUsed.remove(entry); - } + lookupExceedsMaxSize(); } lastUsed.put(key, counter++); @@ -183,42 +166,11 @@ boolean inliningProgress = false; for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { if (!graph.getMark().equals(mark)) { - // Make sure macro substitutions such as - // CompilerDirectives.transferToInterpreter get processed first. - for (Node newNode : graph.getNewNodes(mark)) { - if (newNode instanceof MethodCallTargetNode) { - MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) newNode; - Class macroSubstitution = providers.getReplacements().getMacroSubstitution(methodCallTargetNode.targetMethod()); - if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); - } else { - tryCutOffRuntimeExceptionsAndErrors(methodCallTargetNode); - } - } - } - mark = graph.getMark(); + mark = lookupProcessMacroSubstitutions(graph, mark); } if (methodCallTarget.isAlive() && methodCallTarget.invoke() != null && shouldInline(methodCallTarget)) { inliningProgress = true; - List canonicalizerUsages = new ArrayList(); - for (Node n : methodCallTarget.invoke().asNode().usages()) { - if (n instanceof Canonicalizable) { - canonicalizerUsages.add(n); - } - } - List argumentSnapshot = methodCallTarget.arguments().snapshot(); - Mark beforeInvokeMark = graph.getMark(); - expandInvoke(methodCallTarget); - for (Node arg : argumentSnapshot) { - if (arg != null && arg.recordsUsages()) { - for (Node argUsage : arg.usages()) { - if (graph.isNew(beforeInvokeMark, argUsage) && argUsage instanceof Canonicalizable) { - canonicalizerUsages.add(argUsage); - } - } - } - } - canonicalizerPhase.applyIncremental(graph, phaseContext, canonicalizerUsages); + lookupDoInline(graph, phaseContext, canonicalizerPhase, methodCallTarget); } } @@ -240,7 +192,66 @@ } catch (Throwable e) { throw Debug.handle(e); } + } + private void lookupExceedsMaxSize() { + List lastUsedList = new ArrayList<>(); + for (long l : lastUsed.values()) { + lastUsedList.add(l); + } + Collections.sort(lastUsedList); + long mid = lastUsedList.get(lastUsedList.size() / 2); + + List> toRemoveList = new ArrayList<>(); + for (Entry, Long> entry : lastUsed.entrySet()) { + if (entry.getValue() < mid) { + toRemoveList.add(entry.getKey()); + } + } + + for (List entry : toRemoveList) { + cache.remove(entry); + lastUsed.remove(entry); + } + } + + private Mark lookupProcessMacroSubstitutions(final StructuredGraph graph, Mark mark) throws GraalInternalError { + // Make sure macro substitutions such as + // CompilerDirectives.transferToInterpreter get processed first. + for (Node newNode : graph.getNewNodes(mark)) { + if (newNode instanceof MethodCallTargetNode) { + MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) newNode; + Class macroSubstitution = providers.getReplacements().getMacroSubstitution(methodCallTargetNode.targetMethod()); + if (macroSubstitution != null) { + InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); + } else { + tryCutOffRuntimeExceptionsAndErrors(methodCallTargetNode); + } + } + } + return graph.getMark(); + } + + private void lookupDoInline(final StructuredGraph graph, final PhaseContext phaseContext, CanonicalizerPhase canonicalizerPhase, MethodCallTargetNode methodCallTarget) { + List canonicalizerUsages = new ArrayList<>(); + for (Node n : methodCallTarget.invoke().asNode().usages()) { + if (n instanceof Canonicalizable) { + canonicalizerUsages.add(n); + } + } + List argumentSnapshot = methodCallTarget.arguments().snapshot(); + Mark beforeInvokeMark = graph.getMark(); + expandInvoke(methodCallTarget); + for (Node arg : argumentSnapshot) { + if (arg != null && arg.recordsUsages()) { + for (Node argUsage : arg.usages()) { + if (graph.isNew(beforeInvokeMark, argUsage) && argUsage instanceof Canonicalizable) { + canonicalizerUsages.add(argUsage); + } + } + } + } + canonicalizerPhase.applyIncremental(graph, phaseContext, canonicalizerUsages); } private void expandInvoke(MethodCallTargetNode methodCallTargetNode) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Wed Jul 30 10:39:39 2014 -0700 @@ -78,10 +78,8 @@ this.suites = backend.getSuites().getDefaultSuites(); ResolvedJavaType[] skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess()); - GraphBuilderConfiguration eagerConfig = GraphBuilderConfiguration.getEagerDefault(); - eagerConfig.setSkippedExceptionTypes(skippedExceptionTypes); - this.config = GraphBuilderConfiguration.getDefault(); - this.config.setSkippedExceptionTypes(skippedExceptionTypes); + GraphBuilderConfiguration eagerConfig = GraphBuilderConfiguration.getEagerDefault().withSkippedExceptionTypes(skippedExceptionTypes); + this.config = GraphBuilderConfiguration.getDefault().withSkippedExceptionTypes(skippedExceptionTypes); this.truffleCache = new TruffleCacheImpl(providers, eagerConfig, config, TruffleCompilerImpl.Optimizations); @@ -143,22 +141,27 @@ } if (TraceTruffleCompilation.getValue()) { - int calls = OptimizedCallUtils.countCalls(compilable); - int inlinedCalls = OptimizedCallUtils.countCallsInlined(compilable); - int dispatchedCalls = calls - inlinedCalls; - Map properties = new LinkedHashMap<>(); - OptimizedCallTargetLog.addASTSizeProperty(compilable, properties); - properties.put("Time", String.format("%5.0f(%4.0f+%-4.0f)ms", // - (timeCompilationFinished - timeCompilationStarted) / 1e6, // - (timePartialEvaluationFinished - timeCompilationStarted) / 1e6, // - (timeCompilationFinished - timePartialEvaluationFinished) / 1e6)); - properties.put("CallNodes", String.format("I %5d/D %5d", inlinedCalls, dispatchedCalls)); - properties.put("GraalNodes", String.format("%5d/%5d", nodeCountPartialEval, nodeCountLowered)); - properties.put("CodeSize", compilationResult.getTargetCodeSize()); - properties.put("Source", formatSourceSection(compilable.getRootNode().getSourceSection())); + printTruffleCompilation(compilable, timeCompilationStarted, timePartialEvaluationFinished, nodeCountPartialEval, compilationResult, timeCompilationFinished, nodeCountLowered); + } + } - OptimizedCallTargetLog.logOptimizingDone(compilable, properties); - } + private static void printTruffleCompilation(final OptimizedCallTarget compilable, long timeCompilationStarted, long timePartialEvaluationFinished, int nodeCountPartialEval, + CompilationResult compilationResult, long timeCompilationFinished, int nodeCountLowered) { + int calls = OptimizedCallUtils.countCalls(compilable); + int inlinedCalls = OptimizedCallUtils.countCallsInlined(compilable); + int dispatchedCalls = calls - inlinedCalls; + Map properties = new LinkedHashMap<>(); + OptimizedCallTargetLog.addASTSizeProperty(compilable, properties); + properties.put("Time", String.format("%5.0f(%4.0f+%-4.0f)ms", // + (timeCompilationFinished - timeCompilationStarted) / 1e6, // + (timePartialEvaluationFinished - timeCompilationStarted) / 1e6, // + (timeCompilationFinished - timePartialEvaluationFinished) / 1e6)); + properties.put("CallNodes", String.format("I %5d/D %5d", inlinedCalls, dispatchedCalls)); + properties.put("GraalNodes", String.format("%5d/%5d", nodeCountPartialEval, nodeCountLowered)); + properties.put("CodeSize", compilationResult.getTargetCodeSize()); + properties.put("Source", formatSourceSection(compilable.getRootNode().getSourceSection())); + + OptimizedCallTargetLog.logOptimizingDone(compilable, properties); } private static String formatSourceSection(SourceSection sourceSection) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Wed Jul 30 10:39:39 2014 -0700 @@ -119,6 +119,8 @@ public static final OptionValue TraceTruffleInlining = new OptionValue<>(false); @Option(help = "") public static final OptionValue TraceTruffleSplitting = new OptionValue<>(false); + @Option(help = "Print stack trace on transfer to interpreter") + public static final OptionValue TraceTruffleTransferToInterpreter = new StableOptionValue<>(false); @Option(help = "") public static final OptionValue TruffleCallTargetProfiling = new StableOptionValue<>(false); // @formatter:on diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -54,19 +54,7 @@ return new IntegerAddExactNode(forY, forX); } if (forX.isConstant()) { - Constant xConst = forX.asConstant(); - Constant yConst = forY.asConstant(); - assert xConst.getKind() == yConst.getKind(); - try { - if (xConst.getKind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.addExact(xConst.asInt(), yConst.asInt())); - } else { - assert xConst.getKind() == Kind.Long; - return ConstantNode.forLong(ExactMath.addExact(xConst.asLong(), yConst.asLong())); - } - } catch (ArithmeticException ex) { - // The operation will result in an overflow exception, so do not canonicalize. - } + return canonicalXconstant(forX, forY); } else if (forY.isConstant()) { long c = forY.asConstant().asLong(); if (c == 0) { @@ -76,6 +64,23 @@ return this; } + private ValueNode canonicalXconstant(ValueNode forX, ValueNode forY) { + Constant xConst = forX.asConstant(); + Constant yConst = forY.asConstant(); + assert xConst.getKind() == yConst.getKind(); + try { + if (xConst.getKind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.addExact(xConst.asInt(), yConst.asInt())); + } else { + assert xConst.getKind() == Kind.Long; + return ConstantNode.forLong(ExactMath.addExact(xConst.asLong(), yConst.asLong())); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + return this; + } + @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { return graph().add(new IntegerAddExactSplitNode(stamp(), getX(), getY(), next, deopt)); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -48,11 +48,6 @@ return successor == next ? 1 : 0; } - @Override - public void setProbability(BeginNode successor, double value) { - assert probability(successor) == value; - } - public BeginNode getNext() { return next; } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -47,19 +47,7 @@ return new IntegerMulExactNode(forY, forX); } if (forX.isConstant()) { - Constant xConst = forX.asConstant(); - Constant yConst = forY.asConstant(); - assert xConst.getKind() == yConst.getKind(); - try { - if (xConst.getKind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.multiplyExact(xConst.asInt(), yConst.asInt())); - } else { - assert xConst.getKind() == Kind.Long; - return ConstantNode.forLong(ExactMath.multiplyExact(xConst.asLong(), yConst.asLong())); - } - } catch (ArithmeticException ex) { - // The operation will result in an overflow exception, so do not canonicalize. - } + return canonicalXconstant(forX, forY); } else if (forY.isConstant()) { long c = forY.asConstant().asLong(); if (c == 1) { @@ -72,6 +60,23 @@ return this; } + private ValueNode canonicalXconstant(ValueNode forX, ValueNode forY) { + Constant xConst = forX.asConstant(); + Constant yConst = forY.asConstant(); + assert xConst.getKind() == yConst.getKind(); + try { + if (xConst.getKind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.multiplyExact(xConst.asInt(), yConst.asInt())); + } else { + assert xConst.getKind() == Kind.Long; + return ConstantNode.forLong(ExactMath.multiplyExact(xConst.asLong(), yConst.asLong())); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + return this; + } + @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { return graph().add(new IntegerMulExactSplitNode(stamp(), getX(), getY(), next, deopt)); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -55,19 +55,7 @@ return ConstantNode.forIntegerStamp(stamp(), 0); } if (forX.isConstant() && forY.isConstant()) { - Constant xConst = forX.asConstant(); - Constant yConst = forY.asConstant(); - assert xConst.getKind() == yConst.getKind(); - try { - if (xConst.getKind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.subtractExact(xConst.asInt(), yConst.asInt())); - } else { - assert xConst.getKind() == Kind.Long; - return ConstantNode.forLong(ExactMath.subtractExact(xConst.asLong(), yConst.asLong())); - } - } catch (ArithmeticException ex) { - // The operation will result in an overflow exception, so do not canonicalize. - } + return canonicalXYconstant(forX, forY); } else if (forY.isConstant()) { long c = forY.asConstant().asLong(); if (c == 0) { @@ -77,6 +65,23 @@ return this; } + private ValueNode canonicalXYconstant(ValueNode forX, ValueNode forY) { + Constant xConst = forX.asConstant(); + Constant yConst = forY.asConstant(); + assert xConst.getKind() == yConst.getKind(); + try { + if (xConst.getKind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.subtractExact(xConst.asInt(), yConst.asInt())); + } else { + assert xConst.getKind() == Kind.Long; + return ConstantNode.forLong(ExactMath.subtractExact(xConst.asLong(), yConst.asLong())); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + return this; + } + @Override public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { return graph().add(new IntegerSubExactSplitNode(stamp(), getX(), getY(), next, deopt)); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -24,11 +24,9 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; -public class NeverPartOfCompilationNode extends MacroNode implements IterableNodeType { +public class NeverPartOfCompilationNode extends MacroStateSplitNode implements IterableNodeType { private final String message; @@ -44,9 +42,4 @@ public final String getMessage() { return message + " " + arguments.toString(); } - - @Override - public void lower(LoweringTool tool) { - throw GraphUtil.approxSourceException(this, new VerificationError(getMessage())); - } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -35,9 +35,6 @@ * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean)}. */ public class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable, StateSplit { - - @Input(InputType.State) private FrameState stateAfter; - private static final int ARGUMENT_COUNT = 4; private static final int OBJECT_ARGUMENT_INDEX = 0; private static final int OFFSET_ARGUMENT_INDEX = 1; @@ -47,7 +44,6 @@ public CustomizedUnsafeStoreMacroNode(Invoke invoke) { super(invoke, "The location argument could not be resolved to a constant."); assert arguments.size() == ARGUMENT_COUNT; - this.stateAfter = invoke.stateAfter(); } @Override @@ -64,21 +60,8 @@ locationIdentity = ObjectLocationIdentity.create(locationArgument.asConstant()); } - return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter); + return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter()); } return this; } - - @Override - public FrameState stateAfter() { - return stateAfter; - } - - public void setStateAfter(FrameState x) { - this.stateAfter = x; - } - - public boolean hasSideEffect() { - return true; - } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -24,8 +24,8 @@ import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 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.*; import com.oracle.graal.phases.common.inlining.*; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Wed Jul 30 10:39:39 2014 -0700 @@ -41,12 +41,12 @@ @MethodSubstitution public static void transferToInterpreter() { - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.UnreachedCode); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter); } @MethodSubstitution public static void transferToInterpreterAndInvalidate() { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode); + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter); } @MethodSubstitution diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Wed Jul 30 10:39:39 2014 -0700 @@ -33,32 +33,32 @@ */ public final class VirtualObjectState extends EscapeObjectState implements Node.ValueNumberable { - @Input private final NodeInputList fieldValues; + @Input private final NodeInputList values; - public NodeInputList fieldValues() { - return fieldValues; + public NodeInputList values() { + return values; } - public VirtualObjectState(VirtualObjectNode object, ValueNode[] fieldValues) { + public VirtualObjectState(VirtualObjectNode object, ValueNode[] values) { super(object); - assert object.entryCount() == fieldValues.length; - this.fieldValues = new NodeInputList<>(this, fieldValues); + assert object.entryCount() == values.length; + this.values = new NodeInputList<>(this, values); } - public VirtualObjectState(VirtualObjectNode object, List fieldValues) { + public VirtualObjectState(VirtualObjectNode object, List values) { super(object); - assert object.entryCount() == fieldValues.size(); - this.fieldValues = new NodeInputList<>(this, fieldValues); + assert object.entryCount() == values.size(); + this.values = new NodeInputList<>(this, values); } @Override public VirtualObjectState duplicateWithVirtualState() { - return graph().addWithoutUnique(new VirtualObjectState(object(), fieldValues)); + return graph().addWithoutUnique(new VirtualObjectState(object(), values)); } @Override public void applyToNonVirtual(NodeClosure closure) { - for (ValueNode value : fieldValues) { + for (ValueNode value : values) { closure.apply(this, value); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Wed Jul 30 10:39:39 2014 -0700 @@ -82,7 +82,7 @@ Debug.log(" ==== effects for %s", context); effects.apply(graph, obsoleteNodes); if (TraceEscapeAnalysis.getValue()) { - Debug.dump(graph, EffectsClosure.this.getClass().getSimpleName() + " - after processing %s", context); + Debug.dump(5, graph, "After processing EffectsList for %s", context); } } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Wed Jul 30 10:39:39 2014 -0700 @@ -38,7 +38,8 @@ } public void addCounterAfter(final String group, final String name, final int increment, final boolean addContext, final FixedWithNextNode position) { - add("add counter after", graph -> DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position.next())); + FixedNode nextPosition = position.next(); + add("add counter after", graph -> DynamicCounterNode.addCounterBefore(group, name, increment, addContext, nextPosition)); } public void addWeakCounterCounterBefore(final String group, final String name, final int increment, final boolean addContext, final ValueNode checkedValue, final FixedNode position) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -185,7 +185,7 @@ Invoke invoke = callTargetNode.invoke(); if (!callTargetNode.isStatic()) { - assert callTargetNode.receiver().getKind() == wordKind : "changeToWord() missed the receiver"; + assert callTargetNode.receiver().getKind() == wordKind : "changeToWord() missed the receiver " + callTargetNode.receiver(); targetMethod = wordImplType.resolveMethod(targetMethod, invoke.getContextType()); } Operation operation = targetMethod.getAnnotation(Word.Operation.class); @@ -355,7 +355,7 @@ if (condition == Condition.EQ || condition == Condition.NE) { comparison = new IntegerEqualsNode(a, b); } else if (condition.isUnsigned()) { - comparison = new IntegerBelowThanNode(a, b); + comparison = new IntegerBelowNode(a, b); } else { comparison = new IntegerLessThanNode(a, b); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Wed Jul 30 10:39:39 2014 -0700 @@ -73,9 +73,7 @@ } else if (usage instanceof StoreFieldNode) { verify(!isWord(node) || ((StoreFieldNode) usage).object() != node, node, usage, "cannot store to word value"); } else if (usage instanceof CheckCastNode) { - boolean expectWord = isWord(node); - verify(isWord(node) == expectWord, node, usage, "word cannot be cast to object, and vice versa"); - verify(isWord(((CheckCastNode) usage).type()) == expectWord, node, usage, "word cannot be cast to object, and vice versa"); + verify(isWord(((CheckCastNode) usage).type()) == isWord(node), node, usage, "word cannot be cast to object, and vice versa"); } else if (usage instanceof LoadIndexedNode) { verify(!isWord(node) || ((LoadIndexedNode) usage).array() != node, node, usage, "cannot load from word value"); verify(!isWord(node) || ((LoadIndexedNode) usage).index() != node, node, usage, "cannot use word value as index"); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -95,4 +95,50 @@ return 21; } } + + @Test + public void testMultipleChildrenFields() { + TruffleRuntime runtime = Truffle.getRuntime(); + TestChildNode firstChild = new TestChildNode(); + TestChildNode secondChild = new TestChildNode(); + TestChildNode thirdChild = new TestChildNode(); + TestChildNode forthChild = new TestChildNode(); + TestRootNode rootNode = new TestRoot2Node(new TestChildNode[]{firstChild, secondChild}, new TestChildNode[]{thirdChild, forthChild}); + CallTarget target = runtime.createCallTarget(rootNode); + Assert.assertEquals(rootNode, firstChild.getParent()); + Assert.assertEquals(rootNode, secondChild.getParent()); + Assert.assertEquals(rootNode, thirdChild.getParent()); + Assert.assertEquals(rootNode, forthChild.getParent()); + Iterator iterator = rootNode.getChildren().iterator(); + Assert.assertEquals(firstChild, iterator.next()); + Assert.assertEquals(secondChild, iterator.next()); + Assert.assertEquals(thirdChild, iterator.next()); + Assert.assertEquals(forthChild, iterator.next()); + Assert.assertFalse(iterator.hasNext()); + Object result = target.call(); + Assert.assertEquals(2 * 42, result); + } + + class TestRoot2Node extends TestRootNode { + @Children private final TestChildNode[] children1; + @Children private final TestChildNode[] children2; + + public TestRoot2Node(TestChildNode[] children1, TestChildNode[] children2) { + super(new TestChildNode[0]); + this.children1 = children1; + this.children2 = children2; + } + + @Override + public Object execute(VirtualFrame frame) { + int sum = 0; + for (int i = 0; i < children1.length; ++i) { + sum += children1[i].execute(); + } + for (int i = 0; i < children2.length; ++i) { + sum += children2[i].execute(); + } + return sum; + } + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java Wed Jul 30 10:39:39 2014 -0700 @@ -40,6 +40,7 @@ public class ThreadSafetyTest { @Test + @Ignore("sporadic failures with \"expected:<1000000> but was:<999999>\"") public void test() throws InterruptedException { TruffleRuntime runtime = Truffle.getRuntime(); TestRootNode rootNode1 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new ConstNode(42))))))); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Wed Jul 30 10:39:39 2014 -0700 @@ -65,6 +65,9 @@ * insert a transfer to the interpreter. */ public static void transferToInterpreter() { + if (inInterpreter()) { + Truffle.getRuntime().notifyTransferToInterpreter(); + } } /** @@ -72,6 +75,9 @@ * insert a transfer to the interpreter, invalidating the currently executing machine code. */ public static void transferToInterpreterAndInvalidate() { + if (inInterpreter()) { + Truffle.getRuntime().notifyTransferToInterpreter(); + } } /** diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Wed Jul 30 10:39:39 2014 -0700 @@ -109,9 +109,21 @@ * {@link CallTarget}s. Iteration starts at the caller frame, i.e., it does not include the * current frame. * - * @return a lazy collection of {@link FrameInstance}. + * Iteration continues as long as {@link FrameInstanceVisitor#visitFrame}, which is invoked for + * every {@link FrameInstance}, returns null. Any non-null result of the visitor indicates that + * frame iteration should stop. + * + * @param visitor the visitor that is called for every matching frame. + * @return the last result returned by the visitor (which is non-null to indicate that iteration + * should stop), or null if the whole stack was iterated. */ - Iterable getStackTrace(); + T iterateFrames(FrameInstanceVisitor visitor); + + /** + * Accesses the caller frame. This is a convenience method that returns the first frame that is + * passed to the visitor of {@link #iterateFrames}. + */ + FrameInstance getCallerFrame(); /** * Accesses the current frame, i.e., the frame of the closest {@link CallTarget}. It is @@ -119,4 +131,8 @@ */ FrameInstance getCurrentFrame(); + /** + * Internal API method. Do not use. + */ + void notifyTransferToInterpreter(); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstanceVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstanceVisitor.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,38 @@ +/* + * 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.frame; + +import com.oracle.truffle.api.*; + +/** + * Callback interface for {@link TruffleRuntime#iterateFrames}. Implementations of + * {@link #visitFrame} return null to indicate that frame iteration should continue and the next + * caller frame should be visited; and return any non-null value to indicate that frame iteration + * should stop. + */ +public interface FrameInstanceVisitor { + + T visitFrame(FrameInstance frameInstance); +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Wed Jul 30 10:39:39 2014 -0700 @@ -114,11 +114,28 @@ getThreadLocalStackTrace().removeFirst(); } - public Iterable getStackTrace() { - return getThreadLocalStackTrace(); + @Override + public T iterateFrames(FrameInstanceVisitor visitor) { + T result = null; + for (FrameInstance frameInstance : getThreadLocalStackTrace()) { + result = visitor.visitFrame(frameInstance); + if (result != null) { + return result; + } + } + return result; } + @Override + public FrameInstance getCallerFrame() { + return getThreadLocalStackTrace().peekFirst(); + } + + @Override public FrameInstance getCurrentFrame() { return currentFrames.get(); } + + public void notifyTransferToInterpreter() { + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java Wed Jul 30 10:39:39 2014 -0700 @@ -56,7 +56,24 @@ /** * Marker for a location where ordinary "stepping" should halt. */ - STATEMENT("statement", "basic unit of the language, suitable for \"stepping\" in a debugger"); + STATEMENT("statement", "basic unit of the language, suitable for \"stepping\" in a debugger"), + + /** + * Marker for the start of the body of a method. + */ + START_METHOD("start-method", "start of the body of a method"), + + /** + * Marker for the start of the body of a loop. + */ + START_LOOP("start-loop", "start of the body of a loop"), + + /** + * Marker that is attached to some arbitrary locations that appear often-enough in an AST so + * that a location with this tag is regularly executed. Could be the start of method and loop + * bodies. May be used to implement some kind of safepoint functionality. + */ + PERIODIC("periodic", "arbitrary locations that appear often-enough in an AST so that a location with this tag is regularly executed"); private final String name; private final String description; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java Wed Jul 30 10:39:39 2014 -0700 @@ -66,7 +66,6 @@ p.print(nodeName(node)); - String sep = ""; p.print("("); final SourceSection src = node.getSourceSection(); @@ -76,15 +75,7 @@ } } if (node instanceof SyntaxTagged) { - final SyntaxTagged taggedNode = (SyntaxTagged) node; - p.print("["); - String prefix = ""; - for (SyntaxTag tag : taggedNode.getSyntaxTags()) { - p.print(prefix); - prefix = ","; - p.print(tag.toString()); - } - p.print("]"); + printSyntaxTagged(p, (SyntaxTagged) node); } ArrayList childFields = new ArrayList<>(); @@ -119,23 +110,9 @@ 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); + printChild(p, maxDepth, markNode, level, field, value); } 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("]"); + printChildren(p, maxDepth, markNode, level, field, value); } else { printNewLine(p, level); p.print(field.getName()); @@ -147,6 +124,39 @@ } } + private static void printSyntaxTagged(PrintWriter p, final SyntaxTagged taggedNode) { + p.print("["); + String prefix = ""; + for (SyntaxTag tag : taggedNode.getSyntaxTags()) { + p.print(prefix); + prefix = ","; + p.print(tag.toString()); + } + p.print("]"); + } + + private static void printChildren(PrintWriter p, int maxDepth, Node markNode, int level, NodeField field, Object value) { + printNewLine(p, level); + p.print(field.getName()); + Node[] children = (Node[]) value; + p.print(" = ["); + String sep = ""; + for (Node child : children) { + p.print(sep); + sep = ", "; + printTree(p, child, maxDepth, markNode, level + 1); + } + p.print("]"); + } + + private static void printChild(PrintWriter p, int maxDepth, Node markNode, int level, NodeField field, Object value) { + final Node valueNode = (Node) value; + printNewLine(p, level, valueNode == markNode); + p.print(field.getName()); + p.print(" = "); + printTree(p, valueNode, maxDepth, markNode, level + 1); + } + private static void printNewLine(PrintWriter p, int level, boolean mark) { p.println(); for (int i = 0; i < level; i++) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Wed Jul 30 10:39:39 2014 -0700 @@ -252,53 +252,58 @@ private final class NodeIterator implements Iterator { private final Node node; - private int fieldIndex; - private int arrayIndex; + private final int childrenCount; + private int index; protected NodeIterator(Node node) { this.node = node; + this.index = 0; + this.childrenCount = childrenCount(); + } + + private int childrenCount() { + int nodeCount = childOffsets.length; + for (long fieldOffset : childrenOffsets) { + Node[] children = ((Node[]) unsafe.getObject(node, fieldOffset)); + if (children != null) { + nodeCount += children.length; + } + } + return nodeCount; + } + + private Node nodeAt(int idx) { + int nodeCount = childOffsets.length; + if (idx < nodeCount) { + return (Node) unsafe.getObject(node, childOffsets[idx]); + } else { + for (long fieldOffset : childrenOffsets) { + Node[] nodeArray = (Node[]) unsafe.getObject(node, fieldOffset); + if (idx < nodeCount + nodeArray.length) { + return nodeArray[idx - nodeCount]; + } + nodeCount += nodeArray.length; + } + } + return null; } private void forward() { - if (fieldIndex < childOffsets.length) { - fieldIndex++; - } else if (fieldIndex < childOffsets.length + childrenOffsets.length) { - if (arrayIndex + 1 < currentChildrenArrayLength()) { - arrayIndex++; - } else { - arrayIndex = 0; - do { - fieldIndex++; - } while (fieldIndex < childOffsets.length + childrenOffsets.length && currentChildrenArrayLength() == 0); - } + if (index < childrenCount) { + index++; } } public boolean hasNext() { - return fieldIndex < childOffsets.length || (fieldIndex < childOffsets.length + childrenOffsets.length && arrayIndex < currentChildrenArrayLength()); - } - - private Node[] currentChildrenArray() { - assert fieldIndex >= childOffsets.length && fieldIndex < childOffsets.length + childrenOffsets.length; - return (Node[]) unsafe.getObject(node, childrenOffsets[fieldIndex - childOffsets.length]); - } - - private int currentChildrenArrayLength() { - Node[] childrenArray = currentChildrenArray(); - return childrenArray != null ? childrenArray.length : 0; + return index < childrenCount; } public Node next() { - Node next; - if (fieldIndex < childOffsets.length) { - next = (Node) unsafe.getObject(node, childOffsets[fieldIndex]); - } else if (fieldIndex < childOffsets.length + childrenOffsets.length) { - next = currentChildrenArray()[arrayIndex]; - } else { - throw new NoSuchElementException(); + try { + return nodeAt(index); + } finally { + forward(); } - forward(); - return next; } public void remove() { @@ -795,15 +800,7 @@ p.print(" = "); printTree(p, (Node) value, level + 1); } else if (field.getKind() == NodeFieldKind.CHILDREN) { - Node[] children = (Node[]) value; - p.print(" = ["); - sep = ""; - for (Node child : children) { - p.print(sep); - sep = ", "; - printTree(p, child, level + 1); - } - p.print("]"); + printChildren(p, level, value); } } printNewLine(p, level - 1); @@ -811,6 +808,19 @@ } } + private static void printChildren(PrintWriter p, int level, Object value) { + String sep; + Node[] children = (Node[]) value; + p.print(" = ["); + sep = ""; + for (Node child : children) { + p.print(sep); + sep = ", "; + printTree(p, child, level + 1); + } + p.print("]"); + } + private static void printNewLine(PrintWriter p, int level) { p.println(); for (int i = 0; i < level; i++) { diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java Wed Jul 30 10:39:39 2014 -0700 @@ -171,66 +171,74 @@ int cpi = buffer.get(); if (cpi == VariableLengthIntBuffer.NULL) { - if (fieldClass == int.class) { - unsafe.putInt(nodeInstance, offset, 0); - } else if (fieldClass == long.class) { - unsafe.putLong(nodeInstance, offset, 0L); - } else if (fieldClass == float.class) { - unsafe.putFloat(nodeInstance, offset, 0.0F); - } else if (fieldClass == double.class) { - unsafe.putDouble(nodeInstance, offset, 0.0D); - } else if (fieldClass == byte.class) { - unsafe.putByte(nodeInstance, offset, (byte) 0); - } else if (fieldClass == short.class) { - unsafe.putShort(nodeInstance, offset, (short) 0); - } else if (fieldClass == char.class) { - unsafe.putChar(nodeInstance, offset, (char) 0); - } else if (fieldClass == boolean.class) { - unsafe.putBoolean(nodeInstance, offset, false); - } else { - unsafe.putObject(nodeInstance, offset, null); - } + deserializeDataFieldsLengthNull(nodeInstance, fieldClass, offset); } else { - if (fieldClass == int.class) { - unsafe.putInt(nodeInstance, offset, cp.getInt(cpi)); - } else if (fieldClass == long.class) { - unsafe.putLong(nodeInstance, offset, cp.getLong(cpi)); - } else if (fieldClass == float.class) { - unsafe.putFloat(nodeInstance, offset, cp.getFloat(cpi)); - } else if (fieldClass == double.class) { - unsafe.putDouble(nodeInstance, offset, cp.getDouble(cpi)); - } else if (fieldClass == byte.class) { - unsafe.putByte(nodeInstance, offset, (byte) cp.getInt(cpi)); - } else if (fieldClass == short.class) { - unsafe.putShort(nodeInstance, offset, (short) cp.getInt(cpi)); - } else if (fieldClass == char.class) { - unsafe.putChar(nodeInstance, offset, (char) cp.getInt(cpi)); - } else if (fieldClass == boolean.class) { - unsafe.putBoolean(nodeInstance, offset, cp.getInt(cpi) == 1 ? true : false); - } else if (fieldClass == Integer.class) { - unsafe.putObject(nodeInstance, offset, cp.getInt(cpi)); - } else if (fieldClass == Long.class) { - unsafe.putObject(nodeInstance, offset, cp.getLong(cpi)); - } else if (fieldClass == Float.class) { - unsafe.putObject(nodeInstance, offset, cp.getFloat(cpi)); - } else if (fieldClass == Double.class) { - unsafe.putObject(nodeInstance, offset, cp.getDouble(cpi)); - } else if (fieldClass == Byte.class) { - unsafe.putObject(nodeInstance, offset, (byte) cp.getInt(cpi)); - } else if (fieldClass == Short.class) { - unsafe.putObject(nodeInstance, offset, (short) cp.getInt(cpi)); - } else if (fieldClass == Character.class) { - unsafe.putObject(nodeInstance, offset, (char) cp.getInt(cpi)); - } else if (fieldClass == Boolean.class) { - unsafe.putObject(nodeInstance, offset, cp.getInt(cpi) == 1 ? Boolean.TRUE : Boolean.FALSE); - } else { - unsafe.putObject(nodeInstance, offset, cp.getObject(fieldClass, cpi)); - } + deserializeDataFieldsDefault(nodeInstance, fieldClass, offset, cpi); } } } } + private void deserializeDataFieldsDefault(Node nodeInstance, Class fieldClass, long offset, int cpi) { + if (fieldClass == int.class) { + unsafe.putInt(nodeInstance, offset, cp.getInt(cpi)); + } else if (fieldClass == long.class) { + unsafe.putLong(nodeInstance, offset, cp.getLong(cpi)); + } else if (fieldClass == float.class) { + unsafe.putFloat(nodeInstance, offset, cp.getFloat(cpi)); + } else if (fieldClass == double.class) { + unsafe.putDouble(nodeInstance, offset, cp.getDouble(cpi)); + } else if (fieldClass == byte.class) { + unsafe.putByte(nodeInstance, offset, (byte) cp.getInt(cpi)); + } else if (fieldClass == short.class) { + unsafe.putShort(nodeInstance, offset, (short) cp.getInt(cpi)); + } else if (fieldClass == char.class) { + unsafe.putChar(nodeInstance, offset, (char) cp.getInt(cpi)); + } else if (fieldClass == boolean.class) { + unsafe.putBoolean(nodeInstance, offset, cp.getInt(cpi) == 1 ? true : false); + } else if (fieldClass == Integer.class) { + unsafe.putObject(nodeInstance, offset, cp.getInt(cpi)); + } else if (fieldClass == Long.class) { + unsafe.putObject(nodeInstance, offset, cp.getLong(cpi)); + } else if (fieldClass == Float.class) { + unsafe.putObject(nodeInstance, offset, cp.getFloat(cpi)); + } else if (fieldClass == Double.class) { + unsafe.putObject(nodeInstance, offset, cp.getDouble(cpi)); + } else if (fieldClass == Byte.class) { + unsafe.putObject(nodeInstance, offset, (byte) cp.getInt(cpi)); + } else if (fieldClass == Short.class) { + unsafe.putObject(nodeInstance, offset, (short) cp.getInt(cpi)); + } else if (fieldClass == Character.class) { + unsafe.putObject(nodeInstance, offset, (char) cp.getInt(cpi)); + } else if (fieldClass == Boolean.class) { + unsafe.putObject(nodeInstance, offset, cp.getInt(cpi) == 1 ? Boolean.TRUE : Boolean.FALSE); + } else { + unsafe.putObject(nodeInstance, offset, cp.getObject(fieldClass, cpi)); + } + } + + private static void deserializeDataFieldsLengthNull(Node nodeInstance, Class fieldClass, long offset) { + if (fieldClass == int.class) { + unsafe.putInt(nodeInstance, offset, 0); + } else if (fieldClass == long.class) { + unsafe.putLong(nodeInstance, offset, 0L); + } else if (fieldClass == float.class) { + unsafe.putFloat(nodeInstance, offset, 0.0F); + } else if (fieldClass == double.class) { + unsafe.putDouble(nodeInstance, offset, 0.0D); + } else if (fieldClass == byte.class) { + unsafe.putByte(nodeInstance, offset, (byte) 0); + } else if (fieldClass == short.class) { + unsafe.putShort(nodeInstance, offset, (short) 0); + } else if (fieldClass == char.class) { + unsafe.putChar(nodeInstance, offset, (char) 0); + } else if (fieldClass == boolean.class) { + unsafe.putBoolean(nodeInstance, offset, false); + } else { + unsafe.putObject(nodeInstance, offset, null); + } + } + private void deserializeChildFields(Node parent, NodeField[] nodeFields) { for (int i = nodeFields.length - 1; i >= 0; i--) { NodeField field = nodeFields[i]; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java Wed Jul 30 10:39:39 2014 -0700 @@ -115,28 +115,7 @@ } else if (fieldClass == boolean.class) { cpi = cp.putInt(unsafe.getBoolean(node, offset) ? 1 : 0); } else { - Object value = unsafe.getObject(node, offset); - if (value == null) { - cpi = VariableLengthIntBuffer.NULL; - } else if (fieldClass == Integer.class) { - cpi = cp.putInt((Integer) value); - } else if (fieldClass == Long.class) { - cpi = cp.putLong((Long) value); - } else if (fieldClass == Float.class) { - cpi = cp.putFloat((Float) value); - } else if (fieldClass == Double.class) { - cpi = cp.putDouble((Double) value); - } else if (fieldClass == Byte.class) { - cpi = cp.putInt((Byte) value); - } else if (fieldClass == Short.class) { - cpi = cp.putInt((Short) value); - } else if (fieldClass == Character.class) { - cpi = cp.putInt((Character) value); - } else if (fieldClass == Boolean.class) { - cpi = cp.putInt((Boolean) value ? 1 : 0); - } else { - cpi = cp.putObject(fieldClass, value); - } + cpi = serializeDataFieldsObject(node, fieldClass, offset); } buffer.put(cpi); @@ -144,6 +123,31 @@ } } + private int serializeDataFieldsObject(Node node, Class fieldClass, long offset) { + Object value = unsafe.getObject(node, offset); + if (value == null) { + return VariableLengthIntBuffer.NULL; + } else if (fieldClass == Integer.class) { + return cp.putInt((Integer) value); + } else if (fieldClass == Long.class) { + return cp.putLong((Long) value); + } else if (fieldClass == Float.class) { + return cp.putFloat((Float) value); + } else if (fieldClass == Double.class) { + return cp.putDouble((Double) value); + } else if (fieldClass == Byte.class) { + return cp.putInt((Byte) value); + } else if (fieldClass == Short.class) { + return cp.putInt((Short) value); + } else if (fieldClass == Character.class) { + return cp.putInt((Character) value); + } else if (fieldClass == Boolean.class) { + return cp.putInt((Boolean) value ? 1 : 0); + } else { + return cp.putObject(fieldClass, value); + } + } + private void serializeChildrenFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException { for (int i = 0; i < nodeFields.length; i++) { NodeField field = nodeFields[i]; diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Wed Jul 30 10:39:39 2014 -0700 @@ -152,7 +152,7 @@ if (sourceCallback != null) { sourceCallback.startLoading(source); } - Parser.parseSL(context, source); + Parser.parseSL(context, source, null); if (sourceCallback != null) { sourceCallback.endLoading(source); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Wed Jul 30 10:39:39 2014 -0700 @@ -50,6 +50,6 @@ private static void doDefineFunction(SLContext context, String code) { Source source = Source.fromText(code, "[defineFunction]"); /* The same parsing code as for parsing the initial source. */ - Parser.parseSL(context, source); + Parser.parseSL(context, source, null); } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java Wed Jul 30 10:39:39 2014 -0700 @@ -41,7 +41,7 @@ @Specialization public String change() { - FrameInstance frameInstance = Truffle.getRuntime().getStackTrace().iterator().next(); + FrameInstance frameInstance = Truffle.getRuntime().getCallerFrame(); Frame frame = frameInstance.getFrame(FrameAccess.READ_WRITE, false); FrameSlot slot = frame.getFrameDescriptor().findOrAddFrameSlot("hello"); frame.setObject(slot, "world"); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java Wed Jul 30 10:39:39 2014 -0700 @@ -50,13 +50,11 @@ @SlowPath private static String createStackTrace() { StringBuilder str = new StringBuilder(); - Iterable frames = Truffle.getRuntime().getStackTrace(); - if (frames != null) { - for (FrameInstance frame : frames) { - dumpFrame(str, frame.getCallTarget(), frame.getFrame(FrameAccess.READ_ONLY, true), frame.isVirtualFrame()); - } - } + Truffle.getRuntime().iterateFrames(frameInstance -> { + dumpFrame(str, frameInstance.getCallTarget(), frameInstance.getFrame(FrameAccess.READ_ONLY, true), frameInstance.isVirtualFrame()); + return null; + }); return str.toString(); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,50 @@ +/* + * 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.truffle.sl.factory; + +import java.io.*; + +import com.oracle.truffle.sl.nodes.instrument.*; +import com.oracle.truffle.sl.runtime.*; + +public final class SLContextFactory { + + private static SLASTProber astProber; + + private SLContextFactory() { + + } + + public static SLContext create() { + final SLContext slContext = new SLContext(new BufferedReader(new InputStreamReader(System.in)), System.out); + slContext.initialize(); + slContext.setVisualizer(new SLDefaultVisualizer()); + astProber = new SLASTProber(); + slContext.setASTNodeProber(astProber); + return slContext; + } + + public static void addNodeProber(SLNodeProber nodeProber) { + astProber.addNodeProber(nodeProber); + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Wed Jul 30 10:39:39 2014 -0700 @@ -42,4 +42,8 @@ * Execute this node as as statement, where no return value is necessary. */ public abstract void executeVoid(VirtualFrame frame); + + public SLStatementNode getNonWrapperNode() { + return this; + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,169 @@ +/* + * 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.truffle.sl.nodes.instrument; + +import java.io.*; +import java.util.*; + +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; +import com.oracle.truffle.api.source.*; + +/** + * SLASTPrinter is used to print for SL's internal Truffle AST. This is used by + * {@link SLDefaultVisualizer} to provide a means of displaying the internal Truffle AST + */ +public final class SLASTPrinter implements ASTPrinter { + public SLASTPrinter() { + } + + 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()); + } else if (src instanceof NullSourceSection) { + final NullSourceSection nullSection = (NullSourceSection) src; + p.print(nullSection.getShortDescription()); + } + } + if (node instanceof SyntaxTagged) { + final SyntaxTagged taggedNode = (SyntaxTagged) node; + p.print("["); + String prefix = ""; + for (SyntaxTag tag : taggedNode.getSyntaxTags()) { + p.print(prefix); + prefix = ","; + p.print(tag.toString()); + } + p.print("]"); + } + + ArrayList 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(); + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,118 @@ +/* + * 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.truffle.sl.nodes.instrument; + +import java.util.*; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; + +/** + * SLASTProber contains the collection of {@link SLNodeProber}s and methods to attach the probers to + * nodes. + */ +public final class SLASTProber implements ASTProber, SLNodeProber { + + private ArrayList nodeProbers = new ArrayList<>(); + + public SLASTProber() { + } + + /** + * Adds a {@link SLNodeProber} to this SLASTProber. Probes must be of type {@link SLNodeProber} + * and must not already have been added. + * + * @param nodeProber the {@link SLNodeProber} to add. + */ + public void addNodeProber(ASTNodeProber nodeProber) { + if (nodeProber instanceof SLNodeProber) { + assert !nodeProbers.contains(nodeProber); + nodeProbers.add((SLNodeProber) nodeProber); + } else { + throw new IllegalArgumentException("invalid prober for SL implementation"); + } + } + + /** + * Unimplemented, does nothing. + */ + public Node probeAs(Node astNode, SyntaxTag tag, Object... args) { + return astNode; + } + + /** + * Attaches the current probers to the given {@link SLStatementNode} as a statement. + * + * @param node The {@link SLStatementNode} to attach the stored set of probers to. + */ + @Override + public SLStatementNode probeAsStatement(SLStatementNode node) { + SLStatementNode result = node; + for (SLNodeProber nodeProber : nodeProbers) { + result = nodeProber.probeAsStatement(result); + } + return result; + } + + /** + * Attaches the current probers to the given {@link SLExpressionNode} as a call. This will wrap + * the passed in node in an {@link SLExpressionWrapper}, tag it as a call and attach an + * instrument to it. + * + * @param node The {@link SLExpressionNode} to attach the stored set of probers to. + * @param callName The name of the call ??? + * + */ + @Override + public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) { + SLExpressionNode result = node; + for (SLNodeProber nodeProber : nodeProbers) { + result = nodeProber.probeAsCall(node, callName); + } + return result; + } + + /** + * Attaches the current probers to the given {@link SLExpressionNode} as an assignment. This + * will wrap the passed in node in an {@link SLExpressionWrapper}, tag it as an assignment and + * attach an instrument to it. + * + * @param node The {@link SLExpressionNode} to attached the stored set of probers to. + * @param localName The name of the assignment ??? + * + */ + @Override + public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) { + SLExpressionNode result = node; + for (SLNodeProber nodeProber : nodeProbers) { + result = nodeProber.probeAsLocalAssignment(result, localName); + } + return result; + } + + public ASTNodeProber getCombinedNodeProber() { + return nodeProbers.isEmpty() ? null : this; + } + +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,89 @@ +/* + * 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.truffle.sl.nodes.instrument; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.instrument.impl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * SLDefaultVisualizer provides methods to get the names of SL's internal Truffle AST nodes. + * + */ +public class SLDefaultVisualizer extends DefaultVisualizer { + + private final SLASTPrinter astPrinter; + + public SLDefaultVisualizer() { + this.astPrinter = new SLASTPrinter(); + } + + @Override + public ASTPrinter getASTPrinter() { + return astPrinter; + } + + @Override + public String displayMethodName(Node node) { + + if (node == null) { + return null; + } + RootNode root = node.getRootNode(); + if (root instanceof SLRootNode) { + SLRootNode slRootNode = (SLRootNode) root; + return slRootNode.toString(); + + } + return "unknown"; + } + + @Override + public String displayCallTargetName(CallTarget callTarget) { + if (callTarget instanceof RootCallTarget) { + final RootCallTarget rootCallTarget = (RootCallTarget) callTarget; + SLRootNode slRootNode = (SLRootNode) rootCallTarget.getRootNode(); + return slRootNode.toString(); + } + return callTarget.toString(); + } + + @Override + public String displayValue(ExecutionContext context, Object value) { + if (value == SLNull.SINGLETON) { + return "null"; + } + return value.toString(); + } + + @Override + public String displayIdentifier(FrameSlot slot) { + + final Object id = slot.getIdentifier(); + return id.toString(); + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,148 @@ +/* + * 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.truffle.sl.nodes.instrument; + +import java.math.*; + +import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * SLExpressionWrapper is a Truffle AST node that gets inserted as the parent to the node that it is + * wrapping. Any debugging instruments are attached to this wrapper through {@link Probe}s (which + * themselves contain the instruments. It is through this mechanism that tools can interact directly + * with the AST.
    + * {@link SLExpressionWrapper} specifically wraps {@link SLExpressionNode}s and overrides the + * various execute functions in {@link SLExpressionNode} to operate on the child of the wrapper + * instead of the wrapper itself. + * + */ +public final class SLExpressionWrapper extends SLExpressionNode implements Wrapper { + @Child private SLExpressionNode child; + + private final Probe probe; + + public SLExpressionWrapper(SLContext context, SLExpressionNode child) { + super(child.getSourceSection()); + assert !(child instanceof SLExpressionWrapper); + this.child = insert(child); + this.probe = context.getProbe(child.getSourceSection()); + } + + @Override + public SLExpressionNode getNonWrapperNode() { + return child; + } + + @Override + public Node getChild() { + return child; + } + + @Override + public Probe getProbe() { + return probe; + } + + @Override + @SlowPath + public boolean isTaggedAs(SyntaxTag tag) { + return probe.isTaggedAs(tag); + } + + @Override + @SlowPath + public Iterable getSyntaxTags() { + return probe.getSyntaxTags(); + } + + @SlowPath + public void tagAs(SyntaxTag tag) { + probe.tagAs(tag); + } + + @Override + public Object executeGeneric(VirtualFrame frame) { + this.tagAs(StandardSyntaxTag.STATEMENT); + probe.enter(child, frame); + Object result; + + try { + result = child.executeGeneric(frame); + probe.leave(child, frame, result); + } catch (Exception e) { + probe.leaveExceptional(child, frame, e); + throw (e); + } + return result; + } + + @Override + public long executeLong(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + return SLTypesGen.SLTYPES.expectLong(executeGeneric(frame)); + } + + @Override + public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + return SLTypesGen.SLTYPES.expectBigInteger(executeGeneric(frame)); + } + + @Override + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + return SLTypesGen.SLTYPES.expectBoolean(executeGeneric(frame)); + } + + @Override + public String executeString(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + return SLTypesGen.SLTYPES.expectString(executeGeneric(frame)); + } + + @Override + public SLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + probe.enter(child, frame); + SLFunction result; + + try { + result = child.executeFunction(frame); + probe.leave(child, frame, result); + } catch (Exception e) { + probe.leaveExceptional(child, frame, e); + throw (e); + } + return result; + } + + @Override + public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame)); + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLNodeProber.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLNodeProber.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,35 @@ +/* + * 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.truffle.sl.nodes.instrument; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.sl.nodes.*; + +public interface SLNodeProber extends ASTNodeProber { + + SLStatementNode probeAsStatement(SLStatementNode result); + + SLExpressionNode probeAsCall(SLExpressionNode node, String callName); + + SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName); +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java Wed Jul 30 10:39:39 2014 -0700 @@ -0,0 +1,99 @@ +/* + * 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.truffle.sl.nodes.instrument; + +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * SLStatmentWrapper is a Truffle AST node that gets inserted as the parent to the node that it is + * wrapping. Any debugging instruments are attached to this wrapper through {@link Probe}s (which + * themselves contain the instruments). It is through this mechanism that tools can interact + * directly with the AST.
    + * SLStatmentWrapper specifically wraps {@link SLStatementWrapper}s and overrides the executeVoid + * function of {@link SLStatementNode} to operate on the child of the wrapper instead of the wrapper + * itself. + * + */ +public final class SLStatementWrapper extends SLStatementNode implements Wrapper { + + @Child private SLStatementNode child; + + private final Probe probe; + + public SLStatementWrapper(SLContext context, SLStatementNode child) { + super(child.getSourceSection()); + assert !(child instanceof SLStatementWrapper); + this.child = insert(child); + this.probe = context.getProbe(child.getSourceSection()); + } + + @Override + public SLStatementNode getNonWrapperNode() { + return child; + } + + public Node getChild() { + return child; + } + + public Probe getProbe() { + return probe; + } + + @SlowPath + public boolean isTaggedAs(SyntaxTag tag) { + return probe.isTaggedAs(tag); + } + + @SlowPath + public Iterable getSyntaxTags() { + return probe.getSyntaxTags(); + } + + @SlowPath + public void tagAs(SyntaxTag tag) { + probe.tagAs(tag); + } + + @Override + public void executeVoid(VirtualFrame frame) { + this.tagAs(StandardSyntaxTag.STATEMENT); + probe.enter(child, frame); + + try { + child.executeVoid(frame); + probe.leave(child, frame); + } catch (KillException e) { + throw (e); + } catch (Exception e) { + probe.leaveExceptional(child, frame, e); + throw (e); + } + + } +} diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Wed Jul 30 10:39:39 2014 -0700 @@ -33,6 +33,7 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; // Checkstyle: stop @@ -51,9 +52,9 @@ public final Errors errors; private final SLNodeFactory factory; -->declarations - public Parser(SLContext context, Source source) { + public Parser(SLContext context, Source source, SLNodeProber astProber) { this.scanner = new Scanner(source.getInputStream()); - this.factory = new SLNodeFactory(context, source); + this.factory = new SLNodeFactory(context, source, astProber); errors = new Errors(); } @@ -134,8 +135,8 @@ -->initialization }; - public static void parseSL(SLContext context, Source source) { - Parser parser = new Parser(context, source); + public static void parseSL(SLContext context, Source source, SLNodeProber astProber) { + Parser parser = new Parser(context, source, astProber); parser.Parse(); if (parser.errors.errors.size() > 0) { StringBuilder msg = new StringBuilder("Error(s) parsing script:\n"); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Wed Jul 30 10:39:39 2014 -0700 @@ -30,6 +30,7 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; // Checkstyle: stop @@ -52,10 +53,10 @@ public final Scanner scanner; public final Errors errors; private final SLNodeFactory factory; - - public Parser(SLContext context, Source source) { + + public Parser(SLContext context, Source source, SLNodeProber astProber) { this.scanner = new Scanner(source.getInputStream()); - this.factory = new SLNodeFactory(context, source); + this.factory = new SLNodeFactory(context, source, astProber); errors = new Errors(); } @@ -133,41 +134,41 @@ void Function() { Expect(4); Expect(1); - factory.startFunction(t); + factory.startFunction(t); Expect(5); if (la.kind == 1) { Get(); - factory.addFormalParameter(t); + factory.addFormalParameter(t); while (la.kind == 6) { Get(); Expect(1); - factory.addFormalParameter(t); + factory.addFormalParameter(t); } } Expect(7); SLStatementNode body = Block(false); - factory.finishFunction(body); + factory.finishFunction(body); } SLStatementNode Block(boolean inLoop) { SLStatementNode result; factory.startBlock(); - List body = new ArrayList<>(); + List body = new ArrayList<>(); Expect(8); - int lBracePos = t.charPos; + int lBracePos = t.charPos; while (StartOf(1)) { SLStatementNode s = Statement(inLoop); - body.add(s); + body.add(s); } Expect(9); - int length = (t.charPos + t.val.length()) - lBracePos; - result = factory.finishBlock(body, lBracePos, length); + int length = (t.charPos + t.val.length()) - lBracePos; + result = factory.finishBlock(body, lBracePos, length); return result; } SLStatementNode Statement(boolean inLoop) { SLStatementNode result; - result = null; + result = null; switch (la.kind) { case 13: { result = WhileStatement(); @@ -175,13 +176,13 @@ } case 10: { Get(); - if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } + if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } Expect(11); break; } case 12: { Get(); - if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } + if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } Expect(11); break; } @@ -207,11 +208,11 @@ SLStatementNode result; Expect(13); Expect(5); - Token whileToken = t; + Token whileToken = t; SLExpressionNode condition = Expression(); Expect(7); SLStatementNode body = Block(true); - result = factory.createWhile(whileToken, condition, body); + result = factory.createWhile(whileToken, condition, body); return result; } @@ -219,16 +220,16 @@ SLStatementNode result; Expect(14); Expect(5); - Token ifToken = t; + Token ifToken = t; SLExpressionNode condition = Expression(); Expect(7); SLStatementNode thenPart = Block(inLoop); - SLStatementNode elsePart = null; + SLStatementNode elsePart = null; if (la.kind == 15) { Get(); elsePart = Block(inLoop); } - result = factory.createIf(ifToken, condition, thenPart, elsePart); + result = factory.createIf(ifToken, condition, thenPart, elsePart); return result; } @@ -236,11 +237,11 @@ SLStatementNode result; Expect(16); Token returnToken = t; - SLExpressionNode value = null; + SLExpressionNode value = null; if (StartOf(2)) { value = Expression(); } - result = factory.createReturn(returnToken, value); + result = factory.createReturn(returnToken, value); Expect(11); return result; } @@ -250,9 +251,9 @@ result = LogicTerm(); while (la.kind == 17) { Get(); - Token op = t; + Token op = t; SLExpressionNode right = LogicTerm(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -262,9 +263,9 @@ result = LogicFactor(); while (la.kind == 18) { Get(); - Token op = t; + Token op = t; SLExpressionNode right = LogicFactor(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -299,9 +300,9 @@ break; } } - Token op = t; + Token op = t; SLExpressionNode right = Arithmetic(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -315,9 +316,9 @@ } else { Get(); } - Token op = t; + Token op = t; SLExpressionNode right = Term(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -331,48 +332,48 @@ } else { Get(); } - Token op = t; + Token op = t; SLExpressionNode right = Factor(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } SLExpressionNode Factor() { SLExpressionNode result; - result = null; + result = null; if (la.kind == 1) { Get(); - Token nameToken = t; + Token nameToken = t; if (la.kind == 5) { Get(); List parameters = new ArrayList<>(); - SLExpressionNode parameter; + SLExpressionNode parameter; if (StartOf(2)) { parameter = Expression(); - parameters.add(parameter); + parameters.add(parameter); while (la.kind == 6) { Get(); parameter = Expression(); - parameters.add(parameter); + parameters.add(parameter); } } Expect(7); - Token finalToken = t; - result = factory.createCall(nameToken, parameters, finalToken); + Token finalToken = t; + result = factory.createCall(nameToken, parameters, finalToken); } else if (la.kind == 29) { Get(); SLExpressionNode value = Expression(); - result = factory.createAssignment(nameToken, value); + result = factory.createAssignment(nameToken, value); } else if (StartOf(4)) { - result = factory.createRead(nameToken); + result = factory.createRead(nameToken); } else SynErr(32); } else if (la.kind == 2) { Get(); - result = factory.createStringLiteral(t); + result = factory.createStringLiteral(t); } else if (la.kind == 3) { Get(); - result = factory.createNumericLiteral(t); + result = factory.createNumericLiteral(t); } else if (la.kind == 5) { Get(); result = Expression(); @@ -401,8 +402,8 @@ }; - public static void parseSL(SLContext context, Source source) { - Parser parser = new Parser(context, source); + public static void parseSL(SLContext context, Source source, SLNodeProber astProber) { + Parser parser = new Parser(context, source, astProber); parser.Parse(); if (parser.errors.errors.size() > 0) { StringBuilder msg = new StringBuilder("Error(s) parsing script:\n"); diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Wed Jul 30 10:39:39 2014 -0700 @@ -32,6 +32,7 @@ import com.oracle.truffle.sl.nodes.call.*; import com.oracle.truffle.sl.nodes.controlflow.*; import com.oracle.truffle.sl.nodes.expression.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.nodes.local.*; import com.oracle.truffle.sl.runtime.*; @@ -72,9 +73,12 @@ /* State while parsing a block. */ private LexicalScope lexicalScope; - public SLNodeFactory(SLContext context, Source source) { + private final SLNodeProber prober; + + public SLNodeFactory(SLContext context, Source source, SLNodeProber prober) { this.context = context; this.source = source; + this.prober = prober; } public void startFunction(Token nameToken) { @@ -179,6 +183,14 @@ public SLStatementNode createIf(Token t, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { final int start = t.charPos; final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex(); + + // if (prober != null) { + // SLStatementNode wrappedThenNode = prober.probeAsStatement(thenPartNode); + // // SLStatementNode wrappedElseNode = prober.probeAsStatement(elsePartNode); + // return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode, + // wrappedThenNode, elsePartNode); + // } + return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode, thenPartNode, elsePartNode); } @@ -227,6 +239,10 @@ final int endPos = finalToken.charPos + finalToken.val.length(); final SourceSection src = source.createSection(nameToken.val, startPos, endPos - startPos); SLExpressionNode functionNode = createRead(nameToken); + if (prober != null) { + SLExpressionNode wrappedNode = prober.probeAsCall(functionNode, nameToken.val); + return SLInvokeNode.create(src, wrappedNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])); + } return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])); } @@ -235,6 +251,10 @@ lexicalScope.locals.put(nameToken.val, frameSlot); final int start = nameToken.charPos; final int length = valueNode.getSourceSection().getCharEndIndex() - start; + if (prober != null) { + final SLExpressionNode wrappedNode = prober.probeAsLocalAssignment(valueNode, nameToken.val); + return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), wrappedNode, frameSlot); + } return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot); } diff -r f1fba319d4e3 -r e7b7a5be4d21 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Wed Jul 30 09:36:32 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Wed Jul 30 10:39:39 2014 -0700 @@ -29,8 +29,11 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.builtins.*; import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.nodes.local.*; import com.oracle.truffle.sl.parser.*; @@ -49,6 +52,7 @@ private final PrintStream output; private final SLFunctionRegistry functionRegistry; private SourceCallback sourceCallback = null; + private SLASTProber astProber; public SLContext(BufferedReader input, PrintStream output) { this.input = input; @@ -133,4 +137,28 @@ /* Register the builtin function in our function registry. */ getFunctionRegistry().register(name, rootNode); } + + public void executeMain(Source source) { + + if (sourceCallback != null) { + sourceCallback.startLoading(source); + } + + Parser.parseSL(this, source, astProber); + + if (sourceCallback != null) { + sourceCallback.endLoading(source); + } + + SLFunction main = getFunctionRegistry().lookup("main"); + if (main.getCallTarget() == null) { + throw new SLException("No function main() defined in SL source file."); + } + main.getCallTarget().call(); + } + + public void setASTNodeProber(SLASTProber astProber) { + // TODO Auto-generated method stub + this.astProber = astProber; + } } diff -r f1fba319d4e3 -r e7b7a5be4d21 mx/mx_graal.py --- a/mx/mx_graal.py Wed Jul 30 09:36:32 2014 -0700 +++ b/mx/mx_graal.py Wed Jul 30 10:39:39 2014 -0700 @@ -484,17 +484,30 @@ if exists(toDelete): os.unlink(toDelete) +def _makeHotspotGeneratedSourcesDir(): + hsSrcGenDir = join(mx.project('com.oracle.graal.hotspot').source_gen_dir(), 'hotspot') + if not exists(hsSrcGenDir): + os.makedirs(hsSrcGenDir) + return hsSrcGenDir + + def _update_graalRuntime_inline_hpp(graalJar): p = mx.project('com.oracle.graal.hotspot.sourcegen') mainClass = 'com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp' if exists(join(p.output_dir(), mainClass.replace('.', os.sep) + '.class')): - hsSrcGenDir = join(mx.project('com.oracle.graal.hotspot').source_gen_dir(), 'hotspot') - if not exists(hsSrcGenDir): - os.makedirs(hsSrcGenDir) - + graalRuntime_inline_hpp = join(_makeHotspotGeneratedSourcesDir(), 'graalRuntime.inline.hpp') tmp = StringIO.StringIO() mx.run_java(['-cp', '{}{}{}'.format(graalJar, os.pathsep, p.output_dir()), mainClass], out=tmp.write) - mx.update_file(join(hsSrcGenDir, 'graalRuntime.inline.hpp'), tmp.getvalue()) + mx.update_file(graalRuntime_inline_hpp, tmp.getvalue()) + +def _checkVMIsNewerThanGeneratedSources(jdk, vm, bld): + if isGraalEnabled(vm) and (not _installed_jdks or _installed_jdks == _graal_home): + vmLib = mx.TimeStampFile(join(_vmLibDirInJdk(jdk), vm, mx.add_lib_prefix(mx.add_lib_suffix('jvm')))) + for name in ['graalRuntime.inline.hpp', 'HotSpotVMConfig.inline.hpp']: + genSrc = join(_makeHotspotGeneratedSourcesDir(), name) + if vmLib.isOlderThan(genSrc): + mx.log('The VM ' + vmLib.path + ' is older than ' + genSrc) + mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build"') def _installGraalJarInJdks(graalDist): graalJar = graalDist.path @@ -618,6 +631,35 @@ mx.log('') mx.log('Note that these variables can be given persistent values in the file ' + join(_graal_home, 'mx', 'env') + ' (see \'mx about\').') +cached_graal_version = None + +def graal_version(dev_suffix='dev'): + global cached_graal_version + + if not cached_graal_version: + # extract latest release tag for graal + try: + tags = [x.split() for x in subprocess.check_output(['hg', '-R', _graal_home, 'tags']).split('\n') if x.startswith("graal-")] + current_revision = subprocess.check_output(['hg', '-R', _graal_home, 'id', '-i']).strip() + except: + # not a mercurial repository or hg commands are not available. + tags = None + + if tags and current_revision: + sorted_tags = sorted(tags, key=lambda e: [int(x) for x in e[0][len("graal-"):].split('.')], reverse=True) + most_recent_tag_name, most_recent_tag_revision = sorted_tags[0] + most_recent_tag_version = most_recent_tag_name[len("graal-"):] + + if current_revision == most_recent_tag_revision: + cached_graal_version = most_recent_tag_version + else: + major, minor = map(int, most_recent_tag_version.split('.')) + cached_graal_version = str(major) + '.' + str(minor + 1) + '-' + dev_suffix + else: + cached_graal_version = 'unknown-{}-{}'.format(platform.node(), time.strftime('%Y-%m-%d_%H-%M-%S_%Z')) + + return cached_graal_version + def build(args, vm=None): """build the VM binary @@ -778,22 +820,9 @@ setMakeVar('INCLUDE_GRAAL', 'false') setMakeVar('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os()), env=env) else: - # extract latest release tag for graal - try: - tags = [x.split(' ')[0] for x in subprocess.check_output(['hg', '-R', _graal_home, 'tags']).split('\n') if x.startswith("graal-")] - except: - # not a mercurial repository or hg commands are not available. - tags = None - - if tags: - # extract the most recent tag - tag = sorted(tags, key=lambda e: [int(x) for x in e[len("graal-"):].split('.')], reverse=True)[0] - setMakeVar('USER_RELEASE_SUFFIX', tag) - setMakeVar('GRAAL_VERSION', tag[len("graal-"):]) - else: - version = 'unknown-{}-{}'.format(platform.node(), time.strftime('%Y-%m-%d_%H-%M-%S_%Z')) - setMakeVar('USER_RELEASE_SUFFIX', 'graal-' + version) - setMakeVar('GRAAL_VERSION', version) + version = graal_version() + setMakeVar('USER_RELEASE_SUFFIX', 'graal-' + version) + setMakeVar('GRAAL_VERSION', version) setMakeVar('INCLUDE_GRAAL', 'true') setMakeVar('INSTALL', 'y', env=env) if mx.get_os() == 'solaris': @@ -885,6 +914,7 @@ build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product' jdk = _jdk(build, vmToCheck=vm, installGraalJar=False) _updateInstalledGraalOptionsFile(jdk) + _checkVMIsNewerThanGeneratedSources(jdk, vm, build) mx.expand_project_in_args(args) if _make_eclipse_launch: mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True)) @@ -1054,7 +1084,7 @@ graalDist = mx.distribution('GRAAL') graalJarCp = set([d.output_dir() for d in graalDist.sorted_deps()]) cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in graalJarCp]) - vmArgs = vmArgs + ['-XX:-UseGraalClassLoader'] + vmArgs = ['-XX:-UseGraalClassLoader'] + vmArgs if len(testclasses) == 1: # Execute Junit directly when one test is being run. This simplifies @@ -1473,6 +1503,12 @@ mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]') mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-l', fp.name, 'run'], env=env) +def install(args): + """install Truffle into your local Maven repository""" + mx.archive(["@TRUFFLE"]) + mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle', '-DartifactId=truffle', '-Dversion=' + graal_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=truffle.jar']) + mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle', '-DartifactId=truffle-dsl-processor', '-Dversion=' + graal_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=truffle-dsl-processor.jar']) + def c1visualizer(args): """run the Cl Compiler Visualizer""" libpath = join(_graal_home, 'lib') @@ -1481,10 +1517,14 @@ else: executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer') - 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_2014-04-22.zip']) + # Check whether the current C1Visualizer installation is the up-to-date + if exists(executable) and not exists(mx.library('C1VISUALIZER_DIST').get_path(resolve=False)): + mx.log('Updating C1Visualizer') + shutil.rmtree(join(libpath, 'c1visualizer')) + + archive = mx.library('C1VISUALIZER_DIST').get_path(resolve=True) + + if not exists(executable): zf = zipfile.ZipFile(archive, 'r') zf.extractall(libpath) @@ -1827,8 +1867,20 @@ flavor = 'att' lib = mx.add_lib_suffix('hsdis-' + _arch()) path = join(_graal_home, 'lib', lib) + + sha1s = { + 'att/hsdis-amd64.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72', + 'att/hsdis-amd64.so' : '58919ba085d4ef7a513f25bae75e7e54ee73c049', + 'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30', + 'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192', + 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2', + } + if not exists(path): - mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavor + "/" + lib]) + flavoredLib = flavor + "/" + lib + sha1 = sha1s[flavoredLib] + sha1path = path + '.sha1' + mx.download_file_with_sha1('hsdis', path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False) if copyToDir is not None and exists(copyToDir): shutil.copy(path, copyToDir) @@ -1844,10 +1896,8 @@ args = parser.parse_args(args) - path = join(_graal_home, 'lib', 'hcfdis-1.jar') - if not exists(path): - mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-2.jar']) - mx.run_java(['-jar', path] + args.files) + path = mx.library('HCFDIS').get_path(resolve=True) + mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files) if args.map is not None: addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)') @@ -1904,11 +1954,7 @@ def jol(args): """Java Object Layout""" - jolurl = "http://lafo.ssw.uni-linz.ac.at/truffle/jol/jol-internals.jar" - joljar = "lib/jol-internals.jar" - if not exists(joljar): - mx.download(joljar, [jolurl]) - + joljar = mx.library('JOL_INTERNALS').get_path(resolve=True) candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s)) if len(candidates) > 10: print "Found %d candidates. Please be more precise." % (len(candidates)) @@ -2054,8 +2100,7 @@ if not exists(findbugsLib): tmp = tempfile.mkdtemp(prefix='findbugs-download-tmp', dir=_graal_home) try: - findbugsDist = join(tmp, 'findbugs.zip') - mx.download(findbugsDist, ['http://lafo.ssw.uni-linz.ac.at/graal-external-deps/findbugs-3.0.0.zip', 'http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0.zip']) + findbugsDist = mx.library('FINDBUGS_DIST').get_path(resolve=True) with zipfile.ZipFile(findbugsDist) as zf: candidates = [e for e in zf.namelist() if e.endswith('/lib/findbugs.jar')] assert len(candidates) == 1, candidates @@ -2123,6 +2168,7 @@ 'hsdis': [hsdis, '[att]'], 'hcfdis': [hcfdis, ''], 'igv' : [igv, ''], + 'install' : [install, ''], 'jdkhome': [print_jdkhome, ''], 'jmh': [jmh, '[VM options] [filters|JMH-args-as-json...]'], 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'], diff -r f1fba319d4e3 -r e7b7a5be4d21 mx/projects --- a/mx/projects Wed Jul 30 09:36:32 2014 -0700 +++ b/mx/projects Wed Jul 30 10:39:39 2014 -0700 @@ -20,8 +20,24 @@ library@HAMCREST@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/hamcrest-core-1.3-sources.jar,http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar library@HAMCREST@sourceSha1=1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b -library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar -library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar +#library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar +#library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar + +library@HCFDIS@path=lib/hcfdis-2.jar +library@HCFDIS@urls=http://lafo.ssw.uni-linz.ac.at/hcfdis-2.jar +library@HCFDIS@sha1=bc8b2253436485e9dbaf81771c259ccfa1a24c80 + +library@FINDBUGS_DIST@path=lib/findbugs-dist-3.0.0.zip +library@FINDBUGS_DIST@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/findbugs-3.0.0.zip,http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0.zip/download +library@FINDBUGS_DIST@sha1=6e56d67f238dbcd60acb88a81655749aa6419c5b + +library@C1VISUALIZER_DIST@path=lib/c1visualizer_2014-04-22.zip +library@C1VISUALIZER_DIST@urls=https://java.net/downloads/c1visualizer/c1visualizer_2014-04-22.zip +library@C1VISUALIZER_DIST@sha1=220488d87affb569b893c7201f8ce5d2b0e03141 + +library@JOL_INTERNALS@path=lib/jol-internals.jar +library@JOL_INTERNALS@urls=http://lafo.ssw.uni-linz.ac.at/truffle/jol/jol-internals.jar +library@JOL_INTERNALS@sha1=508bcd26a4d7c4c44048990c6ea789a3b11a62dc library@FINDBUGS@path=lib/findbugs-3.0.0.jar library@FINDBUGS@urls=jar:http://lafo.ssw.uni-linz.ac.at/graal-external-deps/findbugs-3.0.0.zip!/findbugs-3.0.0/lib/findbugs.jar,jar:http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0.zip/download!/findbugs-3.0.0/lib/findbugs.jar @@ -43,19 +59,19 @@ library@DACAPO_SCALA@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/dacapo-scala-0.1.0-20120216.jar,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.9.jar -library@OKRA@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.9.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.9.jar -library@OKRA@sha1=df450b04882e6b5a365299e2cbf1622038ae880e -library@OKRA@sourcePath=lib/okra-1.9-src.jar -library@OKRA@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.9-src.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.9-src.jar -library@OKRA@sourceSha1=41dcda5197ca4d87bc94e4d7b5a90e7f22667756 +library@OKRA@path=lib/okra-1.10.jar +library@OKRA@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.10.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.10.jar +library@OKRA@sha1=96eb3c0ec808ed944ba88d1eb9311058fe0f3d1e +library@OKRA@sourcePath=lib/okra-1.10-src.jar +library@OKRA@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.10-src.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.10-src.jar +library@OKRA@sourceSha1=75751bb148fcebaba78ff590f883a114b2b09176 -library@OKRA_WITH_SIM@path=lib/okra-1.9-with-sim.jar -library@OKRA_WITH_SIM@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.9-with-sim.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim.jar -library@OKRA_WITH_SIM@sha1=816fa24814cf51c02f9c05477447bb55a152b388 -library@OKRA_WITH_SIM@sourcePath=lib/okra-1.9-with-sim-src.jar -library@OKRA_WITH_SIM@sourceSha1=1628919457999a8479d9f39845865de527dbd523 -library@OKRA_WITH_SIM@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.9-with-sim-src.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim-src.jar +library@OKRA_WITH_SIM@path=lib/okra-1.10-with-sim.jar +library@OKRA_WITH_SIM@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.10-with-sim.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.10-with-sim.jar +library@OKRA_WITH_SIM@sha1=7b8db879f1dbcf571290add78d9af24e15a2a50d +library@OKRA_WITH_SIM@sourcePath=lib/okra-1.10-with-sim-src.jar +library@OKRA_WITH_SIM@sourceSha1=7eefd94f16a3e3fd3b8f470cf91e265c6f5e7767 +library@OKRA_WITH_SIM@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.10-with-sim-src.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.10-with-sim-src.jar library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar library@JAVA_ALLOCATION_INSTRUMENTER@sourcePath=lib/java-allocation-instrumenter.jar @@ -776,7 +792,7 @@ project@com.oracle.truffle.sl@sourceDirs=src project@com.oracle.truffle.sl@dependencies=com.oracle.truffle.api.dsl project@com.oracle.truffle.sl@checkstyle=com.oracle.graal.graph -project@com.oracle.truffle.sl@javaCompliance=1.7 +project@com.oracle.truffle.sl@javaCompliance=1.8 project@com.oracle.truffle.sl@annotationProcessors=com.oracle.truffle.dsl.processor project@com.oracle.truffle.sl@workingSets=Truffle,SimpleLanguage @@ -785,7 +801,7 @@ project@com.oracle.truffle.sl.test@sourceDirs=src project@com.oracle.truffle.sl.test@dependencies=com.oracle.truffle.sl,JUNIT project@com.oracle.truffle.sl.test@checkstyle=com.oracle.graal.graph -project@com.oracle.truffle.sl.test@javaCompliance=1.7 +project@com.oracle.truffle.sl.test@javaCompliance=1.8 project@com.oracle.truffle.sl.test@workingSets=Truffle,SimpleLanguage,Test # graal.truffle diff -r f1fba319d4e3 -r e7b7a5be4d21 mxtool/mx.py --- a/mxtool/mx.py Wed Jul 30 09:36:32 2014 -0700 +++ b/mxtool/mx.py Wed Jul 30 10:39:39 2014 -0700 @@ -487,10 +487,39 @@ return join(prefix, path) return path -def _download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False): +def sha1OfFile(path): + with open(path, 'rb') as f: + d = hashlib.sha1() + while True: + buf = f.read(4096) + if not buf: + break + d.update(buf) + return d.hexdigest() + +def download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False): def _download_lib(): - print 'Downloading ' + ("Sources " if sources else "") + name + ' from ' + str(urls) - download(path, urls) + cacheDir = get_env('MX_CACHE_DIR', join(_opts.user_home, '.mx', 'cache')) + if not exists(cacheDir): + os.makedirs(cacheDir) + base = basename(path) + cachePath = join(cacheDir, base + '_' + sha1) + + if not exists(cachePath) or sha1OfFile(cachePath) != sha1: + if exists(cachePath): + log('SHA1 of ' + cachePath + ' does not match expected value (' + sha1 + ') - re-downloading') + print 'Downloading ' + ("sources " if sources else "") + name + ' from ' + str(urls) + download(cachePath, urls) + + d = dirname(path) + if d != '' and not exists(d): + os.makedirs(d) + if 'symlink' in dir(os): + if exists(path): + os.unlink(path) + os.symlink(cachePath, path) + else: + shutil.copy(cachePath, path) def _sha1Cached(): with open(sha1path, 'r') as f: @@ -498,30 +527,21 @@ def _writeSha1Cached(): with open(sha1path, 'w') as f: - f.write(_sha1OfFile()) - - def _sha1OfFile(): - with open(path, 'rb') as f: - d = hashlib.sha1() - while True: - buf = f.read(4096) - if not buf: - break - d.update(buf) - return d.hexdigest() + f.write(sha1OfFile(path)) if resolve and mustExist and not exists(path): assert not len(urls) == 0, 'cannot find required library ' + name + ' ' + path _download_lib() - if sha1 and not exists(sha1path): - _writeSha1Cached() - - if sha1 and sha1 != _sha1Cached(): - _download_lib() - if sha1 != _sha1OfFile(): - abort("SHA1 does not match for " + name + ". Broken download? SHA1 not updated in projects file?") - _writeSha1Cached() + if exists(path): + if sha1 and not exists(sha1path): + _writeSha1Cached() + + if sha1 and sha1 != _sha1Cached(): + _download_lib() + if sha1 != sha1OfFile(path): + abort("SHA1 does not match for " + name + ". Broken download? SHA1 not updated in projects file?") + _writeSha1Cached() return path @@ -587,12 +607,26 @@ self.sha1 = sha1 self.sourcePath = sourcePath self.sourceUrls = sourceUrls + if sourcePath == path: + assert sourceSha1 is None or sourceSha1 == sha1 + sourceSha1 = sha1 self.sourceSha1 = sourceSha1 self.deps = deps - abspath = _make_absolute(self.path, self.suite.dir) + abspath = _make_absolute(path, self.suite.dir) if not optional and not exists(abspath): if not len(urls): abort('Non-optional library {} must either exist at {} or specify one or more URLs from which it can be retrieved'.format(name, abspath)) + + def _checkSha1PropertyCondition(propName, cond, inputPath): + if not cond: + absInputPath = _make_absolute(inputPath, self.suite.dir) + if exists(absInputPath): + abort('Missing "{}" property for library {}. Add the following line to projects file:\nlibrary@{}@{}={}'.format(propName, name, name, propName, sha1OfFile(absInputPath))) + abort('Missing "{}" property for library {}'.format(propName, name)) + + _checkSha1PropertyCondition('sha1', sha1, path) + _checkSha1PropertyCondition('sourceSha1', not sourcePath or sourceSha1, sourcePath) + for url in urls: if url.endswith('/') != self.path.endswith(os.sep): abort('Path for dependency directory must have a URL ending with "/": path=' + self.path + ' url=' + url) @@ -614,7 +648,7 @@ if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK): return None - return _download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, not self.optional) + return download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, not self.optional) def get_source_path(self, resolve): if self.sourcePath is None: @@ -622,7 +656,7 @@ path = _make_absolute(self.sourcePath, self.suite.dir) sha1path = path + '.sha1' - return _download_file_with_sha1(self.name, path, self.sourceUrls, self.sourceSha1, sha1path, resolve, len(self.sourceUrls) != 0, sources=True) + return download_file_with_sha1(self.name, path, self.sourceUrls, self.sourceSha1, sha1path, resolve, len(self.sourceUrls) != 0, sources=True) def append_to_classpath(self, cp, resolve): path = self.get_path(resolve) @@ -1736,9 +1770,18 @@ print e.output abort(e.returncode) - output = output.split() - assert output[1] == 'version' - self.version = VersionSpec(output[2].strip('"')) + def _checkOutput(out): + return 'version' in out + + # hotspot can print a warning, e.g. if there's a .hotspot_compiler file in the cwd + output = output.split('\n') + version = None + for o in output: + if _checkOutput(o): + assert version is None + version = o + + self.version = VersionSpec(version.split()[2].strip('"')) self.javaCompliance = JavaCompliance(self.version.versionString) if self.debug_port is not None: @@ -1751,8 +1794,8 @@ os.makedirs(outDir) javaSource = join(myDir, 'ClasspathDump.java') if not exists(join(outDir, 'ClasspathDump.class')): - subprocess.check_call([self.javac, '-d', outDir, javaSource]) - self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', outDir, 'ClasspathDump']).split('|')] + subprocess.check_call([self.javac, '-d', outDir, javaSource], stderr=subprocess.PIPE, stdout=subprocess.PIPE) + self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', outDir, 'ClasspathDump'], stderr=subprocess.PIPE).split('|')] if not self._bootclasspath or not self._extdirs or not self._endorseddirs: warn("Could not find all classpaths: boot='" + str(self._bootclasspath) + "' extdirs='" + str(self._extdirs) + "' endorseddirs='" + str(self._endorseddirs) + "'") self._bootclasspath = _filter_non_existant_paths(self._bootclasspath) diff -r f1fba319d4e3 -r e7b7a5be4d21 src/gpu/hsail/vm/gpu_hsail.cpp --- a/src/gpu/hsail/vm/gpu_hsail.cpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/gpu/hsail/vm/gpu_hsail.cpp Wed Jul 30 10:39:39 2014 -0700 @@ -72,18 +72,19 @@ void* Hsail::_device_context = NULL; jint Hsail::_notice_safepoints = false; -Hsail::okra_create_context_func_t Hsail::_okra_create_context; +Hsail::okra_get_context_func_t Hsail::_okra_get_context; Hsail::okra_create_kernel_func_t Hsail::_okra_create_kernel; -Hsail::okra_push_object_func_t Hsail::_okra_push_object; +Hsail::okra_push_pointer_func_t Hsail::_okra_push_pointer; Hsail::okra_push_boolean_func_t Hsail::_okra_push_boolean; Hsail::okra_push_byte_func_t Hsail::_okra_push_byte; Hsail::okra_push_double_func_t Hsail::_okra_push_double; Hsail::okra_push_float_func_t Hsail::_okra_push_float; Hsail::okra_push_int_func_t Hsail::_okra_push_int; Hsail::okra_push_long_func_t Hsail::_okra_push_long; -Hsail::okra_execute_with_range_func_t Hsail::_okra_execute_with_range; -Hsail::okra_clearargs_func_t Hsail::_okra_clearargs; -Hsail::okra_register_heap_func_t Hsail::_okra_register_heap; +Hsail::okra_execute_kernel_func_t Hsail::_okra_execute_kernel; +Hsail::okra_clear_args_func_t Hsail::_okra_clear_args; +Hsail::okra_dispose_kernel_func_t Hsail::_okra_dispose_kernel; +Hsail::okra_dispose_context_func_t Hsail::_okra_dispose_context; //static jint in_kernel = 0; @@ -98,16 +99,6 @@ _notice_safepoints = false; } -void Hsail::register_heap() { - // After the okra functions are set up and the heap is initialized, register the java heap with HSA - guarantee(Universe::heap() != NULL, "heap should be there by now."); - if (TraceGPUInteraction) { - tty->print_cr("[HSAIL] heap=" PTR_FORMAT, Universe::heap()); - tty->print_cr("[HSAIL] base=0x%08x, capacity=%ld", Universe::heap()->base(), Universe::heap()->capacity()); - } - _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity()); -} - GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args, jobject donor_threads, jint allocBytesPerWorkitem, jobject oop_map_array)) @@ -156,7 +147,7 @@ HSAILAllocationInfo* allocInfo = (donor_threads == NULL ? NULL : new HSAILAllocationInfo(donor_threads, dimX, allocBytesPerWorkitem)); // Reset the kernel arguments - _okra_clearargs(kernel); + _okra_clear_args(kernel); JavaThread* thread = (JavaThread*)THREAD; HSAILDeoptimizationInfo* e; @@ -194,13 +185,16 @@ } // Run the kernel - bool success = false; + jboolean success = false; { TraceTime t("execute kernel", TraceGPUInteraction); + graal_okra_range_t kernel_range = {0}; //in_kernel = 1; // Run the kernel - success = _okra_execute_with_range(kernel, dimX); + kernel_range.dimension = 1; + kernel_range.global_size[0] = dimX; + success = _okra_execute_kernel(_device_context, kernel, &kernel_range); //in_kernel = 0; } @@ -347,14 +341,12 @@ env->GetByteArrayRegion(code_handle, 0, code_len, (jbyte*) code); env->GetStringUTFRegion(name_handle, 0, name_len, name); - register_heap(); - // The kernel entrypoint is always run for the time being const char* entryPointName = "&run"; - - _device_context = _okra_create_context(); - - return (jlong) _okra_create_kernel(_device_context, code, entryPointName); + jlong okra_kernel; + jint okra_status = _okra_create_kernel(_device_context, code, entryPointName, (void**)&okra_kernel); + guarantee(okra_status==0, "_okra_create_kernel failed"); + return (jlong) okra_kernel; GPU_END #if defined(LINUX) @@ -410,26 +402,31 @@ return false; } - guarantee(_okra_create_context == NULL, "cannot repeat GPU initialization"); + guarantee(_okra_get_context == NULL, "cannot repeat GPU initialization"); // At this point we know okra_lib_handle is valid whether we loaded // here or earlier. In either case, we can lookup the functions. - LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context); + LOOKUP_OKRA_FUNCTION(okra_get_context, okra_get_context); LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel); - LOOKUP_OKRA_FUNCTION(okra_push_object, okra_push_object); + LOOKUP_OKRA_FUNCTION(okra_push_pointer, okra_push_pointer); LOOKUP_OKRA_FUNCTION(okra_push_boolean, okra_push_boolean); LOOKUP_OKRA_FUNCTION(okra_push_byte, okra_push_byte); LOOKUP_OKRA_FUNCTION(okra_push_double, okra_push_double); LOOKUP_OKRA_FUNCTION(okra_push_float, okra_push_float); LOOKUP_OKRA_FUNCTION(okra_push_int, okra_push_int); LOOKUP_OKRA_FUNCTION(okra_push_long, okra_push_long); - LOOKUP_OKRA_FUNCTION(okra_execute_with_range, okra_execute_with_range); - LOOKUP_OKRA_FUNCTION(okra_clearargs, okra_clearargs); - LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap); + LOOKUP_OKRA_FUNCTION(okra_execute_kernel, okra_execute_kernel); + LOOKUP_OKRA_FUNCTION(okra_clear_args, okra_clear_args); + LOOKUP_OKRA_FUNCTION(okra_dispose_kernel, okra_dispose_kernel); + LOOKUP_OKRA_FUNCTION(okra_dispose_context, okra_dispose_context); // if we made it this far, real success Gpu::initialized_gpu(new Hsail()); + // There is 1 context per process + jint result = _okra_get_context(&_device_context); + guarantee(result==0, "get context failed"); + return true; GPU_END diff -r f1fba319d4e3 -r e7b7a5be4d21 src/gpu/hsail/vm/gpu_hsail.hpp --- a/src/gpu/hsail/vm/gpu_hsail.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/gpu/hsail/vm/gpu_hsail.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -190,8 +190,6 @@ static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod* nm, jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS); - static void register_heap(); - static GraalEnv::CodeInstallResult install_code(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations); public: @@ -211,32 +209,45 @@ #endif private: - typedef void* (*okra_create_context_func_t)(); - typedef void* (*okra_create_kernel_func_t)(void*, unsigned char*, const char*); - typedef bool (*okra_push_object_func_t)(void*, void*); - typedef bool (*okra_push_boolean_func_t)(void*, jboolean); - typedef bool (*okra_push_byte_func_t)(void*, jbyte); - typedef bool (*okra_push_double_func_t)(void*, jdouble); - typedef bool (*okra_push_float_func_t)(void*, jfloat); - typedef bool (*okra_push_int_func_t)(void*, jint); - typedef bool (*okra_push_long_func_t)(void*, jlong); - typedef bool (*okra_execute_with_range_func_t)(void*, jint); - typedef bool (*okra_clearargs_func_t)(void*); - typedef bool (*okra_register_heap_func_t)(void*, size_t); + + /* + * Kernel launch options from okra.h + */ + typedef struct graal_okra_range_s { + uint32_t dimension; //max value is 3 + uint32_t global_size[3]; + uint32_t group_size[3]; + uint32_t reserved; //For future use + } graal_okra_range_t; + + typedef jint (*okra_get_context_func_t)(void**); + typedef jint (*okra_create_kernel_func_t)(void*, unsigned char*, const char*, void**); + typedef jint (*okra_push_pointer_func_t)(void*, void*); + typedef jint (*okra_push_boolean_func_t)(void*, jboolean); + typedef jint (*okra_push_byte_func_t)(void*, jbyte); + typedef jint (*okra_push_double_func_t)(void*, jdouble); + typedef jint (*okra_push_float_func_t)(void*, jfloat); + typedef jint (*okra_push_int_func_t)(void*, jint); + typedef jint (*okra_push_long_func_t)(void*, jlong); + typedef jint (*okra_execute_kernel_func_t)(void*, void*, graal_okra_range_t*); + typedef jint (*okra_clear_args_func_t)(void*); + typedef jint (*okra_dispose_kernel_func_t)(void*); + typedef jint (*okra_dispose_context_func_t)(void*); public: - static okra_create_context_func_t _okra_create_context; + static okra_get_context_func_t _okra_get_context; static okra_create_kernel_func_t _okra_create_kernel; - static okra_push_object_func_t _okra_push_object; + static okra_push_pointer_func_t _okra_push_pointer; static okra_push_boolean_func_t _okra_push_boolean; static okra_push_byte_func_t _okra_push_byte; static okra_push_double_func_t _okra_push_double; static okra_push_float_func_t _okra_push_float; static okra_push_int_func_t _okra_push_int; static okra_push_long_func_t _okra_push_long; - static okra_execute_with_range_func_t _okra_execute_with_range; - static okra_clearargs_func_t _okra_clearargs; - static okra_register_heap_func_t _okra_register_heap; + static okra_execute_kernel_func_t _okra_execute_kernel; + static okra_clear_args_func_t _okra_clear_args; + static okra_dispose_kernel_func_t _okra_dispose_kernel; + static okra_dispose_context_func_t _okra_dispose_context; protected: static void* _device_context; diff -r f1fba319d4e3 -r e7b7a5be4d21 src/gpu/hsail/vm/hsailKernelArguments.hpp --- a/src/gpu/hsail/vm/hsailKernelArguments.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/gpu/hsail/vm/hsailKernelArguments.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -47,36 +47,36 @@ } virtual char* argsBuilderName() {return (char*)"HSAILKernelArguments";} virtual void pushObject(void* obj) { - bool pushed = Hsail::_okra_push_object(_kernel, obj); - assert(pushed == true, "arg push failed"); + jint status = Hsail::_okra_push_pointer(_kernel, obj); + assert(status == 0, "arg push failed"); } virtual void pushBool(jboolean z) { - bool pushed = Hsail::_okra_push_boolean(_kernel, z); - assert(pushed == true, "arg push failed"); + jint status = Hsail::_okra_push_boolean(_kernel, z); + assert(status == 0, "arg push failed"); } virtual void pushByte(jbyte b) { - bool pushed = Hsail::_okra_push_byte(_kernel, b); - assert(pushed == true, "arg push failed"); + jint status = Hsail::_okra_push_byte(_kernel, b); + assert(status == 0, "arg push failed"); } virtual void pushDouble(jdouble d) { - bool pushed = Hsail::_okra_push_double(_kernel, d); - assert(pushed == true, "arg push failed"); + jint status = Hsail::_okra_push_double(_kernel, d); + assert(status == 0, "arg push failed"); } virtual void pushFloat(jfloat f) { - bool pushed = Hsail::_okra_push_float(_kernel, f); - assert(pushed == true, "arg push failed"); + jint status = Hsail::_okra_push_float(_kernel, f); + assert(status == 0, "arg push failed"); } virtual void pushInt(jint i) { - bool pushed = Hsail::_okra_push_int(_kernel, i); - assert(pushed == true, "arg push failed"); + jint status = Hsail::_okra_push_int(_kernel, i); + assert(status == 0, "arg push failed"); } virtual void pushLong(jlong j) { - bool pushed = Hsail::_okra_push_long(_kernel, j); - assert(pushed == true, "arg push failed"); + jint status = Hsail::_okra_push_long(_kernel, j); + assert(status == 0, "arg push failed"); } virtual void pushTrailingArgs() { if (UseHSAILDeoptimization) { diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Wed Jul 30 10:39:39 2014 -0700 @@ -1059,7 +1059,9 @@ // deoptimizations. add_to_hierarchy(k, CHECK_NULL); // No exception, but can block - // But, do not add to system dictionary. + // But, do not add to system dictionary. That normally takes + // care of updating _number_of_modifications so do it here. + notice_modification(); } // Rewrite and patch constant pool here. diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -204,6 +204,7 @@ GRAAL_ONLY(do_klass(HotSpotResolvedJavaMethod_klass, com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod, Graal)) \ GRAAL_ONLY(do_klass(HotSpotResolvedObjectType_klass, com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType, Graal)) \ GRAAL_ONLY(do_klass(HotSpotMonitorValue_klass, com_oracle_graal_hotspot_meta_HotSpotMonitorValue, Graal)) \ + GRAAL_ONLY(do_klass(HotSpotCompressedNullConstant_klass, com_oracle_graal_hotspot_meta_HotSpotCompressedNullConstant, Graal)) \ GRAAL_ONLY(do_klass(HotSpotObjectConstant_klass, com_oracle_graal_hotspot_meta_HotSpotObjectConstant, Graal)) \ GRAAL_ONLY(do_klass(HotSpotMetaspaceConstant_klass, com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstant, Graal)) \ GRAAL_ONLY(do_klass(HotSpotStackFrameReference_klass, com_oracle_graal_hotspot_HotSpotStackFrameReference, Graal)) \ @@ -238,6 +239,7 @@ GRAAL_ONLY(do_klass(NullConstant_klass, com_oracle_graal_api_meta_NullConstant, Graal)) \ GRAAL_ONLY(do_klass(ExceptionHandler_klass, com_oracle_graal_api_meta_ExceptionHandler, Graal)) \ GRAAL_ONLY(do_klass(Kind_klass, com_oracle_graal_api_meta_Kind, Graal)) \ + GRAAL_ONLY(do_klass(LIRKind_klass, com_oracle_graal_api_meta_LIRKind, Graal)) \ GRAAL_ONLY(do_klass(JavaMethod_klass, com_oracle_graal_api_meta_JavaMethod, Graal)) \ GRAAL_ONLY(do_klass(JavaType_klass, com_oracle_graal_api_meta_JavaType, Graal)) \ GRAAL_ONLY(do_klass(Value_klass, com_oracle_graal_api_meta_Value, Graal)) \ diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -311,6 +311,7 @@ GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod, "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType, "com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue, "com/oracle/graal/hotspot/meta/HotSpotMonitorValue")) \ + GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotCompressedNullConstant, "com/oracle/graal/hotspot/meta/HotSpotCompressedNullConstant")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotObjectConstant, "com/oracle/graal/hotspot/meta/HotSpotObjectConstant")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstant, "com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstant")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_HotSpotStackFrameReference, "com/oracle/graal/hotspot/HotSpotStackFrameReference")) \ @@ -322,6 +323,7 @@ GRAAL_ONLY(template(com_oracle_graal_api_meta_JavaMethod, "com/oracle/graal/api/meta/JavaMethod")) \ GRAAL_ONLY(template(com_oracle_graal_api_meta_JavaType, "com/oracle/graal/api/meta/JavaType")) \ GRAAL_ONLY(template(com_oracle_graal_api_meta_Kind, "com/oracle/graal/api/meta/Kind")) \ + GRAAL_ONLY(template(com_oracle_graal_api_meta_LIRKind, "com/oracle/graal/api/meta/LIRKind")) \ GRAAL_ONLY(template(com_oracle_graal_api_meta_Value, "com/oracle/graal/api/meta/Value")) \ GRAAL_ONLY(template(com_oracle_graal_api_code_Assumptions, "com/oracle/graal/api/code/Assumptions")) \ GRAAL_ONLY(template(com_oracle_graal_api_code_Assumptions_MethodContents, "com/oracle/graal/api/code/Assumptions$MethodContents")) \ diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Wed Jul 30 10:39:39 2014 -0700 @@ -216,34 +216,44 @@ return new LocationValue(Location::new_stk_loc(Location::invalid, 0)); } - BasicType type = GraalRuntime::kindToBasicType(Kind::typeChar(Value::kind(value))); - Location::Type locationType = Location::normal; - if (type == T_OBJECT || type == T_ARRAY) locationType = Location::oop; + oop lirKind = Value::lirKind(value); + oop platformKind = LIRKind::platformKind(lirKind); + jint referenceMask = LIRKind::referenceMask(lirKind); + assert(referenceMask == 0 || referenceMask == 1, "unexpected referenceMask"); + bool reference = referenceMask == 1; + + BasicType type = GraalRuntime::kindToBasicType(Kind::typeChar(platformKind)); if (value->is_a(RegisterValue::klass())) { jint number = code_Register::number(RegisterValue::reg(value)); jint encoding = code_Register::encoding(RegisterValue::reg(value)); if (number < RegisterImpl::number_of_registers) { - if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE || type == T_ADDRESS) { + Location::Type locationType; + if (type == T_INT) { + locationType = reference ? Location::narrowoop : Location::int_in_long; + } else if (type == T_FLOAT) { locationType = Location::int_in_long; } else if (type == T_LONG) { - locationType = Location::lng; + locationType = reference ? Location::oop : Location::lng; } else { - assert(type == T_OBJECT || type == T_ARRAY, "unexpected type in cpu register"); + assert(type == T_OBJECT && reference, "unexpected type in cpu register"); + locationType = Location::oop; } ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_Register(number)->as_VMReg())); - if (type == T_LONG) { + if (type == T_LONG && !reference) { second = value; } return value; } else { assert(type == T_FLOAT || type == T_DOUBLE, "only float and double expected in xmm register"); + Location::Type locationType; if (type == T_FLOAT) { // this seems weird, but the same value is used in c1_LinearScan locationType = Location::normal; } else { locationType = Location::dbl; } + assert(!reference, "unexpected type in floating point register"); #ifdef TARGET_ARCH_x86 ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg())); if (type == T_DOUBLE) { @@ -263,41 +273,54 @@ #endif } } else if (value->is_a(StackSlot::klass())) { - if (type == T_DOUBLE) { + Location::Type locationType; + if (type == T_LONG) { + locationType = reference ? Location::oop : Location::lng; + } else if (type == T_INT) { + locationType = reference ? Location::narrowoop : Location::normal; + } else if (type == T_FLOAT) { + assert(!reference, "unexpected type in stack slot"); + locationType = Location::normal; + } else if (type == T_DOUBLE) { + assert(!reference, "unexpected type in stack slot"); locationType = Location::dbl; - } else if (type == T_LONG) { - locationType = Location::lng; + } else { + assert(type == T_OBJECT && reference, "unexpected type in stack slot"); + locationType = Location::oop; } jint offset = StackSlot::offset(value); if (StackSlot::addFrameSize(value)) { offset += total_frame_size; } ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset)); - if (type == T_DOUBLE || type == T_LONG) { + if (type == T_DOUBLE || (type == T_LONG && !reference)) { second = value; } return value; } else if (value->is_a(Constant::klass())){ record_metadata_in_constant(value, oop_recorder); - if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) { - jint prim = (jint)PrimitiveConstant::primitive(value); - return new ConstantIntValue(prim); - } else if (type == T_LONG || type == T_DOUBLE) { - jlong prim = PrimitiveConstant::primitive(value); - second = new ConstantIntValue(0); - return new ConstantLongValue(prim); - } else if (type == T_OBJECT) { - if (value->is_a(NullConstant::klass())) { + if (value->is_a(PrimitiveConstant::klass())) { + assert(!reference, "unexpected primitive constant type"); + if (type == T_INT || type == T_FLOAT) { + jint prim = (jint)PrimitiveConstant::primitive(value); + return new ConstantIntValue(prim); + } else { + assert(type == T_LONG || type == T_DOUBLE, "unexpected primitive constant type"); + jlong prim = PrimitiveConstant::primitive(value); + second = new ConstantIntValue(0); + return new ConstantLongValue(prim); + } + } else { + assert(reference, "unexpected object constant type"); + if (value->is_a(NullConstant::klass()) || value->is_a(HotSpotCompressedNullConstant::klass())) { return new ConstantOopWriteValue(NULL); } else { + assert(value->is_a(HotSpotObjectConstant::klass()), "unexpected constant type"); oop obj = HotSpotObjectConstant::object(value); assert(obj != NULL, "null value must be in NullConstant"); return new ConstantOopWriteValue(JNIHandles::make_local(obj)); } - } else if (type == T_ADDRESS) { - ShouldNotReachHere(); } - tty->print("%i", type); } else if (value->is_a(VirtualObject::klass())) { oop type = VirtualObject::type(value); int id = VirtualObject::id(value); @@ -558,7 +581,7 @@ ShouldNotReachHere(); } } - + jint last_pc_offset = -1; for (int i = 0; i < _sites->length(); i++) { oop site = ((objArrayOop) (_sites))->obj_at(i); jint pc_offset = CompilationResult_Site::pcOffset(site); @@ -576,6 +599,7 @@ // if the infopoint is not an actual safepoint, it must have one of the other reasons // (safeguard against new safepoint types that require handling above) assert(InfopointReason::METHOD_START() == reason || InfopointReason::METHOD_END() == reason || InfopointReason::LINE_NUMBER() == reason, ""); + site_Infopoint(buffer, pc_offset, site); } } else if (site->is_a(CompilationResult_DataPatch::klass())) { TRACE_graal_4("datapatch at %i", pc_offset); @@ -586,6 +610,7 @@ } else { fatal("unexpected Site subclass"); } + last_pc_offset = pc_offset; } #ifndef PRODUCT @@ -683,83 +708,95 @@ return true; } -void CodeInstaller::record_scope(jint pc_offset, oop frame, GrowableArray* objects) { - assert(frame->klass() == BytecodeFrame::klass(), "BytecodeFrame expected"); - oop caller_frame = BytecodePosition::caller(frame); +void CodeInstaller::record_scope(jint pc_offset, oop position, GrowableArray* objects) { + oop frame = NULL; + if (position->is_a(BytecodeFrame::klass())) { + frame = position; + } + oop caller_frame = BytecodePosition::caller(position); if (caller_frame != NULL) { record_scope(pc_offset, caller_frame, objects); } - oop hotspot_method = BytecodePosition::method(frame); + oop hotspot_method = BytecodePosition::method(position); Method* method = getMethodFromHotSpotMethod(hotspot_method); - jint bci = BytecodePosition::bci(frame); + jint bci = BytecodePosition::bci(position); if (bci == BytecodeFrame::BEFORE_BCI()) { bci = SynchronizationEntryBCI; } - bool reexecute; - if (bci == SynchronizationEntryBCI){ - reexecute = false; - } else { - Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci)); - reexecute = bytecode_should_reexecute(code); - if (frame != NULL) { - reexecute = (BytecodeFrame::duringCall(frame) == JNI_FALSE); - } - } if (TraceGraal >= 2) { tty->print_cr("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string()); } - jint local_count = BytecodeFrame::numLocals(frame); - jint expression_count = BytecodeFrame::numStack(frame); - jint monitor_count = BytecodeFrame::numLocks(frame); - arrayOop values = (arrayOop) BytecodeFrame::values(frame); - - assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length"); - - GrowableArray* locals = new GrowableArray (); - GrowableArray* expressions = new GrowableArray (); - GrowableArray* monitors = new GrowableArray (); - - if (TraceGraal >= 2) { - tty->print_cr("Scope at bci %d with %d values", bci, values->length()); - tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); - } - - for (jint i = 0; i < values->length(); i++) { - ScopeValue* second = NULL; - oop value=((objArrayOop) (values))->obj_at(i); - if (i < local_count) { - ScopeValue* first = get_scope_value(value, _total_frame_size, objects, second, _oop_recorder); - if (second != NULL) { - locals->append(second); + bool reexecute = false; + if (frame != NULL) { + if (bci == SynchronizationEntryBCI){ + reexecute = false; + } else { + Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci)); + reexecute = bytecode_should_reexecute(code); + if (frame != NULL) { + reexecute = (BytecodeFrame::duringCall(frame) == JNI_FALSE); } - locals->append(first); - } else if (i < local_count + expression_count) { - ScopeValue* first = get_scope_value(value, _total_frame_size, objects, second, _oop_recorder); - if (second != NULL) { - expressions->append(second); - } - expressions->append(first); - } else { - monitors->append(get_monitor_value(value, _total_frame_size, objects, _oop_recorder)); - } - if (second != NULL) { - i++; - assert(i < values->length(), "double-slot value not followed by Value.ILLEGAL"); - assert(((objArrayOop) (values))->obj_at(i) == Value::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL"); } } + DebugToken* locals_token = NULL; + DebugToken* expressions_token = NULL; + DebugToken* monitors_token = NULL; + bool throw_exception = false; - _debug_recorder->dump_object_pool(objects); + if (frame != NULL) { + jint local_count = BytecodeFrame::numLocals(frame); + jint expression_count = BytecodeFrame::numStack(frame); + jint monitor_count = BytecodeFrame::numLocks(frame); + arrayOop values = (arrayOop) BytecodeFrame::values(frame); + + assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length"); + + GrowableArray* locals = new GrowableArray (); + GrowableArray* expressions = new GrowableArray (); + GrowableArray* monitors = new GrowableArray (); + + if (TraceGraal >= 2) { + tty->print_cr("Scope at bci %d with %d values", bci, values->length()); + tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); + } - DebugToken* locals_token = _debug_recorder->create_scope_values(locals); - DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions); - DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors); + for (jint i = 0; i < values->length(); i++) { + ScopeValue* second = NULL; + oop value=((objArrayOop) (values))->obj_at(i); + if (i < local_count) { + ScopeValue* first = get_scope_value(value, _total_frame_size, objects, second, _oop_recorder); + if (second != NULL) { + locals->append(second); + } + locals->append(first); + } else if (i < local_count + expression_count) { + ScopeValue* first = get_scope_value(value, _total_frame_size, objects, second, _oop_recorder); + if (second != NULL) { + expressions->append(second); + } + expressions->append(first); + } else { + monitors->append(get_monitor_value(value, _total_frame_size, objects, _oop_recorder)); + } + if (second != NULL) { + i++; + assert(i < values->length(), "double-slot value not followed by Value.ILLEGAL"); + assert(((objArrayOop) (values))->obj_at(i) == Value::ILLEGAL(), "double-slot value not followed by Value.ILLEGAL"); + } + } - bool throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE; + _debug_recorder->dump_object_pool(objects); + + locals_token = _debug_recorder->create_scope_values(locals); + expressions_token = _debug_recorder->create_scope_values(expressions); + monitors_token = _debug_recorder->create_monitor_values(monitors); + + throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE; + } _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token); } @@ -782,6 +819,20 @@ _debug_recorder->end_safepoint(pc_offset); } +void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, oop site) { + oop debug_info = CompilationResult_Infopoint::debugInfo(site); + assert(debug_info != NULL, "debug info expected"); + + _debug_recorder->add_non_safepoint(pc_offset); + + oop position = DebugInfo::bytecodePosition(debug_info); + if (position != NULL) { + record_scope(pc_offset, position, NULL); + } + + _debug_recorder->end_non_safepoint(pc_offset); +} + void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) { oop target = CompilationResult_Call::target(site); InstanceKlass* target_klass = InstanceKlass::cast(target->klass()); diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -115,6 +115,7 @@ void assumption_CallSiteTargetValue(Handle assumption); void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site); + void site_Infopoint(CodeBuffer& buffer, jint pc_offset, oop site); void site_Call(CodeBuffer& buffer, jint pc_offset, oop site); void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site); void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site); diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/graal/graalJavaAccess.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -207,6 +207,8 @@ end_class \ start_class(NullConstant) \ end_class \ + start_class(HotSpotCompressedNullConstant) \ + end_class \ start_class(HotSpotObjectConstant) \ oop_field(HotSpotObjectConstant, object, "Ljava/lang/Object;") \ end_class \ @@ -223,8 +225,13 @@ static_oop_field(Kind, Int, "Lcom/oracle/graal/api/meta/Kind;"); \ static_oop_field(Kind, Long, "Lcom/oracle/graal/api/meta/Kind;"); \ end_class \ + start_class(LIRKind) \ + oop_field(LIRKind, platformKind, "Lcom/oracle/graal/api/meta/PlatformKind;") \ + int_field(LIRKind, referenceMask) \ + end_class \ start_class(Value) \ oop_field(Value, kind, "Lcom/oracle/graal/api/meta/Kind;") \ + oop_field(Value, lirKind, "Lcom/oracle/graal/api/meta/LIRKind;") \ static_oop_field(Value, ILLEGAL, "Lcom/oracle/graal/api/meta/AllocatableValue;"); \ end_class \ start_class(RegisterValue) \ diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/graal/graalRuntime.cpp Wed Jul 30 10:39:39 2014 -0700 @@ -117,7 +117,6 @@ case 'j': return T_LONG; case 'd': return T_DOUBLE; case 'a': return T_OBJECT; - case 'r': return T_ADDRESS; case '-': return T_ILLEGAL; default: fatal(err_msg("unexpected Kind: %c", ch)); diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/graal/vmStructs_graal.hpp --- a/src/share/vm/graal/vmStructs_graal.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/graal/vmStructs_graal.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -34,12 +34,14 @@ nonstatic_field(InstanceKlass, _graal_node_class, oop) \ nonstatic_field(ThreadShadow, _pending_deoptimization, int) \ nonstatic_field(ThreadShadow, _pending_failed_speculation, oop) \ + nonstatic_field(ThreadShadow, _pending_transfer_to_interpreter, bool) \ nonstatic_field(MethodData, _graal_node_count, int) \ #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type) \ #define VM_INT_CONSTANTS_GRAAL(declare_constant, declare_preprocessor_constant) \ declare_constant(Deoptimization::Reason_aliasing) \ + declare_constant(Deoptimization::Reason_transfer_to_interpreter) \ declare_constant(GraalEnv::ok) \ declare_constant(GraalEnv::dependencies_failed) \ declare_constant(GraalEnv::cache_full) \ diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/opto/chaitin.cpp --- a/src/share/vm/opto/chaitin.cpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/opto/chaitin.cpp Wed Jul 30 10:39:39 2014 -0700 @@ -1682,9 +1682,21 @@ // (where top() node is placed). base->init_req(0, _cfg.get_root_node()); Block *startb = _cfg.get_block_for_node(C->top()); - startb->insert_node(base, startb->find_node(C->top())); + uint node_pos = startb->find_node(C->top()); + startb->insert_node(base, node_pos); _cfg.map_node_to_block(base, startb); assert(_lrg_map.live_range_id(base) == 0, "should not have LRG yet"); + + // The loadConP0 might have projection nodes depending on architecture + // Add the projection nodes to the CFG + for (DUIterator_Fast imax, i = base->fast_outs(imax); i < imax; i++) { + Node* use = base->fast_out(i); + if (use->is_MachProj()) { + startb->insert_node(use, ++node_pos); + _cfg.map_node_to_block(use, startb); + new_lrg(use, maxlrg++); + } + } } if (_lrg_map.live_range_id(base) == 0) { new_lrg(base, maxlrg++); diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/runtime/deoptimization.cpp Wed Jul 30 10:39:39 2014 -0700 @@ -1393,7 +1393,12 @@ trap_bci = 0; Thread::current()->set_pending_monitorenter(true); } + + if (reason == Deoptimization::Reason_transfer_to_interpreter) { + thread->set_pending_transfer_to_interpreter(true); + } #endif + Bytecodes::Code trap_bc = trap_method->java_code_at(trap_bci); if (trap_scope->rethrow_exception()) { @@ -1996,7 +2001,10 @@ "age" GRAAL_ONLY("_or_jsr_mismatch"), "predicate", "loop_limit_check", - GRAAL_ONLY("aliasing") +#ifdef GRAAL + "aliasing", + "transfer_to_interpreter", +#endif }; const char* Deoptimization::_trap_action_name[Action_LIMIT] = { // Note: Keep this in sync. with enum DeoptAction. diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/runtime/deoptimization.hpp --- a/src/share/vm/runtime/deoptimization.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/runtime/deoptimization.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -74,6 +74,7 @@ Reason_loop_limit_check, // compiler generated loop limits check failed #ifdef GRAAL Reason_aliasing, // optimistic assumption about aliasing failed + Reason_transfer_to_interpreter, // explicit transferToInterpreter() #endif Reason_LIMIT, diff -r f1fba319d4e3 -r e7b7a5be4d21 src/share/vm/utilities/exceptions.hpp --- a/src/share/vm/utilities/exceptions.hpp Wed Jul 30 09:36:32 2014 -0700 +++ b/src/share/vm/utilities/exceptions.hpp Wed Jul 30 10:39:39 2014 -0700 @@ -65,6 +65,7 @@ int _pending_deoptimization; oop _pending_failed_speculation; bool _pending_monitorenter; + bool _pending_transfer_to_interpreter; #endif oop _pending_exception; // Thread has gc actions. const char* _exception_file; // file information for exception (debugging only) @@ -100,6 +101,7 @@ void set_pending_monitorenter(bool b) { _pending_monitorenter = b; } void set_pending_deoptimization(int reason) { _pending_deoptimization = reason; } void set_pending_failed_speculation(oop failed_speculation) { _pending_failed_speculation = failed_speculation; } + void set_pending_transfer_to_interpreter(bool b) { _pending_transfer_to_interpreter = b; } #endif // use THROW whenever possible! @@ -111,7 +113,7 @@ ThreadShadow() : _pending_exception(NULL), _exception_file(NULL), _exception_line(0) #ifdef GRAAL - , _pending_monitorenter(false), _pending_deoptimization(-1), _pending_failed_speculation(NULL) + , _pending_monitorenter(false), _pending_deoptimization(-1), _pending_failed_speculation(NULL), _pending_transfer_to_interpreter(false) #endif {} };