# HG changeset patch # User Christian Humer # Date 1366453409 -7200 # Node ID 9d29e5aa54d271dc0e80db72f9dc25ab169a4443 # Parent b69312e4eceb81cae50811f37236a3d30ca68f5b# Parent 9b455ec158209804faa330951445d394930b664c Merge. diff -r b69312e4eceb -r 9d29e5aa54d2 .hgignore --- a/.hgignore Sat Apr 20 12:22:54 2013 +0200 +++ b/.hgignore Sat Apr 20 12:23:29 2013 +0200 @@ -4,6 +4,7 @@ ^mx/ecj.jar ^mx/includes ^build/ +^build-nograal/ ^dist/ ^java/ ^lib/ diff -r b69312e4eceb -r 9d29e5aa54d2 .hgtags --- a/.hgtags Sat Apr 20 12:22:54 2013 +0200 +++ b/.hgtags Sat Apr 20 12:23:29 2013 +0200 @@ -330,3 +330,6 @@ 8d0f263a370c5f3e61791bb06054560804117288 hs25-b25 af788b85010ebabbc1e8f52c6766e08c7a95cf99 jdk8-b84 a947f40fb536e5b9e0aa210cf26abb430f80887a hs25-b26 +42fe530cd478744a4d12a0cbf803f0fc804bab1a jdk8-b85 +09b0d3e9ba6cdf7da07d4010d2d1df14596f6864 hs25-b27 +6d88a566d369f6a1f86912cad7d0912686b2fda1 hs25-b28 diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Sat Apr 20 12:23:29 2013 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.Register.RegisterFlag; +import com.oracle.graal.api.meta.*; /** * Represents the AMD64 architecture. @@ -105,7 +106,10 @@ rip }; - public AMD64() { + private final int supportedSSEVersion; + private final int supportedAVXVersion; + + public AMD64(int supportedSSEVersion, int supportedAVXVersion) { super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, @@ -114,6 +118,65 @@ 1, r15.encoding + 1, 8); + assert supportedSSEVersion >= 2; + this.supportedSSEVersion = supportedSSEVersion; + this.supportedAVXVersion = supportedAVXVersion; } // @formatter:on + + @Override + public int getMaxVectorLength(Kind kind) { + if (supportedAVXVersion > 0) { + switch (kind) { + case Boolean: + return 32; + case Byte: + return 32; + case Short: + return 16; + case Char: + return 16; + case Int: + return 8; + case Float: + return 8; + case Long: + return 4; + case Double: + return 4; + case Object: + return 4; + } + } else { + switch (kind) { + case Boolean: + return 16; + case Byte: + return 16; + case Short: + return 8; + case Char: + return 8; + case Int: + return 4; + case Float: + return 4; + case Long: + return 2; + case Double: + return 2; + case Object: + return 2; + } + } + return 1; + } + + public int getSupportedSSEVersion() { + return supportedSSEVersion; + } + + public int getSupportedAVXVersion() { + return supportedAVXVersion; + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Sat Apr 20 12:23:29 2013 +0200 @@ -24,6 +24,8 @@ import java.nio.*; +import com.oracle.graal.api.meta.*; + /** * Represents a CPU architecture, including information such as its endianness, CPU registers, word * width, etc. @@ -154,4 +156,12 @@ public final int requiredBarriers(int barriers) { return barriers & ~implicitMemoryBarriers; } + + /** + * Determine the maximum vector length supported for vector operations on values of a given + * {@link Kind}. + */ + public int getMaxVectorLength(@SuppressWarnings("unused") Kind kind) { + return 1; + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.meta.MetaUtil.*; import java.io.*; +import java.lang.invoke.*; import java.util.*; import com.oracle.graal.api.meta.*; @@ -44,6 +45,37 @@ private static final long serialVersionUID = -1936652569665112915L; } + public static final class NoFinalizableSubclass extends Assumption { + + private static final long serialVersionUID = 6451169735564055081L; + + private ResolvedJavaType receiverType; + + public NoFinalizableSubclass(ResolvedJavaType receiverType) { + this.receiverType = receiverType; + } + + @Override + public int hashCode() { + return 31 + receiverType.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof NoFinalizableSubclass) { + NoFinalizableSubclass other = (NoFinalizableSubclass) obj; + return other.receiverType == receiverType; + } + return false; + } + + @Override + public String toString() { + return "NoFinalizableSubclass[receiverType=" + toJavaName(receiverType) + "]"; + } + + } + /** * An assumption about a unique subtype of a given type. */ @@ -160,10 +192,7 @@ @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + method.hashCode(); - return result; + return 31 + method.hashCode(); } @Override @@ -182,6 +211,45 @@ } /** + * Assumption that a call site's method handle did not change. + */ + public static final class CallSiteTargetValue extends Assumption { + + private static final long serialVersionUID = 1732459941784550371L; + + public final CallSite callSite; + public final MethodHandle methodHandle; + + public CallSiteTargetValue(CallSite callSite, MethodHandle methodHandle) { + this.callSite = callSite; + this.methodHandle = methodHandle; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + callSite.hashCode(); + result = prime * result + methodHandle.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CallSiteTargetValue) { + CallSiteTargetValue other = (CallSiteTargetValue) obj; + return other.callSite == callSite && other.methodHandle == methodHandle; + } + return false; + } + + @Override + public String toString() { + return "CallSiteTargetValue[callSite=" + callSite + ", methodHandle=" + methodHandle + "]"; + } + } + + /** * Array with the assumptions. This field is directly accessed from C++ code in the * Graal/HotSpot implementation. */ @@ -233,12 +301,10 @@ * Records an assumption that the specified type has no finalizable subclasses. * * @param receiverType the type that is assumed to have no finalizable subclasses - * @return {@code true} if the assumption was recorded and can be assumed; {@code false} - * otherwise */ - public boolean recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { + public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { assert useOptimisticAssumptions; - return false; + record(new NoFinalizableSubclass(receiverType)); } /** diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -52,42 +52,45 @@ } /** - * Represents a safepoint with associated debug info. + * Represents an infopoint with associated debug info. Note that safepoints are also infopoints. */ - public static class Safepoint extends Site implements Comparable { + public static class Infopoint extends Site implements Comparable { private static final long serialVersionUID = 2479806696381720162L; public final DebugInfo debugInfo; - public Safepoint(int pcOffset, DebugInfo debugInfo) { + public final InfopointReason reason; + + public Infopoint(int pcOffset, DebugInfo debugInfo, InfopointReason reason) { super(pcOffset); this.debugInfo = debugInfo; + this.reason = reason; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(pcOffset); - sb.append("[]"); + sb.append("[]"); appendDebugInfo(sb, debugInfo); return sb.toString(); } @Override - public int compareTo(Safepoint o) { + public int compareTo(Infopoint o) { if (pcOffset < o.pcOffset) { return -1; } else if (pcOffset > o.pcOffset) { return 1; } - return 0; + return this.reason.compareTo(o.reason); } } /** * Represents a call in the code. */ - public static final class Call extends Safepoint { + public static final class Call extends Infopoint { private static final long serialVersionUID = 1440741241631046954L; @@ -109,7 +112,7 @@ public final boolean direct; public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) { - super(pcOffset, debugInfo); + super(pcOffset, debugInfo, InfopointReason.CALL); this.size = size; this.target = target; this.direct = direct; @@ -284,7 +287,7 @@ } } - private final List safepoints = new ArrayList<>(); + private final List infopoints = new ArrayList<>(); private final List dataReferences = new ArrayList<>(); private final List exceptionHandlers = new ArrayList<>(); private final List marks = new ArrayList<>(); @@ -377,7 +380,7 @@ */ public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) { final Call call = new Call(target, codePos, size, direct, debugInfo); - addSafepoint(call); + addInfopoint(call); } /** @@ -391,22 +394,22 @@ } /** - * Records a safepoint in the code array. + * Records an infopoint in the code array. * - * @param codePos the position of the safepoint in the code array - * @param debugInfo the debug info for the safepoint + * @param codePos the position of the infopoint in the code array + * @param debugInfo the debug info for the infopoint */ - public void recordSafepoint(int codePos, DebugInfo debugInfo) { - addSafepoint(new Safepoint(codePos, debugInfo)); + public void recordInfopoint(int codePos, DebugInfo debugInfo, InfopointReason reason) { + addInfopoint(new Infopoint(codePos, debugInfo, reason)); } - private void addSafepoint(Safepoint safepoint) { - // The safepoints list must always be sorted - if (!getSafepoints().isEmpty() && getSafepoints().get(getSafepoints().size() - 1).pcOffset >= safepoint.pcOffset) { + private void addInfopoint(Infopoint infopoint) { + // The infopoints list must always be sorted + if (!getInfopoints().isEmpty() && getInfopoints().get(getInfopoints().size() - 1).pcOffset >= infopoint.pcOffset) { // This re-sorting should be very rare - Collections.sort(getSafepoints()); + Collections.sort(getInfopoints()); } - getSafepoints().add(safepoint); + getInfopoints().add(infopoint); } /** @@ -522,10 +525,10 @@ } /** - * @return the list of safepoints, sorted by {@link Site#pcOffset} + * @return the list of infopoints, sorted by {@link Site#pcOffset} */ - public List getSafepoints() { - return safepoints; + public List getInfopoints() { + return infopoints; } /** diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,32 @@ +/* + * 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.api.code; + +/** + * A reason for infopoint insertion. + */ +public enum InfopointReason { + + UNKNOWN, SAFEPOINT, CALL, IMPLICIT_EXCEPTION, METHOD_START, METHOD_END, LINE_NUMBER; + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java Sat Apr 20 12:23:29 2013 +0200 @@ -31,14 +31,6 @@ public interface InstalledCode { /** - * Exception thrown by the runtime in case an invalidated machine code is called. - */ - public abstract class MethodInvalidatedException extends RuntimeException { - - private static final long serialVersionUID = -3540232440794244844L; - } - - /** * Returns the method (if any) to which the installed code belongs. */ ResolvedJavaMethod getMethod(); @@ -61,6 +53,12 @@ boolean isValid(); /** + * Invalidates this installed code such that any subsequent invocation will throw an + * {@link InvalidInstalledCodeException}. + */ + void invalidate(); + + /** * Executes the installed code with three object arguments. * * @param arg1 the first argument @@ -68,7 +66,7 @@ * @param arg3 the third argument * @return the value returned by the executed code */ - Object execute(Object arg1, Object arg2, Object arg3); + Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException; /** * Executes the installed code with a variable number of arguments. @@ -76,5 +74,5 @@ * @param args the array of object arguments * @return the value returned by the executed code */ - Object executeVarargs(Object... args); + Object executeVarargs(Object... args) throws InvalidInstalledCodeException; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,31 @@ +/* + * 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.api.code; + +/** + * Exception thrown by the runtime in case an invalidated machine code is called. + */ +public final class InvalidInstalledCodeException extends Exception { + + private static final long serialVersionUID = -3540232440794244844L; +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Sat Apr 20 12:23:29 2013 +0200 @@ -114,4 +114,6 @@ long getMaxCallTargetOffset(); Descriptor getDescriptor(); + + boolean preservesRegisters(); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Sat Apr 20 12:23:29 2013 +0200 @@ -36,10 +36,31 @@ */ public class TypeCheckHints { - private static final ResolvedJavaType[] NO_TYPES = {}; + /** + * A receiver type profiled in a type check instruction. + */ + public static class Hint { + + /** + * A type seen while profiling a type check instruction. + */ + public final ResolvedJavaType type; + + /** + * Specifies if {@link #type} was a sub-type of the checked type. + */ + public final boolean positive; + + Hint(ResolvedJavaType type, boolean positive) { + this.type = type; + this.positive = positive; + } + } + + private static final Hint[] NO_HINTS = {}; /** - * If true, then {@link #types} contains the only possible type that could pass the type check + * If true, then {@link #hints} contains the only possible type that could pass the type check * because the target of the type check is a final class or has been speculated to be a final * class. */ @@ -48,63 +69,63 @@ /** * The most likely types that the type check instruction will see. */ - public final ResolvedJavaType[] types; + public final Hint[] hints; /** * Derives hint information for use when generating the code for a type check instruction. * - * @param type the target type of the type check + * @param targetType the target type of the type check * @param profile the profiling information available for the instruction (if any) * @param assumptions the object in which speculations are recorded. This is null if * speculations are not supported. * @param minHintHitProbability if the probability that the type check will hit one of the - * profiled types (up to {@code maxHints}) is below this value, then {@link #types} + * profiled types (up to {@code maxHints}) is below this value, then {@link #hints} * will be null - * @param maxHints the maximum length of {@link #types} + * @param maxHints the maximum length of {@link #hints} */ - public TypeCheckHints(ResolvedJavaType type, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) { - if (type != null && !canHaveSubtype(type)) { - types = new ResolvedJavaType[]{type}; + public TypeCheckHints(ResolvedJavaType targetType, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) { + if (targetType != null && !canHaveSubtype(targetType)) { + hints = new Hint[]{new Hint(targetType, true)}; exact = true; } else { - ResolvedJavaType uniqueSubtype = type == null ? null : type.findUniqueConcreteSubtype(); + ResolvedJavaType uniqueSubtype = targetType == null ? null : targetType.findUniqueConcreteSubtype(); if (uniqueSubtype != null) { - types = new ResolvedJavaType[]{uniqueSubtype}; + hints = new Hint[]{new Hint(uniqueSubtype, true)}; if (assumptions.useOptimisticAssumptions()) { - assumptions.recordConcreteSubtype(type, uniqueSubtype); + assumptions.recordConcreteSubtype(targetType, uniqueSubtype); exact = true; } else { exact = false; } } else { exact = false; - ResolvedJavaType[] hintTypes = NO_TYPES; + Hint[] hintsBuf = NO_HINTS; JavaTypeProfile typeProfile = profile; if (typeProfile != null) { double notRecordedTypes = typeProfile.getNotRecordedProbability(); ProfiledType[] ptypes = typeProfile.getTypes(); if (notRecordedTypes < (1D - minHintHitProbability) && ptypes != null && ptypes.length > 0) { - hintTypes = new ResolvedJavaType[ptypes.length]; + hintsBuf = new Hint[ptypes.length]; int hintCount = 0; double totalHintProbability = 0.0d; for (ProfiledType ptype : ptypes) { - ResolvedJavaType hint = ptype.getType(); - if (type != null && type.isAssignableFrom(hint)) { - hintTypes[hintCount++] = hint; + if (targetType != null) { + ResolvedJavaType hintType = ptype.getType(); + hintsBuf[hintCount++] = new Hint(hintType, targetType.isAssignableFrom(hintType)); totalHintProbability += ptype.getProbability(); } } if (totalHintProbability >= minHintHitProbability) { - if (hintTypes.length != hintCount || hintCount > maxHints) { - hintTypes = Arrays.copyOf(hintTypes, Math.min(maxHints, hintCount)); + if (hintsBuf.length != hintCount || hintCount > maxHints) { + hintsBuf = Arrays.copyOf(hintsBuf, Math.min(maxHints, hintCount)); } } else { - hintTypes = NO_TYPES; + hintsBuf = NO_HINTS; } } } - this.types = hintTypes; + this.hints = hintsBuf; } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Sat Apr 20 12:23:29 2013 +0200 @@ -89,13 +89,19 @@ } public static Register asIntReg(Value value) { - assert value.getKind() == Kind.Int; - return asRegister(value); + if (value.getKind() != Kind.Int) { + throw new InternalError("needed Int got: " + value.getKind()); + } else { + return asRegister(value); + } } public static Register asLongReg(Value value) { - assert value.getKind() == Kind.Long : value.getKind(); - return asRegister(value); + if (value.getKind() != Kind.Long) { + throw new InternalError("needed Long got: " + value.getKind()); + } else { + return asRegister(value); + } } public static Register asObjectReg(Value value) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Sat Apr 20 12:23:29 2013 +0200 @@ -402,7 +402,7 @@ if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) { Method overridden = vtable.methods.put(new NameAndSignature(m), m); if (overridden != null) { - // System.out.println(m + " overrides " + overridden); + // println(m + " overrides " + overridden); } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,13 @@ public interface ConstantPool { /** + * Returns the number of entries the constant pool. + * + * @return number of entries in the constant pool + */ + int length(); + + /** * Ensures that the type referenced by the specified constant pool entry is loaded and * initialized. This can be used to compile time resolve a type. It works for field, method, or * type constant pool entries. @@ -93,4 +100,14 @@ * entry */ Object lookupConstant(int cpi); + + /** + * Looks up the appendix at the specified index. + * + * @param cpi the constant pool index + * @param opcode the opcode of the instruction for which the lookup is being performed or + * {@code -1} + * @return the appendix if it exists and is resolved or {@code null} + */ + Object lookupAppendix(int cpi, int opcode); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Sat Apr 20 12:23:29 2013 +0200 @@ -122,7 +122,9 @@ } /** - * A list of types for which the runtime has recorded probability information. + * A list of types for which the runtime has recorded probability information. Note that this + * includes both positive and negative types where a positive type is a subtype of the checked + * type and a negative type is not. */ public ProfiledType[] getTypes() { return ptypes; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Sat Apr 20 12:23:29 2013 +0200 @@ -47,6 +47,17 @@ } /** + * Calls {@link JavaType#resolve(ResolvedJavaType)} on an array of types. + */ + public static ResolvedJavaType[] resolveJavaTypes(JavaType[] types, ResolvedJavaType accessingClass) { + ResolvedJavaType[] result = new ResolvedJavaType[types.length]; + for (int i = 0; i < result.length; i++) { + result[i] = types[i].resolve(accessingClass); + } + return result; + } + + /** * Calls {@link MetaAccessProvider#lookupJavaType(Class)} on an array of classes. */ public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class[] classes) { @@ -58,54 +69,6 @@ } /** - * Gets the {@link Class} mirror for a given resolved type. - * - * @param type the type for which the Java mirror is requested - * @param loader class loader from which the class must be loaded (null means use the class - * loader of the {@link MetaUtil} class) - * @return the mirror for {@code type} - * @throws NoClassDefFoundError if the mirror is not available - */ - public static Class getMirrorOrFail(ResolvedJavaType type, ClassLoader loader) throws NoClassDefFoundError { - ResolvedJavaType elementalType = getElementalType(type); - Class elementalClass; - if (elementalType.isPrimitive()) { - elementalClass = elementalType.getKind().toJavaClass(); - } else { - try { - elementalClass = Class.forName(toJavaName(elementalType), true, loader); - } catch (ClassNotFoundException e) { - throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e); - } - } - if (type.isArray()) { - ResolvedJavaType t = type; - while (t.getComponentType() != null) { - elementalClass = Array.newInstance(elementalClass, 0).getClass(); - t = t.getComponentType(); - } - } - assert elementalClass != null : toJavaName(type); - return elementalClass; - } - - /** - * Gets the {@link Class} mirror for a given resolved type. - * - * @param type the type for which the Java mirror is requested - * @param loader class loader from which the class must be loaded (null means use the class - * loader of the {@link MetaUtil} class) - * @return the mirror for {@code type} or null if it is not available - */ - public static Class getMirror(ResolvedJavaType type, ClassLoader loader) { - try { - return getMirrorOrFail(type, loader); - } catch (NoClassDefFoundError e) { - return null; - } - } - - /** * Gets the elemental type for a given type. The elemental type of an array type is the * corresponding zero dimensional (e.g., the elemental type of {@code int[][][]} is {@code int} * ). A non-array type is its own elemental type. diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Sat Apr 20 12:23:29 2013 +0200 @@ -180,4 +180,26 @@ * Returns the localvariable table of this method. */ LocalVariableTable getLocalVariableTable(); + + /** + * Invokes the underlying method represented by this object, on the specified object with the + * specified parameters. This method is similar to a reflective method invocation by + * {@link Method#invoke}. + * + * @param receiver The receiver for the invocation, or {@code null} if it is a static method. + * @param arguments The arguments for the invocation. + * @return The value returned by the method invocation, or {@code null} if the return type is + * {@code void}. + */ + Constant invoke(Constant receiver, Constant[] arguments); + + /** + * Uses the constructor represented by this object to create and initialize a new instance of + * the constructor's declaring class, with the specified initialization parameters. This method + * is similar to a reflective instantiation by {@link Constructor#newInstance}. + * + * @param arguments The arguments for the constructor. + * @return The newly created and initialized object. + */ + Constant newInstance(Constant[] arguments); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Sat Apr 20 12:23:29 2013 +0200 @@ -274,4 +274,22 @@ * Returns the enclosing type of this type, if it exists, or {@code null}. */ ResolvedJavaType getEnclosingType(); + + /** + * Returns an array reflecting all the constructors declared by this type. This method is + * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors. + */ + ResolvedJavaMethod[] getDeclaredConstructors(); + + /** + * Returns an array reflecting all the methods declared by this type. This method is similar to + * {@link Class#getDeclaredMethods()} in terms of returned methods. + */ + ResolvedJavaMethod[] getDeclaredMethods(); + + /** + * Creates a new array with this type as the component type and the specified length. This + * method is similar to {@link Array#newInstance(Class, int)}. + */ + Constant newArray(int length); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java --- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java Sat Apr 20 12:23:29 2013 +0200 @@ -54,4 +54,20 @@ * is the same as the substitute method. */ String signature() default ""; + + /** + * Determines if this method should be substituted in all cases, even if inlining thinks it is + * not important. + * + * Not that this is still depending on whether inlining sees the correct call target, so it's + * only a hard guarantee for static and special invocations. + */ + boolean forced() default false; + + /** + * Determines if the substitution is for a method that may not be part of the runtime. For + * example, a method introduced in a later JDK version. Substitutions for such methods are + * omitted if the original method cannot be found. + */ + boolean optional() default false; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetTemplateCache.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetTemplateCache.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,29 @@ +/* + * 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.api.replacements; + +/** + * Marker interface for classes that cache snippet templates. + */ +public interface SnippetTemplateCache { +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java --- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java Sat Apr 20 12:23:29 2013 +0200 @@ -24,7 +24,7 @@ import java.lang.annotation.*; -@Retention(RetentionPolicy.SOURCE) +@Retention(RetentionPolicy.CLASS) @Target(ElementType.TYPE) public @interface ServiceProvider { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Sat Apr 20 12:23:29 2013 +0200 @@ -26,8 +26,7 @@ public class PTXAssembler extends AbstractPTXAssembler { - @SuppressWarnings("unused") - public PTXAssembler(TargetDescription target, RegisterConfig registerConfig) { + public PTXAssembler(TargetDescription target, @SuppressWarnings("unused") RegisterConfig registerConfig) { super(target); } @@ -35,6 +34,18 @@ emitString("@%p" + " " + ""); } + public final void atq() { + emitString("@%q" + " " + ""); + } + + public final void add_f32(Register d, Register a, Register b) { + emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_f64(Register d, Register a, Register b) { + emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + public final void add_s16(Register d, Register a, Register b) { emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -59,6 +70,14 @@ emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); } + public final void add_f32(Register d, Register a, float f32) { + emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); + } + + public final void add_f64(Register d, Register a, double f64) { + emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); + } + public final void add_u16(Register d, Register a, Register b) { emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -123,7 +142,63 @@ emitString("bra.uni" + " " + tgt + ";" + ""); } - public final void div_s16(Register d, Register a, Register b) { + public final void cvt_s32_f32(Register d, Register a) { + emitString("cvt.s32.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s64_f32(Register d, Register a) { + emitString("cvt.s64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_f64_f32(Register d, Register a) { + emitString("cvt.f64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_f32_f64(Register d, Register a) { + emitString("cvt.f32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s32_f64(Register d, Register a) { + emitString("cvt.s32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s64_f64(Register d, Register a) { + emitString("cvt.s64.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_f32_s32(Register d, Register a) { + emitString("cvt.f32.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_f64_s32(Register d, Register a) { + emitString("cvt.f64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s8_s32(Register d, Register a) { + emitString("cvt.s8.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_b16_s32(Register d, Register a) { + emitString("cvt.b16.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s64_s32(Register d, Register a) { + emitString("cvt.s64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s32_s64(Register d, Register a) { + emitString("cvt.s32.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void div_f32(Register d, Register a, Register b) { + emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_f64(Register d, Register a, Register b) { + emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_s16(Register d, Register a, Register b) { emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -143,10 +218,30 @@ emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); } + public final void div_s32(Register d, int s32, Register b) { + emitString("div.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_f32(Register d, float f32, Register b) { + emitString("div.f32" + " " + "%r" + d.encoding() + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_f64(Register d, double f64, Register b) { + emitString("div.f64" + " " + "%r" + d.encoding() + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + public final void div_s64(Register d, Register a, long s64) { emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); } + public final void div_f32(Register d, Register a, float f32) { + emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); + } + + public final void div_f64(Register d, Register a, double f64) { + emitString("div.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); + } + public final void div_u16(Register d, Register a, Register b) { emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -255,6 +350,11 @@ emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } + public final void mov_u64(@SuppressWarnings("unused") Register d, + @SuppressWarnings("unused") AbstractAddress a) { + // emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + public final void mov_s16(Register d, Register a) { emitString("mov.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } @@ -319,6 +419,14 @@ emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + ""); } + public final void mul_f32(Register d, Register a, Register b) { + emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void mul_f64(Register d, Register a, Register b) { + emitString("smul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + public final void mul_s16(Register d, Register a, Register b) { emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -343,6 +451,14 @@ emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); } + public final void mul_f32(Register d, Register a, float f32) { + emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); + } + + public final void mul_f64(Register d, Register a, double f64) { + emitString("mul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); + } + public final void mul_u16(Register d, Register a, Register b) { emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -367,6 +483,14 @@ emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); } + public final void neg_f32(Register d, Register a) { + emitString("neg.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void neg_f64(Register d, Register a) { + emitString("neg.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + public final void neg_s16(Register d, Register a) { emitString("neg.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } @@ -379,6 +503,42 @@ emitString("neg.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } + public final void not_s16(Register d, Register a) { + emitString("not.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void not_s32(Register d, Register a) { + emitString("not.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void not_s64(Register d, Register a) { + emitString("not.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void or_b16(Register d, Register a, Register b) { + emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void or_b32(Register d, Register a, Register b) { + emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void or_b64(Register d, Register a, Register b) { + emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void or_b16(Register d, Register a, short b16) { + emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + ""); + } + + public final void or_b32(Register d, Register a, int b32) { + emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + ""); + } + + public final void or_b64(Register d, Register a, long b64) { + emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + ""); + } + public final void popc_b32(Register d, Register a) { emitString("popc.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } @@ -443,6 +603,86 @@ emitString("ret.uni;" + " " + ""); } + public final void setp_eq_f32(Register a, Register b) { + emitString("setp.eq.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_f32(Register a, Register b) { + emitString("setp.ne.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_f32(Register a, Register b) { + emitString("setp.lt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_f32(Register a, Register b) { + emitString("setp.le.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_f32(Register a, Register b) { + emitString("setp.gt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_f32(Register a, Register b) { + emitString("setp.ge.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_f32(float f32, Register b) { + emitString("setp.eq.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_f32(float f32, Register b) { + emitString("setp.ne.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_f32(float f32, Register b) { + emitString("setp.lt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_f32(float f32, Register b) { + emitString("setp.le.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_f32(float f32, Register b) { + emitString("setp.gt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_f32(float f32, Register b) { + emitString("setp.ge.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_f64(double f64, Register b) { + emitString("setp.eq.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_f64(double f64, Register b) { + emitString("setp.ne.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_f64(double f64, Register b) { + emitString("setp.lt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_f64(double f64, Register b) { + emitString("setp.le.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_f64(double f64, Register b) { + emitString("setp.gt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_f64(double f64, Register b) { + emitString("setp.ge.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_s64(Register a, Register b) { + emitString("setp.eq.s64" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_s64(long s64, Register b) { + emitString("setp.eq.s64" + " " + "%p" + ", " + s64 + ", %r" + b.encoding() + ";" + ""); + } + public final void setp_eq_s32(Register a, Register b) { emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -587,6 +827,54 @@ emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); } + public final void shl_s16(Register d, Register a, Register b) { + emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_s32(Register d, Register a, Register b) { + emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_s64(Register d, Register a, Register b) { + emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_s16(Register d, Register a, int u32) { + emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_s32(Register d, Register a, int u32) { + emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_s64(Register d, Register a, int u32) { + emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_u16(Register d, Register a, Register b) { + emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_u32(Register d, Register a, Register b) { + emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_u64(Register d, Register a, Register b) { + emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_u16(Register d, Register a, int u32) { + emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_u32(Register d, Register a, int u32) { + emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_u64(Register d, Register a, int u32) { + emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + public final void shr_s16(Register d, Register a, Register b) { emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -631,8 +919,8 @@ emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); } - public final void shr_u64(Register d, Register a, int u32) { - emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + public final void shr_u64(Register d, Register a, long u64) { + emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); } public final void st_global_b8(Register a, long immOff, Register b) { @@ -691,6 +979,14 @@ emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); } + public final void sub_f32(Register d, Register a, Register b) { + emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_f64(Register d, Register a, Register b) { + emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + public final void sub_s16(Register d, Register a, Register b) { emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -711,10 +1007,22 @@ emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); } + public final void sub_s64(Register d, Register a, int s32) { + emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + public final void sub_s64(Register d, Register a, long s64) { emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); } + public final void sub_f32(Register d, Register a, float f32) { + emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); + } + + public final void sub_f64(Register d, Register a, double f64) { + emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); + } + public final void sub_s16(Register d, short s16, Register b) { emitString("sub.s16" + " " + "%r" + d.encoding() + ", " + s16 + ", %r" + b.encoding() + ";" + ""); } @@ -727,6 +1035,14 @@ emitString("sub.s64" + " " + "%r" + d.encoding() + ", " + s64 + ", %r" + b.encoding() + ";" + ""); } + public final void sub_f32(Register d, float f32, Register b) { + emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f32 + ";" + ""); + } + + public final void sub_f64(Register d, double f64, Register b) { + emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f64 + ";" + ""); + } + public final void sub_sat_s32(Register d, Register a, Register b) { emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -739,6 +1055,30 @@ emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); } + public final void xor_b16(Register d, Register a, Register b) { + emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void xor_b32(Register d, Register a, Register b) { + emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void xor_b64(Register d, Register a, Register b) { + emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void xor_b16(Register d, Register a, short b16) { + emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + ""); + } + + public final void xor_b32(Register d, Register a, int b32) { + emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + ""); + } + + public final void xor_b64(Register d, Register a, long b64) { + emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + ""); + } + @Override public PTXAddress makeAddress(Register base, int displacement) { return new PTXAddress(base, displacement); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -67,7 +67,11 @@ protected Object runTest(String methodName, CodeGenTest test, Object... args) { Method method = getMethod(methodName); InstalledCode code = assembleMethod(method, test); - return code.executeVarargs(args); + try { + return code.executeVarargs(args); + } catch (InvalidInstalledCodeException e) { + throw new RuntimeException(e); + } } protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java --- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java Sat Apr 20 12:23:29 2013 +0200 @@ -168,6 +168,16 @@ } /** + * Reads a constant pool index for an invokedynamic instruction. + * + * @return the constant pool index + */ + public int readCPI4() { + assert opcode == Bytecodes.INVOKEDYNAMIC; + return Bytes.beS4(code, curBCI + 1); + } + + /** * Reads a signed, 1-byte value for the current instruction (e.g. BIPUSH). * * @return the byte diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Sat Apr 20 12:23:29 2013 +0200 @@ -926,4 +926,9 @@ Value[] parameters = visitInvokeArguments(cc, node.arguments); append(new AMD64BreakpointOp(parameters)); } + + @Override + public void visitInfopointNode(InfopointNode i) { + append(new InfopointOp(stateFor(i.stateAfter(), DeoptimizationReason.None), i.reason)); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import java.lang.reflect.Method; + +import org.junit.Test; + +public class ArrayTest extends PTXTestBase { + + @Test + public void testArray() { + compile("testArray1I"); + compile("testArray1J"); + compile("testArray1B"); + compile("testArray1S"); + compile("testArray1C"); + compile("testArray1F"); + compile("testArray1D"); + compile("testArray1L"); + compile("testStoreArray1I"); + compile("testStoreArray1J"); + compile("testStoreArray1B"); + compile("testStoreArray1S"); + compile("testStoreArray1F"); + compile("testStoreArray1D"); + } + + public static int testArray1I(int[] array, int i) { + return array[i]; + } + + public static long testArray1J(long[] array, int i) { + return array[i]; + } + + public static byte testArray1B(byte[] array, int i) { + return array[i]; + } + + public static short testArray1S(short[] array, int i) { + return array[i]; + } + + public static char testArray1C(char[] array, int i) { + return array[i]; + } + + public static float testArray1F(float[] array, int i) { + return array[i]; + } + + public static double testArray1D(double[] array, int i) { + return array[i]; + } + + public static Object testArray1L(Object[] array, int i) { + return array[i]; + } + + public static void testStoreArray1I(int[] array, int i, int val) { + array[i] = val; + } + + public static void testStoreArray1B(byte[] array, int i, byte val) { + array[i] = val; + } + + public static void testStoreArray1S(short[] array, int i, short val) { + array[i] = val; + } + + public static void testStoreArray1J(long[] array, int i, long val) { + array[i] = val; + } + + public static void testStoreArray1F(float[] array, int i, float val) { + array[i] = val; + } + + public static void testStoreArray1D(double[] array, int i, double val) { + array[i] = val; + } + + public static void main(String[] args) { + ArrayTest test = new ArrayTest(); + for (Method m : ArrayTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,81 +22,33 @@ */ package com.oracle.graal.compiler.ptx.test; -import java.lang.reflect.*; - -import org.junit.*; +import java.lang.reflect.Method; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.ptx.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; -import com.oracle.graal.ptx.*; +import org.junit.Test; /** * Test class for small Java methods compiled to PTX kernels. */ -public class BasicPTXTest extends GraalCompilerTest { +public class BasicPTXTest extends PTXTestBase { @Test public void testAdd() { - test("testAddSnippet"); + compile("testAddConst1I"); } - public static int testAddSnippet(int a) { + public static int testAddConst1I(int a) { return a + 1; } - @Test - public void testArray() { - test("testArraySnippet"); - } - - public static int testArraySnippet(int[] array) { - return array[0]; - } - - private CompilationResult test(String snippet) { - StructuredGraph graph = parse(snippet); - Debug.dump(graph, "Graph"); - TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); - PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target); - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); - new PTXPhase().apply(graph); - CompilationResult result = GraalCompiler.compileMethod(runtime, replacements, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog()); - return result; - } - - private static class PTXPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - for (LocalNode local : graph.getNodes(LocalNode.class)) { - if (local.kind() == Kind.Object) { - local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type())); - } - } - } - - } - public static void main(String[] args) { - BasicPTXTest basicPTXTest = new BasicPTXTest(); + BasicPTXTest test = new BasicPTXTest(); Method[] methods = BasicPTXTest.class.getMethods(); for (Method m : methods) { - if (m.getAnnotation(Test.class) != null) { - String name = m.getName() + "Snippet"; - System.out.println(name + ": \n" + new String(basicPTXTest.test(name).getTargetCode())); + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import org.junit.Test; + +import java.lang.reflect.Method; + +public class ControlTest extends PTXTestBase { + + @Test + public void testControl() { + compile("testSwitch1I"); + compile("testStatic"); + compile("testCall"); + compile("testLookupSwitch1I"); + } + + public static int testSwitch1I(int a) { + switch (a) { + case 1: + return 2; + case 2: + return 3; + default: + return 4; + } + } + + public static int testLookupSwitch1I(int a) { + switch (a) { + case 0: return 1; + case 1: return 2; + case 2: return 3; + case 3: return 1; + case 4: return 2; + case 5: return 3; + case 6: return 1; + case 7: return 2; + case 8: return 3; + case 9: return 1; + case 10: return 2; + case 11: return 3; + default: return -1; + } + } + + @SuppressWarnings("unused") + private static Object foo = null; + + public static boolean testStatic(Object o) { + foo = o; + return true; + } + + private static int method(int a, int b) { + return a + b; + } + + public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) { + return method(a, b); + } + + public static void main(String[] args) { + ControlTest test = new ControlTest(); + for (Method m : ControlTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import java.lang.reflect.Method; + +import org.junit.*; + + +/* PTX ISA 3.1 - 8.7.3 Floating-Point Instructions */ +public class FloatPTXTest extends PTXTestBase { + + @Test + public void testAdd() { + compile("testAdd2F"); + compile("testAdd2D"); + compile("testAddFConst"); + compile("testAddConstF"); + compile("testAddDConst"); + compile("testAddConstD"); + } + + public static float testAdd2F(float a, float b) { + return a + b; + } + + public static double testAdd2D(double a, double b) { + return a + b; + } + + public static float testAddFConst(float a) { + return a + 32.0F; + } + + public static float testAddConstF(float a) { + return 32.0F + a; + } + + public static double testAddDConst(double a) { + return a + 32.0; + } + + public static double testAddConstD(double a) { + return 32.0 + a; + } + + @Test + public void testSub() { + compile("testSub2F"); + compile("testSub2D"); + compile("testSubFConst"); + compile("testSubConstF"); + compile("testSubDConst"); + compile("testSubConstD"); + } + + public static float testSub2F(float a, float b) { + return a - b; + } + + public static double testSub2D(double a, double b) { + return a - b; + } + + public static float testSubFConst(float a) { + return a - 32.0F; + } + + public static float testSubConstF(float a) { + return 32.0F - a; + } + + public static double testSubDConst(double a) { + return a - 32.0; + } + + public static double testSubConstD(double a) { + return 32.0 - a; + } + + @Test + public void testMul() { + compile("testMul2F"); + compile("testMul2D"); + compile("testMulFConst"); + compile("testMulConstF"); + compile("testMulDConst"); + compile("testMulConstD"); + } + + public static float testMul2F(float a, float b) { + return a * b; + } + + public static double testMul2D(double a, double b) { + return a * b; + } + + public static float testMulFConst(float a) { + return a * 32.0F; + } + + public static float testMulConstF(float a) { + return 32.0F * a; + } + + public static double testMulDConst(double a) { + return a * 32.0; + } + + public static double testMulConstD(double a) { + return 32.0 * a; + } + + @Test + public void testDiv() { + compile("testDiv2F"); + compile("testDiv2D"); + compile("testDivFConst"); + compile("testDivConstF"); + compile("testDivDConst"); + compile("testDivConstD"); + } + + public static float testDiv2F(float a, float b) { + return a / b; + } + + public static double testDiv2D(double a, double b) { + return a / b; + } + + public static float testDivFConst(float a) { + return a / 32.0F; + } + + public static float testDivConstF(float a) { + return 32.0F / a; + } + + public static double testDivDConst(double a) { + return a / 32.0; + } + + public static double testDivConstD(double a) { + return 32.0 / a; + } + + @Test + public void testNeg() { + compile("testNeg2F"); + compile("testNeg2D"); + } + + public static float testNeg2F(float a) { + return -a; + } + + public static double testNeg2D(double a) { + return -a; + } + + @Test + public void testRem() { + // need linkage to PTX remainder() + // compile("testRem2F"); + // compile("testRem2D"); + } + + public static float testRem2F(float a, float b) { + return a % b; + } + + public static double testRem2D(double a, double b) { + return a % b; + } + + @Test + public void testFloatConversion() { + compile("testF2I"); + compile("testF2L"); + compile("testF2D"); + compile("testD2I"); + compile("testD2L"); + compile("testD2F"); + } + + public static int testF2I(float a) { + return (int) a; + } + + public static long testF2L(float a) { + return (long) a; + } + + public static double testF2D(float a) { + return a; + } + + public static int testD2I(double a) { + return (int) a; + } + + public static long testD2L(double a) { + return (long) a; + } + + public static float testD2F(double a) { + return (float) a; + } + + public static void main(String[] args) { + FloatPTXTest test = new FloatPTXTest(); + for (Method m : FloatPTXTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && + name.startsWith("test") && + name.startsWith("testRem") == false) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import org.junit.Test; + +import java.lang.reflect.Method; + + +public class IntegerPTXTest extends PTXTestBase { + + @Test + public void testAdd() { + compile("testAdd2I"); + compile("testAdd2L"); + compile("testAdd2B"); + compile("testAddIConst"); + compile("testAddConstI"); + } + + public static int testAdd2I(int a, int b) { + return a + b; + } + + public static long testAdd2L(long a, long b) { + return a + b; + } + + public static int testAdd2B(byte a, byte b) { + return a + b; + } + + public static int testAddIConst(int a) { + return a + 32; + } + + public static int testAddConstI(int a) { + return 32 + a; + } + + @Test + public void testSub() { + compile("testSub2I"); + compile("testSub2L"); + compile("testSubIConst"); + compile("testSubConstI"); + } + + public static int testSub2I(int a, int b) { + return a - b; + } + + public static long testSub2L(long a, long b) { + return a - b; + } + + public static int testSubIConst(int a) { + return a - 32; + } + + public static int testSubConstI(int a) { + return 32 - a; + } + + @Test + public void testMul() { + compile("testMul2I"); + compile("testMul2L"); + compile("testMulIConst"); + compile("testMulConstI"); + } + + public static int testMul2I(int a, int b) { + return a * b; + } + + public static long testMul2L(long a, long b) { + return a * b; + } + + public static int testMulIConst(int a) { + return a * 32; + } + + public static int testMulConstI(int a) { + return 32 * a; + } + + @Test + public void testDiv() { + compile("testDiv2I"); + compile("testDiv2L"); + compile("testDivIConst"); + compile("testDivConstI"); + } + + public static int testDiv2I(int a, int b) { + return a / b; + } + + public static long testDiv2L(long a, long b) { + return a / b; + } + + public static int testDivIConst(int a) { + return a / 32; + } + + public static int testDivConstI(int a) { + return 32 / a; + } + + @Test + public void testRem() { + compile("testRem2I"); + compile("testRem2L"); + } + + public static int testRem2I(int a, int b) { + return a % b; + } + + public static long testRem2L(long a, long b) { + return a % b; + } + + @Test + public void testIntConversion() { + compile("testI2L"); + compile("testL2I"); + compile("testI2C"); + compile("testI2B"); + compile("testI2F"); + compile("testI2D"); + } + + public static long testI2L(int a) { + return a; + } + + public static char testI2C(int a) { + return (char) a; + } + + public static byte testI2B(int a) { + return (byte) a; + } + + public static float testI2F(int a) { + return a; + } + + public static double testI2D(int a) { + return a; + } + + public static int testL2I(long a) { + return (int) a; + } + + public static void main(String[] args) { + IntegerPTXTest test = new IntegerPTXTest(); + for (Method m : IntegerPTXTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import java.lang.reflect.Method; + +import org.junit.Test; + + +/* PTX ISA 3.1 - 8.7.5 Logic and Shift Instructions */ +public class LogicPTXTest extends PTXTestBase { + + @Test + public void testAnd() { + compile("testAnd2I"); + compile("testAnd2L"); + } + + public static int testAnd2I(int a, int b) { + return a & b; + } + + public static long testAnd2L(long a, long b) { + return a & b; + } + + @Test + public void testOr() { + compile("testOr2I"); + compile("testOr2L"); + } + + public static int testOr2I(int a, int b) { + return a | b; + } + + public static long testOr2L(long a, long b) { + return a | b; + } + + @Test + public void testXor() { + compile("testXor2I"); + compile("testXor2L"); + } + + public static int testXor2I(int a, int b) { + return a ^ b; + } + + public static long testXor2L(long a, long b) { + return a ^ b; + } + + @Test + public void testNot() { + compile("testNot1I"); + compile("testNot1L"); + } + + public static int testNot1I(int a) { + return ~a; + } + + public static long testNot1L(long a) { + return ~a; + } + + @Test + public void testShiftLeft() { + compile("testShiftLeft2I"); + compile("testShiftLeft2L"); + } + + public static int testShiftLeft2I(int a, int b) { + return a << b; + } + + public static long testShiftLeft2L(long a, int b) { + return a << b; + } + + @Test + public void testShiftRight() { + compile("testShiftRight2I"); + compile("testShiftRight2L"); + compile("testUnsignedShiftRight2I"); + compile("testUnsignedShiftRight2L"); + } + + public static int testShiftRight2I(int a, int b) { + return a >> b; + } + + public static long testShiftRight2L(long a, int b) { + return a >> b; + } + + public static int testUnsignedShiftRight2I(int a, int b) { + return a >>> b; + } + + public static long testUnsignedShiftRight2L(long a, long b) { + return a >>> b; + } + + public static void main(String[] args) { + LogicPTXTest test = new LogicPTXTest(); + for (Method m : LogicPTXTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.nodes.LocalNode; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.type.StampFactory; +import com.oracle.graal.phases.Phase; + + +public class PTXPhase extends Phase { + @Override + protected void run(StructuredGraph graph) { + /* + * Assume that null checks would be done on the CPU caller side prior + * to copying data onto the GPU. + */ + for (LocalNode local : graph.getNodes(LocalNode.class)) { + if (local.kind() == Kind.Object) { + local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type())); + } + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import com.oracle.graal.api.code.CodeCacheProvider; +import com.oracle.graal.api.code.CompilationResult; +import com.oracle.graal.api.code.SpeculationLog; +import com.oracle.graal.api.code.TargetDescription; +import com.oracle.graal.api.runtime.Graal; +import com.oracle.graal.compiler.GraalCompiler; +import com.oracle.graal.compiler.ptx.PTXBackend; +import com.oracle.graal.compiler.test.GraalCompilerTest; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.java.GraphBuilderConfiguration; +import com.oracle.graal.java.GraphBuilderPhase; +import com.oracle.graal.hotspot.HotSpotGraalRuntime; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.phases.OptimisticOptimizations; +import com.oracle.graal.phases.PhasePlan; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.ptx.PTX; + +public abstract class PTXTestBase extends GraalCompilerTest { + + protected CompilationResult compile(String test) { + StructuredGraph graph = parse(test); + Debug.dump(graph, "Graph"); + TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); + PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target); + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), + OptimisticOptimizations.NONE); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); + new PTXPhase().apply(graph); + CompilationResult result = GraalCompiler.compileMethod(runtime, HotSpotGraalRuntime.getInstance().getReplacements(), + ptxBackend, target, graph.method(), graph, null, phasePlan, + OptimisticOptimizations.NONE, new SpeculationLog()); + return result; + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Sat Apr 20 12:23:29 2013 +0200 @@ -94,7 +94,7 @@ codeBuffer.emitString(""); // XXX For now declare one predicate and all registers - codeBuffer.emitString(" .reg .pred %p;"); + codeBuffer.emitString(" .reg .pred %p,%q;"); codeBuffer.emitString(" .reg .u32 %r<16>;"); // Emit code for the LIR diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Sat Apr 20 12:23:29 2013 +0200 @@ -28,35 +28,59 @@ import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.ptx.PTXCompare.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.api.code.AllocatableValue; +import com.oracle.graal.api.code.CodeCacheProvider; +import com.oracle.graal.api.code.DeoptimizationAction; +import com.oracle.graal.api.code.RuntimeCallTarget; +import com.oracle.graal.api.code.StackSlot; +import com.oracle.graal.api.code.TargetDescription; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.Constant; +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.api.meta.Value; +import com.oracle.graal.asm.NumUtil; +import com.oracle.graal.compiler.gen.LIRGenerator; +import com.oracle.graal.compiler.target.LIRGenLowerable; +import com.oracle.graal.graph.GraalInternalError; +import com.oracle.graal.lir.FrameMap; +import com.oracle.graal.lir.LIR; +import com.oracle.graal.lir.LIRFrameState; +import com.oracle.graal.lir.LIRInstruction; +import com.oracle.graal.lir.LIRValueUtil; +import com.oracle.graal.lir.LabelRef; import com.oracle.graal.lir.StandardOp.JumpOp; -import com.oracle.graal.lir.ptx.*; +import com.oracle.graal.lir.Variable; +import com.oracle.graal.lir.ptx.PTXAddressValue; import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp; +import com.oracle.graal.lir.ptx.PTXBitManipulationOp; import com.oracle.graal.lir.ptx.PTXCompare.CompareOp; import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp; import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.TableSwitchOp; import com.oracle.graal.lir.ptx.PTXMove.LoadOp; import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp; import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp; import com.oracle.graal.lir.ptx.PTXMove.StoreOp; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.calc.Condition; +import com.oracle.graal.nodes.calc.ConvertNode; +import com.oracle.graal.nodes.java.CompareAndSwapNode; /** * This class implements the PTX specific portion of the LIR generator. */ public class PTXLIRGenerator extends LIRGenerator { + public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, float.class, float.class, float.class); + public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, double.class, double.class, double.class); + public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory { @Override @@ -131,7 +155,7 @@ baseRegister = asAllocatable(base); } - if (index != Value.ILLEGAL) { + if (index != Value.ILLEGAL && scale != 0) { if (isConstant(index)) { finalDisp += asConstant(index).asLong() * scale; } else { @@ -145,6 +169,9 @@ if (baseRegister == AllocatableValue.UNUSED) { baseRegister = asAllocatable(indexRegister); } else { + Variable newBase = newVariable(Kind.Int); + emitMove(newBase, baseRegister); + baseRegister = newBase; baseRegister = emitAdd(baseRegister, indexRegister); } } @@ -190,6 +217,18 @@ append(new CompareOp(ICMP, cond, left, right)); append(new BranchOp(cond, label)); break; + case Long: + append(new CompareOp(LCMP, cond, left, right)); + append(new BranchOp(cond, label)); + break; + case Float: + append(new CompareOp(FCMP, cond, left, right)); + append(new BranchOp(cond, label)); + break; + case Double: + append(new CompareOp(DCMP, cond, left, right)); + append(new BranchOp(cond, label)); + break; case Object: append(new CompareOp(ACMP, cond, left, right)); append(new BranchOp(cond, label)); @@ -211,7 +250,67 @@ @Override public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { - throw new InternalError("NYI"); + boolean mirrored = emitCompare(cond, left, right); + Condition finalCondition = mirrored ? cond.mirror() : cond; + + Variable result = newVariable(trueValue.getKind()); + switch (left.getKind().getStackKind()) { + case Int: + case Long: + case Object: + append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); + break; + case Float: + case Double: + append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind()); + } + return result; + } + + /** + * This method emits the compare instruction, and may reorder the operands. It returns true if + * it did so. + * + * @param a the left operand of the comparison + * @param b the right operand of the comparison + * @return true if the left and right operands were switched, false otherwise + */ + private boolean emitCompare(Condition cond, Value a, Value b) { + Variable left; + Value right; + boolean mirrored; + if (LIRValueUtil.isVariable(b)) { + left = load(b); + right = loadNonConst(a); + mirrored = true; + } else { + left = load(a); + right = loadNonConst(b); + mirrored = false; + } + switch (left.getKind().getStackKind()) { + case Int: + append(new CompareOp(ICMP, cond, left, right)); + break; + case Long: + append(new CompareOp(LCMP, cond, left, right)); + break; + case Object: + append(new CompareOp(ACMP, cond, left, right)); + break; + case Float: + append(new CompareOp(FCMP, cond, left, right)); + break; + case Double: + append(new CompareOp(DCMP, cond, left, right)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return mirrored; } @Override @@ -226,6 +325,12 @@ case Int: append(new Op1Stack(INEG, result, input)); break; + case Float: + append(new Op1Stack(FNEG, result, input)); + break; + case Double: + append(new Op1Stack(DNEG, result, input)); + break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -239,8 +344,17 @@ case Int: append(new Op2Stack(IADD, result, a, loadNonConst(b))); break; + case Long: + append(new Op2Stack(LADD, result, a, loadNonConst(b))); + break; + case Float: + append(new Op2Stack(FADD, result, a, loadNonConst(b))); + break; + case Double: + append(new Op2Stack(DADD, result, a, loadNonConst(b))); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind() + " prim: " + a.getKind().isPrimitive()); } return result; } @@ -252,8 +366,17 @@ case Int: append(new Op2Stack(ISUB, result, a, loadNonConst(b))); break; + case Long: + append(new Op2Stack(LSUB, result, a, loadNonConst(b))); + break; + case Float: + append(new Op2Stack(FSUB, result, a, loadNonConst(b))); + break; + case Double: + append(new Op2Stack(DSUB, result, a, loadNonConst(b))); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); } return result; } @@ -265,8 +388,17 @@ case Int: append(new Op2Reg(IMUL, result, a, loadNonConst(b))); break; + case Long: + append(new Op2Reg(LMUL, result, a, loadNonConst(b))); + break; + case Float: + append(new Op2Stack(FMUL, result, a, loadNonConst(b))); + break; + case Double: + append(new Op2Stack(DMUL, result, a, loadNonConst(b))); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); } return result; } @@ -279,12 +411,40 @@ @Override public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Reg(IDIV, result, a, loadNonConst(b))); + break; + case Long: + append(new Op2Reg(LDIV, result, a, loadNonConst(b))); + break; + case Float: + append(new Op2Stack(FDIV, result, a, loadNonConst(b))); + break; + case Double: + append(new Op2Stack(DDIV, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); + } + return result; } @Override public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Reg(IREM, result, a, loadNonConst(b))); + break; + case Long: + append(new Op2Reg(LREM, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); + } + return result; } @Override @@ -304,6 +464,42 @@ case Int: append(new Op2Stack(IAND, result, a, loadNonConst(b))); break; + case Long: + append(new Op2Stack(LAND, result, a, loadNonConst(b))); + break; + + default: + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); + } + return result; + } + + @Override + public Variable emitOr(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(IOR, result, a, loadNonConst(b))); + break; + case Long: + append(new Op2Stack(LOR, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); + } + return result; + } + + @Override + public Variable emitXor(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(IXOR, result, a, loadNonConst(b))); + break; + case Long: + append(new Op2Stack(LXOR, result, a, loadNonConst(b))); + break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -311,23 +507,35 @@ } @Override - public Variable emitOr(Value a, Value b) { - throw new InternalError("NYI"); - } - - @Override - public Variable emitXor(Value a, Value b) { - throw new InternalError("NYI"); - } - - @Override public Variable emitShl(Value a, Value b) { - throw new InternalError("NYI"); + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(ISHL, result, a, loadNonConst(b))); + break; + case Long: + append(new Op1Stack(LSHL, result, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; } @Override public Variable emitShr(Value a, Value b) { - throw new InternalError("NYI"); + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(ISHR, result, a, loadNonConst(b))); + break; + case Long: + append(new Op1Stack(LSHR, result, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; } @Override @@ -337,15 +545,87 @@ case Int: append(new ShiftOp(IUSHR, result, a, b)); break; + case Long: + append(new ShiftOp(LUSHR, result, a, b)); + break; default: - GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } return result; } @Override public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { - throw new InternalError("NYI"); + Variable input = load(inputVal); + Variable result = newVariable(opcode.to); + switch (opcode) { + case I2L: + append(new Unary2Op(I2L, result, input)); + break; + case L2I: + append(new Unary1Op(L2I, result, input)); + break; + case I2B: + append(new Unary2Op(I2B, result, input)); + break; + case I2C: + append(new Unary1Op(I2C, result, input)); + break; + case I2S: + append(new Unary2Op(I2S, result, input)); + break; + case F2D: + append(new Unary2Op(F2D, result, input)); + break; + case D2F: + append(new Unary2Op(D2F, result, input)); + break; + case I2F: + append(new Unary2Op(I2F, result, input)); + break; + case I2D: + append(new Unary2Op(I2D, result, input)); + break; + case F2I: + append(new Unary2Op(F2I, result, input)); + break; + case D2I: + append(new Unary2Op(D2I, result, input)); + break; + case L2F: + append(new Unary2Op(L2F, result, input)); + break; + case L2D: + append(new Unary2Op(L2D, result, input)); + break; + case F2L: + append(new Unary2Op(F2L, result, input)); + break; + case D2L: + append(new Unary2Op(D2L, result, input)); + break; + case MOV_I2F: + append(new Unary2Op(MOV_I2F, result, input)); + break; + case MOV_L2D: + append(new Unary2Op(MOV_L2D, result, input)); + break; + case MOV_F2I: + append(new Unary2Op(MOV_F2I, result, input)); + break; + case MOV_D2L: + append(new Unary2Op(MOV_D2L, result, input)); + break; + case UNSIGNED_I2L: + // Instructions that move or generate 32-bit register values also set the upper 32 + // bits of the register to zero. + // Consequently, there is no need for a special zero-extension move. + emitMove(result, input); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; } @Override @@ -434,7 +714,14 @@ @Override protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { - throw new InternalError("NYI"); + // Making a copy of the switch value is necessary because jump table destroys the input + // value + if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) { + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL)); + } else { + assert key.getKind() == Kind.Object : key.getKind(); + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object))); + } } @Override @@ -444,7 +731,10 @@ @Override protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { - throw new InternalError("NYI"); + // Making a copy of the switch value is necessary because jump table destroys the input + // value + Variable tmp = emitMove(key); + append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind))); } @Override @@ -459,17 +749,23 @@ @Override public void visitSafepointNode(SafepointNode i) { + // LIRFrameState info = state(); + // append(new PTXSafepointOp(info, runtime().config, this)); throw new InternalError("NYI"); } @Override public void emitUnwind(Value operand) { - // TODO Auto-generated method stub - + throw new InternalError("NYI"); } @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { throw new InternalError("NYI"); } + + @Override + public void visitInfopointNode(InfopointNode i) { + throw new InternalError("NYI"); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Sat Apr 20 12:23:29 2013 +0200 @@ -368,4 +368,10 @@ // SPARC: Auto-generated method stub } + + @Override + public void visitInfopointNode(InfopointNode i) { + // SPARC: Auto-generated method stub + + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,17 +22,17 @@ */ package com.oracle.graal.compiler.test; -import java.util.*; - import org.junit.*; import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; +import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.virtual.nodes.*; +import com.oracle.graal.virtual.phases.ea.*; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -57,17 +57,25 @@ return 1; } - public static Object boxedObject() { + public static Object boxedObjectShort() { return (short) 1; } + public static Object boxedObjectInteger() { + return (int) 1; + } + + public static Integer boxedInteger() { + return 2; + } + public static Short constantBoxedShort() { return s; } @Test public void test1() { - test("test1Snippet", "referenceSnippet1"); + compareGraphs("test1Snippet", "referenceSnippet1"); } @SuppressWarnings("all") @@ -77,17 +85,17 @@ @Test public void test2() { - test("test2Snippet", "referenceSnippet1"); + compareGraphs("test2Snippet", "referenceSnippet1"); } @SuppressWarnings("all") public static short test2Snippet() { - return (Short) boxedObject(); + return (Short) boxedObjectShort(); } @Test public void test3() { - test("test3Snippet", "referenceSnippet1"); + compareGraphs("test3Snippet", "referenceSnippet1"); } @SuppressWarnings("all") @@ -101,7 +109,7 @@ @Test public void test4() { - test("test4Snippet", "referenceSnippet2"); + compareGraphs("test4Snippet", "referenceSnippet2"); } @SuppressWarnings("all") @@ -109,33 +117,238 @@ return constantBoxedShort(); } - private void test(final String snippet, final String referenceSnippet) { - Debug.scope("BoxingEliminationTest", new DebugDumpScope(snippet), new Runnable() { + @Test + public void testLoop() { + compareGraphs("testLoopSnippet", "referenceLoopSnippet", false, true); + } + + public static int testLoopSnippet(int n, int a) { + Integer sum = a; + for (Integer i = 0; i < n; i++) { + sum += i; + } + return sum; + } + + public static int referenceLoopSnippet(int n, int a) { + int sum = a; + for (int i = 0; i < n; i++) { + sum += i; + } + return sum; + } + + @Test + public void testLoop2() { + compareGraphs("testLoop2Snippet", "referenceLoop2Snippet", true, true); + } + + public static int testLoop2Snippet(int n, Integer a) { + Integer sum = a; + for (Integer i = 0; i < n; i++) { + sum += i; + } + return sum; + } + + public static int referenceLoop2Snippet(int n, Integer a) { + Integer sum0; + if (n <= 0) { + sum0 = a; + } else { + int sum = a; + for (int i = 0; i < n; i++) { + sum += i; + } + sum0 = sum; + } + return sum0; + } + + public static int referenceIfSnippet(int a) { + int result; + if (a < 0) { + result = 2; + } else { + result = 1; + } + return result; + } + + @Test + public void testIf() { + compareGraphs("testIfSnippet", "referenceIfSnippet"); + } + + public static int testIfSnippet(int a) { + Integer result; + if (a < 0) { + result = boxedInteger(); + } else { + result = (Integer) boxedObjectInteger(); + } + return result; + } + + @Test + public void testComparison() { + compareGraphs("testComparison1Snippet", "referenceComparisonSnippet"); + compareGraphs("testComparison2Snippet", "referenceComparisonSnippet"); + } + + @SuppressWarnings("cast") + public static boolean testComparison1Snippet(int a, int b) { + return ((Integer) a) == b; + } + + public static boolean testComparison2Snippet(int a, int b) { + Integer x = a; + Integer y = b; + return x == y; + } + + public static boolean referenceComparisonSnippet(int a, int b) { + return a == b; + } + + @Test + public void testLateCanonicalization() { + compareGraphs("testLateCanonicalizationSnippet", "referenceLateCanonicalizationSnippet"); + } + + public static boolean testLateCanonicalizationSnippet(int a) { + Integer x = a; + Integer y = 1000; + return x == y; + } + + public static boolean referenceLateCanonicalizationSnippet(int a) { + return a == 1000; + } + + private StructuredGraph graph; + + public static Integer materializeReferenceSnippet(int a) { + return Integer.valueOf(a); + } + + public static Integer materializeTest1Snippet(int a) { + Integer v = a; + + if (v == a) { + return v; + } else { + return null; + } + } + + @Test + public void materializeTest1() { + test("materializeTest1Snippet", 1); + } + + public static int intTest1Snippet() { + return Integer.valueOf(1); + } + + @Test + public void intTest1() { + ValueNode result = getResult("intTest1Snippet"); + Assert.assertTrue(result.isConstant()); + Assert.assertEquals(1, result.asConstant().asInt()); + } + + public static int mergeTest1Snippet(boolean d, int a, int b) { + Integer v; + if (d) { + v = a; + } else { + v = b; + } + return v; + } + + @Test + public void mergeTest1() { + processMethod("mergeTest1Snippet"); + } + + public static boolean equalsTest1Snippet(int x, int y) { + Integer a = x; + Integer b = y; + return a == b; + } + + @Test + public void equalsTest1() { + processMethod("equalsTest1Snippet"); + } + + public static int loopTest1Snippet(int n, int v) { + Integer sum = 0; + for (int i = 0; i < n; i++) { + sum += v; + } + return sum; + } + + @Test + public void loopTest1() { + processMethod("loopTest1Snippet"); + + } + + final ValueNode getResult(String snippet) { + processMethod(snippet); + assertEquals(1, graph.getNodes(ReturnNode.class).count()); + return graph.getNodes(ReturnNode.class).first().result(); + } + + private void processMethod(final String snippet) { + graph = parse(snippet); + new ComputeProbabilityPhase().apply(graph); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); + new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new PartialEscapeAnalysisPhase(false, false).apply(graph, context); + new CullFrameStatesPhase().apply(graph); + } + + private void compareGraphs(final String snippet, final String referenceSnippet) { + compareGraphs(snippet, referenceSnippet, false, false); + } + + private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) { + Debug.scope("BoxingEliminationTest " + snippet, new DebugDumpScope(snippet), new Runnable() { @Override public void run() { - StructuredGraph graph = parse(snippet); - BoxingMethodPool pool = new BoxingMethodPool(runtime()); - IdentifyBoxingPhase identifyBoxingPhase = new IdentifyBoxingPhase(pool); - PhasePlan phasePlan = getDefaultPhasePlan(); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, identifyBoxingPhase); - identifyBoxingPhase.apply(graph); - Map hints = new HashMap<>(); - for (Invoke invoke : graph.getInvokes()) { - hints.put(invoke, 1000d); + graph = parse(snippet); + + new ComputeProbabilityPhase().apply(graph); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); + new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + if (loopPeeling) { + new LoopTransformHighPhase().apply(graph); + } + new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase().apply(graph, context); + new PartialEscapeAnalysisPhase(false, false).apply(graph, context); + + for (MaterializeObjectNode materialize : graph.getNodes(MaterializeObjectNode.class)) { + materialize.getVirtualObject().materializeAt(materialize, materialize.getValues(), false, materialize.getLockCount()); } - Assumptions assumptions = new Assumptions(false); - new InliningPhase(runtime(), hints, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - Debug.dump(graph, "Graph"); - new BoxingEliminationPhase(runtime()).apply(graph); - Debug.dump(graph, "Graph"); - new ExpandBoxingNodesPhase(pool).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CullFrameStatesPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase().apply(graph, context); + StructuredGraph referenceGraph = parse(referenceSnippet); - assertEquals(referenceGraph, graph); + new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(referenceGraph); + new DeadCodeEliminationPhase().apply(referenceGraph); + new CanonicalizerPhase().apply(referenceGraph, context); + assertEquals(referenceGraph, graph, excludeVirtual); } }); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -35,7 +35,7 @@ private StructuredGraph getCanonicalizedGraph(String name) { StructuredGraph graph = parse(name); - new CanonicalizerPhase(runtime(), null).apply(graph); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); return graph; } @@ -53,7 +53,7 @@ assertEquals(referenceGraph, graph); } Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph); for (int i = 1; i < 4; i++) { StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i); assertEquals(referenceGraph, graph); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -82,7 +82,7 @@ public void run() { StructuredGraph graph = parse(snippet); new InliningPhase(runtime(), null, replacements, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); Debug.dump(graph, "Graph"); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); Debug.dump(referenceGraph, "ReferenceGraph"); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import java.util.concurrent.*; + +import junit.framework.Assert; + +import org.junit.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.common.*; + +public class EliminateNestedCheckCastsTest extends GraalCompilerTest { + + public static long test1Snippet(A1 a1) { + A2 a2 = (A2) a1; + A3 a3 = (A3) a2; + A4 a4 = (A4) a3; + A5 a5 = (A5) a4; + A6 a6 = (A6) a5; + return a6.x6; + } + + @Test + public void test1() { + compileSnippet("test1Snippet", 5, 1); + } + + public static long test2Snippet(A1 a1) { + A2 a2 = (A2) a1; + A3 a3 = (A3) a2; + A4 a4 = (A4) a3; + A5 a5 = (A5) a4; + A6 a6 = (A6) a5; + // as a3 has an usage, thus don't remove the A3 checkcast. + return a3.x2 + a6.x6; + } + + @Test + public void test2() { + compileSnippet("test2Snippet", 5, 2); + } + + private StructuredGraph compileSnippet(final String snippet, final int checkcasts, final int afterCanon) { + return Debug.scope(snippet, new Callable() { + + @Override + public StructuredGraph call() throws Exception { + StructuredGraph graph = parse(snippet); + Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count()); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); + Assert.assertEquals(afterCanon, graph.getNodes(CheckCastNode.class).count()); + return graph; + } + + }); + } + + public static class A1 { + + public long x1 = 1; + } + + public static class A2 extends A1 { + + public long x2 = 2; + } + + public static class A3 extends A2 { + + public long x3 = 3; + } + + public static class A4 extends A3 { + + public long x4 = 4; + } + + public static class A5 extends A4 { + + public long x5 = 5; + } + + public static class A6 extends A5 { + + public long x6 = 6; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Assumptions.Assumption; +import com.oracle.graal.api.code.Assumptions.NoFinalizableSubclass; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +public class FinalizableSubclassTest extends GraalCompilerTest { + + /** + * used as template to generate class files at runtime. + */ + public static class NoFinalizerEverAAAA { + } + + public static class NoFinalizerYetAAAA { + } + + public static class WithFinalizerAAAA extends NoFinalizerYetAAAA { + + @Override + protected void finalize() throws Throwable { + super.finalize(); + } + } + + private StructuredGraph parseAndProcess(Class cl, Assumptions assumptions) { + Constructor[] constructors = cl.getConstructors(); + Assert.assertTrue(constructors.length == 1); + final ResolvedJavaMethod javaMethod = runtime.lookupJavaConstructor(constructors[0]); + StructuredGraph graph = new StructuredGraph(javaMethod); + + GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(); + new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph); + new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); + return graph; + } + + private void checkForRegisterFinalizeNode(Class cl, boolean shouldContainFinalizer, boolean optimistic) { + Assumptions assumptions = new Assumptions(optimistic); + StructuredGraph graph = parseAndProcess(cl, assumptions); + Assert.assertTrue(graph.getNodes().filter(RegisterFinalizerNode.class).count() == (shouldContainFinalizer ? 1 : 0)); + int noFinalizerAssumption = 0; + for (Assumption a : assumptions) { + if (a instanceof NoFinalizableSubclass) { + noFinalizerAssumption++; + } + } + Assert.assertTrue(noFinalizerAssumption == (shouldContainFinalizer ? 0 : 1)); + } + + /** + * Use a custom class loader to generate classes, to make sure the given classes are loaded in + * correct order. + */ + @Test + public void test1() throws ClassNotFoundException { + for (int i = 0; i < 2; i++) { + ClassTemplateLoader loader = new ClassTemplateLoader(); + checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), true, false); + checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, true); + + checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), false, true); + + checkForRegisterFinalizeNode(loader.findClass("WithFinalizerAAAA"), true, true); + checkForRegisterFinalizeNode(loader.findClass("NoFinalizerYetAAAA"), true, true); + } + } + + private static class ClassTemplateLoader extends ClassLoader { + + private static int loaderInstance = 0; + + private final String replaceTo; + private HashMap cache = new HashMap<>(); + + public ClassTemplateLoader() { + loaderInstance++; + replaceTo = String.format("%04d", loaderInstance); + } + + @Override + protected Class findClass(final String name) throws ClassNotFoundException { + return Debug.scope("FinalizableSubclassTest", new Callable>() { + + @Override + public Class call() throws Exception { + String nameReplaced = name.replaceAll("AAAA", replaceTo); + if (cache.containsKey(nameReplaced)) { + return cache.get(nameReplaced); + } + + // copy classfile to byte array + byte[] classData = null; + try { + InputStream is = FinalizableSubclassTest.class.getResourceAsStream("FinalizableSubclassTest$" + name + ".class"); + assert is != null; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + byte[] buf = new byte[1024]; + int size; + while ((size = is.read(buf, 0, buf.length)) != -1) { + baos.write(buf, 0, size); + } + baos.flush(); + classData = baos.toByteArray(); + } catch (IOException e) { + Assert.fail("can't access class: " + name); + } + dumpStringsInByteArray(classData); + + // replace all occurrences of "AAAA" in classfile + int index = -1; + while ((index = indexOfAAAA(classData, index + 1)) != -1) { + replaceAAAA(classData, index, replaceTo); + } + dumpStringsInByteArray(classData); + + Class c = defineClass(null, classData, 0, classData.length); + cache.put(nameReplaced, c); + return c; + } + }); + } + + private static int indexOfAAAA(byte[] b, int index) { + for (int i = index; i < b.length; i++) { + boolean match = true; + for (int j = i; j < i + 4; j++) { + if (b[j] != (byte) 'A') { + match = false; + break; + } + } + if (match) { + return i; + } + } + return -1; + } + + private static void replaceAAAA(byte[] b, int index, String replacer) { + assert replacer.length() == 4; + for (int i = index; i < index + 4; i++) { + b[i] = (byte) replacer.charAt(i - index); + } + } + + private static void dumpStringsInByteArray(byte[] b) { + boolean wasChar = true; + StringBuilder sb = new StringBuilder(); + for (Byte x : b) { + // check for [a-zA-Z0-9] + if ((x >= 0x41 && x <= 0x7a) || (x >= 0x30 && x <= 0x39)) { + if (!wasChar) { + Debug.log(sb + ""); + sb.setLength(0); + } + sb.append(String.format("%c", x)); + wasChar = true; + } else { + wasChar = false; + } + } + Debug.log(sb + ""); + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -40,11 +40,13 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.printer.*; import com.oracle.graal.test.*; +import com.oracle.graal.hotspot.phases.WriteBarrierAdditionPhase; /** * Base class for Graal compiler unit tests. @@ -83,11 +85,15 @@ } protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { - String expectedString = getCanonicalGraphString(expected); - String actualString = getCanonicalGraphString(graph); + assertEquals(expected, graph, false); + } + + protected void assertEquals(StructuredGraph expected, StructuredGraph graph, boolean excludeVirtual) { + String expectedString = getCanonicalGraphString(expected, excludeVirtual); + String actualString = getCanonicalGraphString(graph, excludeVirtual); String mismatchString = "mismatch in graphs:\n========= expected =========\n" + expectedString + "\n\n========= actual =========\n" + actualString; - if (expected.getNodeCount() != graph.getNodeCount()) { + if (!excludeVirtual && expected.getNodeCount() != graph.getNodeCount()) { Debug.dump(expected, "Node count not matching - expected"); Debug.dump(graph, "Node count not matching - actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString); @@ -100,7 +106,7 @@ } protected void assertConstantReturn(StructuredGraph graph, int value) { - String graphString = getCanonicalGraphString(graph); + String graphString = getCanonicalGraphString(graph, false); Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1); ValueNode result = graph.getNodes(ReturnNode.class).first().result(); Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant()); @@ -108,7 +114,7 @@ Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asConstant().asInt(), value); } - protected static String getCanonicalGraphString(StructuredGraph graph) { + protected static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual) { SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph); @@ -127,15 +133,17 @@ } result.append("\n"); for (Node node : schedule.getBlockToNodesMap().get(block)) { - int id; - if (canonicalId.get(node) != null) { - id = canonicalId.get(node); - } else { - id = nextId++; - canonicalId.set(node, id); + if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) { + int id; + if (canonicalId.get(node) != null) { + id = canonicalId.get(node); + } else { + id = nextId++; + canonicalId.set(node, id); + } + String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); + result.append(" " + id + "|" + name + (excludeVirtual ? "\n" : " (" + node.usages().count() + ")\n")); } - String name = node instanceof ConstantNode ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); - result.append(" " + id + "|" + name + " (" + node.usages().count() + ")\n"); } } return result.toString(); @@ -397,14 +405,17 @@ } long start = System.currentTimeMillis(); PhasePlan phasePlan = new PhasePlan(); + StructuredGraph graphCopy = graph.copy(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase()); editPhasePlan(method, graph, phasePlan); - CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog()); + CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, + new SpeculationLog()); if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } - return addMethod(method, compResult); + return addMethod(method, compResult, graphCopy); } }); @@ -414,12 +425,12 @@ return installedCode; } - protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) { + protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) { return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable() { @Override public InstalledCode call() throws Exception { - InstalledCode installedCode = runtime.addMethod(method, compResult); + InstalledCode installedCode = runtime.addMethod(method, compResult, graph); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } @@ -442,25 +453,41 @@ * Parses a Java method to produce a graph. */ protected StructuredGraph parse(Method m) { - ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); - return graph; + return parse0(m, GraphBuilderConfiguration.getEagerDefault()); } /** * Parses a Java method to produce a graph. */ protected StructuredGraph parseProfiled(Method m) { + return parse0(m, GraphBuilderConfiguration.getDefault()); + } + + /** + * Parses a Java method in debug mode to produce a graph with extra infopoints. + */ + protected StructuredGraph parseDebug(Method m) { + GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault(); + gbConf.setEagerInfopointMode(true); + return parse0(m, gbConf); + } + + private StructuredGraph parse0(Method m, GraphBuilderConfiguration conf) { ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m); StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph); return graph; } protected PhasePlan getDefaultPhasePlan() { + return getDefaultPhasePlan(false); + } + + protected PhasePlan getDefaultPhasePlan(boolean eagerInfopointMode) { PhasePlan plan = new PhasePlan(); - plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL)); + GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault(); + gbConf.setEagerInfopointMode(eagerInfopointMode); + plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, gbConf, OptimisticOptimizations.ALL)); return plan; } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.test; - -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; -import com.oracle.graal.phases.common.*; - -public class IfBoxingEliminationTest extends GraalCompilerTest { - - private static final String REFERENCE_SNIPPET = "referenceSnippet"; - - public static int referenceSnippet(int a) { - int result; - if (a < 0) { - result = 1; - } else { - result = 2; - } - return result; - } - - public static Integer boxedInteger() { - return 1; - } - - public static Object boxedObject() { - return 2; - } - - @Test - public void test1() { - test("test1Snippet"); - } - - public static int test1Snippet(int a) { - Integer result; - if (a < 0) { - result = boxedInteger(); - } else { - result = (Integer) boxedObject(); - } - return result; - } - - private void test(final String snippet) { - Debug.scope("IfBoxingEliminationTest", new DebugDumpScope(snippet), new Runnable() { - - @Override - public void run() { - StructuredGraph graph = parse(snippet); - BoxingMethodPool pool = new BoxingMethodPool(runtime()); - IdentifyBoxingPhase identifyBoxingPhase = new IdentifyBoxingPhase(pool); - PhasePlan phasePlan = getDefaultPhasePlan(); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, identifyBoxingPhase); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PhiStampPhase()); - identifyBoxingPhase.apply(graph); - Map hints = new HashMap<>(); - for (Invoke invoke : graph.getInvokes()) { - hints.put(invoke, 1000d); - } - - Assumptions assumptions = new Assumptions(false); - new InliningPhase(runtime(), hints, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new PhiStampPhase().apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - Debug.dump(graph, "Graph"); - new BoxingEliminationPhase(runtime()).apply(graph); - Debug.dump(graph, "Graph"); - new ExpandBoxingNodesPhase(pool).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); - new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); - new DeadCodeEliminationPhase().apply(referenceGraph); - - assertEquals(referenceGraph, graph); - } - }); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -144,7 +144,7 @@ n.replaceFirstInput(local, constant); } Debug.dump(graph, "Graph"); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import static org.junit.Assert.*; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.Call; +import com.oracle.graal.api.code.CompilationResult.Infopoint; +import com.oracle.graal.compiler.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.test.*; + +/** + * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons. + */ +public class InfopointReasonTest extends GraalCompilerTest { + + public static final String[] STRINGS = new String[]{"world", "everyone", "you"}; + + public String testMethod() { + StringBuilder sb = new StringBuilder("Hello "); + for (String s : STRINGS) { + sb.append(s).append(", "); + } + sb.replace(sb.length() - 2, sb.length(), "!"); + return sb.toString(); + } + + @Test + public void callInfopoints() { + final Method method = getMethod("testMethod"); + final StructuredGraph graph = parse(method); + final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(), + OptimisticOptimizations.ALL, new SpeculationLog()); + for (Infopoint sp : cr.getInfopoints()) { + assertNotNull(sp.reason); + if (sp instanceof Call) { + assertEquals(InfopointReason.CALL, sp.reason); + } + } + } + + @LongTest + public void lineInfopoints() { + final Method method = getMethod("testMethod"); + final StructuredGraph graph = parseDebug(method); + int graphLineSPs = 0; + for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) { + if (ipn.reason == InfopointReason.LINE_NUMBER) { + ++graphLineSPs; + } + } + assertTrue(graphLineSPs > 0); + final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(true), + OptimisticOptimizations.ALL, new SpeculationLog()); + int lineSPs = 0; + for (Infopoint sp : cr.getInfopoints()) { + assertNotNull(sp.reason); + if (sp.reason == InfopointReason.LINE_NUMBER) { + ++lineSPs; + } + } + assertTrue(lineSPs > 0); + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -66,7 +66,7 @@ } Assumptions assumptions = new Assumptions(false); new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -77,7 +77,7 @@ Assumptions assumptions = new Assumptions(false); new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -133,8 +133,8 @@ } Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph); Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() { @Override diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -94,7 +94,7 @@ } Assumptions assumptions = new Assumptions(false); new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.java.*; public class NestedLoopTest extends GraalCompilerTest { @@ -134,9 +135,9 @@ } private static Invoke getInvoke(String name, StructuredGraph graph) { - for (Invoke invoke : graph.getInvokes()) { - if (invoke.methodCallTarget().targetMethod().getName().equals(name)) { - return invoke; + for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.class)) { + if (callTarget.targetMethod().getName().equals(name)) { + return callTarget.invoke(); } } return null; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -83,9 +83,9 @@ private StructuredGraph compileTestSnippet(final String snippet) { StructuredGraph graph = parse(snippet); new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph); - new CanonicalizerPhase(runtime(), null).apply(graph); - new PushNodesThroughPi().apply(graph); - new CanonicalizerPhase(runtime(), null).apply(graph); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); + new PushThroughPiPhase().apply(graph); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); return graph; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +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.compiler.test; - -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.phases.common.*; - -/* consider - * B b = (B) a; - * return b.x10; - * - * With snippets a typecheck is performed and if it was successful, a UnsafeCastNode is created. - * For the read node, however, there is only a dependency to the UnsafeCastNode, but not to the - * typecheck itself. With special crafting, it's possible to get the scheduler moving the - * FloatingReadNode before the typecheck. Assuming the object is of the wrong type (here for - * example A), an invalid field read is done. - * - * In order to avoid this situation, an anchor node is introduced in CheckCastSnippts. - */ - -public class ReadAfterCheckCast extends GraphScheduleTest { - - public static long foo = 0; - - public static class A { - - public long x1; - } - - public static class B extends A { - - public long x10; - } - - public static long test1Snippet(A a) { - if (foo > 4) { - B b = (B) a; - b.x10 += 1; - return b.x10; - } else { - B b = (B) a; - b.x10 += 1; - return b.x10; - } - } - - @Test - public void test1() { - test("test1Snippet"); - } - - private void test(final String snippet) { - Debug.scope("FloatingReadTest", new DebugDumpScope(snippet), new Runnable() { - - // check shape of graph, with lots of assumptions. will probably fail if graph - // structure changes significantly - public void run() { - StructuredGraph graph = parse(snippet); - new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph); - new FloatingReadPhase().apply(graph); - new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph); - new ReadEliminationPhase().apply(graph); - new CanonicalizerPhase(runtime(), null).apply(graph); - - Debug.dump(graph, "After lowering"); - - ArrayList merges = new ArrayList<>(); - ArrayList reads = new ArrayList<>(); - for (Node n : graph.getNodes()) { - if (n instanceof MergeNode) { - // check shape - MergeNode merge = (MergeNode) n; - - if (merge.inputs().count() == 2) { - for (EndNode m : merge.forwardEnds()) { - if (m.predecessor() != null && m.predecessor() instanceof BeginNode && m.predecessor().predecessor() instanceof IfNode) { - IfNode o = (IfNode) m.predecessor().predecessor(); - if (o.falseSuccessor().next() instanceof DeoptimizeNode) { - merges.add(merge); - } - } - } - } - } - if (n instanceof IntegerAddNode) { - IntegerAddNode ian = (IntegerAddNode) n; - - Assert.assertTrue(ian.y() instanceof ConstantNode); - Assert.assertTrue(ian.x() instanceof FloatingReadNode); - reads.add((FloatingReadNode) ian.x()); - } - } - - Assert.assertTrue(merges.size() >= reads.size()); - for (int i = 0; i < reads.size(); i++) { - assertOrderedAfterSchedule(graph, merges.get(i), reads.get(i)); - } - } - }); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.phases.common.*; + +/* consider + * B b = (B) a; + * return b.x10; + * + * With snippets a typecheck is performed and if it was successful, a UnsafeCastNode is created. + * For the read node, however, there is only a dependency to the UnsafeCastNode, but not to the + * typecheck itself. With special crafting, it's possible to get the scheduler moving the + * FloatingReadNode before the typecheck. Assuming the object is of the wrong type (here for + * example A), an invalid field read is done. + * + * In order to avoid this situation, an anchor node is introduced in CheckCastSnippts. + */ + +public class ReadAfterCheckCastTest extends GraphScheduleTest { + + public static long foo = 0; + + public static class A { + + public long x1; + } + + public static class B extends A { + + public long x10; + } + + public static long test1Snippet(A a) { + if (foo > 4) { + B b = (B) a; + b.x10 += 1; + return b.x10; + } else { + B b = (B) a; + b.x10 += 1; + return b.x10; + } + } + + @Test + public void test1() { + test("test1Snippet"); + } + + private void test(final String snippet) { + Debug.scope("FloatingReadTest", new DebugDumpScope(snippet), new Runnable() { + + // check shape of graph, with lots of assumptions. will probably fail if graph + // structure changes significantly + public void run() { + StructuredGraph graph = parse(snippet); + new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph); + new FloatingReadPhase().apply(graph); + new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph); + new ReadEliminationPhase().apply(graph); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); + + Debug.dump(graph, "After lowering"); + + ArrayList merges = new ArrayList<>(); + ArrayList reads = new ArrayList<>(); + for (Node n : graph.getNodes()) { + if (n instanceof MergeNode) { + // check shape + MergeNode merge = (MergeNode) n; + + if (merge.inputs().count() == 2) { + for (EndNode m : merge.forwardEnds()) { + if (m.predecessor() != null && m.predecessor() instanceof BeginNode && m.predecessor().predecessor() instanceof IfNode) { + IfNode o = (IfNode) m.predecessor().predecessor(); + if (o.falseSuccessor().next() instanceof DeoptimizeNode) { + merges.add(merge); + } + } + } + } + } + if (n instanceof IntegerAddNode) { + IntegerAddNode ian = (IntegerAddNode) n; + + Assert.assertTrue(ian.y() instanceof ConstantNode); + Assert.assertTrue(ian.x() instanceof FloatingReadNode); + reads.add((FloatingReadNode) ian.x()); + } + } + + Assert.assertTrue(merges.size() >= reads.size()); + for (int i = 0; i < reads.size(); i++) { + assertOrderedAfterSchedule(graph, merges.get(i), reads.get(i)); + } + } + }); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -244,9 +244,9 @@ private void test(String test, String ref) { StructuredGraph testGraph = parse(test); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(testGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(testGraph); StructuredGraph refGraph = parse(ref); - new CanonicalizerPhase(runtime(), assumptions).apply(refGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(refGraph); assertEquals(testGraph, refGraph); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -166,9 +166,9 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -98,7 +98,7 @@ private void testZeroReturn(String methodName) { StructuredGraph graph = parse(methodName); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -89,7 +89,7 @@ // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -186,13 +186,13 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); // a second canonicalizer is needed to process nested MaterializeNodes - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); - new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph); assertEquals(referenceGraph, graph); } @@ -206,19 +206,19 @@ } public static void outputGraph(StructuredGraph graph, String message) { - System.out.println("========================= " + message); + TTY.println("========================= " + message); SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph); for (Block block : schedule.getCFG().getBlocks()) { - System.out.print("Block " + block + " "); + TTY.print("Block " + block + " "); if (block == schedule.getCFG().getStartBlock()) { - System.out.print("* "); + TTY.print("* "); } - System.out.print("-> "); + TTY.print("-> "); for (Block succ : block.getSuccessors()) { - System.out.print(succ + " "); + TTY.print(succ + " "); } - System.out.println(); + TTY.println(); for (Node node : schedule.getBlockToNodesMap().get(block)) { outputNode(node); } @@ -226,11 +226,11 @@ } private static void outputNode(Node node) { - System.out.print(" " + node + " (usage count: " + node.usages().count() + ") (inputs:"); + TTY.print(" " + node + " (usage count: " + node.usages().count() + ") (inputs:"); for (Node input : node.inputs()) { - System.out.print(" " + input.toString(Verbosity.Id)); + TTY.print(" " + input.toString(Verbosity.Id)); } - System.out.println(")"); + TTY.println(")"); if (node instanceof MergeNode) { for (PhiNode phi : ((MergeNode) node).phis()) { outputNode(phi); @@ -242,9 +242,9 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext()); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,13 +27,10 @@ import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.InstalledCode.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.graph.*; -import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.test.*; @@ -58,7 +55,7 @@ public void test1() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); for (Node node : graph.getNodes()) { @@ -75,7 +72,7 @@ try { Object result = compiledMethod.execute("1", "2", "3"); Assert.assertEquals("1-2-3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } @@ -89,7 +86,7 @@ try { Object result = compiledMethod.executeVarargs("1", "2", "3"); Assert.assertEquals("1 2 3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } @@ -104,98 +101,8 @@ f1 = "0"; Object result = compiledMethod.executeVarargs(this, "1", "2", "3"); Assert.assertEquals("0 1 2 3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } - - @LongTest - public void test2() throws NoSuchMethodException, SecurityException { - Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class); - ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); - StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph); - new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - for (Node node : graph.getNodes()) { - if (node instanceof ConstantNode) { - ConstantNode constant = (ConstantNode) node; - if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) { - graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph)); - } - } - } - - InstalledCode compiledMethod = getCode(javaMethod, graph); - final CompilableObject compilableObject = new CompilableObjectImpl(0); - - Object result; - result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3"); - Assert.assertEquals("1-3", result); - } - - public abstract class CompilableObject { - - private CompiledObject compiledObject; - private final int compileThreshold; - private int counter; - - public CompilableObject(int compileThreshold) { - this.compileThreshold = compileThreshold; - } - - public final Object execute(ObjectCompiler compiler, String args) { - if (counter++ < compileThreshold || compiler == null) { - return executeHelper(compiler, args); - } else { - compiledObject = compiler.compile(this); - return compiledObject.execute(compiler, args); - } - } - - protected abstract Object executeHelper(ObjectCompiler context, String args); - } - - private final class CompilableObjectImpl extends CompilableObject { - - private CompilableObjectImpl(int compileThreshold) { - super(compileThreshold); - } - - @Override - protected Object executeHelper(ObjectCompiler compiler, String args) { - return "1 " + args; - } - } - - public interface CompiledObject { - - Object execute(ObjectCompiler context, String args); - } - - public interface ObjectCompiler { - - CompiledObject compile(CompilableObject node); - } - - private final class ObjectCompilerImpl implements ObjectCompiler { - - private final InstalledCode compiledMethod; - - private ObjectCompilerImpl(InstalledCode compiledMethod) { - this.compiledMethod = compiledMethod; - } - - @Override - public CompiledObject compile(final CompilableObject node) { - return new CompiledObject() { - - @Override - public Object execute(ObjectCompiler compiler, String args) { - return compiledMethod.execute(node, compiler, args); - } - }; - } - } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,7 +27,6 @@ import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.InstalledCode.MethodInvalidatedException; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; @@ -59,7 +58,7 @@ try { Object result = compiledMethod.executeVarargs(testString); Assert.assertEquals(testString, result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } @@ -67,7 +66,7 @@ Object result = compiledMethod.executeVarargs(new Object[]{null}); Assert.assertEquals(null, result); Assert.assertFalse(compiledMethod.isValid()); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,7 +22,8 @@ */ package com.oracle.graal.compiler.test.ea; -import junit.framework.*; +import java.util.concurrent.*; + import junit.framework.Assert; import org.junit.Test; @@ -30,10 +31,13 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; @@ -83,8 +87,8 @@ public static int testMonitorSnippet() { Integer x = new Integer(0); - Integer[] y = new Integer[0]; - Integer[] z = new Integer[1]; + Double y = new Double(0); + Object z = new Object(); synchronized (x) { synchronized (y) { synchronized (z) { @@ -106,8 +110,8 @@ */ public static int testMonitor2Snippet() { Integer x = new Integer(0); - Integer[] y = new Integer[0]; - Integer[] z = new Integer[1]; + Double y = new Double(0); + Object z = new Object(); synchronized (x) { synchronized (y) { synchronized (z) { @@ -161,6 +165,20 @@ return obj.x; } + @Test + public void testModifyingLoop() { + testEscapeAnalysis("testModifyingLoopSnippet", Constant.forInt(1), false); + } + + public int testModifyingLoopSnippet(int a) { + TestObject obj = new TestObject(1, 2); + for (int i = 0; i < a; i++) { + obj.x = 3; + notInlineable(); + } + return obj.x <= 3 ? 1 : 0; + } + public static class TestObject2 { Object o; @@ -192,28 +210,33 @@ return obj2.o instanceof TestObject2; } - private ReturnNode testEscapeAnalysis(String snippet, Constant expectedConstantResult, boolean iterativeEscapeAnalysis) { - StructuredGraph graph = parse(snippet); - try { - for (Invoke n : graph.getInvokes()) { - n.setInliningRelevance(1); - } + private ReturnNode testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) { + ResolvedJavaMethod method = runtime.lookupJavaMethod(getMethod(snippet)); + final StructuredGraph graph = new StructuredGraph(method); + + return Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Callable() { + + public ReturnNode call() { + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + for (Invoke n : graph.getInvokes()) { + n.setInliningRelevance(1); + } - Assumptions assumptions = new Assumptions(false); - new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - new PartialEscapeAnalysisPhase(runtime(), assumptions, iterativeEscapeAnalysis, false).apply(graph); - Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); - ReturnNode returnNode = graph.getNodes(ReturnNode.class).first(); - if (expectedConstantResult != null) { - Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); - Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); + new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false).apply(graph, context); + Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); + ReturnNode returnNode = graph.getNodes(ReturnNode.class).first(); + if (expectedConstantResult != null) { + Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); + Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); + } + int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count(); + Assert.assertEquals(0, newInstanceCount); + return returnNode; } - int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count(); - Assert.assertEquals(0, newInstanceCount); - return returnNode; - } catch (AssertionFailedError t) { - throw new RuntimeException(t.getMessage() + "\n" + getCanonicalGraphString(graph), t); - } + }); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -34,6 +34,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; public class IterativeInliningTest extends GraalCompilerTest { @@ -102,6 +103,7 @@ graph = parse(snippet); new ComputeProbabilityPhase().apply(graph); GraalOptions.OptEarlyReadElimination = true; - new IterativeInliningPhase(runtime(), replacements, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph); + HighTierContext context = new HighTierContext(runtime(), new Assumptions(false)); + new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph, context); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -34,6 +34,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; public class PEAReadEliminationTest extends GraalCompilerTest { @@ -143,10 +144,11 @@ } @SuppressWarnings("all") - public static int testBadLoopSnippet(TestObject obj, int a, int b) { + public static int testBadLoopSnippet(TestObject obj, TestObject obj2, int a, int b) { obj.x = a; for (int i = 0; i < 10; i++) { staticField = obj; + obj2.x = 10; obj.x = 0; } return obj.x; @@ -155,6 +157,24 @@ @Test public void testBadLoop() { ValueNode result = getReturn("testBadLoopSnippet").result(); + assertEquals(0, graph.getNodes(LoadFieldNode.class).count()); + assertTrue(result instanceof ProxyNode); + assertTrue(((ProxyNode) result).value() instanceof PhiNode); + } + + @SuppressWarnings("all") + public static int testBadLoop2Snippet(TestObject obj, TestObject obj2, int a, int b) { + obj.x = a; + for (int i = 0; i < 10; i++) { + obj.x = 0; + obj2.x = 10; + } + return obj.x; + } + + @Test + public void testBadLoop2() { + ValueNode result = getReturn("testBadLoop2Snippet").result(); assertEquals(1, graph.getNodes(LoadFieldNode.class).count()); assertTrue(result instanceof LoadFieldNode); } @@ -203,7 +223,8 @@ graph = parse(snippet); new ComputeProbabilityPhase().apply(graph); Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new PartialEscapeAnalysisPhase(runtime(), assumptions, false, true).apply(graph); + new PartialEscapeAnalysisPhase(false, true).apply(graph, context); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,18 +22,21 @@ */ package com.oracle.graal.compiler.test.ea; -import junit.framework.*; +import java.util.concurrent.*; + import junit.framework.Assert; import org.junit.Test; import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; @@ -72,8 +75,8 @@ } @SuppressWarnings("all") - public static Object test1Snippet(int a, int b) { - TestObject obj = new TestObject(1, 2); + public static Object test1Snippet(int a, int b, Object x, Object y) { + TestObject2 obj = new TestObject2(x, y); if (a < 0) { if (b < 0) { return obj; @@ -90,9 +93,9 @@ testMaterialize("test2Snippet", 1.5, 3, LoadIndexedNode.class); } - public static Object test2Snippet(int a) { - TestObject2 obj = new TestObject2(1, 2); - obj.x = new TestObject2(obj, 3); + public static Object test2Snippet(int a, Object x, Object y, Object z) { + TestObject2 obj = new TestObject2(x, y); + obj.x = new TestObject2(obj, z); if (a < 0) { ((TestObject2) obj.x).y = null; obj.y = null; @@ -125,42 +128,50 @@ @SafeVarargs final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class... invalidNodeClasses) { StructuredGraph result = processMethod(snippet); - Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty()); - Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty()); - double probabilitySum = 0; - int materializeCount = 0; - for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) { - probabilitySum += materialize.probability(); - materializeCount++; - } - Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount); - Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01); - for (Node node : result.getNodes()) { - for (Class clazz : invalidNodeClasses) { - Assert.assertFalse("instance of invalid class: " + clazz.getSimpleName(), clazz.isInstance(node) && node.usages().isNotEmpty()); + try { + Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty()); + Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty()); + double probabilitySum = 0; + int materializeCount = 0; + for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) { + probabilitySum += materialize.probability(); + materializeCount++; } + Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount); + Assert.assertEquals("unexpected probability of MaterializeObjectNodes", expectedProbability, probabilitySum, 0.01); + for (Node node : result.getNodes()) { + for (Class clazz : invalidNodeClasses) { + Assert.assertFalse("instance of invalid class: " + clazz.getSimpleName(), clazz.isInstance(node) && node.usages().isNotEmpty()); + } + } + } catch (AssertionError e) { + TypeSystemTest.outputGraph(result, snippet + ": " + e.getMessage()); + throw e; } } private StructuredGraph processMethod(final String snippet) { - StructuredGraph graph = parse(snippet); - try { - new ComputeProbabilityPhase().apply(graph); - for (Invoke n : graph.getInvokes()) { - n.node().setProbability(100000); + return Debug.scope("PartialEscapeAnalysisTest " + snippet, new DebugDumpScope(snippet), new Callable() { + + @Override + public StructuredGraph call() { + StructuredGraph graph = parse(snippet); + new ComputeProbabilityPhase().apply(graph); + for (Invoke n : graph.getInvokes()) { + n.asNode().setProbability(100000); + } + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); + new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase().apply(graph, context); + new PartialEscapeAnalysisPhase(false, false).apply(graph, context); + + new CullFrameStatesPhase().apply(graph); + new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase().apply(graph, context); + return graph; } - Assumptions assumptions = new Assumptions(false); - new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new PartialEscapeAnalysisPhase(runtime(), assumptions, false, false).apply(graph); - - new CullFrameStatesPhase().apply(graph); - new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - return graph; - } catch (AssertionFailedError t) { - throw new RuntimeException(t.getMessage() + "\n" + getCanonicalGraphString(graph), t); - } + }); } } diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -24,6 +24,7 @@ import static org.junit.Assert.*; +import java.lang.reflect.*; import java.util.concurrent.*; import org.junit.*; @@ -35,14 +36,15 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.test.*; @SuppressWarnings("unused") public class InliningTest extends GraalCompilerTest { @Test public void testInvokeStaticInlining() { - assertInlined(getGraph("invokeStaticSnippet")); - assertInlined(getGraph("invokeStaticOnInstanceSnippet")); + assertInlined(getGraph("invokeStaticSnippet", false)); + assertInlined(getGraph("invokeStaticOnInstanceSnippet", false)); } @SuppressWarnings("all") @@ -57,9 +59,16 @@ @Test public void testStaticBindableInlining() { - assertInlined(getGraph("invokeConstructorSnippet")); - assertInlined(getGraph("invokeFinalMethodSnippet")); - assertInlined(getGraph("invokeMethodOnFinalClassSnippet")); + assertInlined(getGraph("invokeConstructorSnippet", false)); + assertInlined(getGraph("invokeFinalMethodSnippet", false)); + assertInlined(getGraph("invokeMethodOnFinalClassSnippet", false)); + } + + @LongTest + public void testStaticBindableInliningIP() { + assertManyMethodInfopoints(assertInlined(getGraph("invokeConstructorSnippet", true))); + assertManyMethodInfopoints(assertInlined(getGraph("invokeFinalMethodSnippet", true))); + assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFinalClassSnippet", true))); } @SuppressWarnings("all") @@ -81,14 +90,28 @@ @Test public void testClassHierarchyAnalysis() { - assertInlined(getGraph("invokeLeafClassMethodSnippet")); - assertInlined(getGraph("invokeConcreteMethodSnippet")); - assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet")); - // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet")); + assertInlined(getGraph("invokeLeafClassMethodSnippet", false)); + assertInlined(getGraph("invokeConcreteMethodSnippet", false)); + assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", false)); + // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", false)); + + assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", false)); + assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", false)); + assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", false)); + } - assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet")); - assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet")); - assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet")); + @LongTest + public void testClassHierarchyAnalysisIP() { + assertManyMethodInfopoints(assertInlined(getGraph("invokeLeafClassMethodSnippet", true))); + assertManyMethodInfopoints(assertInlined(getGraph("invokeConcreteMethodSnippet", true))); + assertManyMethodInfopoints(assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", true))); + //@formatter:off + // assertInlineInfopoints(assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", true))); + //@formatter:on + + assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", true))); + assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", true))); + assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", true))); } @SuppressWarnings("all") @@ -126,19 +149,20 @@ return superClass.protectedOverriddenMethod(); } - private StructuredGraph getGraph(final String snippet) { + private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) { return Debug.scope("InliningTest", new DebugDumpScope(snippet), new Callable() { @Override public StructuredGraph call() { - StructuredGraph graph = parse(snippet); - PhasePlan phasePlan = getDefaultPhasePlan(); + Method method = getMethod(snippet); + StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method); + PhasePlan phasePlan = getDefaultPhasePlan(eagerInfopointMode); Assumptions assumptions = new Assumptions(true); new ComputeProbabilityPhase().apply(graph); Debug.dump(graph, "Graph"); new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; } @@ -172,6 +196,35 @@ return graph; } + private static int[] countMethodInfopoints(StructuredGraph graph) { + int start = 0; + int end = 0; + for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) { + if (ipn.reason == InfopointReason.METHOD_START) { + ++start; + } else if (ipn.reason == InfopointReason.METHOD_END) { + ++end; + } + } + return new int[]{start, end}; + } + + private static StructuredGraph assertManyMethodInfopoints(StructuredGraph graph) { + int[] counts = countMethodInfopoints(graph); + if (counts[0] <= 1 || counts[1] <= 1) { + fail(String.format("Graph contains too few required method boundary infopoints: %d starts, %d ends.", counts[0], counts[1])); + } + return graph; + } + + private static StructuredGraph assertFewMethodInfopoints(StructuredGraph graph) { + int[] counts = countMethodInfopoints(graph); + if (counts[0] > 1 || counts[1] > 1) { + fail(String.format("Graph contains too many method boundary infopoints: %d starts, %d ends.", counts[0], counts[1])); + } + return graph; + } + // some interfaces and classes for testing private interface MultipleImplementorsInterface { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java Sat Apr 20 12:23:29 2013 +0200 @@ -132,9 +132,6 @@ } } } - // if (match) { - // System.out.println(this + " matches " + input); - // } return match; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Sat Apr 20 12:23:29 2013 +0200 @@ -35,7 +35,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; @@ -43,6 +42,7 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; public class GraalCompiler { @@ -118,113 +118,49 @@ } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); } + HighTierContext highTierContext = new HighTierContext(runtime, assumptions); + if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) { if (GraalOptions.IterativeInlining) { - new IterativeInliningPhase(runtime, replacements, assumptions, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph); + new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph, highTierContext); } else { new InliningPhase(runtime, null, replacements, assumptions, cache, plan, optimisticOpts).apply(graph); new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); + new IterativeConditionalEliminationPhase().apply(graph, highTierContext); } } } - // new ConvertUnreachedToGuardPhase(optimisticOpts).apply(graph); - plan.runPhases(PhasePosition.HIGH_LEVEL, graph); - if (GraalOptions.FullUnroll) { - new LoopFullUnrollPhase(runtime, assumptions).apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } - } - - if (GraalOptions.OptTailDuplication) { - new TailDuplicationPhase().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } - } - - if (GraalOptions.PartialEscapeAnalysis && !plan.isPhaseDisabled(PartialEscapeAnalysisPhase.class)) { - new PartialEscapeAnalysisPhase(runtime, assumptions, true, GraalOptions.OptEarlyReadElimination).apply(graph); - } - - if (GraalOptions.OptConvertDeoptsToGuards) { - new ConvertDeoptimizeToGuardPhase().apply(graph); - } - - new LockEliminationPhase().apply(graph); - - if (GraalOptions.OptLoopTransform) { - new LoopTransformHighPhase().apply(graph); - new LoopTransformLowPhase().apply(graph); - } - new RemoveValueProxyPhase().apply(graph); - - if (GraalOptions.CullFrameStates) { - new CullFrameStatesPhase().apply(graph); - } - - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + Suites.DEFAULT.getHighTier().apply(graph, highTierContext); new LoweringPhase(target, runtime, replacements, assumptions).apply(graph); - if (GraalOptions.OptPushThroughPi) { - new PushNodesThroughPi().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } - } - - if (GraalOptions.OptFloatingReads) { - int mark = graph.getMark(); - new FloatingReadPhase().apply(graph); - new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); - if (GraalOptions.OptReadElimination) { - new ReadEliminationPhase().apply(graph); - } - } - new RemoveValueProxyPhase().apply(graph); - - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } - - if (GraalOptions.OptEliminatePartiallyRedundantGuards) { - new EliminatePartiallyRedundantGuardsPhase(false, true).apply(graph); - } - - if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) { - new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph); - } - - if (GraalOptions.OptEliminatePartiallyRedundantGuards) { - new EliminatePartiallyRedundantGuardsPhase(true, true).apply(graph); - } - - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + MidTierContext midTierContext = new MidTierContext(runtime, assumptions, replacements); + Suites.DEFAULT.getMidTier().apply(graph, midTierContext); plan.runPhases(PhasePosition.MID_LEVEL, graph); - plan.runPhases(PhasePosition.LOW_LEVEL, graph); - // Add safepoints to loops new SafepointInsertionPhase().apply(graph); new GuardLoweringPhase(target).apply(graph); + plan.runPhases(PhasePosition.LOW_LEVEL, graph); + + new LoweringPhase(target, runtime, replacements, assumptions).apply(graph); + + new FrameStateAssignmentPhase().apply(graph); + + new DeadCodeEliminationPhase().apply(graph); + final SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph); Debug.dump(schedule, "final schedule"); diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Sat Apr 20 12:23:29 2013 +0200 @@ -82,21 +82,16 @@ for (Entry entry : virtualObjectsCopy.entrySet()) { if (entry.getValue().getValues() == null) { VirtualObjectNode vobj = entry.getKey(); - if (vobj instanceof BoxedVirtualObjectNode) { - BoxedVirtualObjectNode boxedVirtualObjectNode = (BoxedVirtualObjectNode) vobj; - entry.getValue().setValues(new Value[]{toValue(boxedVirtualObjectNode.getUnboxedValue())}); - } else { - Value[] values = new Value[vobj.entryCount()]; - if (values.length > 0) { - changed = true; - VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobj); - assert currentField != null; - for (int i = 0; i < vobj.entryCount(); i++) { - values[i] = toValue(currentField.fieldValues().get(i)); - } + Value[] values = new Value[vobj.entryCount()]; + if (values.length > 0) { + changed = true; + VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobj); + assert currentField != null; + for (int i = 0; i < vobj.entryCount(); i++) { + values[i] = toValue(currentField.fieldValues().get(i)); } - entry.getValue().setValues(values); } + entry.getValue().setValues(values); } } } while (changed); @@ -127,7 +122,7 @@ if (state.outerFrameState() != null) { caller = computeFrameForState(state.outerFrameState()); } - assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI : "bci == " + state.bci; + assert state.bci != FrameState.UNKNOWN_BCI : "bci == " + state.bci; return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks); } @@ -165,7 +160,7 @@ if (value instanceof VirtualObjectNode) { VirtualObjectNode obj = (VirtualObjectNode) value; EscapeObjectState state = objectStates.get(obj); - if (state == null && obj.entryCount() > 0 && !(obj instanceof BoxedVirtualObjectNode)) { + if (state == null && obj.entryCount() > 0) { // null states occur for objects with 0 fields throw new GraalInternalError("no mapping found for virtual object %s", obj); } @@ -173,7 +168,7 @@ assert !(((MaterializedObjectState) state).materializedValue() instanceof VirtualObjectNode); return toValue(((MaterializedObjectState) state).materializedValue()); } else { - assert obj.entryCount() == 0 || state instanceof VirtualObjectState || obj instanceof BoxedVirtualObjectNode; + assert obj.entryCount() == 0 || state instanceof VirtualObjectState; VirtualObject vobject = virtualObjects.get(value); if (vobject == null) { vobject = VirtualObject.get(obj.type(), null, virtualObjects.size()); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Sat Apr 20 12:23:29 2013 +0200 @@ -225,6 +225,13 @@ return stateFor(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason()); } + public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) { + if (!deopt.canDeoptimize()) { + return null; + } + return stateForWithExceptionEdge(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason(), exceptionEdge); + } + public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) { return stateForWithExceptionEdge(state, reason, null); } @@ -233,6 +240,7 @@ if (needOnlyOopMaps()) { return new LIRFrameState(null, null, null, (short) -1); } + assert state != null; return debugInfoBuilder.build(state, lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge); } @@ -327,17 +335,10 @@ TTY.println("LIRGen for " + instr); } FrameState stateAfter = null; - if (instr instanceof StateSplit) { + if (instr instanceof StateSplit && !(instr instanceof InfopointNode)) { stateAfter = ((StateSplit) instr).stateAfter(); } - if (instr instanceof DeoptimizingNode) { - DeoptimizingNode deopt = (DeoptimizingNode) instr; - if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) { - deopt.setDeoptimizationState(lastState); - } - } if (instr instanceof ValueNode) { - ValueNode valueNode = (ValueNode) instr; if (operand(valueNode) == null) { if (!peephole(valueNode)) { @@ -597,19 +598,19 @@ @Override public void emitInvoke(Invoke x) { - AbstractCallTargetNode callTarget = (AbstractCallTargetNode) x.callTarget(); - CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().stamp().javaType(runtime), callTarget.signature(), target(), false); + LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget(); + CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(runtime), callTarget.signature(), target(), false); frameMap.callsMethod(cc); Value[] parameters = visitInvokeArguments(cc, callTarget.arguments()); - LIRFrameState callState = null; - if (x.stateAfter() != null) { - callState = stateForWithExceptionEdge(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null); + LabelRef exceptionEdge = null; + if (x instanceof InvokeWithExceptionNode) { + exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()); } + LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge); Value result = cc.getReturn(); - if (callTarget instanceof DirectCallTargetNode) { emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, cc.getTemporaries(), callState); } else if (callTarget instanceof IndirectCallTargetNode) { @@ -619,7 +620,7 @@ } if (isLegal(result)) { - setResult(x.node(), emitMove(result)); + setResult(x.asNode(), emitMove(result)); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.phases; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +@ServiceProvider(CompilerConfiguration.class) +public class BasicCompilerConfiguration implements CompilerConfiguration { + + public PhaseSuite createHighTier() { + return new HighTier(); + } + + public PhaseSuite createMidTier() { + return new MidTier(); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.phases; + +import com.oracle.graal.loop.phases.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.virtual.phases.ea.*; + +public class HighTier extends PhaseSuite { + + public HighTier() { + if (GraalOptions.FullUnroll) { + addPhase(new LoopFullUnrollPhase()); + if (GraalOptions.OptCanonicalizer) { + addPhase(new CanonicalizerPhase()); + } + } + + if (GraalOptions.OptTailDuplication) { + addPhase(new TailDuplicationPhase()); + if (GraalOptions.OptCanonicalizer) { + addPhase(new CanonicalizerPhase()); + } + } + + if (GraalOptions.PartialEscapeAnalysis) { + addPhase(new PartialEscapeAnalysisPhase(true, GraalOptions.OptEarlyReadElimination)); + } + + if (GraalOptions.OptConvertDeoptsToGuards) { + addPhase(new ConvertDeoptimizeToGuardPhase()); + } + + addPhase(new LockEliminationPhase()); + + if (GraalOptions.OptLoopTransform) { + addPhase(new LoopTransformHighPhase()); + addPhase(new LoopTransformLowPhase()); + } + addPhase(new RemoveValueProxyPhase()); + + if (GraalOptions.CullFrameStates) { + addPhase(new CullFrameStatesPhase()); + } + + if (GraalOptions.OptCanonicalizer) { + addPhase(new CanonicalizerPhase()); + } + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.phases; + +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +public class MidTier extends PhaseSuite { + + public MidTier() { + if (GraalOptions.OptPushThroughPi) { + addPhase(new PushThroughPiPhase()); + if (GraalOptions.OptCanonicalizer) { + addPhase(new CanonicalizerPhase()); + } + } + + if (GraalOptions.OptFloatingReads) { + IncrementalCanonicalizerPhase canonicalizer = new IncrementalCanonicalizerPhase<>(); + canonicalizer.addPhase(new FloatingReadPhase()); + addPhase(canonicalizer); + if (GraalOptions.OptReadElimination) { + addPhase(new ReadEliminationPhase()); + } + } + addPhase(new RemoveValueProxyPhase()); + + if (GraalOptions.OptCanonicalizer) { + addPhase(new CanonicalizerPhase()); + } + + if (GraalOptions.OptEliminatePartiallyRedundantGuards) { + addPhase(new EliminatePartiallyRedundantGuardsPhase(false, true)); + } + + if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) { + addPhase(new IterativeConditionalEliminationPhase()); + } + + if (GraalOptions.OptEliminatePartiallyRedundantGuards) { + addPhase(new EliminatePartiallyRedundantGuardsPhase(true, true)); + } + + if (GraalOptions.OptCanonicalizer) { + addPhase(new CanonicalizerPhase()); + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013, 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.debug.test; + +import java.io.*; + +import org.junit.*; + +import com.oracle.graal.debug.*; + +public class DebugHistogramTest { + + @Test + public void testEmptyHistogram() { + DebugHistogram histogram = Debug.createHistogram("TestHistogram"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + histogram.print(new PrintStream(outputStream)); + Assert.assertEquals("TestHistogram is empty.\n", outputStream.toString()); + } + + @Test + public void testSingleEntryHistogram() { + DebugHistogram histogram = Debug.createHistogram("TestHistogram"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + histogram.add(new Integer(1)); + histogram.add(new Integer(1)); + histogram.print(new PrintStream(outputStream)); + String[] lines = outputStream.toString().split("\n"); + Assert.assertEquals(4, lines.length); + Assert.assertEquals("TestHistogram has 1 unique elements and 2 total elements:", lines[0]); + Assert.assertEquals( + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + lines[1]); + Assert.assertEquals( + "| 1 | 2 | ==================================================================================================== |", + lines[2]); + Assert.assertEquals( + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + lines[3]); + } + + @Test + public void testMultipleEntryHistogram() { + DebugHistogram histogram = Debug.createHistogram("TestHistogram"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + histogram.add(new Integer(1)); + histogram.add(new Integer(2)); + histogram.add(new Integer(2)); + histogram.print(new PrintStream(outputStream)); + String[] lines = outputStream.toString().split("\n"); + Assert.assertEquals(5, lines.length); + Assert.assertEquals("TestHistogram has 2 unique elements and 3 total elements:", lines[0]); + Assert.assertEquals( + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + lines[1]); + Assert.assertEquals( + "| 2 | 2 | ==================================================================================================== |", + lines[2]); + Assert.assertEquals( + "| 1 | 1 | ================================================== |", + lines[3]); + Assert.assertEquals( + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + lines[4]); + } + + @Test + public void testTooLongValueString() { + DebugHistogram histogram = Debug.createHistogram("TestHistogram"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + histogram.add("MyCustomValue"); + histogram.print(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10); + String[] lines = outputStream.toString().split("\n"); + Assert.assertEquals(4, lines.length); + Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]); + Assert.assertEquals("----------------------------------------", lines[1]); + Assert.assertEquals("| MyCusto... | 1 | ========== |", lines[2]); + Assert.assertEquals("----------------------------------------", lines[3]); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat Apr 20 12:23:29 2013 +0200 @@ -189,6 +189,10 @@ } } + public static DebugHistogram createHistogram(String name) { + return new DebugHistogramImpl(name); + } + public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled, final Collection dumpHandlers, final PrintStream output) { return new DebugConfig() { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,36 @@ +/* + * 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.debug; + +import java.io.*; + +public interface DebugHistogram { + + String getName(); + + void add(Object value); + + void print(PrintStream os); + + void print(PrintStream os, int limit, int nameSize, int barSize); +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,110 @@ +/* + * 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.debug.internal; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.debug.*; + +public class DebugHistogramImpl implements DebugHistogram { + + public static final int NumberSize = 10; + public static final int DefaultNameSize = 50; + public static final int DefaultBarSize = 100; + private final String name; + private HashMap map = new HashMap<>(); + + public DebugHistogramImpl(String name) { + this.name = name; + } + + public void add(Object value) { + if (!map.containsKey(value)) { + map.put(value, 1); + } else { + map.put(value, map.get(value) + 1); + } + } + + @Override + public String getName() { + return name; + } + + @Override + public void print(PrintStream os) { + print(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize); + } + + public void print(PrintStream os, int limit, int nameSize, int barSize) { + + List list = new ArrayList<>(map.keySet()); + if (list.size() == 0) { + // No elements in the histogram. + os.printf("%s is empty.\n", name); + return; + } + + // Sort from highest to smallest. + Collections.sort(list, new Comparator() { + + @Override + public int compare(Object o1, Object o2) { + return map.get(o2) - map.get(o1); + } + }); + + // Sum up the total number of elements. + int total = 0; + for (Object o : list) { + total += map.get(o); + } + + // Print header. + os.printf("%s has %d unique elements and %d total elements:\n", name, list.size(), total); + + int max = map.get(list.get(0)); + final int lineSize = nameSize + NumberSize + barSize + 10; + printLine(os, '-', lineSize); + String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n"; + for (int i = 0; i < list.size() && i < limit; ++i) { + Object o = list.get(i); + int value = map.get(o); + char[] bar = new char[(int) (((double) value / (double) max) * barSize)]; + Arrays.fill(bar, '='); + String objectString = o.toString(); + if (objectString.length() > nameSize) { + objectString = objectString.substring(0, nameSize - 3) + "..."; + } + os.printf(formatString, objectString, value, new String(bar)); + } + printLine(os, '-', lineSize); + } + + private static void printLine(PrintStream printStream, char c, int lineSize) { + char[] charArr = new char[lineSize]; + Arrays.fill(charArr, c); + printStream.printf("%s\n", new String(charArr)); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNodeInterface.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNodeInterface.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.graph; - -public interface TestNodeInterface { - - String getName(); -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.graph; - -import static org.junit.Assert.*; - -import java.util.*; - -import org.junit.*; - -public class TypedNodeIteratorTest { - - private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface { - - private final String name; - - public TestNode(String name) { - this.name = name; - } - - public String getName() { - return name; - } - } - - @Test - public void singleNodeTest() { - Graph graph = new Graph(); - graph.add(new TestNode("a")); - assertTrue(graph.hasNode(TestNode.class)); - assertEquals("a", toString(graph.getNodes(TestNode.class))); - } - - @Test - public void deletingNodeTest() { - TestNode testNode = new TestNode("a"); - Graph graph = new Graph(); - graph.add(testNode); - testNode.safeDelete(); - assertEquals("", toString(graph.getNodes(TestNode.class))); - } - - @Test - public void deleteAndAddTest() { - TestNode testNode = new TestNode("b"); - Graph graph = new Graph(); - graph.add(new TestNode("a")); - graph.add(testNode); - testNode.safeDelete(); - assertEquals("a", toString(graph.getNodes(TestNode.class))); - graph.add(new TestNode("c")); - assertEquals("ac", toString(graph.getNodes(TestNode.class))); - } - - @Test - public void iteratorBehaviorTest() { - Graph graph = new Graph(); - graph.add(new TestNode("a")); - Iterator iterator = graph.getNodes(TestNode.class).iterator(); - assertTrue(iterator.hasNext()); - assertEquals("a", iterator.next().getName()); - assertFalse(iterator.hasNext()); - graph.add(new TestNode("b")); - assertTrue(iterator.hasNext()); - assertEquals("b", iterator.next().getName()); - assertFalse(iterator.hasNext()); - TestNode c = new TestNode("c"); - graph.add(c); - assertTrue(iterator.hasNext()); - c.safeDelete(); - assertFalse(iterator.hasNext()); - } - - @Test - public void complicatedIterationTest() { - Graph graph = new Graph(); - graph.add(new TestNode("a")); - for (TestNode tn : graph.getNodes(TestNode.class)) { - String name = tn.getName(); - for (int i = 0; i < name.length(); ++i) { - char c = name.charAt(i); - if (c == 'a') { - tn.safeDelete(); - graph.add(new TestNode("b")); - graph.add(new TestNode("c")); - } else if (c == 'b') { - tn.safeDelete(); - } else if (c == 'c') { - graph.add(new TestNode("d")); - graph.add(new TestNode("e")); - graph.add(new TestNode("d")); - graph.add(new TestNode("e")); - graph.add(new TestNode("e")); - graph.add(new TestNode("d")); - graph.add(new TestNode("e")); - graph.add(new TestNode("d")); - } else if (c == 'd') { - for (TestNode tn2 : graph.getNodes(TestNode.class)) { - if (tn2.getName().equals("e")) { - tn2.safeDelete(); - } else if (tn2.getName().equals("c")) { - tn2.safeDelete(); - } - } - } else if (c == 'e') { - fail("All e nodes must have been deleted by visiting the d node"); - } - } - } - assertEquals("dddd", toString(graph.getNodes(TestNode.class))); - } - - @Test - public void addingNodeDuringIterationTest() { - Graph graph = new Graph(); - graph.add(new TestNode("a")); - StringBuilder sb = new StringBuilder(); - int z = 0; - for (TestNode tn : graph.getNodes(TestNode.class)) { - if (z == 0) { - graph.add(new TestNode("b")); - } - sb.append(tn.getName()); - z++; - } - assertEquals(2, z); - assertEquals("ab", sb.toString()); - z = 0; - for (TestNode tn : graph.getNodes(TestNode.class)) { - if (z == 0) { - graph.add(new TestNode("c")); - } - assertNotNull(tn); - z++; - } - assertEquals(3, z); - } - - public static String toString(Iterable nodes) { - StringBuilder sb = new StringBuilder(); - for (TestNodeInterface tn : nodes) { - sb.append(tn.getName()); - } - return sb.toString(); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest2.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest2.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +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.graph; - -import static org.junit.Assert.*; - -import org.junit.*; - -public class TypedNodeIteratorTest2 { - - private static class NodeA extends Node implements TestNodeInterface { - - private final String name; - - public NodeA(String name) { - this.name = name; - } - - public String getName() { - return name; - } - } - - private static class NodeB extends NodeA implements Node.IterableNodeType { - - public NodeB(String name) { - super(name); - } - } - - private static class NodeC extends NodeB { - - public NodeC(String name) { - super(name); - } - } - - private static class NodeD extends NodeC { - - public NodeD(String name) { - super(name); - } - } - - @Test - public void simpleSubclassTest() { - Graph graph = new Graph(); - graph.add(new NodeB("b")); - graph.add(new NodeD("d")); - - Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class))); - Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class))); - } - - @Test - public void addingNodeDuringIterationTest() { - Graph graph = new Graph(); - graph.add(new NodeB("b1")); - NodeD d1 = graph.add(new NodeD("d1")); - StringBuilder sb = new StringBuilder(); - for (NodeB tn : graph.getNodes(NodeB.class)) { - if (tn == d1) { - graph.add(new NodeB("b2")); - } - sb.append(tn.getName()); - } - assertEquals("b1d1b2", sb.toString()); - for (NodeB tn : graph.getNodes(NodeB.class)) { - if (tn == d1) { - graph.add(new NodeB("b3")); - } - assertNotNull(tn); - } - assertEquals(4, graph.getNodes(NodeB.class).count()); - assertEquals(1, graph.getNodes(NodeD.class).count()); - } - -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TestNodeInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TestNodeInterface.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.test; + +public interface TestNodeInterface { + + String getName(); +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.test; + +import static org.junit.Assert.*; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.graph.*; + +public class TypedNodeIteratorTest { + + private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface { + + private final String name; + + public TestNode(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + @Test + public void singleNodeTest() { + Graph graph = new Graph(); + graph.add(new TestNode("a")); + assertTrue(graph.hasNode(TestNode.class)); + assertEquals("a", toString(graph.getNodes(TestNode.class))); + } + + @Test + public void deletingNodeTest() { + TestNode testNode = new TestNode("a"); + Graph graph = new Graph(); + graph.add(testNode); + testNode.safeDelete(); + assertEquals("", toString(graph.getNodes(TestNode.class))); + } + + @Test + public void deleteAndAddTest() { + TestNode testNode = new TestNode("b"); + Graph graph = new Graph(); + graph.add(new TestNode("a")); + graph.add(testNode); + testNode.safeDelete(); + assertEquals("a", toString(graph.getNodes(TestNode.class))); + graph.add(new TestNode("c")); + assertEquals("ac", toString(graph.getNodes(TestNode.class))); + } + + @Test + public void iteratorBehaviorTest() { + Graph graph = new Graph(); + graph.add(new TestNode("a")); + Iterator iterator = graph.getNodes(TestNode.class).iterator(); + assertTrue(iterator.hasNext()); + assertEquals("a", iterator.next().getName()); + assertFalse(iterator.hasNext()); + graph.add(new TestNode("b")); + assertTrue(iterator.hasNext()); + assertEquals("b", iterator.next().getName()); + assertFalse(iterator.hasNext()); + TestNode c = new TestNode("c"); + graph.add(c); + assertTrue(iterator.hasNext()); + c.safeDelete(); + assertFalse(iterator.hasNext()); + } + + @Test + public void complicatedIterationTest() { + Graph graph = new Graph(); + graph.add(new TestNode("a")); + for (TestNode tn : graph.getNodes(TestNode.class)) { + String name = tn.getName(); + for (int i = 0; i < name.length(); ++i) { + char c = name.charAt(i); + if (c == 'a') { + tn.safeDelete(); + graph.add(new TestNode("b")); + graph.add(new TestNode("c")); + } else if (c == 'b') { + tn.safeDelete(); + } else if (c == 'c') { + graph.add(new TestNode("d")); + graph.add(new TestNode("e")); + graph.add(new TestNode("d")); + graph.add(new TestNode("e")); + graph.add(new TestNode("e")); + graph.add(new TestNode("d")); + graph.add(new TestNode("e")); + graph.add(new TestNode("d")); + } else if (c == 'd') { + for (TestNode tn2 : graph.getNodes(TestNode.class)) { + if (tn2.getName().equals("e")) { + tn2.safeDelete(); + } else if (tn2.getName().equals("c")) { + tn2.safeDelete(); + } + } + } else if (c == 'e') { + fail("All e nodes must have been deleted by visiting the d node"); + } + } + } + assertEquals("dddd", toString(graph.getNodes(TestNode.class))); + } + + @Test + public void addingNodeDuringIterationTest() { + Graph graph = new Graph(); + graph.add(new TestNode("a")); + StringBuilder sb = new StringBuilder(); + int z = 0; + for (TestNode tn : graph.getNodes(TestNode.class)) { + if (z == 0) { + graph.add(new TestNode("b")); + } + sb.append(tn.getName()); + z++; + } + assertEquals(2, z); + assertEquals("ab", sb.toString()); + z = 0; + for (TestNode tn : graph.getNodes(TestNode.class)) { + if (z == 0) { + graph.add(new TestNode("c")); + } + assertNotNull(tn); + z++; + } + assertEquals(3, z); + } + + public static String toString(Iterable nodes) { + StringBuilder sb = new StringBuilder(); + for (TestNodeInterface tn : nodes) { + sb.append(tn.getName()); + } + return sb.toString(); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,100 @@ +/* + * 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.graph.test; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.graph.*; + +public class TypedNodeIteratorTest2 { + + private static class NodeA extends Node implements TestNodeInterface { + + private final String name; + + public NodeA(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + private static class NodeB extends NodeA implements Node.IterableNodeType { + + public NodeB(String name) { + super(name); + } + } + + private static class NodeC extends NodeB { + + public NodeC(String name) { + super(name); + } + } + + private static class NodeD extends NodeC { + + public NodeD(String name) { + super(name); + } + } + + @Test + public void simpleSubclassTest() { + Graph graph = new Graph(); + graph.add(new NodeB("b")); + graph.add(new NodeD("d")); + + Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class))); + Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class))); + } + + @Test + public void addingNodeDuringIterationTest() { + Graph graph = new Graph(); + graph.add(new NodeB("b1")); + NodeD d1 = graph.add(new NodeD("d1")); + StringBuilder sb = new StringBuilder(); + for (NodeB tn : graph.getNodes(NodeB.class)) { + if (tn == d1) { + graph.add(new NodeB("b2")); + } + sb.append(tn.getName()); + } + assertEquals("b1d1b2", sb.toString()); + for (NodeB tn : graph.getNodes(NodeB.class)) { + if (tn == d1) { + graph.add(new NodeB("b3")); + } + assertNotNull(tn); + } + assertEquals(4, graph.getNodes(NodeB.class).count()); + assertEquals(1, graph.getNodes(NodeD.class).count()); + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph/.checkstyle_checks.xml --- a/graal/com.oracle.graal.graph/.checkstyle_checks.xml Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.graph/.checkstyle_checks.xml Sat Apr 20 12:23:29 2013 +0200 @@ -1,15 +1,15 @@ - - - + @@ -197,4 +197,14 @@ + + + + + + + + + + diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEvent.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEvent.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEvent.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.graph; +import java.io.*; + public abstract class GraphEvent { private Exception exceptionContext; @@ -43,9 +45,9 @@ } @Override - public StackTraceElement[] print(StackTraceElement[] last) { - System.out.println(type.toString() + ", " + nodeString); - return super.print(last); + public StackTraceElement[] print(StackTraceElement[] last, PrintStream stream) { + stream.println(type.toString() + ", " + nodeString); + return super.print(last, stream); } } @@ -72,7 +74,7 @@ exceptionContext = new Exception(); } - public StackTraceElement[] print(StackTraceElement[] last) { + public StackTraceElement[] print(StackTraceElement[] last, PrintStream stream) { StackTraceElement[] stackTrace = exceptionContext.getStackTrace(); boolean atTop = true; @@ -90,7 +92,7 @@ continue; } } - System.out.println(String.format("%s.%s(%s:%d)", elem.getClassName(), elem.getMethodName(), elem.getFileName(), elem.getLineNumber())); + stream.println(String.format("%s.%s(%s:%d)", elem.getClassName(), elem.getMethodName(), elem.getFileName(), elem.getLineNumber())); } return stackTrace; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEventLog.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEventLog.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphEventLog.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.graph; +import java.io.*; import java.util.*; public class GraphEventLog { @@ -32,10 +33,10 @@ this.events.add(e); } - public void printEvents() { + public void printEvents(PrintStream stream) { StackTraceElement[] last = new StackTraceElement[0]; for (GraphEvent e : events) { - last = e.print(last); + last = e.print(last, stream); } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Sat Apr 20 12:23:29 2013 +0200 @@ -49,7 +49,7 @@ protected TargetDescription createTarget() { final int stackFrameAlignment = 16; final int implicitNullCheckLimit = 4096; - return new TargetDescription(new AMD64(), true, stackFrameAlignment, implicitNullCheckLimit, true); + return new TargetDescription(new AMD64(config.useSSE, config.useAVX), true, stackFrameAlignment, implicitNullCheckLimit, true); } @Override diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Sat Apr 20 12:23:29 2013 +0200 @@ -44,6 +44,7 @@ import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*; import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; @@ -71,13 +72,13 @@ /* ret */ ret(Kind.Void)); addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub, - /* temps */ null, + /* temps */ new Register[]{AMD64.rax}, /* ret */ ret(Kind.Float), /* arg0: a */ javaCallingConvention(Kind.Float, /* arg1: b */ Kind.Float)); addRuntimeCall(ARITHMETIC_DREM, config.arithmeticDremStub, - /* temps */ null, + /* temps */ new Register[]{AMD64.rax}, /* ret */ ret(Kind.Double), /* arg0: a */ javaCallingConvention(Kind.Double, /* arg1: b */ Kind.Double)); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Sat Apr 20 12:23:29 2013 +0200 @@ -52,7 +52,7 @@ @Use({REG}) protected Value metaspaceMethod; - AMD64IndirectCallOp(InvokeTarget targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) { + AMD64IndirectCallOp(ResolvedJavaMethod targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) { super(targetMethod, result, parameters, temps, targetAddress, state); this.metaspaceMethod = metaspaceMethod; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Sat Apr 20 12:23:29 2013 +0200 @@ -63,11 +63,11 @@ if (config.isPollingPageFar) { asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset); tasm.recordMark(Marks.MARK_POLL_FAR); - tasm.recordSafepoint(pos, state); + tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister())); } else { tasm.recordMark(Marks.MARK_POLL_NEAR); - tasm.recordSafepoint(pos, state); + tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); // The C++ code transforms the polling page offset into an RIP displacement // to the real address at that offset in the polling page. asm.movq(scratch.getRegister(), new AMD64Address(rip, offset)); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java --- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/InvocationSocket.java Sat Apr 20 12:23:29 2013 +0200 @@ -26,6 +26,7 @@ import java.lang.reflect.*; import java.util.*; +import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.logging.*; /** @@ -73,7 +74,7 @@ sorted.put(entry.getValue(), entry.getKey()); } for (Map.Entry entry : sorted.entrySet()) { - System.out.println(entry.getKey() + ": " + entry.getValue()); + TTY.println(entry.getKey() + ": " + entry.getValue()); } } }); @@ -246,15 +247,15 @@ } result = new Result(result); } catch (IllegalArgumentException e) { - System.out.println("error while invoking " + invoke.methodName); + TTY.println("error while invoking " + invoke.methodName); e.getCause().printStackTrace(); result = e.getCause(); } catch (InvocationTargetException e) { - System.out.println("error while invoking " + invoke.methodName); + TTY.println("error while invoking " + invoke.methodName); e.getCause().printStackTrace(); result = e.getCause(); } catch (IllegalAccessException e) { - System.out.println("error while invoking " + invoke.methodName); + TTY.println("error while invoking " + invoke.methodName); e.getCause().printStackTrace(); result = e.getCause(); } finally { @@ -279,4 +280,5 @@ output.writeObject(new Result(obj)); output.flush(); } + // CheckStyle: resume system..print check } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot; - -import static org.junit.Assert.*; - -import java.lang.reflect.*; -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; - -/** - * Tests intrinsification of {@link System#arraycopy(Object, int, Object, int, int)}. - */ -public class ArrayCopyIntrinsificationTest extends GraalCompilerTest { - - @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { - int nodeCount = graph.getNodeCount(); - InstalledCode result = super.getCode(method, graph); - boolean graphWasProcessed = nodeCount != graph.getNodeCount(); - if (graphWasProcessed) { - if (mustIntrinsify) { - for (Node node : graph.getNodes()) { - if (node instanceof Invoke) { - Invoke invoke = (Invoke) node; - Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode); - AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget(); - JavaMethod callee = directCall.target(); - Assert.assertTrue(callee.getName().equals("")); - Assert.assertTrue(runtime.lookupJavaType(ArrayIndexOutOfBoundsException.class).equals(callee.getDeclaringClass()) || - runtime.lookupJavaType(NullPointerException.class).equals(callee.getDeclaringClass())); - } - } - } else { - boolean found = false; - for (Node node : graph.getNodes()) { - if (node instanceof Invoke) { - Invoke invoke = (Invoke) node; - AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget(); - JavaMethod callee = directCall.target(); - if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) { - found = true; - } else { - fail("found invoke to some method other than arraycopy: " + callee); - } - } - } - Assert.assertTrue("did not find invoke to arraycopy", found); - } - } - return result; - } - - boolean mustIntrinsify = true; - - @Test - public void test0() { - mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified - // Array store checks - test("genericArraycopy", new Object(), 0, new Object[0], 0, 0); - test("genericArraycopy", new Object[0], 0, new Object(), 0, 0); - - mustIntrinsify = true; - } - - @Test - public void test1() { - String name = "intArraycopy"; - int[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; - // Null checks - test(name, null, 0, src, 0, 0); - test(name, src, 0, null, 0, 0); - // Bounds checks - test(name, src, 0, src, 0, -1); - test(name, src, 0, src, 0, src.length + 1); - } - - @Test - public void testByte() { - byte[] src = {-1, 0, 1, 2, 3, 4}; - testHelper("byteArraycopy", src); - } - - @Test - public void testChar() { - char[] src = "some string of chars".toCharArray(); - testHelper("charArraycopy", src); - } - - @Test - public void testShort() { - short[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; - testHelper("shortArraycopy", src); - } - - @Test - public void testInt() { - int[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; - testHelper("intArraycopy", src); - } - - @Test - public void testFloat() { - float[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; - testHelper("floatArraycopy", src); - } - - @Test - public void testLong() { - long[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; - testHelper("longArraycopy", src); - } - - @Test - public void testDouble() { - double[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; - testHelper("doubleArraycopy", src); - } - - @Test - public void testObject() { - mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified - - Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()}; - testHelper("objectArraycopy", src); - - mustIntrinsify = true; - } - - @Test - public void testObjectExact() { - Integer[] src = {1, 2, 3, 4}; - testHelper("objectArraycopyExact", src); - } - - private static Object newArray(Object proto, int length) { - assert proto != null; - assert proto.getClass().isArray(); - return Array.newInstance(proto.getClass().getComponentType(), length); - } - - private void testHelper(String name, Object src) { - int srcLength = Array.getLength(src); - - // Complete array copy - test(name, src, 0, newArray(src, srcLength), 0, srcLength); - - for (int length : new int[]{0, 1, srcLength - 1, srcLength}) { - // Partial array copying - test(name, src, 0, newArray(src, length), 0, length); - test(name, src, srcLength - length, newArray(src, length), 0, length); - test(name, src, 0, newArray(src, srcLength), 0, length); - } - } - - public static Object genericArraycopy(Object src, int srcPos, Object dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static Object[] objectArraycopy(Object[] src, int srcPos, Object[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static Object[] objectArraycopyExact(Integer[] src, int srcPos, Integer[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static boolean[] booleanArraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static byte[] byteArraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static char[] charArraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static short[] shortArraycopy(short[] src, int srcPos, short[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static int[] intArraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static float[] floatArraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static long[] longArraycopy(long[] src, int srcPos, long[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - - public static double[] doubleArraycopy(double[] src, int srcPos, double[] dst, int dstPos, int length) { - System.arraycopy(src, srcPos, dst, dstPos, length); - return dst; - } - -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/HotSpotMethodSubstitutionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/HotSpotMethodSubstitutionTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot; - -import org.junit.*; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.replacements.*; - -/** - * Tests HotSpot specific {@link MethodSubstitution}s. - */ -public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest { - - @Test - public void testObjectSubstitutions() { - test("getClass_"); - test("objectHashCode"); - - Object obj = new Object(); - - assertEquals("a string".getClass(), ObjectSubstitutions.getClass("a string")); - assertEquals(obj.hashCode(), ObjectSubstitutions.hashCode(obj)); - } - - @SuppressWarnings("all") - public static boolean getClass_(Object obj, Class clazz) { - return obj.getClass() == clazz; - } - - @SuppressWarnings("all") - public static int objectHashCode(TestClassA obj) { - return obj.hashCode(); - } - - @Test - public void testClassSubstitutions() { - test("getModifiers"); - test("isInstance"); - test("isInterface"); - test("isArray"); - test("isPrimitive"); - test("getSuperClass"); - test("getComponentType"); - - for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) { - assertEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c)); - assertEquals(c.isInterface(), ClassSubstitutions.isInterface(c)); - assertEquals(c.isArray(), ClassSubstitutions.isArray(c)); - assertEquals(c.isPrimitive(), ClassSubstitutions.isPrimitive(c)); - assertEquals(c.getSuperclass(), ClassSubstitutions.getSuperclass(c)); - assertEquals(c.getComponentType(), ClassSubstitutions.getComponentType(c)); - for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { - assertEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o)); - } - } - } - - @SuppressWarnings("all") - public static int getModifiers(Class clazz) { - return clazz.getModifiers(); - } - - @SuppressWarnings("all") - public static boolean isInstance(Class clazz) { - return clazz.isInstance(Number.class); - } - - @SuppressWarnings("all") - public static boolean isInterface(Class clazz) { - return clazz.isInterface(); - } - - @SuppressWarnings("all") - public static boolean isArray(Class clazz) { - return clazz.isArray(); - } - - @SuppressWarnings("all") - public static boolean isPrimitive(Class clazz) { - return clazz.isPrimitive(); - } - - @SuppressWarnings("all") - public static Class getSuperClass(Class clazz) { - return clazz.getSuperclass(); - } - - @SuppressWarnings("all") - public static Class getComponentType(Class clazz) { - return clazz.getComponentType(); - } - - @Test - public void testThreadSubstitutions() { - test("currentThread"); - test("threadIsInterrupted"); - test("threadInterrupted"); - - Thread currentThread = Thread.currentThread(); - assertEquals(currentThread, ThreadSubstitutions.currentThread()); - assertEquals(currentThread.isInterrupted(), ThreadSubstitutions.isInterrupted(currentThread, false)); - } - - @SuppressWarnings("all") - public static Thread currentThread() { - return Thread.currentThread(); - } - - @SuppressWarnings("all") - public static boolean threadIsInterrupted(Thread thread) { - return thread.isInterrupted(); - } - - @SuppressWarnings("all") - public static boolean threadInterrupted() { - return Thread.interrupted(); - } - - @Test - public void testSystemSubstitutions() { - test("systemTime"); - test("systemIdentityHashCode"); - - SystemSubstitutions.currentTimeMillis(); - SystemSubstitutions.nanoTime(); - for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { - assertEquals(System.identityHashCode(o), SystemSubstitutions.identityHashCode(o)); - } - } - - @SuppressWarnings("all") - public static long systemTime() { - return System.currentTimeMillis() + System.nanoTime(); - } - - @SuppressWarnings("all") - public static int systemIdentityHashCode(Object obj) { - return System.identityHashCode(obj); - } - - private static class TestClassA { - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/InstalledCodeExecuteHelperTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/InstalledCodeExecuteHelperTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot; - -import java.lang.reflect.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.spi.*; - -public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { - - private static final int ITERATIONS = 100000000; - - @Ignore - @Test - public void test1() throws NoSuchMethodException, SecurityException { - - final Method benchrMethod = InstalledCodeExecuteHelperTest.class.getMethod("bench", long.class, long.class); - final ResolvedJavaMethod benchJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(benchrMethod); - HotSpotInstalledCode benchCode = (HotSpotInstalledCode) getCode(benchJavaMethod, parse(benchrMethod)); - - final Method wrapperMethod = InstalledCodeExecuteHelperTest.class.getMethod("executeWrapper", long.class, long.class, Object.class, Object.class, Object.class); - final ResolvedJavaMethod wrapperJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(wrapperMethod); - HotSpotInstalledCode wrapperCode = (HotSpotInstalledCode) getCode(wrapperJavaMethod, parse(wrapperMethod)); - - final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class); - final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(fooMethod); - HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod)); - - System.out.println(wrapperCode.executeVarargs(fooCode.getnmethod(), fooJavaMethod.getMetaspaceMethod(), null, null, null)); - - long nmethod = fooCode.getnmethod(); - long metaspacemethod = fooJavaMethod.getMetaspaceMethod(); - - System.out.println("Without replaced InstalledCode.execute:" + bench(nmethod, metaspacemethod)); - - System.out.println("WITH replaced InstalledCode.execute:" + benchCode.executeVarargs(nmethod, metaspacemethod)); - - } - - public static Long bench(long nmethod, long metaspacemethod) { - long start = System.currentTimeMillis(); - - for (int i = 0; i < ITERATIONS; i++) { - HotSpotInstalledCode.executeHelper(nmethod, metaspacemethod, null, null, null); - } - - long end = System.currentTimeMillis(); - return (end - start); - } - - public static Object foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) { - return 42; - } - - public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) { - return HotSpotInstalledCode.executeHelper(nmethod, metaspaceMethod, arg1, arg2, arg3); - } - -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ArrayCopyIntrinsificationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ArrayCopyIntrinsificationTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import static org.junit.Assert.*; + +import java.lang.reflect.*; +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; + +/** + * Tests intrinsification of {@link System#arraycopy(Object, int, Object, int, int)}. + */ +public class ArrayCopyIntrinsificationTest extends GraalCompilerTest { + + @Override + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { + int nodeCount = graph.getNodeCount(); + InstalledCode result = super.getCode(method, graph); + boolean graphWasProcessed = nodeCount != graph.getNodeCount(); + if (graphWasProcessed) { + if (mustIntrinsify) { + for (Node node : graph.getNodes()) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode); + LoweredCallTargetNode directCall = (LoweredCallTargetNode) invoke.callTarget(); + JavaMethod callee = directCall.target(); + Assert.assertTrue(callee.getName().equals("")); + Assert.assertTrue(runtime.lookupJavaType(ArrayIndexOutOfBoundsException.class).equals(callee.getDeclaringClass()) || + runtime.lookupJavaType(NullPointerException.class).equals(callee.getDeclaringClass())); + } + } + } else { + boolean found = false; + for (Node node : graph.getNodes()) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + LoweredCallTargetNode directCall = (LoweredCallTargetNode) invoke.callTarget(); + JavaMethod callee = directCall.target(); + if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) { + found = true; + } else { + fail("found invoke to some method other than arraycopy: " + callee); + } + } + } + Assert.assertTrue("did not find invoke to arraycopy", found); + } + } + return result; + } + + boolean mustIntrinsify = true; + + @Test + public void test0() { + mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified + // Array store checks + test("genericArraycopy", new Object(), 0, new Object[0], 0, 0); + test("genericArraycopy", new Object[0], 0, new Object(), 0, 0); + + mustIntrinsify = true; + } + + @Test + public void test1() { + String name = "intArraycopy"; + int[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; + // Null checks + test(name, null, 0, src, 0, 0); + test(name, src, 0, null, 0, 0); + // Bounds checks + test(name, src, 0, src, 0, -1); + test(name, src, 0, src, 0, src.length + 1); + } + + @Test + public void testByte() { + byte[] src = {-1, 0, 1, 2, 3, 4}; + testHelper("byteArraycopy", src); + } + + @Test + public void testChar() { + char[] src = "some string of chars".toCharArray(); + testHelper("charArraycopy", src); + } + + @Test + public void testShort() { + short[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; + testHelper("shortArraycopy", src); + } + + @Test + public void testInt() { + int[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; + testHelper("intArraycopy", src); + } + + @Test + public void testFloat() { + float[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; + testHelper("floatArraycopy", src); + } + + @Test + public void testLong() { + long[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; + testHelper("longArraycopy", src); + } + + @Test + public void testDouble() { + double[] src = {234, 5345, 756, 23, 8, 345, 873, 440}; + testHelper("doubleArraycopy", src); + } + + @Test + public void testObject() { + mustIntrinsify = false; // a generic call to arraycopy will not be intrinsified + + Object[] src = {"one", "two", "three", new ArrayList<>(), new HashMap<>()}; + testHelper("objectArraycopy", src); + + mustIntrinsify = true; + } + + @Test + public void testObjectExact() { + Integer[] src = {1, 2, 3, 4}; + testHelper("objectArraycopyExact", src); + } + + private static Object newArray(Object proto, int length) { + assert proto != null; + assert proto.getClass().isArray(); + return Array.newInstance(proto.getClass().getComponentType(), length); + } + + private void testHelper(String name, Object src) { + int srcLength = Array.getLength(src); + + // Complete array copy + test(name, src, 0, newArray(src, srcLength), 0, srcLength); + + for (int length : new int[]{0, 1, srcLength - 1, srcLength}) { + // Partial array copying + test(name, src, 0, newArray(src, length), 0, length); + test(name, src, srcLength - length, newArray(src, length), 0, length); + test(name, src, 0, newArray(src, srcLength), 0, length); + } + } + + public static Object genericArraycopy(Object src, int srcPos, Object dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static Object[] objectArraycopy(Object[] src, int srcPos, Object[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static Object[] objectArraycopyExact(Integer[] src, int srcPos, Integer[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static boolean[] booleanArraycopy(boolean[] src, int srcPos, boolean[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static byte[] byteArraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static char[] charArraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static short[] shortArraycopy(short[] src, int srcPos, short[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static int[] intArraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static float[] floatArraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static long[] longArraycopy(long[] src, int srcPos, long[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + + public static double[] doubleArraycopy(double[] src, int srcPos, double[] dst, int dstPos, int length) { + System.arraycopy(src, srcPos, dst, dstPos, length); + return dst; + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import org.junit.*; + +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.hotspot.*; + +/** + * Tests {@link CompileTheWorld} functionality. + */ +public class CompileTheWorldTest extends GraalCompilerTest { + + @Test + public void testRtJar() throws Throwable { + // Compile a couple classes in rt.jar + String file = System.getProperty("java.home") + "/lib/rt.jar"; + new CompileTheWorld(file, 1, 5).compile(); + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; + +public class HotSpotInstalledCodeTest extends GraalCompilerTest { + + private static final int ITERATION_COUNT = 100000; + + @Test + public void testInstallCodeInvalidation() { + final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo")); + final StructuredGraph graph = parse("otherFoo"); + final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph); + Assert.assertTrue(installedCode.isValid()); + Object result; + try { + result = installedCode.execute("a", "b", "c"); + assertEquals(43, result); + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code was invalidated"); + } + Assert.assertTrue(installedCode.isValid()); + installedCode.invalidate(); + Assert.assertFalse(installedCode.isValid()); + try { + result = installedCode.execute(null, null, null); + Assert.fail("Code was not invalidated"); + } catch (InvalidInstalledCodeException e) { + } + Assert.assertFalse(installedCode.isValid()); + } + + @Test + public void testInstalledCodeCalledFromCompiledCode() { + final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo")); + final StructuredGraph graph = parse("otherFoo"); + final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph); + Assert.assertTrue(installedCode.isValid()); + try { + for (int i = 0; i < ITERATION_COUNT; ++i) { + installedCode.execute("a", "b", "c"); + } + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code was invalidated"); + } + } + + @SuppressWarnings("unused") + public static Object foo(Object a1, Object a2, Object a3) { + return 42; + } + + @SuppressWarnings("unused") + public static Object otherFoo(Object a1, Object a2, Object a3) { + return 43; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import org.junit.*; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.replacements.test.*; + +/** + * Tests HotSpot specific {@link MethodSubstitution}s. + */ +public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest { + + @Test + public void testObjectSubstitutions() { + test("getClass_"); + test("objectHashCode"); + + Object obj = new Object(); + + assertEquals("a string".getClass(), ObjectSubstitutions.getClass("a string")); + assertEquals(obj.hashCode(), ObjectSubstitutions.hashCode(obj)); + } + + @SuppressWarnings("all") + public static boolean getClass_(Object obj, Class clazz) { + return obj.getClass() == clazz; + } + + @SuppressWarnings("all") + public static int objectHashCode(TestClassA obj) { + return obj.hashCode(); + } + + @Test + public void testClassSubstitutions() { + test("getModifiers"); + test("isInstance"); + test("isInterface"); + test("isArray"); + test("isPrimitive"); + test("getSuperClass"); + test("getComponentType"); + + for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) { + assertEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c)); + assertEquals(c.isInterface(), ClassSubstitutions.isInterface(c)); + assertEquals(c.isArray(), ClassSubstitutions.isArray(c)); + assertEquals(c.isPrimitive(), ClassSubstitutions.isPrimitive(c)); + assertEquals(c.getSuperclass(), ClassSubstitutions.getSuperclass(c)); + assertEquals(c.getComponentType(), ClassSubstitutions.getComponentType(c)); + for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { + assertEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o)); + } + } + } + + @SuppressWarnings("all") + public static int getModifiers(Class clazz) { + return clazz.getModifiers(); + } + + @SuppressWarnings("all") + public static boolean isInstance(Class clazz) { + return clazz.isInstance(Number.class); + } + + @SuppressWarnings("all") + public static boolean isInterface(Class clazz) { + return clazz.isInterface(); + } + + @SuppressWarnings("all") + public static boolean isArray(Class clazz) { + return clazz.isArray(); + } + + @SuppressWarnings("all") + public static boolean isPrimitive(Class clazz) { + return clazz.isPrimitive(); + } + + @SuppressWarnings("all") + public static Class getSuperClass(Class clazz) { + return clazz.getSuperclass(); + } + + @SuppressWarnings("all") + public static Class getComponentType(Class clazz) { + return clazz.getComponentType(); + } + + @Test + public void testThreadSubstitutions() { + test("currentThread"); + test("threadIsInterrupted"); + test("threadInterrupted"); + + Thread currentThread = Thread.currentThread(); + assertEquals(currentThread, ThreadSubstitutions.currentThread()); + assertEquals(currentThread.isInterrupted(), ThreadSubstitutions.isInterrupted(currentThread, false)); + } + + @SuppressWarnings("all") + public static Thread currentThread() { + return Thread.currentThread(); + } + + @SuppressWarnings("all") + public static boolean threadIsInterrupted(Thread thread) { + return thread.isInterrupted(); + } + + @SuppressWarnings("all") + public static boolean threadInterrupted() { + return Thread.interrupted(); + } + + @Test + public void testSystemSubstitutions() { + test("systemTime"); + test("systemIdentityHashCode"); + + SystemSubstitutions.currentTimeMillis(); + SystemSubstitutions.nanoTime(); + for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { + assertEquals(System.identityHashCode(o), SystemSubstitutions.identityHashCode(o)); + } + } + + @SuppressWarnings("all") + public static long systemTime() { + return System.currentTimeMillis() + System.nanoTime(); + } + + @SuppressWarnings("all") + public static int systemIdentityHashCode(Object obj) { + return System.identityHashCode(obj); + } + + private static class TestClassA { + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import static com.oracle.graal.api.meta.MetaUtil.*; +import static java.lang.reflect.Modifier.*; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; + +public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { + + private static final int ITERATIONS = 100000; + private final MetaAccessProvider metaAccessProvider; + Object[] argsToBind; + + public InstalledCodeExecuteHelperTest() { + this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class); + } + + @Test + public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException { + final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class); + final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod); + final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod)); + + argsToBind = new Object[]{fooCode}; + + final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class); + final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod); + final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod)); + + Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode)); + + Assert.assertEquals(Integer.valueOf(42), installedBenchmarkCode.executeVarargs(argsToBind[0])); + + } + + public static Integer benchmark(HotSpotInstalledCode code) throws InvalidInstalledCodeException { + int val = 0; + for (int j = 0; j < 100; j++) { + for (int i = 0; i < ITERATIONS; i++) { + val = (Integer) code.execute(null, null, null); + } + } + return val; + } + + public static Integer foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) { + return 42; + } + + @Override + protected StructuredGraph parse(Method m) { + StructuredGraph graph = super.parse(m); + if (argsToBind != null) { + Object receiver = isStatic(m.getModifiers()) ? null : this; + Object[] args = argsWithReceiver(receiver, argsToBind); + JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m)); + assert parameterTypes.length == args.length; + for (int i = 0; i < argsToBind.length; i++) { + LocalNode local = graph.getLocal(i); + Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]); + ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph); + local.replaceAtUsages(replacement); + } + } + return graph; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.nodes.StructuredGraph.*; import static com.oracle.graal.phases.common.InliningUtil.*; +import java.lang.reflect.Modifier; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -32,6 +33,7 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -133,6 +135,9 @@ TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(), entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") ")); } + if (GraalOptions.HotSpotPrintCompilation) { + printCompilation(); + } CompilationResult result = null; TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method); @@ -163,7 +168,7 @@ } } - installMethod(result); + installMethod(result, null); } catch (BailoutException bailout) { Debug.metric("Bailouts").increment(); if (GraalOptions.ExitVMOnBailout) { @@ -183,12 +188,22 @@ stats.finish(method); } - private void installMethod(final CompilationResult compResult) { + /** + * Print a HotSpot-style compilation message to the console. + */ + private void printCompilation() { + final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; + final int mod = method.getModifiers(); + TTY.println(String.format("%7d %4d %c%c%c%c%c %s %s(%d bytes)", 0, id, isOSR ? '%' : ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ', + MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize())); + } + + private void installMethod(final CompilationResult compResult, final Graph graph) { Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() { @Override public void run() { - HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult); + HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, graph, entryBCI, compResult); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.*; +import java.util.Enumeration; +import java.util.jar.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.bytecode.Bytecodes; +import com.oracle.graal.debug.*; +import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.replacements.*; + +/** + * This class implements compile-the-world functionality in Graal. + */ +public final class CompileTheWorld { + + /** + * This is our magic token to trigger reading files from the boot class path. + */ + public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path"; + + // Some runtime instances we need. + private final HotSpotGraalRuntime graalRuntime = HotSpotGraalRuntime.getInstance(); + private final VMToCompilerImpl vmToCompiler = (VMToCompilerImpl) graalRuntime.getVMToCompiler(); + + /** List of Zip/Jar files to compile (see {@link GraalOptions#CompileTheWorld}. */ + private final String files; + + /** Class index to start compilation at (see {@link GraalOptions#CompileTheWorldStartAt}. */ + private final int startAt; + + /** Class index to stop compilation at (see {@link GraalOptions#CompileTheWorldStopAt}. */ + private final int stopAt; + + // Counters + private int classFileCounter = 0; + private int compiledMethodsCounter = 0; + private long compileTime = 0; + + /** + * Create a compile-the-world instance with default values from + * {@link GraalOptions#CompileTheWorld}, {@link GraalOptions#CompileTheWorldStartAt} and + * {@link GraalOptions#CompileTheWorldStopAt}. + */ + public CompileTheWorld() { + this(GraalOptions.CompileTheWorld, GraalOptions.CompileTheWorldStartAt, GraalOptions.CompileTheWorldStopAt); + } + + /** + * Create a compile-the-world instance. + * + * @param files {@link File#pathSeparator} separated list of Zip/Jar files to compile + * @param startAt index of the class file to start compilation at + * @param stopAt index of the class file to stop compilation at + */ + public CompileTheWorld(String files, int startAt, int stopAt) { + this.files = files; + this.startAt = startAt; + this.stopAt = stopAt; + + // We don't want the VM to exit when a method fails to compile. + GraalOptions.ExitVMOnException = false; + } + + /** + * Compile all methods in all classes in the Zip/Jar files in + * {@link GraalOptions#CompileTheWorld}. If the GraalOptions.CompileTheWorld contains the magic + * token {@link CompileTheWorld#SUN_BOOT_CLASS_PATH} passed up from HotSpot we take the files + * from the boot class path. + * + * @throws Throwable + */ + public void compile() throws Throwable { + if (SUN_BOOT_CLASS_PATH.equals(files)) { + final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator); + String bcpFiles = ""; + for (int i = 0; i < entries.length; i++) { + final String entry = entries[i]; + + // We stop at rt.jar, unless it is the first boot class path entry. + if (entry.endsWith("rt.jar") && (i > 0)) { + break; + } + if (i > 0) { + bcpFiles += File.pathSeparator; + } + bcpFiles += entry; + } + compile(bcpFiles); + } else { + compile(files); + } + } + + /** + * Compile all methods in all classes in the Zip/Jar files passed. + * + * @param fileList {@link File#pathSeparator} separated list of Zip/Jar files to compile + * @throws Throwable + */ + private void compile(String fileList) throws Throwable { + final String[] entries = fileList.split(File.pathSeparator); + + for (int i = 0; i < entries.length; i++) { + final String entry = entries[i]; + + // For now we only compile all methods in all classes in zip/jar files. + if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) { + TTY.println("CompileTheWorld : Skipped classes in " + entry); + TTY.println(); + continue; + } + + TTY.println("CompileTheWorld : Compiling all classes in " + entry); + TTY.println(); + + URL url = new URL("jar", "", "file:" + entry + "!/"); + ClassLoader loader = new URLClassLoader(new URL[]{url}); + + JarFile jarFile = new JarFile(entry); + Enumeration e = jarFile.entries(); + + while (e.hasMoreElements()) { + JarEntry je = e.nextElement(); + if (je.isDirectory() || !je.getName().endsWith(".class")) { + continue; + } + + // Are we done? + if (classFileCounter >= stopAt) { + break; + } + + String className = je.getName().substring(0, je.getName().length() - ".class".length()); + className = className.replace('/', '.'); + classFileCounter++; + + try { + // Load and initialize class + Class javaClass = Class.forName(className, true, loader); + + // Pre-load all classes in the constant pool. + try { + HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass); + ConstantPool constantPool = objectType.constantPool(); + for (int cpi = 1; cpi < constantPool.length(); cpi++) { + constantPool.loadReferencedType(cpi, Bytecodes.LDC); + } + } catch (Throwable t) { + // If something went wrong during pre-loading we just ignore it. + TTY.println("CompileTheWorld (%d) : Preloading failed for %s", classFileCounter, className); + } + + // Are we compiling this class? + if (classFileCounter >= startAt) { + TTY.println("CompileTheWorld (%d) : %s", classFileCounter, className); + + // Enqueue each constructor/method in the class for compilation. + for (Constructor constructor : javaClass.getDeclaredConstructors()) { + HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) graalRuntime.getRuntime().lookupJavaConstructor(constructor); + if (canBeCompiled(javaMethod, constructor.getModifiers())) { + compileMethod(javaMethod); + } + } + for (Method method : javaClass.getDeclaredMethods()) { + HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) graalRuntime.getRuntime().lookupJavaMethod(method); + if (canBeCompiled(javaMethod, method.getModifiers())) { + compileMethod(javaMethod); + } + } + } + } catch (Throwable t) { + TTY.println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className); + } + } + jarFile.close(); + } + + TTY.println(); + TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime); + } + + /** + * Helper method to schedule a method for compilation and gather some statistics. + */ + private void compileMethod(HotSpotResolvedJavaMethod method) { + try { + long start = System.currentTimeMillis(); + vmToCompiler.compileMethod(method, StructuredGraph.INVOCATION_ENTRY_BCI, true, 10); + compileTime += (System.currentTimeMillis() - start); + compiledMethodsCounter++; + method.reprofile(); // makes the method also not-entrant + } catch (Throwable t) { + // Catch everything and print a message + TTY.println("CompileTheWorld (%d) : Error compiling method: %s", classFileCounter, MetaUtil.format("%H.%n(%p):%r", method)); + t.printStackTrace(TTY.cachedOut); + } + } + + /** + * Helper method for CompileTheWorld to determine if a method should be compiled (Cf. + * CompilationPolicy::can_be_compiled). + * + * @return true if it can be compiled, false otherwise + */ + private static boolean canBeCompiled(HotSpotResolvedJavaMethod javaMethod, int modifiers) { + if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + return false; + } + // This number is from HotSpot: + final int hugeMethodLimit = 8000; + if (javaMethod.getCodeSize() > hugeMethodLimit) { + return false; + } + // Skip @Snippets for now + if (javaMethod.getAnnotation(Snippet.class) != null) { + return false; + } + return true; + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Sat Apr 20 12:23:29 2013 +0200 @@ -67,7 +67,7 @@ } private static Site[] getSortedSites(CompilationResult target) { - List[] lists = new List[]{target.getSafepoints(), target.getDataReferences(), target.getMarks()}; + List[] lists = new List[]{target.getInfopoints(), target.getDataReferences(), target.getMarks()}; int count = 0; for (List list : lists) { count += list.size(); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Sat Apr 20 12:23:29 2013 +0200 @@ -139,6 +139,19 @@ compilerToVm.initializeConfiguration(config); config.check(); + // Set some global options: + if (config.compileTheWorld) { + GraalOptions.CompileTheWorld = CompileTheWorld.SUN_BOOT_CLASS_PATH; + } + if (config.compileTheWorldStartAt != 1) { + GraalOptions.CompileTheWorldStartAt = config.compileTheWorldStartAt; + } + if (config.compileTheWorldStopAt != Integer.MAX_VALUE) { + GraalOptions.CompileTheWorldStopAt = config.compileTheWorldStopAt; + } + GraalOptions.HotSpotPrintCompilation = config.printCompilation; + GraalOptions.HotSpotPrintInlining = config.printInlining; + if (Boolean.valueOf(System.getProperty("graal.printconfig"))) { printConfig(config); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,12 +25,15 @@ import java.lang.reflect.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.*; /** - * Filters certain method substitutions based on whether there is underlying hardware support for them. + * Filters certain method substitutions based on whether there is underlying hardware support for + * them. */ public class HotSpotReplacementsImpl extends ReplacementsImpl { @@ -42,22 +45,42 @@ } @Override - protected void registerMethodSubstitution(Member originalMethod, Method substituteMethod) { + protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) { if (substituteMethod.getDeclaringClass() == IntegerSubstitutions.class || substituteMethod.getDeclaringClass() == LongSubstitutions.class) { if (substituteMethod.getName().equals("bitCount")) { if (!config.usePopCountInstruction) { - return; + return null; } } } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class || substituteMethod.getDeclaringClass() == CipherBlockChainingSubstitutions.class) { if (!config.useAESIntrinsics) { - return; + return null; } assert config.aescryptEncryptBlockStub != 0L; assert config.aescryptDecryptBlockStub != 0L; assert config.cipherBlockChainingEncryptAESCryptStub != 0L; assert config.cipherBlockChainingDecryptAESCryptStub != 0L; } - super.registerMethodSubstitution(originalMethod, substituteMethod); + return super.registerMethodSubstitution(originalMethod, substituteMethod); + } + + @Override + public Class getMacroSubstitution(ResolvedJavaMethod method) { + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; + int intrinsicId = hsMethod.intrinsicId(); + if (intrinsicId != 0) { + if (intrinsicId == config.vmIntrinsicInvokeBasic) { + return MethodHandleInvokeBasicNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { + return MethodHandleLinkToInterfaceNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { + return MethodHandleLinkToSpecialNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { + return MethodHandleLinkToStaticNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { + return MethodHandleLinkToVirtualNode.class; + } + } + return super.getMacroSubstitution(method); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Sat Apr 20 12:23:29 2013 +0200 @@ -90,4 +90,9 @@ address = stub.getAddress(backend); } } + + @Override + public boolean preservesRegisters() { + return stub == null; + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -37,6 +37,11 @@ public int codeEntryAlignment; public boolean verifyOops; public boolean ciTime; + public boolean compileTheWorld; + public int compileTheWorldStartAt; + public int compileTheWorldStopAt; + public boolean printCompilation; + public boolean printInlining; public boolean useFastLocking; public boolean useTLAB; public boolean useBiasedLocking; @@ -44,6 +49,10 @@ public boolean useAESIntrinsics; public boolean useG1GC; + // CPU capabilities + public int useSSE; + public int useAVX; + // offsets, ... public int stackShadowPages; @@ -185,6 +194,11 @@ public int methodAccessFlagsOffset; /** + * Offset of _intrinsic_id in a metaspace Method object. + */ + public int methodIntrinsicIdOffset; + + /** * Offset of _max_locals in a metaspace Method object. */ public int methodMaxLocalsOffset; @@ -376,6 +390,12 @@ public int deoptActionMakeNotEntrant; public int deoptActionMakeNotCompilable; + public int vmIntrinsicInvokeBasic; + public int vmIntrinsicLinkToVirtual; + public int vmIntrinsicLinkToStatic; + public int vmIntrinsicLinkToSpecial; + public int vmIntrinsicLinkToInterface; + public void check() { assert codeEntryAlignment > 0; assert stackShadowPages > 0; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Sat Apr 20 12:23:29 2013 +0200 @@ -128,6 +128,8 @@ */ JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve); + int constantPoolLength(HotSpotResolvedObjectType pool); + Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi); JavaMethod lookupMethodInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); @@ -138,6 +140,8 @@ void lookupReferencedTypeInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + // Must be kept in sync with enum in graalEnv.hpp public enum CodeInstallResult { OK, DEPENDENCIES_FAILED, CACHE_FULL @@ -165,6 +169,8 @@ HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedObjectType klass); + boolean hasFinalizableSubclass(HotSpotResolvedObjectType klass); + /** * Gets the compiled code size for a method. * @@ -199,9 +205,9 @@ StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); - Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3); + Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException; - Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args); + Object executeCompiledMethodVarargs(Object[] args, long nativeMethod) throws InvalidInstalledCodeException; int getVtableEntryOffset(long metaspaceMethod); @@ -221,4 +227,8 @@ * @param metaspaceMethod the metaspace Method object */ void reprofile(long metaspaceMethod); + + void invalidateInstalledCode(long nativeMethod); + + boolean isInstalledCodeValid(long nativeMethod); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Sat Apr 20 12:23:29 2013 +0200 @@ -79,6 +79,9 @@ public native JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve); @Override + public native int constantPoolLength(HotSpotResolvedObjectType pool); + + @Override public native Object lookupConstantInPool(HotSpotResolvedObjectType pool, int cpi); @Override @@ -103,6 +106,9 @@ public native boolean isTypeInitialized(HotSpotResolvedObjectType klass); @Override + public native boolean hasFinalizableSubclass(HotSpotResolvedObjectType klass); + + @Override public native void initializeType(HotSpotResolvedObjectType klass); @Override @@ -133,10 +139,7 @@ public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); @Override - public native Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3); - - @Override - public native Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args); + public native Object executeCompiledMethodVarargs(Object[] args, long nativeMethod); @Override public native int getVtableEntryOffset(long metaspaceMethod); @@ -158,4 +161,27 @@ @Override public native void reprofile(long metaspaceMethod); + + @Override + public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + + @Override + public native void invalidateInstalledCode(long nativeMethod); + + @Override + public native boolean isInstalledCodeValid(long nativeMethod); + + @Override + public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException { + return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod); + } + + /** + * Direct call to the given nativeMethod with three object arguments and an object return value. + * This method does not have an implementation on the C++ side, but its entry points (from + * interpreter and from compiled code) are directly pointing to a manually generated assembly + * stub that does the necessary argument shuffling and a tail call via an indirect jump to the + * verified entry point of the given native method. + */ + private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/MetricRateInPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/MetricRateInPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/MetricRateInPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.bridge; +import java.io.*; import java.util.concurrent.*; import com.oracle.graal.debug.*; @@ -65,10 +66,10 @@ return (int) (v / t); } - public void printAll(String label) { + public void printAll(String label, PrintStream stream) { MetricRateInPhase rs = this; while (rs != null) { - System.out.println(label + "@" + rs.phase + ": " + rs.rate()); + stream.println(label + "@" + rs.phase + ": " + rs.rate()); rs = rs.previous; } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Sat Apr 20 12:23:29 2013 +0200 @@ -34,8 +34,23 @@ */ public interface VMToCompiler { + /** + * Compiles a method to machine code. This method is called from the VM + * (VMToCompiler::compileMethod). + * + * @return true if the method is in the queue (either added to the queue or already in the + * queue) + */ boolean compileMethod(long metaspaceMethod, HotSpotResolvedObjectType holder, int entryBCI, boolean blocking, int priority) throws Throwable; + /** + * Compiles a method to machine code. + * + * @return true if the method is in the queue (either added to the queue or already in the + * queue) + */ + boolean compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, boolean blocking, int priority) throws Throwable; + void shutdownCompiler() throws Throwable; void startCompiler() throws Throwable; @@ -61,7 +76,6 @@ * @param name the {@linkplain JavaType#getName() name} of the type * @param simpleName a simple, unqualified name for the type * @param javaMirror the {@link Class} mirror - * @param hasFinalizableSubclass specifies if the type has a finalizable subtype * @param sizeOrSpecies the size of an instance of the type, or * {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} or * {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} @@ -69,7 +83,7 @@ * instantiated by this call in the case of another thread racing to create the same * type */ - ResolvedJavaType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, boolean hasFinalizableSubclass, int sizeOrSpecies); + ResolvedJavaType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, int sizeOrSpecies); Constant createConstant(Kind kind, long value); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Sat Apr 20 12:23:29 2013 +0200 @@ -37,6 +37,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.meta.*; @@ -152,10 +153,18 @@ @Override public void run() { - for (ReplacementsProvider provider : ServiceLoader.loadInstalled(ReplacementsProvider.class)) { - provider.registerReplacements(replacements); + ServiceLoader serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class); + for (ReplacementsProvider provider : serviceLoader) { + provider.registerReplacements(runtime, replacements, runtime.getTarget()); } runtime.registerReplacements(replacements); + if (GraalOptions.BootstrapReplacements) { + for (ResolvedJavaMethod method : replacements.getAllReplacements()) { + replacements.getMacroSubstitution(method); + replacements.getMethodSubstitution(method); + replacements.getSnippet(method); + } + } } }); @@ -197,9 +206,22 @@ t.start(); } - if (GraalOptions.BenchmarkDynamicCounters) { - System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, " starting =====", " PASSED in ", "\n"))); - System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, "Iteration ~ (~s) begins: ", "Iteration ~ (~s) ends: ", "\n"))); + if (GraalOptions.BenchmarkDynamicCounters != null) { + String[] arguments = GraalOptions.BenchmarkDynamicCounters.split(","); + if (arguments.length == 0 || (arguments.length % 3) != 0) { + throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)"); + } + for (int i = 0; i < arguments.length; i += 3) { + if (arguments[i].equals("err")) { + System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, arguments[i + 1], arguments[i + 2]))); + } else if (arguments[i].equals("out")) { + System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, arguments[i + 1], arguments[i + 2]))); + } else { + throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: err|out"); + } + // dacapo: "err, starting =====, PASSED in " + // specjvm2008: "out,Iteration ~ (~s) begins: ,Iteration ~ (~s) ends: " + } DynamicCounterNode.excludedClassPrefix = "Lcom/oracle/graal/"; DynamicCounterNode.enabled = true; } @@ -214,8 +236,8 @@ private long startTime; private boolean waitingForEnd; - private BenchmarkCountersOutputStream(PrintStream delegate, String... patterns) { - super(delegate, patterns); + private BenchmarkCountersOutputStream(PrintStream delegate, String start, String end) { + super(delegate, new String[]{start, end, "\n"}); } @Override @@ -371,6 +393,10 @@ System.gc(); phaseTransition("bootstrap2"); + if (GraalOptions.CompileTheWorld != null) { + new CompileTheWorld().compile(); + System.exit(0); + } } private MetricRateInPhase parsedBytecodesPerSecond; @@ -438,8 +464,8 @@ phaseTransition("final"); if (graalRuntime.getConfig().ciTime) { - parsedBytecodesPerSecond.printAll("ParsedBytecodesPerSecond"); - inlinedBytecodesPerSecond.printAll("InlinedBytecodesPerSecond"); + parsedBytecodesPerSecond.printAll("ParsedBytecodesPerSecond", System.out); + inlinedBytecodesPerSecond.printAll("InlinedBytecodesPerSecond", System.out); } SnippetCounter.printGroups(TTY.out().out()); @@ -657,8 +683,8 @@ } @Override - public HotSpotResolvedObjectType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, boolean hasFinalizableSubclass, int sizeOrSpecies) { - HotSpotResolvedObjectType type = new HotSpotResolvedObjectType(metaspaceKlass, name, simpleName, javaMirror, hasFinalizableSubclass, sizeOrSpecies); + public HotSpotResolvedObjectType createResolvedJavaType(long metaspaceKlass, String name, String simpleName, Class javaMirror, int sizeOrSpecies) { + HotSpotResolvedObjectType type = new HotSpotResolvedObjectType(metaspaceKlass, name, simpleName, javaMirror, sizeOrSpecies); long offset = HotSpotGraalRuntime.getInstance().getConfig().graalMirrorInClassOffset; if (!unsafe.compareAndSwapObject(javaMirror, offset, null, type)) { @@ -713,6 +739,11 @@ if (onStackReplacement) { phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase()); } + phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase()); + if (GraalOptions.VerifyPhases) { + phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierVerificationPhase()); + + } return phasePlan; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,6 +27,8 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; +import com.oracle.graal.debug.*; + /** * A java.lang.reflect proxy that hierarchically logs all method invocations along with their * parameters and return values. @@ -41,7 +43,7 @@ public CountingProxy(T delegate) { assert ENABLED; - System.out.println("Counting proxy for " + delegate.getClass().getSimpleName() + " created"); + TTY.println("Counting proxy for " + delegate.getClass().getSimpleName() + " created"); this.delegate = delegate; proxies.add(this); } @@ -92,6 +94,7 @@ } } + // CheckStyle: stop system..print check protected void print() { long sum = 0; for (Map.Entry entry : calls.entrySet()) { @@ -102,4 +105,5 @@ } System.out.println(delegate.getClass().getSimpleName() + " calls: " + sum); } + // CheckStyle: resume system..print check } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java Sat Apr 20 12:23:29 2013 +0200 @@ -26,6 +26,8 @@ import java.lang.reflect.*; import java.util.*; +import com.oracle.graal.debug.*; + /** * Scoped logging class used to display the call hierarchy of VMToCompiler/CompilerToVM calls. */ @@ -74,7 +76,7 @@ if (ENABLED) { log(message); } else { - System.out.println(message); + TTY.println(message); } if (out != null) { out.println(message); @@ -87,11 +89,11 @@ Logger logger = loggerTL.get(); for (String line : message.split("\n")) { if (logger.open) { - System.out.println("..."); + TTY.println("..."); logger.open = false; } - System.out.print(space(logger.level)); - System.out.println(line); + TTY.print(space(logger.level)); + TTY.println(line); } } } @@ -100,11 +102,11 @@ if (ENABLED) { Logger logger = loggerTL.get(); if (logger.open) { - System.out.println("..."); + TTY.println("..."); logger.open = false; } - System.out.print(space(logger.level)); - System.out.print(message); + TTY.print(space(logger.level)); + TTY.print(message); logger.openStack.push(logger.open); logger.open = true; logger.level++; @@ -116,9 +118,9 @@ Logger logger = loggerTL.get(); logger.level--; if (logger.open) { - System.out.println(message); + TTY.println(message); } else { - System.out.println(space(logger.level) + "..." + message); + TTY.println(space(logger.level) + "..." + message); } logger.open = logger.openStack.pop(); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; +import com.oracle.graal.bytecode.*; import com.oracle.graal.hotspot.*; /** @@ -39,6 +40,11 @@ } @Override + public int length() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().constantPoolLength(type); + } + + @Override public Object lookupConstant(int cpi) { assert cpi != 0; Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupConstantInPool(type, cpi); @@ -51,6 +57,12 @@ } @Override + public Object lookupAppendix(int cpi, int opcode) { + assert Bytecodes.isInvoke(opcode); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi, (byte) opcode); + } + + @Override public JavaMethod lookupMethod(int cpi, int opcode) { return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupMethodInPool(type, cpi, (byte) opcode); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Sat Apr 20 12:23:29 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; /** @@ -39,11 +40,13 @@ private final HotSpotResolvedJavaMethod method; private final boolean isDefault; + private final Graph graph; long nmethod; long start; - public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) { + public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) { this.method = method; + this.graph = graph; this.isDefault = isDefault; } @@ -51,10 +54,14 @@ return isDefault; } - public long getnmethod() { + public long getMethodAddress() { return nmethod; } + public Graph getGraph() { + return graph; + } + @Override public ResolvedJavaMethod getMethod() { return method; @@ -62,7 +69,12 @@ @Override public boolean isValid() { - return nmethod != 0; + return HotSpotGraalRuntime.getInstance().getCompilerToVM().isInstalledCodeValid(nmethod); + } + + @Override + public void invalidate() { + HotSpotGraalRuntime.getInstance().getCompilerToVM().invalidateInstalledCode(nmethod); } @Override @@ -71,12 +83,12 @@ } @Override - public Object execute(Object arg1, Object arg2, Object arg3) { + public Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException { assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3; assert method.getSignature().getParameterKind(0) == Kind.Object; assert method.getSignature().getParameterKind(1) == Kind.Object; assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object; - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(method.metaspaceMethod, nmethod, arg1, arg2, arg3); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod); } private boolean checkArgs(Object... args) { @@ -94,9 +106,9 @@ } @Override - public Object executeVarargs(Object... args) { + public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { assert checkArgs(args); - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(method.metaspaceMethod, nmethod, args); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(args, nmethod); } @Override @@ -108,8 +120,4 @@ public byte[] getCode() { return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod); } - - public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(metaspaceMethod, nmethod, arg1, arg2, arg3); - } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; + import com.oracle.graal.api.meta.*; /** @@ -51,6 +53,6 @@ @Override public String toString() { - return "HotSpotMethod<" + holder.getName() + ". " + name + ", unresolved>"; + return format("HotSpotMethod<%H.%n(%p), unresolved>", this); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; + import java.lang.annotation.*; import java.lang.reflect.*; @@ -150,7 +152,7 @@ @Override public String toString() { - return "HotSpotField<" + MetaUtil.format("%h.%n", this) + ":" + offset + ">"; + return format("HotSpotField<%H.%n %t:", this) + offset + ">"; } @Override diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.graph.FieldIntrospection.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; @@ -186,7 +187,7 @@ @Override public String toString() { - return "HotSpotMethod<" + MetaUtil.format("%h.%n", this) + ">"; + return format("HotSpotMethod<%H.%n(%p)>", this); } public int getCompiledCodeSize() { @@ -361,4 +362,51 @@ } return speculationLog; } + + public int intrinsicId() { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + return unsafe.getByte(metaspaceMethod + config.methodIntrinsicIdOffset) & 0xff; + } + + @Override + public Constant invoke(Constant receiver, Constant[] arguments) { + assert !isConstructor(); + Method javaMethod = toJava(); + javaMethod.setAccessible(true); + + Object[] objArguments = new Object[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + objArguments[i] = arguments[i].asBoxedValue(); + } + Object objReceiver = receiver != null ? receiver.asObject() : null; + + try { + Object objResult = javaMethod.invoke(objReceiver, objArguments); + return javaMethod.getReturnType() == void.class ? null : Constant.forBoxed(getSignature().getReturnKind(), objResult); + + } catch (IllegalAccessException | InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + } + + @Override + public Constant newInstance(Constant[] arguments) { + assert isConstructor(); + Constructor javaConstructor = toJavaConstructor(); + javaConstructor.setAccessible(true); + + Object[] objArguments = new Object[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + objArguments[i] = arguments[i].asBoxedValue(); + } + + try { + Object objResult = javaConstructor.newInstance(objArguments); + assert objResult != null; + return Constant.forObject(objResult); + + } catch (IllegalAccessException | InvocationTargetException | InstantiationException ex) { + throw new IllegalArgumentException(ex); + } + } } diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.meta.MetaUtil.*; -import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.graph.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static java.lang.reflect.Modifier.*; @@ -63,7 +63,6 @@ private final Class javaMirror; // this could be read directly from 'metaspaceKlass'... private final String simpleName; - private final boolean hasFinalizableSubclass; /** * The instance size (in bytes) for an instance type, @@ -120,22 +119,19 @@ } /** - * @param hasFinalizableSubclass * @param sizeOrSpecies the size of an instance of the type, or * {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} or * {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} */ - public HotSpotResolvedObjectType(long metaspaceKlass, String name, String simpleName, Class javaMirror, boolean hasFinalizableSubclass, int sizeOrSpecies) { + public HotSpotResolvedObjectType(long metaspaceKlass, String name, String simpleName, Class javaMirror, int sizeOrSpecies) { super(name); this.metaspaceKlass = metaspaceKlass; this.javaMirror = javaMirror; this.simpleName = simpleName; - this.hasFinalizableSubclass = hasFinalizableSubclass; this.sizeOrSpecies = sizeOrSpecies; assert name.charAt(0) != '[' || sizeOrSpecies == ARRAY_SPECIES_VALUE : name + " " + Long.toHexString(sizeOrSpecies); assert javaMirror.isArray() == isArray(); assert javaMirror.isInterface() == isInterface(); - // System.out.println("0x" + Long.toHexString(metaspaceKlass) + ": " + name); } @Override @@ -261,7 +257,8 @@ @Override public boolean hasFinalizableSubclass() { - return hasFinalizableSubclass; + assert !isArray(); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().hasFinalizableSubclass(this); } @Override @@ -520,4 +517,31 @@ final Class encl = mirror().getEnclosingClass(); return encl == null ? null : fromClass(encl); } + + @Override + public ResolvedJavaMethod[] getDeclaredConstructors() { + Constructor[] constructors = javaMirror.getDeclaredConstructors(); + ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length]; + for (int i = 0; i < constructors.length; i++) { + result[i] = HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaConstructor(constructors[i]); + assert result[i].isConstructor(); + } + return result; + } + + @Override + public ResolvedJavaMethod[] getDeclaredMethods() { + Method[] methods = javaMirror.getDeclaredMethods(); + ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length]; + for (int i = 0; i < methods.length; i++) { + result[i] = HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaMethod(methods[i]); + assert !result[i].isConstructor(); + } + return result; + } + + @Override + public Constant newArray(int length) { + return Constant.forObject(Array.newInstance(javaMirror, length)); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Sat Apr 20 12:23:29 2013 +0200 @@ -210,4 +210,19 @@ public ResolvedJavaType getEnclosingType() { return null; } + + @Override + public ResolvedJavaMethod[] getDeclaredConstructors() { + return new ResolvedJavaMethod[0]; + } + + @Override + public ResolvedJavaMethod[] getDeclaredMethods() { + return new ResolvedJavaMethod[0]; + } + + @Override + public Constant newArray(int length) { + return Constant.forObject(Array.newInstance(javaMirror, length)); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Sat Apr 20 12:23:29 2013 +0200 @@ -48,7 +48,7 @@ import com.oracle.graal.api.code.CompilationResult.Call; import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.CompilationResult.Mark; -import com.oracle.graal.api.code.CompilationResult.Safepoint; +import com.oracle.graal.api.code.CompilationResult.Infopoint; import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; @@ -64,6 +64,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; @@ -89,6 +90,7 @@ private NewObjectSnippets.Templates newObjectSnippets; private MonitorSnippets.Templates monitorSnippets; private WriteBarrierSnippets.Templates writeBarrierSnippets; + private BoxingSnippets.Templates boxingSnippets; private LoadExceptionObjectSnippets.Templates exceptionObjectSnippets; private final Map runtimeCalls = new HashMap<>(); @@ -223,25 +225,25 @@ /* arg0: index */ javaCallingConvention(Kind.Int)); addRuntimeCall(JAVA_TIME_MILLIS, config.javaTimeMillisStub, - /* temps */ null, + /* temps */ this.regConfig.getCallerSaveRegisters(), /* ret */ ret(Kind.Long)); addRuntimeCall(JAVA_TIME_NANOS, config.javaTimeNanosStub, - /* temps */ null, + /* temps */ this.regConfig.getCallerSaveRegisters(), /* ret */ ret(Kind.Long)); addRuntimeCall(ARITHMETIC_SIN, config.arithmeticSinStub, - /* temps */ null, + /* temps */ this.regConfig.getCallerSaveRegisters(), /* ret */ ret(Kind.Double), /* arg0: index */ javaCallingConvention(Kind.Double)); addRuntimeCall(ARITHMETIC_COS, config.arithmeticCosStub, - /* temps */ null, + /* temps */ this.regConfig.getCallerSaveRegisters(), /* ret */ ret(Kind.Double), /* arg0: index */ javaCallingConvention(Kind.Double)); addRuntimeCall(ARITHMETIC_TAN, config.arithmeticTanStub, - /* temps */ null, + /* temps */ this.regConfig.getCallerSaveRegisters(), /* ret */ ret(Kind.Double), /* arg0: index */ javaCallingConvention(Kind.Double)); @@ -277,7 +279,7 @@ * @param ret where the call returns its result * @param args where arguments are passed to the call */ - protected void addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, Value ret, Value... args) { + protected RuntimeCallTarget addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, Value ret, Value... args) { Value[] temps = tempRegs == null || tempRegs.length == 0 ? Value.NONE : new Value[tempRegs.length]; for (int i = 0; i < temps.length; i++) { temps[i] = tempRegs[i].asValue(); @@ -290,6 +292,7 @@ } HotSpotRuntimeCallTarget runtimeCall = new HotSpotRuntimeCallTarget(descriptor, address, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM()); runtimeCalls.put(descriptor, runtimeCall); + return runtimeCall; } private boolean checkAssignable(Class spec, Value value) { @@ -325,18 +328,13 @@ replacements.registerSubstitutions(AESCryptSubstitutions.class); replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class); } - if (GraalOptions.IntrinsifyArrayCopy) { - replacements.registerSnippets(ArrayCopySnippets.class); - } - if (GraalOptions.IntrinsifyObjectClone) { - replacements.registerSnippets(ObjectCloneSnippets.class); - } checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget()); instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget()); newObjectSnippets = new NewObjectSnippets.Templates(this, replacements, graalRuntime.getTarget(), config.useTLAB); monitorSnippets = new MonitorSnippets.Templates(this, replacements, graalRuntime.getTarget(), config.useFastLocking); writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, replacements, graalRuntime.getTarget()); + boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget()); exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget()); registerStub(new NewInstanceStub(this, replacements, graalRuntime.getTarget(), runtimeCalls.get(NEW_INSTANCE))); @@ -373,18 +371,18 @@ addExceptionHandlersComment(compResult, hcf); Register fp = regConfig.getFrameRegister(); RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0); - for (Safepoint safepoint : compResult.getSafepoints()) { - if (safepoint instanceof Call) { - Call call = (Call) safepoint; + for (Infopoint infopoint : compResult.getInfopoints()) { + if (infopoint instanceof Call) { + Call call = (Call) infopoint; if (call.debugInfo != null) { hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString()); } addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}"); } else { - if (safepoint.debugInfo != null) { - hcf.addComment(safepoint.pcOffset, CodeUtil.append(new StringBuilder(100), safepoint.debugInfo, slotFormatter).toString()); + if (infopoint.debugInfo != null) { + hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString()); } - addOperandComment(hcf, safepoint.pcOffset, "{safepoint}"); + addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}"); } } for (DataPatch site : compResult.getDataReferences()) { @@ -504,15 +502,15 @@ } else if (n instanceof Invoke) { Invoke invoke = (Invoke) n; if (invoke.callTarget() instanceof MethodCallTargetNode) { - MethodCallTargetNode callTarget = invoke.methodCallTarget(); + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); NodeInputList parameters = callTarget.arguments(); ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) { - invoke.node().dependencies().add(tool.createNullCheckGuard(receiver)); + invoke.asNode().dependencies().add(tool.createNullCheckGuard(receiver)); } JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); - AbstractCallTargetNode loweredCallTarget = null; + LoweredCallTargetNode loweredCallTarget = null; if (callTarget.invokeKind() == InvokeKind.Virtual && GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || invoke.isPolymorphic())) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); @@ -528,10 +526,10 @@ ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), StampFactory.forKind(wordKind()))); - loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), + loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall)); - graph.addBeforeFixed(invoke.node(), hub); + graph.addBeforeFixed(invoke.asNode(), hub); graph.addAfterFixed(hub, metaspaceMethod); graph.addAfterFixed(metaspaceMethod, compiledEntry); } @@ -539,7 +537,7 @@ } if (loweredCallTarget == null) { - loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, + loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, callTarget.invokeKind())); } callTarget.replaceAndDelete(loweredCallTarget); @@ -548,16 +546,11 @@ LoadFieldNode loadField = (LoadFieldNode) n; HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object(); - LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph); assert loadField.kind() != Kind.Illegal; ReadNode memoryRead = graph.add(new ReadNode(object, LocationNode.create(field, field.getKind(), field.offset(), graph), loadField.stamp())); memoryRead.dependencies().add(tool.createNullCheckGuard(object)); graph.replaceFixedWithFixed(loadField, memoryRead); - if (config.useG1GC && field.getKind() == Kind.Object && field.getDeclaringClass().getName().toString().equals("Ljava/lang/ref/Reference;") && field.getName().equals("referent")) { - WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(memoryRead.object(), memoryRead, location, false)); - graph.addAfterFixed(memoryRead, writeBarrierPre); - } if (loadField.isVolatile()) { MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); @@ -570,27 +563,14 @@ HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object(); LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph); - WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location)); + WriteBarrierType barrierType = getFieldStoreBarrierType(storeField); + WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location, barrierType)); memoryWrite.dependencies().add(tool.createNullCheckGuard(object)); memoryWrite.setStateAfter(storeField.stateAfter()); graph.replaceFixedWithFixed(storeField, memoryWrite); FixedWithNextNode last = memoryWrite; FixedWithNextNode first = memoryWrite; - if (field.getKind() == Kind.Object && !memoryWrite.value().objectStamp().alwaysNull()) { - if (config.useG1GC) { - WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(memoryWrite.object(), null, memoryWrite.location(), true)); - WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(memoryWrite.object(), memoryWrite.value(), memoryWrite.location(), false)); - graph.addBeforeFixed(memoryWrite, writeBarrierPre); - graph.addAfterFixed(memoryWrite, writeBarrierPost); - first = writeBarrierPre; - last = writeBarrierPost; - } else { - FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object())); - graph.addAfterFixed(memoryWrite, writeBarrier); - last = writeBarrier; - } - } if (storeField.isVolatile()) { MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); graph.addBeforeFixed(first, preMembar); @@ -600,31 +580,9 @@ } else if (n instanceof CompareAndSwapNode) { // Separate out GC barrier semantics CompareAndSwapNode cas = (CompareAndSwapNode) n; - ValueNode expected = cas.expected(); LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); - if (expected.kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) { - ResolvedJavaType type = cas.object().objectStamp().type(); - if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) { - // Use a field write barrier since it's not an array store - if (config.useG1GC) { - WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(cas.object(), null, location, true)); - WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(cas.object(), cas.newValue(), location, false)); - graph.addBeforeFixed(cas, writeBarrierPre); - graph.addAfterFixed(cas, writeBarrierPost); - } else { - graph.addAfterFixed(cas, graph.add(new FieldWriteBarrier(cas.object()))); - } - } else { - // This may be an array store so use an array write barrier - if (config.useG1GC) { - WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(cas.object(), null, location, true)); - graph.addBeforeFixed(cas, writeBarrierPre); - graph.addAfterFixed(cas, graph.add(new WriteBarrierPost(cas.object(), cas.newValue(), location, true))); - } else { - graph.addAfterFixed(cas, graph.add(new ArrayWriteBarrier(cas.object(), location))); - } - } - } + cas.setLocation(location); + cas.setWriteBarrierType(getCompareAndSwapBarrier(cas)); } else if (n instanceof LoadIndexedNode) { LoadIndexedNode loadIndexed = (LoadIndexedNode) n; ValueNode boundsCheck = createBoundsCheck(loadIndexed, tool); @@ -660,21 +618,12 @@ value = checkcast; } } - WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation)); + WriteBarrierType barrierType = getArrayStoreBarrierType(storeIndexed); + WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType)); memoryWrite.dependencies().add(boundsCheck); memoryWrite.setStateAfter(storeIndexed.stateAfter()); graph.replaceFixedWithFixed(storeIndexed, memoryWrite); - if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) { - if (config.useG1GC) { - WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(array, null, arrayLocation, true)); - graph.addBeforeFixed(memoryWrite, writeBarrierPre); - WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(array, value, arrayLocation, true)); - graph.addAfterFixed(memoryWrite, writeBarrierPost); - } else { - graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation))); - } - } } else if (n instanceof UnsafeLoadNode) { UnsafeLoadNode load = (UnsafeLoadNode) n; assert load.kind() != Kind.Illegal; @@ -688,32 +637,11 @@ UnsafeStoreNode store = (UnsafeStoreNode) n; IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1); ValueNode object = store.object(); - WriteNode write = graph.add(new WriteNode(object, store.value(), location)); + WriteBarrierType barrierType = getUnsafeStoreBarrierType(store); + WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType)); write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); - if (write.value().kind() == Kind.Object && !write.value().objectStamp().alwaysNull()) { - ResolvedJavaType type = object.objectStamp().type(); - // WriteBarrier writeBarrier; - if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) { - // Use a field write barrier since it's not an array store - if (config.useG1GC) { - WriteBarrierPre writeBarrierPre = new WriteBarrierPre(object, null, location, true); - graph.addBeforeFixed(write, graph.add(writeBarrierPre)); - graph.addAfterFixed(write, graph.add(new WriteBarrierPost(object, write.value(), location, false))); - } else { - graph.addAfterFixed(write, graph.add(new FieldWriteBarrier(object))); - } - } else { - // This may be an array store so use an array write barrier - if (config.useG1GC) { - WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(object, null, location, true)); - graph.addBeforeFixed(write, writeBarrierPre); - graph.addAfterFixed(write, graph.add(new WriteBarrierPost(object, write.value(), location, true))); - } else { - graph.addAfterFixed(write, graph.add(new ArrayWriteBarrier(object, location))); - } - } - } + } else if (n instanceof LoadHubNode) { LoadHubNode loadHub = (LoadHubNode) n; assert loadHub.kind() == wordKind; @@ -744,14 +672,10 @@ monitorSnippets.lower((MonitorEnterNode) n, tool); } else if (n instanceof MonitorExitNode) { monitorSnippets.lower((MonitorExitNode) n, tool); - } else if (n instanceof FieldWriteBarrier) { - writeBarrierSnippets.lower((FieldWriteBarrier) n, tool); - } else if (n instanceof ArrayWriteBarrier) { - writeBarrierSnippets.lower((ArrayWriteBarrier) n, tool); - } else if (n instanceof WriteBarrierPre) { - writeBarrierSnippets.lower((WriteBarrierPre) n, tool); - } else if (n instanceof WriteBarrierPost) { - writeBarrierSnippets.lower((WriteBarrierPost) n, tool); + } else if (n instanceof SerialWriteBarrier) { + writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); + } else if (n instanceof SerialArrayRangeWriteBarrier) { + writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool); } else if (n instanceof TLABAllocateNode) { newObjectSnippets.lower((TLABAllocateNode) n, tool); } else if (n instanceof InitializeObjectNode) { @@ -765,14 +689,60 @@ } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. - } else if (n instanceof UnwindNode) { + } else if (n instanceof UnwindNode || n instanceof DeoptimizeNode) { // Nothing to do, using direct LIR lowering for these nodes. + } else if (n instanceof BoxNode) { + boxingSnippets.lower((BoxNode) n); + } else if (n instanceof UnboxNode) { + boxingSnippets.lower((UnboxNode) n); } else { assert false : "Node implementing Lowerable not handled: " + n; throw GraalInternalError.shouldNotReachHere(); } } + private static WriteBarrierType getFieldStoreBarrierType(StoreFieldNode storeField) { + WriteBarrierType barrierType = WriteBarrierType.NONE; + if (storeField.field().getKind() == Kind.Object && !storeField.value().objectStamp().alwaysNull()) { + barrierType = WriteBarrierType.IMPRECISE; + } + return barrierType; + } + + private static WriteBarrierType getArrayStoreBarrierType(StoreIndexedNode store) { + WriteBarrierType barrierType = WriteBarrierType.NONE; + if (store.elementKind() == Kind.Object && !store.value().objectStamp().alwaysNull()) { + barrierType = WriteBarrierType.PRECISE; + } + return barrierType; + } + + private static WriteBarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) { + WriteBarrierType barrierType = WriteBarrierType.NONE; + if (store.value().kind() == Kind.Object && !store.value().objectStamp().alwaysNull()) { + ResolvedJavaType type = store.object().objectStamp().type(); + if (type != null && type.isArray()) { + barrierType = WriteBarrierType.PRECISE; + } else { + barrierType = WriteBarrierType.IMPRECISE; + } + } + return barrierType; + } + + private static WriteBarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) { + WriteBarrierType barrierType = WriteBarrierType.NONE; + if (cas.expected().kind() == Kind.Object && !cas.newValue().objectStamp().alwaysNull()) { + ResolvedJavaType type = cas.object().objectStamp().type(); + if (type != null && type.isArray()) { + barrierType = WriteBarrierType.PRECISE; + } else { + barrierType = WriteBarrierType.IMPRECISE; + } + } + return barrierType; + } + private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { int scale = this.graalRuntime.getTarget().sizeInBytes(elementKind); return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale); @@ -828,16 +798,21 @@ return graalRuntime.getCompilerToVM().getJavaField(reflectionField); } - public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) { - HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, true); + public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, Graph graph, int entryBCI, CompilationResult compResult) { + HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, graph, true); graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), installedCode, method.getSpeculationLog()); return installedCode; } @Override public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + return addMethod(method, compResult, null); + } + + @Override + public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) { HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; - HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, false); + HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, graph, false); CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, null); if (result != CodeInstallResult.OK) { return null; @@ -956,7 +931,7 @@ public String disassemble(InstalledCode code) { if (code.isValid()) { - long nmethod = ((HotSpotInstalledCode) code).nmethod; + long nmethod = ((HotSpotInstalledCode) code).getMethodAddress(); return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod); } return null; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; + import com.oracle.graal.api.meta.*; /** @@ -60,6 +62,6 @@ */ @Override public String toString() { - return MetaUtil.format("%H.%n [unresolved]", this); + return format("HotSpotField<%H.%n %t, unresolved>", this); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -public final class ArrayWriteBarrier extends FixedWithNextNode implements Lowerable { - - @Input private ValueNode object; - @Input private LocationNode location; - - public ValueNode getObject() { - return object; - } - - public LocationNode getLocation() { - return location; - } - - public ArrayWriteBarrier(ValueNode object, LocationNode location) { - super(StampFactory.forVoid()); - this.object = object; - this.location = location; - } - - public void lower(LoweringTool generator) { - generator.getRuntime().lower(this, generator); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -70,7 +70,6 @@ @Override public void generate(LIRGenerator gen) { assert lockDepth != -1; - assert stateAfter() != null; HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen; StackSlot slot = hsGen.getLockSlot(lockDepth); if (!eliminated) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FieldWriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FieldWriteBarrier.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -public final class FieldWriteBarrier extends FixedWithNextNode implements Lowerable { - - @Input private ValueNode object; - - public ValueNode getObject() { - return object; - } - - public FieldWriteBarrier(ValueNode object) { - super(StampFactory.forVoid()); - this.object = object; - } - - public void lower(LoweringTool generator) { - generator.getRuntime().lower(this, generator); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -24,22 +24,24 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.word.*; +import com.oracle.graal.phases.common.*; public class HotSpotInstalledCodeExecuteNode extends AbstractCallNode implements Lowerable { - @Input private final ValueNode targetAddress; - @Input private final ValueNode metaspaceObject; + @Input private final ValueNode code; private final Class[] signature; - public HotSpotInstalledCodeExecuteNode(Kind kind, ValueNode targetAddress, ValueNode metaspaceObject, Class[] signature, ValueNode arg1, ValueNode arg2, ValueNode arg3) { + public HotSpotInstalledCodeExecuteNode(Kind kind, Class[] signature, ValueNode code, ValueNode arg1, ValueNode arg2, ValueNode arg3) { super(StampFactory.forKind(kind), new ValueNode[]{arg1, arg2, arg3}); - this.targetAddress = targetAddress; - this.metaspaceObject = metaspaceObject; + this.code = code; this.signature = signature; } @@ -50,30 +52,57 @@ @Override public void lower(LoweringTool tool) { - replaceWithInvoke(tool); + if (code.isConstant() && code.asConstant().asObject() instanceof HotSpotInstalledCode) { + HotSpotInstalledCode hsCode = (HotSpotInstalledCode) code.asConstant().asObject(); + InvokeNode invoke = replaceWithInvoke(tool.getRuntime()); + StructuredGraph graph = (StructuredGraph) hsCode.getGraph(); + if (graph != null) { + InliningUtil.inline(invoke, (StructuredGraph) hsCode.getGraph(), false); + } + } else { + replaceWithInvoke(tool.getRuntime()); + } } - private InvokeNode replaceWithInvoke(LoweringTool tool) { - InvokeNode invoke = createInvoke(tool); - ((StructuredGraph) graph()).replaceFixedWithFixed(this, invoke); - return invoke; - } - - protected InvokeNode createInvoke(LoweringTool tool) { + protected InvokeNode replaceWithInvoke(MetaAccessProvider tool) { ResolvedJavaMethod method = null; + ResolvedJavaField methodField = null; + ResolvedJavaField metaspaceMethodField = null; + ResolvedJavaField nmethodField = null; try { - method = tool.getRuntime().lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class)); - } catch (NoSuchMethodException | SecurityException e) { - throw new IllegalStateException(); + method = tool.lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class)); + methodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("method")); + nmethodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("nmethod")); + metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod")); + } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) { + throw new IllegalStateException(e); } ResolvedJavaType[] signatureTypes = new ResolvedJavaType[signature.length]; for (int i = 0; i < signature.length; i++) { - signatureTypes[i] = tool.getRuntime().lookupJavaType(signature[i]); + signatureTypes[i] = tool.lookupJavaType(signature[i]); } - HotSpotIndirectCallTargetNode callTarget = graph().add( - new HotSpotIndirectCallTargetNode(metaspaceObject, targetAddress, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall)); - InvokeNode invoke = graph().add(new InvokeNode(callTarget, 0)); + final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset(); + + StructuredGraph g = (StructuredGraph) graph(); + + LoadFieldNode loadnmethod = g.add(new LoadFieldNode(code, nmethodField)); + UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadnmethod, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), HotSpotGraalRuntime.getInstance().getTarget().wordKind)); + + LoadFieldNode loadMethod = g.add(new LoadFieldNode(code, methodField)); + LoadFieldNode loadmetaspaceMethod = g.add(new LoadFieldNode(loadMethod, metaspaceMethodField)); + + HotSpotIndirectCallTargetNode callTarget = g.add(new HotSpotIndirectCallTargetNode(loadmetaspaceMethod, load, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall)); + + InvokeNode invoke = g.add(new InvokeNode(callTarget, 0)); + invoke.setStateAfter(stateAfter()); + g.replaceFixedWithFixed(this, invoke); + + g.addBeforeFixed(invoke, loadmetaspaceMethod); + g.addBeforeFixed(loadmetaspaceMethod, loadMethod); + g.addBeforeFixed(invoke, load); + g.addBeforeFixed(load, loadnmethod); + return invoke; } @@ -82,6 +111,6 @@ } @NodeIntrinsic - public static native T call(@ConstantNodeParameter Kind kind, Word targetAddress, long metaspaceObject, @ConstantNodeParameter Class[] signature, Object arg1, Object arg2, Object arg3); + public static native T call(@ConstantNodeParameter Kind kind, @ConstantNodeParameter Class[] signature, Object code, Object arg1, Object arg2, Object arg3); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -75,7 +74,7 @@ public boolean fillContents() { // We fill contents when G1 GC is used since we want to record // the original field values prior to stores - return HotSpotSnippetUtils.useG1GC() ? true : fillContents; + return fillContents; } public boolean locked() { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -57,7 +56,7 @@ } public boolean fillContents() { - return HotSpotSnippetUtils.useG1GC() ? true : fillContents; + return fillContents; } public boolean locked() { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -36,7 +36,7 @@ * Causes the VM to exit with a description of the current Java location and an optional * {@linkplain Log#printf(String, long) formatted} error message specified. */ -public final class VMErrorNode extends FixedWithNextNode implements LIRGenLowerable { +public final class VMErrorNode extends DeoptimizingStubCall implements LIRGenLowerable { @Input private ValueNode format; @Input private ValueNode value; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.phases; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; + +public class WriteBarrierAdditionPhase extends Phase { + + public WriteBarrierAdditionPhase() { + } + + @Override + protected void run(StructuredGraph graph) { + for (WriteNode node : graph.getNodes(WriteNode.class)) { + addWriteNodeBarriers(node, graph); + } + for (CompareAndSwapNode node : graph.getNodes(CompareAndSwapNode.class)) { + addCASBarriers(node, graph); + } + for (GenericArrayRangeWriteBarrier node : graph.getNodes(GenericArrayRangeWriteBarrier.class)) { + addArrayRangeBarriers(node, graph); + } + } + + private static void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) { + WriteBarrierType barrierType = node.getWriteBarrierType(); + if (barrierType == WriteBarrierType.PRECISE) { + graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), true))); + } else if (barrierType == WriteBarrierType.IMPRECISE) { + graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.location(), false))); + } else { + assert barrierType == WriteBarrierType.NONE; + } + + } + + private static void addCASBarriers(CompareAndSwapNode node, StructuredGraph graph) { + WriteBarrierType barrierType = node.getWriteBarrierType(); + if (barrierType == WriteBarrierType.PRECISE) { + graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getLocation(), true))); + } else if (barrierType == WriteBarrierType.IMPRECISE) { + graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getLocation(), false))); + } else { + assert barrierType == WriteBarrierType.NONE; + } + } + + private static void addArrayRangeBarriers(GenericArrayRangeWriteBarrier node, StructuredGraph graph) { + SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getDstObject(), node.getDstPos(), node.getLength())); + graph.replaceFixedWithFixed(node, serialArrayRangeWriteBarrier); + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.hotspot.phases; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.graph.*; + +public class WriteBarrierVerificationPhase extends Phase { + + private class MemoryMap implements MergeableState { + + private IdentityHashMap> lastMemorySnapshot; + private IdentityHashMap> lastWriteBarrierSnapshot; + + public MemoryMap(MemoryMap memoryMap) { + lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot); + lastWriteBarrierSnapshot = new IdentityHashMap<>(memoryMap.lastWriteBarrierSnapshot); + } + + public MemoryMap() { + lastMemorySnapshot = new IdentityHashMap<>(); + lastWriteBarrierSnapshot = new IdentityHashMap<>(); + } + + @Override + public String toString() { + return "Map=" + lastMemorySnapshot.toString(); + } + + @Override + public boolean merge(MergeNode merge, List withStates) { + if (withStates.size() == 0) { + return true; + } + + for (MemoryMap other : withStates) { + for (Object otherObject : other.lastMemorySnapshot.keySet()) { + LinkedList currentLocations = lastMemorySnapshot.get(otherObject); + LinkedList otherLocations = other.lastMemorySnapshot.get(otherObject); + if (otherLocations != null) { + if (currentLocations == null) { + currentLocations = new LinkedList<>(); + } + for (LocationNode location : otherLocations) { + if (!currentLocations.contains(location)) { + currentLocations.add(location); + } + } + } + } + for (Object otherObject : other.lastWriteBarrierSnapshot.keySet()) { + LinkedList currentWriteBarriers = lastWriteBarrierSnapshot.get(otherObject); + LinkedList otherWriteBarriers = other.lastWriteBarrierSnapshot.get(otherObject); + if (otherWriteBarriers != null) { + if (currentWriteBarriers == null) { + currentWriteBarriers = new LinkedList<>(); + } + for (SerialWriteBarrier barrier : otherWriteBarriers) { + if (!currentWriteBarriers.contains(barrier)) { + currentWriteBarriers.add(barrier); + } + } + } + } + } + return true; + } + + @Override + public void loopBegin(LoopBeginNode loopBegin) { + } + + @Override + public void loopEnds(LoopBeginNode loopBegin, List loopEndStates) { + } + + @Override + public void afterSplit(BeginNode node) { + } + + @Override + public MemoryMap clone() { + return new MemoryMap(this); + } + } + + @Override + protected void run(StructuredGraph graph) { + new PostOrderNodeIterator(graph.start(), new MemoryMap()) { + + @Override + protected void node(FixedNode node) { + processNode(node, state); + } + }.apply(); + } + + private static void processNode(FixedNode node, MemoryMap state) { + if (node instanceof WriteNode) { + processWriteNode((WriteNode) node, state); + } else if (node instanceof CompareAndSwapNode) { + processCASNode((CompareAndSwapNode) node, state); + } else if (node instanceof SerialWriteBarrier) { + processWriteBarrier((SerialWriteBarrier) node, state); + } else if ((node instanceof DeoptimizingNode)) { + if (((DeoptimizingNode) node).canDeoptimize()) { + validateWriteBarriers(state); + processSafepoint(state); + } + } + } + + private static void processWriteNode(WriteNode node, MemoryMap state) { + if (node.getWriteBarrierType() != WriteBarrierType.NONE) { + LinkedList locations = state.lastMemorySnapshot.get(node.object()); + if (locations == null) { + locations = new LinkedList<>(); + locations.add(node.location()); + state.lastMemorySnapshot.put(node.object(), locations); + } else if ((node.getWriteBarrierType() == WriteBarrierType.PRECISE) && !locations.contains(node.location())) { + locations.add(node.location()); + } + } + } + + private static void processCASNode(CompareAndSwapNode node, MemoryMap state) { + if (node.getWriteBarrierType() != WriteBarrierType.NONE) { + LinkedList locations = state.lastMemorySnapshot.get(node.object()); + if (locations == null) { + locations = new LinkedList<>(); + locations.add(node.getLocation()); + state.lastMemorySnapshot.put(node.object(), locations); + } else if ((node.getWriteBarrierType() == WriteBarrierType.PRECISE) && !locations.contains(node.getLocation())) { + locations.add(node.getLocation()); + } + } + } + + private static void processWriteBarrier(SerialWriteBarrier currentBarrier, MemoryMap state) { + LinkedList writeBarriers = state.lastWriteBarrierSnapshot.get(currentBarrier.getObject()); + if (writeBarriers == null) { + writeBarriers = new LinkedList<>(); + writeBarriers.add(currentBarrier); + state.lastWriteBarrierSnapshot.put(currentBarrier.getObject(), writeBarriers); + } else if (currentBarrier.usePrecise()) { + boolean found = false; + for (SerialWriteBarrier barrier : writeBarriers) { + if (barrier.getLocation() == currentBarrier.getLocation()) { + found = true; + break; + } + } + if (!found) { + writeBarriers.add(currentBarrier); + } + } + } + + private static void validateWriteBarriers(MemoryMap state) { + Set objects = state.lastMemorySnapshot.keySet(); + for (Object write : objects) { + LinkedList writeBarriers = state.lastWriteBarrierSnapshot.get(write); + if (writeBarriers == null) { + throw new GraalInternalError("Failed to find any write barrier at safepoint for written object"); + } + /* + * Check the first write barrier of the object to determine if it is precise or not. If + * it is not, the validation for this object has passed (since we had a hit in the write + * barrier hashmap), otherwise we have to ensure the presence of write barriers for + * every written location. + */ + final boolean precise = writeBarriers.getFirst().usePrecise(); + if (precise) { + LinkedList locations = state.lastMemorySnapshot.get(write); + for (LocationNode location : locations) { + boolean found = false; + for (SerialWriteBarrier barrier : writeBarriers) { + if (location == barrier.getLocation()) { + found = true; + break; + } + } + if (!found) { + throw new GraalInternalError("Failed to find write barrier at safepoint for precise written object"); + } + } + } + } + } + + private static void processSafepoint(MemoryMap state) { + state.lastMemorySnapshot.clear(); + state.lastWriteBarrierSnapshot.clear(); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Sat Apr 20 12:23:29 2013 +0200 @@ -79,7 +79,7 @@ } } - abstract static class CryptBlockStubCall extends FixedWithNextNode implements LIRGenLowerable { + abstract static class CryptBlockStubCall extends DeoptimizingStubCall implements LIRGenLowerable { @Input private final ValueNode in; @Input private final ValueNode out; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.nodes.*; public class ArrayCopyNode extends MacroNode implements Virtualizable, IterableNodeType, Lowerable { @@ -81,9 +82,10 @@ } // the canonicalization before loop unrolling is needed to propagate the length into // additions, etc. - new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); - new LoopFullUnrollPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); - new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); + HighTierContext context = new HighTierContext(tool.getRuntime(), tool.assumptions()); + new CanonicalizerPhase().apply(snippetGraph, context); + new LoopFullUnrollPhase().apply(snippetGraph, context); + new CanonicalizerPhase().apply(snippetGraph, context); } @Override diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -37,7 +37,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -75,7 +74,7 @@ private static final Kind VECTOR_KIND = Kind.Long; private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long); - public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) { + private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) { checkNonNull(src); checkNonNull(dest); checkLimits(src, srcPos, dest, destPos, length); @@ -236,9 +235,14 @@ } } + @Snippet + public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { + arrayObjectCopy(src, srcPos, dest, destPos, length); + } + // Does NOT perform store checks @Snippet - public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { + public static void arrayObjectCopy(Object src, int srcPos, Object dest, int destPos, int length) { objectCounter.inc(); checkNonNull(src); checkNonNull(dest); @@ -260,15 +264,7 @@ } } if (length > 0) { - int cardShift = cardTableShift(); - long cardStart = cardTableStart(); - long dstAddr = GetObjectAddressNode.get(dest); - long start = (dstAddr + header + (long) destPos * scale) >>> cardShift; - long end = (dstAddr + header + ((long) destPos + length - 1) * scale) >>> cardShift; - long count = end - start + 1; - while (count-- > 0) { - DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean); - } + GenericArrayRangeWriteBarrier.insertWriteBarrier(dest, destPos, length); } } @@ -278,14 +274,22 @@ // loading the hubs also checks for nullness Word srcHub = loadHub(src); Word destHub = loadHub(dest); + int layoutHelper = checkArrayType(srcHub); + int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); + final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0); - int layoutHelper = checkArrayType(srcHub); if (srcHub.equal(destHub) && src != dest) { probability(FAST_PATH_PROBABILITY); checkLimits(src, srcPos, dest, destPos, length); - - arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper); + if (isObjectArray) { + genericObjectExactCallCounter.inc(); + probability(FAST_PATH_PROBABILITY); + arrayObjectCopy(src, srcPos, dest, destPos, length); + } else { + genericPrimitiveCallCounter.inc(); + arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper); + } } else { genericObjectCallCounter.inc(); System.arraycopy(src, srcPos, dest, destPos, length); @@ -317,25 +321,6 @@ destOffset = destOffset.add(wordSize()); srcOffset = srcOffset.add(wordSize()); } - - if ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) != 0) { - genericPrimitiveCallCounter.inc(); - - } else { - probability(LIKELY_PROBABILITY); - genericObjectExactCallCounter.inc(); - - if (length > 0) { - int cardShift = cardTableShift(); - long cardStart = cardTableStart(); - Word destCardOffset = destStart.unsignedShiftRight(cardShift).add(Word.unsigned(cardStart)); - Word destCardEnd = destEnd.subtract(1).unsignedShiftRight(cardShift).add(Word.unsigned(cardStart)); - while (destCardOffset.belowOrEqual(destCardEnd)) { - DirectStoreNode.store(destCardOffset.rawValue(), false, Kind.Boolean); - destCardOffset = destCardOffset.add(1); - } - } - } } private static final SnippetCounter.Group checkCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("System.arraycopy checkInputs") : null; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; + +@ServiceProvider(ReplacementsProvider.class) +public class CallSiteSubstitutions implements ReplacementsProvider { + + @Override + public void registerReplacements(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + if (GraalOptions.IntrinsifyCallSiteTarget) { + replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class); + replacements.registerSubstitutions(MutableCallSiteSubstitutions.class); + replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class); + } + } + + @ClassSubstitution(ConstantCallSite.class) + private static class ConstantCallSiteSubstitutions { + + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(ConstantCallSite callSite); + } + + @ClassSubstitution(MutableCallSite.class) + private static class MutableCallSiteSubstitutions { + + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(MutableCallSite callSite); + } + + @ClassSubstitution(VolatileCallSite.class) + private static class VolatileCallSiteSubstitutions { + + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(VolatileCallSite callSite); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; + +public class CallSiteTargetNode extends MacroNode implements Canonicalizable, Lowerable { + + public CallSiteTargetNode(Invoke invoke) { + super(invoke); + } + + private ValueNode getCallSite() { + return arguments.get(0); + } + + private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccessProvider, Assumptions assumptions) { + if (getCallSite().isConstant() && !getCallSite().isNullConstant()) { + CallSite callSite = (CallSite) getCallSite().asConstant().asObject(); + if (callSite instanceof ConstantCallSite) { + return ConstantNode.forObject(callSite.getTarget(), metaAccessProvider, graph()); + } else if (callSite instanceof MutableCallSite || callSite instanceof VolatileCallSite && assumptions != null && assumptions.useOptimisticAssumptions()) { + MethodHandle target = callSite.getTarget(); + assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target)); + return ConstantNode.forObject(target, metaAccessProvider, graph()); + } + } + return null; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + ConstantNode target = getConstantCallTarget(tool.runtime(), tool.assumptions()); + if (target != null) { + return target; + } + + return this; + } + + @Override + public void lower(LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) graph(); + ConstantNode target = getConstantCallTarget(tool.getRuntime(), tool.assumptions()); + + if (target != null) { + graph.replaceFixedWithFloating(this, target); + } else { + graph.replaceFixedWithFixed(this, createInvoke()); + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -28,11 +28,9 @@ import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.*; @@ -42,7 +40,11 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -58,16 +60,11 @@ @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word hub, Word objectHub); - // @formatter:off - /** * Type test used when the type being tested against is a final type. */ @Snippet - public static Object checkcastExact( - @Parameter("object") Object object, - @Parameter("exactHub") Word exactHub, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -76,30 +73,25 @@ if (objectHub.notEqual(exactHub)) { probability(DEOPT_PATH_PROBABILITY); exactMiss.inc(); - //bkpt(object, exactHub, objectHub); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } exactHit.inc(); } - /* make sure that the unsafeCast is done *after* the check above, - * cf. ReadAfterCheckCast */ + /* + * make sure that the unsafeCast is done *after* the check above, cf. ReadAfterCheckCast + */ BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } /** * Type test used when the type being tested against is a restricted primary type. - * - * This test ignores use of hints altogether as the display-based type check only - * involves one extra load where the second load should hit the same cache line as the - * first. + * + * This test ignores use of hints altogether as the display-based type check only involves one + * extra load where the second load should hit the same cache line as the first. */ @Snippet - public static Object checkcastPrimary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { + public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -120,11 +112,7 @@ * Type test used when the type being tested against is a restricted secondary type. */ @Snippet - public static Object checkcastSecondary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @VarargsParameter("hints") Word[] hints, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -149,14 +137,11 @@ } /** - * Type test used when the type being tested against is not known at compile time (e.g. the type test - * in an object array store check). + * Type test used when the type being tested against is not known at compile time (e.g. the type + * test in an object array store check). */ @Snippet - public static Object checkcastDynamic( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -170,21 +155,15 @@ return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } - // @formatter:on - - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod exact; - private final ResolvedJavaMethod primary; - private final ResolvedJavaMethod secondary; - private final ResolvedJavaMethod dynamic; + private final SnippetInfo exact = snippet(CheckCastSnippets.class, "checkcastExact"); + private final SnippetInfo primary = snippet(CheckCastSnippets.class, "checkcastPrimary"); + private final SnippetInfo secondary = snippet(CheckCastSnippets.class, "checkcastSecondary"); + private final SnippetInfo dynamic = snippet(CheckCastSnippets.class, "checkcastDynamic"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, CheckCastSnippets.class); - exact = snippet("checkcastExact", Object.class, Word.class, boolean.class); - primary = snippet("checkcastPrimary", Word.class, Object.class, boolean.class, int.class); - secondary = snippet("checkcastSecondary", Word.class, Object.class, Word[].class, boolean.class); - dynamic = snippet("checkcastDynamic", Word.class, Object.class, boolean.class); + super(runtime, replacements, target); } /** @@ -193,31 +172,34 @@ public void lower(CheckCastNode checkcast, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); ValueNode object = checkcast.object(); - final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph()); - boolean checkNull = !object.stamp().nonNull(); - Arguments arguments; - Key key; - assert type != null; + Arguments args; if (hintInfo.exact) { - ConstantNode[] hints = createHints(hintInfo, runtime, graph); + ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; assert hints.length == 1; - key = new Key(exact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]); + args = new Arguments(exact); + args.add("object", object); + args.add("exactHub", hints[0]); } else if (type.isPrimaryType()) { - key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object); + args = new Arguments(primary); + args.add("hub", hub); + args.add("object", object); + args.addConst("superCheckOffset", type.superCheckOffset()); } else { - ConstantNode[] hints = createHints(hintInfo, runtime, graph); - key = new Key(secondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints); + ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; + args = new Arguments(secondary); + args.add("hub", hub); + args.add("object", object); + args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints); } + args.addConst("checkNull", !object.stamp().nonNull()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + SnippetTemplate template = template(args); + Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); } /** @@ -225,16 +207,16 @@ */ public void lower(CheckCastDynamicNode checkcast) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); - ValueNode hub = checkcast.type(); ValueNode object = checkcast.object(); - boolean checkNull = !object.stamp().nonNull(); - Key key = new Key(dynamic).add("checkNull", checkNull); - Arguments arguments = arguments("hub", hub).add("object", object); + Arguments args = new Arguments(dynamic); + args.add("hub", checkcast.type()); + args.add("object", object); + args.addConst("checkNull", !object.stamp().nonNull()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + SnippetTemplate template = template(args); + Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Sat Apr 20 12:23:29 2013 +0200 @@ -96,7 +96,7 @@ } } - abstract static class AESCryptStubCall extends FixedWithNextNode implements LIRGenLowerable { + abstract static class AESCryptStubCall extends DeoptimizingStubCall implements LIRGenLowerable { @Input private final ValueNode in; @Input private final ValueNode out; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeIntrinsics.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeIntrinsics.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeIntrinsics.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.replacements; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -30,7 +32,7 @@ public class HotSpotInstalledCodeIntrinsics implements ReplacementsProvider { @Override - public void registerReplacements(Replacements replacements) { + public void registerReplacements(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { if (GraalOptions.IntrinsifyInstalledCodeMethods) { replacements.registerSubstitutions(HotSpotInstalledCodeSubstitutions.class); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,20 +27,18 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.word.*; @ClassSubstitution(HotSpotInstalledCode.class) public class HotSpotInstalledCodeSubstitutions { - @MethodSubstitution - public static Object executeHelper(long nmethod, long metaspaceMethod, final Object arg1, final Object arg2, final Object arg3) { - final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset(); - final Word callTarget = Word.unsigned(nmethod).readWord(verifiedEntryPointOffset); - return HotSpotInstalledCodeExecuteNode.call(Kind.Object, callTarget, metaspaceMethod, getSignature(), arg1, arg2, arg3); + @MethodSubstitution(isStatic = false) + public static Object execute(HotSpotInstalledCode code, final Object arg1, final Object arg2, final Object arg3) { + return HotSpotInstalledCodeExecuteNode.call(Kind.Object, getSignature(), code, arg1, arg2, arg3); } @Fold private static Class[] getSignature() { return new Class[]{Object.class, Object.class, Object.class}; } + } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -24,20 +24,22 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -51,18 +53,11 @@ */ public class InstanceOfSnippets implements Snippets { - // @formatter:off - /** * A test against a final type. */ @Snippet - public static Object instanceofExact( - @Parameter("object") Object object, - @Parameter("exactHub") Word exactHub, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -82,13 +77,7 @@ * A test against a primary type. */ @Snippet - public static Object instanceofPrimary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { + public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -108,13 +97,8 @@ * A test against a restricted secondary type type. */ @Snippet - public static Object instanceofSecondary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @VarargsParameter("hints") Word[] hints, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, + @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -125,10 +109,11 @@ ExplodeLoopNode.explodeLoop(); for (int i = 0; i < hints.length; i++) { Word hintHub = hints[i]; + boolean positive = hintIsPositive[i]; if (hintHub.equal(objectHub)) { probability(NOT_FREQUENT_PROBABILITY); hintsHit.inc(); - return trueValue; + return positive ? trueValue : falseValue; } } if (!checkSecondarySubType(hub, objectHub)) { @@ -141,12 +126,7 @@ * Type test used when the type being tested against is not known at compile time. */ @Snippet - public static Object instanceofDynamic( - @Parameter("mirror") Class mirror, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -161,61 +141,63 @@ return trueValue; } - // @formatter:on - - public static class Templates extends InstanceOfSnippetsTemplates { + public static class Templates extends InstanceOfSnippetsTemplates { - private final ResolvedJavaMethod instanceofExact; - private final ResolvedJavaMethod instanceofPrimary; - private final ResolvedJavaMethod instanceofSecondary; - private final ResolvedJavaMethod instanceofDynamic; + private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact"); + private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary"); + private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary"); + private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, InstanceOfSnippets.class); - instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class); - instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class); - instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean.class); - instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class); + super(runtime, replacements, target); } @Override - protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { + protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { if (replacer.instanceOf instanceof InstanceOfNode) { InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf; - ValueNode trueValue = replacer.trueValue; - ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph()); - boolean checkNull = !object.stamp().nonNull(); - Arguments arguments; - Key key; + + Arguments args; if (hintInfo.exact) { - ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph()); + ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs; assert hints.length == 1; - key = new Key(instanceofExact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofExact); + args.add("object", object); + args.add("exactHub", hints[0]); } else if (type.isPrimaryType()) { - key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofPrimary); + args.add("hub", hub); + args.add("object", object); + args.addConst("superCheckOffset", type.superCheckOffset()); } else { - ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph()); - key = new Key(instanceofSecondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue); + Hints hints = createHints(hintInfo, runtime, false, hub.graph()); + args = new Arguments(instanceofSecondary); + args.add("hub", hub); + args.add("object", object); + args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs); + args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive); } - return new KeyAndArguments(key, arguments); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + args.addConst("checkNull", !object.stamp().nonNull()); + return args; + } else { assert replacer.instanceOf instanceof InstanceOfDynamicNode; InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; - ValueNode trueValue = replacer.trueValue; - ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); - ValueNode mirror = instanceOf.mirror(); - boolean checkNull = !object.stamp().nonNull(); - Key key = new Key(instanceofDynamic).add("checkNull", checkNull); - Arguments arguments = arguments("mirror", mirror).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); - return new KeyAndArguments(key, arguments); + + Arguments args = new Arguments(instanceofDynamic); + args.add("mirror", instanceOf.mirror()); + args.add("object", object); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + args.addConst("checkNull", !object.stamp().nonNull()); + return args; } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,16 +27,13 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -53,23 +50,17 @@ return unsafeCast(exception, StampFactory.forNodeIntrinsic()); } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod loadException; + private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, LoadExceptionObjectSnippets.class); - loadException = snippet("loadException"); + super(runtime, replacements, target); } public void lower(LoadExceptionObjectNode loadExceptionObject) { - StructuredGraph graph = (StructuredGraph) loadExceptionObject.graph(); - Arguments arguments = new Arguments(); - - Key key = new Key(loadException); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering exception object in %s: node=%s, template=%s, arguments=%s", graph, loadExceptionObject, template, arguments); - template.instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(loadException); + template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args); } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}. + */ +public class MethodHandleInvokeBasicNode extends MacroNode { + + public MethodHandleInvokeBasicNode(Invoke invoke) { + super(invoke); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}. + */ +public class MethodHandleLinkToInterfaceNode extends MacroNode { + + public MethodHandleLinkToInterfaceNode(Invoke invoke) { + super(invoke); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}. + */ +public class MethodHandleLinkToSpecialNode extends MacroNode { + + public MethodHandleLinkToSpecialNode(Invoke invoke) { + super(invoke); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}. + */ +public class MethodHandleLinkToStaticNode extends MacroNode { + + public MethodHandleLinkToStaticNode(Invoke invoke) { + super(invoke); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}. + */ +public class MethodHandleLinkToVirtualNode extends MacroNode { + + public MethodHandleLinkToVirtualNode(Invoke invoke) { + super(invoke); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -46,7 +46,10 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -73,7 +76,7 @@ public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced"); @Snippet - public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { + public static void monitorenter(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); if (checkNull && object == null) { @@ -262,7 +265,7 @@ * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { + public static void monitorenterStub(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); incCounter(); if (checkNull && object == null) { @@ -276,7 +279,7 @@ } @Snippet - public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { + public static void monitorexit(Object object, @ConstantParameter boolean trace) { trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); if (useBiasedLocking()) { // Check for biased locking unlock case, which is a no-op @@ -328,7 +331,7 @@ * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { + public static void monitorexitStub(Object object, @ConstantParameter boolean trace) { verifyOop(object); traceObject(trace, "-lock{stub}", object); MonitorExitStubCall.call(object); @@ -398,54 +401,45 @@ } } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod monitorenter; - private final ResolvedJavaMethod monitorexit; - private final ResolvedJavaMethod monitorenterStub; - private final ResolvedJavaMethod monitorexitStub; - private final ResolvedJavaMethod monitorenterEliminated; - private final ResolvedJavaMethod monitorexitEliminated; - private final ResolvedJavaMethod initCounter; - private final ResolvedJavaMethod checkCounter; + private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter"); + private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit"); + private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub"); + private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub"); + private final SnippetInfo monitorenterEliminated = snippet(MonitorSnippets.class, "monitorenterEliminated"); + private final SnippetInfo monitorexitEliminated = snippet(MonitorSnippets.class, "monitorexitEliminated"); + private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter"); + private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter"); + private final boolean useFastLocking; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useFastLocking) { - super(runtime, replacements, target, MonitorSnippets.class); - monitorenter = snippet("monitorenter", Object.class, boolean.class, boolean.class); - monitorexit = snippet("monitorexit", Object.class, boolean.class); - monitorenterStub = snippet("monitorenterStub", Object.class, boolean.class, boolean.class); - monitorexitStub = snippet("monitorexitStub", Object.class, boolean.class); - monitorenterEliminated = snippet("monitorenterEliminated"); - monitorexitEliminated = snippet("monitorexitEliminated"); - initCounter = snippet("initCounter"); - checkCounter = snippet("checkCounter", String.class); + super(runtime, replacements, target); this.useFastLocking = useFastLocking; } public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorenterNode.graph(); - checkBalancedMonitors(graph); - FrameState stateAfter = monitorenterNode.stateAfter(); - boolean eliminated = monitorenterNode.eliminated(); - ResolvedJavaMethod method = eliminated ? monitorenterEliminated : useFastLocking ? monitorenter : monitorenterStub; - boolean checkNull = !monitorenterNode.object().stamp().nonNull(); - Key key = new Key(method); - if (method != monitorenterEliminated) { - key.add("checkNull", checkNull); - } - if (!eliminated) { - key.add("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + + Arguments args; + if (monitorenterNode.eliminated()) { + args = new Arguments(monitorenterEliminated); + } else { + if (useFastLocking) { + args = new Arguments(monitorenter); + } else { + args = new Arguments(monitorenterStub); + } + args.add("object", monitorenterNode.object()); + args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull()); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); } - Arguments arguments = new Arguments(); - if (!eliminated) { - arguments.add("object", monitorenterNode.object()); - } - SnippetTemplate template = cache.get(key); - Map nodes = template.instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, arguments); + Map nodes = template(args).instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, args); + for (Node n : nodes.values()) { if (n instanceof BeginLockScopeNode) { BeginLockScopeNode begin = (BeginLockScopeNode) n; @@ -460,18 +454,22 @@ public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorexitNode.graph(); FrameState stateAfter = monitorexitNode.stateAfter(); - boolean eliminated = monitorexitNode.eliminated(); - ResolvedJavaMethod method = eliminated ? monitorexitEliminated : useFastLocking ? monitorexit : monitorexitStub; - Key key = new Key(method); - if (!eliminated) { - key.add("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + + Arguments args; + if (monitorexitNode.eliminated()) { + args = new Arguments(monitorexitEliminated); + } else { + if (useFastLocking) { + args = new Arguments(monitorexit); + } else { + args = new Arguments(monitorexitStub); + } + args.add("object", monitorexitNode.object()); + args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); } - Arguments arguments = new Arguments(); - if (!eliminated) { - arguments.add("object", monitorexitNode.object()); - } - SnippetTemplate template = cache.get(key); - Map nodes = template.instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, arguments); + + Map nodes = template(args).instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, args); + for (Node n : nodes.values()) { if (n instanceof EndLockScopeNode) { EndLockScopeNode end = (EndLockScopeNode) n; @@ -521,27 +519,27 @@ NodeIterable nodes = graph.getNodes().filter(MonitorCounterNode.class); if (nodes.isEmpty()) { // Only insert the nodes if this is the first monitorenter being lowered. - JavaType returnType = initCounter.getSignature().getReturnType(initCounter.getDeclaringClass()); - MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter, new ValueNode[0], returnType)); + JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass()); + MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType)); InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0)); invoke.setStateAfter(graph.start().stateAfter()); graph.addAfterFixed(graph.start(), invoke); - StructuredGraph inlineeGraph = replacements.getSnippet(initCounter); + StructuredGraph inlineeGraph = replacements.getSnippet(initCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); List rets = graph.getNodes().filter(ReturnNode.class).snapshot(); for (ReturnNode ret : rets) { - returnType = checkCounter.getSignature().getReturnType(checkCounter.getDeclaringClass()); + returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass()); Object msg = ((HotSpotRuntime) runtime).registerGCRoot("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d"); ConstantNode errMsg = ConstantNode.forObject(msg, runtime, graph); - callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[]{errMsg}, returnType)); + callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType)); invoke = graph.add(new InvokeNode(callTarget, 0)); List stack = Collections.emptyList(); FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false); invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); - inlineeGraph = replacements.getSnippet(checkCounter); + inlineeGraph = replacements.getSnippet(checkCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -26,9 +26,7 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; -import static com.oracle.graal.replacements.Snippet.Varargs.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*; @@ -43,7 +41,11 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -52,15 +54,16 @@ */ public class NewObjectSnippets implements Snippets { - // @formatter:off - @Snippet - public static Word allocate(@Parameter("size") int size) { + public static Word allocate(int size) { Word thread = thread(); Word top = readTlabTop(thread); Word end = readTlabEnd(thread); Word newTop = top.add(size); - // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code) + /* + * this check might lead to problems if the TLAB is within 16GB of the address space end + * (checked in c++ code) + */ if (newTop.belowOrEqual(end)) { probability(FAST_PATH_PROBABILITY); writeTlabTop(thread, newTop); @@ -70,13 +73,7 @@ } @Snippet - public static Object initializeObject( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("size") int size, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { + public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) { Object result; if (memory.equal(0)) { @@ -91,19 +88,17 @@ } result = memory.toObject(); } - return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic()); + /* + * make sure that the unsafeCast is anchored after initialization, see ReadAfterCheckCast + * and CheckCastSnippets + */ + BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); + return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode); } @Snippet - public static Object initializeArray( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("length") int length, - @Parameter("allocationSize") int allocationSize, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { + public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents, + @ConstantParameter boolean locked) { if (locked) { return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents); } else { @@ -122,7 +117,8 @@ formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents); result = memory.toObject(); } - return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); + return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode); } /** @@ -131,13 +127,8 @@ public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet - public static Object allocateArrayAndInitialize( - @Parameter("length") int length, - @ConstantParameter("alignment") int alignment, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("log2ElementSize") int log2ElementSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("type") ResolvedJavaType type) { + public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) { if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { probability(DEOPT_PATH_PROBABILITY); // This handles both negative array sizes and very large array sizes @@ -149,9 +140,10 @@ } /** - * Computes the size of the memory chunk allocated for an array. This size accounts for the array - * header size, boy size and any padding after the last element to satisfy object alignment requirements. - * + * Computes the size of the memory chunk allocated for an array. This size accounts for the + * array header size, boy size and any padding after the last element to satisfy object + * alignment requirements. + * * @param length the number of elements in the array * @param alignment the object alignment requirement * @param headerSize the size of the array header @@ -167,10 +159,7 @@ * Calls the runtime stub for implementing MULTIANEWARRAY. */ @Snippet - public static Object newmultiarray( - @Parameter("hub") Word hub, - @ConstantParameter("rank") int rank, - @VarargsParameter("dimensions") int[] dimensions) { + public static Object newmultiarray(Word hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) { Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { @@ -180,9 +169,8 @@ } /** - * Maximum size of an object whose body is initialized by a sequence of - * zero-stores to its fields. Larger objects have their bodies initialized - * in a loop. + * Maximum size of an object whose body is initialized by a sequence of zero-stores to its + * fields. Larger objects have their bodies initialized in a loop. */ private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize(); @@ -213,7 +201,10 @@ */ public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION); - // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null + /* + * store hub last as the concurrent garbage collectors assume length is valid if hub field + * is not null + */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { @@ -222,27 +213,19 @@ } } - // @formatter:on - - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod allocate; - private final ResolvedJavaMethod initializeObject; - private final ResolvedJavaMethod initializeArray; - private final ResolvedJavaMethod allocateArrayAndInitialize; - private final ResolvedJavaMethod newmultiarray; - private final TargetDescription target; + private final SnippetInfo allocate = snippet(NewObjectSnippets.class, "allocate"); + private final SnippetInfo initializeObject = snippet(NewObjectSnippets.class, "initializeObject"); + private final SnippetInfo initializeArray = snippet(NewObjectSnippets.class, "initializeArray"); + private final SnippetInfo allocateArrayAndInitialize = snippet(NewObjectSnippets.class, "allocateArrayAndInitialize"); + private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray"); + private final boolean useTLAB; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useTLAB) { - super(runtime, replacements, target, NewObjectSnippets.class); - this.target = target; + super(runtime, replacements, target); this.useTLAB = useTLAB; - allocate = snippet("allocate", int.class); - initializeObject = snippet("initializeObject", Word.class, Word.class, Word.class, int.class, boolean.class, boolean.class); - initializeArray = snippet("initializeArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class); - allocateArrayAndInitialize = snippet("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, boolean.class, ResolvedJavaType.class); - newmultiarray = snippet("newmultiarray", Word.class, int.class, int[].class); } /** @@ -285,9 +268,10 @@ int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind)); if (!useTLAB) { ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph); - // value for 'size' doesn't matter as it isn't used since a stub call will be made - // anyway - // for both allocation and initialization - it just needs to be non-null + /* + * value for 'size' doesn't matter as it isn't used since a stub call will be made + * anyway for both allocation and initialization - it just needs to be non-null + */ ConstantNode size = ConstantNode.forInt(-1, graph); InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); @@ -300,12 +284,17 @@ InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); } else { - Key key = new Key(allocateArrayAndInitialize).add("alignment", alignment).add("headerSize", headerSize).add("log2ElementSize", log2ElementSize).add("fillContents", - newArrayNode.fillContents()).add("type", arrayType); - Arguments arguments = new Arguments().add("length", lengthNode); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments); - template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(allocateArrayAndInitialize); + args.add("length", lengthNode); + args.addConst("alignment", alignment); + args.addConst("headerSize", headerSize); + args.addConst("log2ElementSize", log2ElementSize); + args.addConst("fillContents", newArrayNode.fillContents()); + args.addConst("type", arrayType); + + SnippetTemplate template = template(args); + Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); + template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args); } } @@ -313,11 +302,11 @@ public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); ValueNode size = tlabAllocateNode.size(); - Key key = new Key(allocate); - Arguments arguments = arguments("size", size); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); - template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(allocate).add("size", size); + + SnippetTemplate template = template(args); + Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, args); + template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -327,12 +316,18 @@ assert !type.isArray(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); int size = instanceSize(type); - Key key = new Key(initializeObject).add("size", size).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(initializeObject); + args.add("memory", memory); + args.add("hub", hub); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("size", size).addConst("fillContents", initializeNode.fillContents()); + args.addConst("locked", initializeNode.locked()); + + SnippetTemplate template = template(args); + Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); + template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -344,13 +339,21 @@ ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); Kind elementKind = elementType.getKind(); final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); - Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length", - initializeNode.length()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(initializeArray); + args.add("memory", memory); + args.add("hub", hub); + args.add("length", initializeNode.length()); + args.add("allocationSize", initializeNode.allocationSize()); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("headerSize", headerSize); + args.addConst("fillContents", initializeNode.fillContents()); + args.addConst("locked", initializeNode.locked()); + + SnippetTemplate template = template(args); + Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); + template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -363,10 +366,12 @@ } HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); - Key key = new Key(newmultiarray).add("dimensions", vargargs(new int[rank], StampFactory.forKind(Kind.Int))).add("rank", rank); - Arguments arguments = arguments("dimensions", dims).add("hub", hub); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(newmultiarray); + args.add("hub", hub); + args.addConst("rank", rank); + args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims); + template(args).instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, args); } private static int instanceSize(HotSpotResolvedObjectType type) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,6 +25,8 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; @@ -98,12 +100,45 @@ return false; } - static ConstantNode[] createHints(TypeCheckHints hints, MetaAccessProvider runtime, Graph graph) { - ConstantNode[] hintHubs = new ConstantNode[hints.types.length]; - for (int i = 0; i < hintHubs.length; i++) { - hintHubs[i] = ConstantNode.forConstant(((HotSpotResolvedObjectType) hints.types[i]).klass(), runtime, graph); + /** + * A set of type check hints ordered by decreasing probabilities. + */ + public static class Hints { + + /** + * The hubs of the hint types. + */ + public final ConstantNode[] hubs; + + /** + * A predicate over {@link #hubs} specifying whether the corresponding hint type is a + * sub-type of the checked type. + */ + public final boolean[] isPositive; + + Hints(ConstantNode[] hints, boolean[] hintIsPositive) { + this.hubs = hints; + this.isPositive = hintIsPositive; } - return hintHubs; + } + + static Hints createHints(TypeCheckHints hints, MetaAccessProvider runtime, boolean positiveOnly, Graph graph) { + ConstantNode[] hubs = new ConstantNode[hints.hints.length]; + boolean[] isPositive = new boolean[hints.hints.length]; + int index = 0; + for (int i = 0; i < hubs.length; i++) { + if (!positiveOnly || hints.hints[i].positive) { + hubs[index] = ConstantNode.forConstant(((HotSpotResolvedObjectType) hints.hints[i].type).klass(), runtime, graph); + isPositive[index] = hints.hints[i].positive; + index++; + } + } + if (positiveOnly && index != hubs.length) { + assert index < hubs.length; + hubs = Arrays.copyOf(hubs, index); + isPositive = Arrays.copyOf(isPositive, index); + } + return new Hints(hubs, isPositive); } static Word loadSecondarySupersElement(Word metaspaceArray, int index) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -28,100 +28,27 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.Parameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; public class WriteBarrierSnippets implements Snippets { @Snippet - public static void g1PreWriteBarrier(@Parameter("object") Object obj, @Parameter("expectedObject") Object expobj, @Parameter("location") Object location, - @ConstantParameter("doLoad") boolean doLoad) { - Word thread = thread(); + public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) { Object object = FixedValueAnchorNode.getObject(obj); - Object expectedObject = FixedValueAnchorNode.getObject(expobj); - Word field = (Word) Word.fromArray(object, location); - Word previousOop = (Word) Word.fromObject(expectedObject); - byte markingValue = thread.readByte(HotSpotSnippetUtils.g1SATBQueueMarkingOffset()); - - Word bufferAddress = thread.readWord(HotSpotSnippetUtils.g1SATBQueueBufferOffset()); - Word indexAddress = thread.add(HotSpotSnippetUtils.g1SATBQueueIndexOffset()); - Word indexValue = indexAddress.readWord(0); - - if (markingValue != (byte) 0) { - if (doLoad) { - previousOop = field.readWord(0); - } - if (previousOop.notEqual(Word.zero())) { - if (indexValue.notEqual(Word.zero())) { - Word nextIndex = indexValue.subtract(HotSpotSnippetUtils.wordSize()); - Word logAddress = bufferAddress.add(nextIndex); - logAddress.writeWord(0, previousOop); - indexAddress.writeWord(0, nextIndex); - } else { - WriteBarrierPreStubCall.call(previousOop); - - } - } - } - } - - @Snippet - public static void g1PostWriteBarrier(@Parameter("object") Object obj, @Parameter("value") Object value, @Parameter("location") Object location, @ConstantParameter("usePrecise") boolean usePrecise) { - Word thread = thread(); - Object object = FixedValueAnchorNode.getObject(obj); - Object wrObject = FixedValueAnchorNode.getObject(value); - Word oop = (Word) Word.fromObject(object); - Word field; + Pointer oop; if (usePrecise) { - field = (Word) Word.fromArray(object, location); + oop = Word.fromArray(object, location); } else { - field = oop; - } - Word writtenValue = (Word) Word.fromObject(wrObject); - Word bufferAddress = thread.readWord(HotSpotSnippetUtils.g1CardQueueBufferOffset()); - Word indexAddress = thread.add(HotSpotSnippetUtils.g1CardQueueIndexOffset()); - Word indexValue = thread.readWord(HotSpotSnippetUtils.g1CardQueueIndexOffset()); - Word xorResult = (field.xor(writtenValue)).unsignedShiftRight(HotSpotSnippetUtils.logOfHRGrainBytes()); - - // Card Table - Word cardBase = field.unsignedShiftRight(cardTableShift()); - long startAddress = cardTableStart(); - int displacement = 0; - if (((int) startAddress) == startAddress) { - displacement = (int) startAddress; - } else { - cardBase = cardBase.add(Word.unsigned(cardTableStart())); + oop = Word.fromObject(object); } - Word cardAddress = cardBase.add(displacement); - - if (xorResult.notEqual(Word.zero())) { - if (writtenValue.notEqual(Word.zero())) { - byte cardByte = cardAddress.readByte(0); - if (cardByte != (byte) 0) { - cardAddress.writeByte(0, (byte) 0); // smash zero into card - if (indexValue.notEqual(Word.zero())) { - Word nextIndex = indexValue.subtract(HotSpotSnippetUtils.wordSize()); - Word logAddress = bufferAddress.add(nextIndex); - logAddress.writeWord(0, cardAddress); - indexAddress.writeWord(0, nextIndex); - } else { - WriteBarrierPostStubCall.call(object, cardAddress); - } - } - } - } - } - - @Snippet - public static void serialFieldWriteBarrier(@Parameter("object") Object obj) { - Object object = FixedValueAnchorNode.getObject(obj); - Pointer oop = Word.fromObject(object); Word base = (Word) oop.unsignedShiftRight(cardTableShift()); long startAddress = cardTableStart(); int displacement = 0; @@ -134,77 +61,44 @@ } @Snippet - public static void serialArrayWriteBarrier(@Parameter("object") Object obj, @Parameter("location") Object location) { - Object object = FixedValueAnchorNode.getObject(obj); - Pointer oop = Word.fromArray(object, location); - Word base = (Word) oop.unsignedShiftRight(cardTableShift()); - long startAddress = cardTableStart(); - int displacement = 0; - if (((int) startAddress) == startAddress) { - displacement = (int) startAddress; - } else { - base = base.add(Word.unsigned(cardTableStart())); + public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) { + Object dest = FixedValueAnchorNode.getObject(object); + int cardShift = cardTableShift(); + long cardStart = cardTableStart(); + final int scale = arrayIndexScale(Kind.Object); + int header = arrayBaseOffset(Kind.Object); + long dstAddr = GetObjectAddressNode.get(dest); + long start = (dstAddr + header + (long) startIndex * scale) >>> cardShift; + long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift; + long count = end - start + 1; + while (count-- > 0) { + DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean); } - base.writeByte(displacement, (byte) 0); } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod serialFieldWriteBarrier; - private final ResolvedJavaMethod serialArrayWriteBarrier; - private final ResolvedJavaMethod g1PreWriteBarrier; - private final ResolvedJavaMethod g1PostWriteBarrier; + private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier"); + private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, WriteBarrierSnippets.class); - serialFieldWriteBarrier = snippet("serialFieldWriteBarrier", Object.class); - serialArrayWriteBarrier = snippet("serialArrayWriteBarrier", Object.class, Object.class); - g1PreWriteBarrier = snippet("g1PreWriteBarrier", Object.class, Object.class, Object.class, boolean.class); - g1PostWriteBarrier = snippet("g1PostWriteBarrier", Object.class, Object.class, Object.class, boolean.class); + super(runtime, replacements, target); } - public void lower(ArrayWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = serialArrayWriteBarrier; - Key key = new Key(method); - Arguments arguments = new Arguments(); - arguments.add("object", arrayWriteBarrier.getObject()); - arguments.add("location", arrayWriteBarrier.getLocation()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, arguments); - } - - public void lower(FieldWriteBarrier fieldWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = serialFieldWriteBarrier; - Key key = new Key(method); - Arguments arguments = new Arguments(); - arguments.add("object", fieldWriteBarrier.getObject()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, fieldWriteBarrier, DEFAULT_REPLACER, arguments); + public void lower(SerialWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { + Arguments args = new Arguments(serialArrayWriteBarrier); + args.add("obj", arrayWriteBarrier.getObject()); + args.add("location", arrayWriteBarrier.getLocation()); + args.addConst("usePrecise", arrayWriteBarrier.usePrecise()); + template(args).instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, args); } - public void lower(WriteBarrierPre writeBarrierPre, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = g1PreWriteBarrier; - Key key = new Key(method); - key.add("doLoad", writeBarrierPre.doLoad()); - Arguments arguments = new Arguments(); - arguments.add("object", writeBarrierPre.getObject()); - arguments.add("expectedObject", writeBarrierPre.getExpectedObject()); - arguments.add("location", writeBarrierPre.getLocation()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, arguments); + public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { + Arguments args = new Arguments(serialArrayRangeWriteBarrier); + args.add("object", arrayRangeWriteBarrier.getObject()); + args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); + args.add("length", arrayRangeWriteBarrier.getLength()); + template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } - - public void lower(WriteBarrierPost writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = g1PostWriteBarrier; - Key key = new Key(method); - key.add("usePrecise", writeBarrierPost.usePrecise()); - Arguments arguments = new Arguments(); - arguments.add("object", writeBarrierPost.getObject()); - arguments.add("location", writeBarrierPost.getLocation()); - arguments.add("value", writeBarrierPost.getValue()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, writeBarrierPost, DEFAULT_REPLACER, arguments); - } - } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,15 +27,15 @@ import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -47,14 +47,19 @@ public class NewArrayStub extends Stub { public NewArrayStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, linkage); + super(runtime, replacements, target, linkage, "newArray"); } @Override - protected void populateKey(Key key) { + protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); - Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewArrayStub")); + + Arguments args = new Arguments(stub); + args.add("hub", null); + args.add("length", null); + args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub")); + return args; } /** @@ -67,7 +72,7 @@ * @param log specifies if logging is enabled */ @Snippet - private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { + private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) { int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Sat Apr 20 12:23:29 2013 +0200 @@ -36,8 +36,8 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -49,14 +49,18 @@ public class NewInstanceStub extends Stub { public NewInstanceStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, linkage); + super(runtime, replacements, target, linkage, "newInstance"); } @Override - protected void populateKey(Key key) { + protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); - Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewInstanceStub")); + + Arguments args = new Arguments(stub); + args.add("hub", null); + args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("log", Boolean.getBoolean("graal.logNewInstanceStub")); + return args; } /** @@ -67,7 +71,7 @@ * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { + private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) { int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION); if (!forceSlowPath() && inlineContiguousAllocationSupported()) { if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) { @@ -95,9 +99,6 @@ * operation was unsuccessful */ static Word refillAllocate(Word intArrayHub, int sizeInBytes, boolean log) { - if (useG1GC()) { - return Word.zero(); - } if (!useTLAB()) { return edenAllocate(Word.unsigned(sizeInBytes), log); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,9 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static java.lang.reflect.Modifier.*; - -import java.lang.reflect.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -42,7 +39,8 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; /** * Base class for implementing some low level code providing the out-of-line slow path for a @@ -56,7 +54,7 @@ /** * The method implementing the stub. */ - protected final HotSpotResolvedJavaMethod stubMethod; + protected final SnippetInfo stubInfo; /** * The linkage information for the stub. @@ -69,15 +67,14 @@ protected InstalledCode stubCode; /** - * Creates a new stub container. The new stub still needs to be {@linkplain #getAddress(Backend) - * installed}. + * Creates a new stub container. The new stub still needs to be + * {@linkplain #getAddress(Backend) installed}. * * @param linkage linkage details for a call to the stub */ - @SuppressWarnings("unchecked") - public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, null); - stubMethod = findStubMethod(runtime, getClass()); + public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage, String methodName) { + super(runtime, replacements, target); + this.stubInfo = snippet(getClass(), methodName); this.linkage = linkage; } @@ -85,7 +82,7 @@ /** * Adds the {@linkplain ConstantParameter constant} arguments of this stub. */ - protected abstract void populateKey(Key key); + protected abstract Arguments makeArguments(SnippetInfo stub); protected HotSpotRuntime runtime() { return (HotSpotRuntime) runtime; @@ -95,7 +92,7 @@ * Gets the method implementing this stub. */ public ResolvedJavaMethod getMethod() { - return stubMethod; + return stubInfo.getMethod(); } public HotSpotRuntimeCallTarget getLinkage() { @@ -109,25 +106,22 @@ */ public synchronized long getAddress(Backend backend) { if (stubCode == null) { - StructuredGraph graph = replacements.getSnippet(stubMethod); - - Key key = new Key(stubMethod); - populateKey(key); - SnippetTemplate template = cache.get(key); - graph = template.copySpecializedGraph(); + Arguments args = makeArguments(stubInfo); + SnippetTemplate template = template(args); + StructuredGraph graph = template.copySpecializedGraph(); PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, - OptimisticOptimizations.ALL, new SpeculationLog()); + final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL, + new SpeculationLog()); - stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable() { + stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable() { @Override public InstalledCode call() { - InstalledCode installedCode = runtime().addMethod(stubMethod, compResult); - assert installedCode != null : "error installing stub " + stubMethod; + InstalledCode installedCode = runtime().addMethod(getMethod(), compResult); + assert installedCode != null : "error installing stub " + getMethod(); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } @@ -135,24 +129,8 @@ } }); - assert stubCode != null : "error installing stub " + stubMethod; + assert stubCode != null : "error installing stub " + getMethod(); } return stubCode.getStart(); } - - /** - * Finds the static method annotated with {@link Snippet} in a given class of which there must - * be exactly one. - */ - private static HotSpotResolvedJavaMethod findStubMethod(HotSpotRuntime runtime, Class stubClass) { - HotSpotResolvedJavaMethod m = null; - for (Method candidate : stubClass.getDeclaredMethods()) { - if (isStatic(candidate.getModifiers()) && candidate.getAnnotation(Snippet.class) != null) { - assert m == null : "more than one method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; - m = (HotSpotResolvedJavaMethod) runtime.lookupJavaMethod(candidate); - } - } - assert m != null : "no static method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; - return m; - } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java Sat Apr 20 12:23:29 2013 +0200 @@ -102,6 +102,13 @@ buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), calleeDesc)); break; } + case INVOKEDYNAMIC: { + int cpi = stream.readCPI4(); + JavaMethod callee = cp.lookupMethod(cpi, opcode); + String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee); + buf.append(String.format("#%-10d // %s", cpi, calleeDesc)); + break; + } case LDC : case LDC_W : case LDC2_W : { diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -23,6 +23,7 @@ package com.oracle.graal.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; public class GraphBuilderConfiguration { @@ -30,6 +31,13 @@ private final boolean omitAllExceptionEdges; private ResolvedJavaType[] skippedExceptionTypes; + /** + * 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; + protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges) { this.eagerResolving = eagerResolving; this.omitAllExceptionEdges = omitAllExceptionEdges; @@ -39,6 +47,10 @@ this.skippedExceptionTypes = skippedExceptionTypes; } + public void setEagerInfopointMode(boolean eagerInfopointMode) { + this.eagerInfopointMode = eagerInfopointMode; + } + public ResolvedJavaType[] getSkippedExceptionTypes() { return skippedExceptionTypes; } @@ -51,6 +63,10 @@ return omitAllExceptionEdges; } + public boolean eagerInfopointMode() { + return eagerInfopointMode; + } + public static GraphBuilderConfiguration getDefault() { return new GraphBuilderConfiguration(false, false); } @@ -64,9 +80,9 @@ } /** - * Returns {@code true} if it is an error for a class/field/method resolution to fail. - * The default is the same result as returned by {@link #eagerResolving()}. - * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}. + * Returns {@code true} if it is an error for a class/field/method resolution to fail. The + * default is the same result as returned by {@link #eagerResolving()}. However, it may be + * overridden to allow failure even when {@link #eagerResolving} is {@code true}. */ public boolean unresolvedIsError() { return eagerResolving; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -75,6 +75,10 @@ */ public static final int TRACELEVEL_STATE = 2; + private LineNumberTable lnt; + private int previousLineNumber; + private int currentLineNumber; + protected StructuredGraph currentGraph; private final MetaAccessProvider runtime; @@ -141,6 +145,10 @@ @Override protected void run(StructuredGraph graph) { method = graph.method(); + if (graphBuilderConfig.eagerInfopointMode()) { + lnt = method.getLineNumberTable(); + previousLineNumber = -1; + } entryBCI = graph.getEntryBCI(); profilingInfo = method.getProfilingInfo(); assert method.getCode() != null : "method must contain bytecodes: " + method; @@ -193,6 +201,13 @@ } frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn); + if (graphBuilderConfig.eagerInfopointMode()) { + ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); + InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START)); + lastInstr.setNext(ipn); + lastInstr = ipn; + } + // finish the start block ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); @@ -267,7 +282,15 @@ } private void storeLocal(Kind kind, int index) { - frameState.storeLocal(index, frameState.pop(kind)); + ValueNode value; + if (kind == Kind.Object) { + value = frameState.xpop(); + // astore and astore_ may be used to store a returnAddress (jsr) see JVMS par. 6.5.astore + assert value.kind() == Kind.Object || value.kind() == Kind.Int; + } else { + value = frameState.pop(kind); + } + frameState.storeLocal(index, value); } public static boolean covers(ExceptionHandler handler, int bci) { @@ -1054,10 +1077,35 @@ } } + private void genInvokeDynamic(JavaMethod target) { + if (target instanceof ResolvedJavaMethod) { + Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC); + if (appendix != null) { + frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph)); + } + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(false), target.getSignature().getParameterCount(false)); + appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); + } else { + handleUnresolvedInvoke(target, InvokeKind.Static); + } + } + private void genInvokeVirtual(JavaMethod target) { if (target instanceof ResolvedJavaMethod) { - ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); - genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); + // Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...) + // or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see + // https://wikis.oracle.com/display/HotSpotInternals/Method+handles+and+invokedynamic + boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers()); + Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL); + if (appendix != null) { + frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph)); + } + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver)); + if (hasReceiver) { + genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); + } else { + appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); + } } else { handleUnresolvedInvoke(target, InvokeKind.Virtual); } @@ -1493,7 +1541,7 @@ } private void processBlock(Block block) { - // Ignore blocks that have no predecessors by the time it their bytecodes are parsed + // Ignore blocks that have no predecessors by the time their bytecodes are parsed if (block == null || block.firstInstruction == null) { Debug.log("Ignoring block %s", block); return; @@ -1574,6 +1622,12 @@ } ReturnNode returnNode = currentGraph.add(new ReturnNode(x)); + if (graphBuilderConfig.eagerInfopointMode()) { + InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_END)); + ipn.setStateAfter(frameState.create(FrameState.AFTER_BCI)); + append(ipn); + } + append(returnNode); } @@ -1684,6 +1738,16 @@ BytecodesParsed.add(block.endBci - bci); while (bci < endBCI) { + if (graphBuilderConfig.eagerInfopointMode() && lnt != null) { + currentLineNumber = lnt.getLineNumber(bci); + if (currentLineNumber != previousLineNumber) { + InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.LINE_NUMBER)); + ipn.setStateAfter(frameState.create(bci)); + append(ipn); + previousLineNumber = currentLineNumber; + } + } + // read the opcode int opcode = stream.currentBC(); traceState(); @@ -1732,15 +1796,15 @@ } private void traceState() { - if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { - TTY.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method)); + if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && Debug.isLogEnabled()) { + Debug.log(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method)); for (int i = 0; i < frameState.localsSize(); ++i) { ValueNode value = frameState.localAt(i); - TTY.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); + Debug.log(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); } for (int i = 0; i < frameState.stackSize(); ++i) { ValueNode value = frameState.stackAt(i); - TTY.println(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); + Debug.log(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); } } } @@ -1937,6 +2001,7 @@ case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break; case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break; case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break; + case INVOKEDYNAMIC : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break; case NEW : genNewInstance(stream.readCPI()); break; case NEWARRAY : genNewPrimitiveArray(stream.readLocalIndex()); break; case ANEWARRAY : genNewObjectArray(stream.readCPI()); break; @@ -1961,7 +2026,7 @@ } private void traceInstruction(int bci, int opcode, boolean blockStart) { - if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_INSTRUCTIONS && !TTY.isSuppressed()) { + if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { StringBuilder sb = new StringBuilder(40); sb.append(blockStart ? '+' : '|'); if (bci < 10) { @@ -1976,7 +2041,7 @@ if (!currentBlock.jsrScope.isEmpty()) { sb.append(' ').append(currentBlock.jsrScope); } - TTY.println(sb.toString()); + Debug.log(sb.toString()); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java Sat Apr 20 12:23:29 2013 +0200 @@ -46,6 +46,7 @@ return sum; } + // CheckStyle: stop system..print check private static void doPrint(int n) { for (int i = 0; i < n; i++) { System.out.print('x'); @@ -56,6 +57,8 @@ System.out.println(test(10000)); } + // CheckStyle: resume system..print check + @LongTest public void run0() throws Throwable { runTest("test", 10000); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Sat Apr 20 12:23:29 2013 +0200 @@ -35,43 +35,14 @@ public class AMD64Call { - @Opcode("CALL_DIRECT") - public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { + public abstract static class CallOp extends AMD64LIRInstruction { @Def({REG, ILLEGAL}) protected Value result; @Use({REG, STACK}) protected Value[] parameters; @Temp protected Value[] temps; @State protected LIRFrameState state; - protected final ResolvedJavaMethod callTarget; - - public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { - this.callTarget = callTarget; - this.result = result; - this.parameters = parameters; - this.state = state; - this.temps = temps; - assert temps != null; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - directCall(tasm, masm, callTarget, null, true, state); - } - } - - @Opcode("CALL_NEAR_RUNTIME") - public static class DirectNearRuntimeCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { - - @Def({REG, ILLEGAL}) protected Value result; - @Use({REG, STACK}) protected Value[] parameters; - @Temp protected Value[] temps; - @State protected LIRFrameState state; - - protected final RuntimeCallTarget callTarget; - - public DirectNearRuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { - this.callTarget = callTarget; + public CallOp(Value result, Value[] parameters, Value[] temps, LIRFrameState state) { this.result = result; this.parameters = parameters; this.state = state; @@ -80,57 +51,43 @@ } @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - directCall(tasm, masm, callTarget, null, false, state); + public boolean hasCall() { + return true; } } - @Opcode("CALL_FAR_RUNTIME") - public static class DirectFarRuntimeCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { + public abstract static class MethodCallOp extends CallOp { - @Def({REG, ILLEGAL}) protected Value result; - @Use({REG, STACK}) protected Value[] parameters; - @Temp protected Value[] temps; - @State protected LIRFrameState state; - @Temp({REG}) protected AllocatableValue callTemp; + protected final ResolvedJavaMethod callTarget; - protected final RuntimeCallTarget callTarget; - - public DirectFarRuntimeCallOp(LIRGeneratorTool gen, RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + public MethodCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(result, parameters, temps, state); this.callTarget = callTarget; - this.result = result; - this.parameters = parameters; - this.state = state; - this.temps = temps; - assert temps != null; - callTemp = gen.newVariable(Kind.Long); + } + + } + + @Opcode("CALL_DIRECT") + public static class DirectCallOp extends MethodCallOp { + + public DirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(callTarget, result, parameters, temps, state); } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - directCall(tasm, masm, callTarget, ((RegisterValue) callTemp).getRegister(), false, state); + directCall(tasm, masm, callTarget, null, true, state); } } @Opcode("CALL_INDIRECT") - public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { + public static class IndirectCallOp extends MethodCallOp { - @Def({REG, ILLEGAL}) protected Value result; - @Use({REG, STACK}) protected Value[] parameters; @Use({REG}) protected Value targetAddress; - @Temp protected Value[] temps; - @State protected LIRFrameState state; - protected final InvokeTarget callTarget; - - public IndirectCallOp(InvokeTarget callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { - this.callTarget = callTarget; - this.result = result; - this.parameters = parameters; + public IndirectCallOp(ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { + super(callTarget, result, parameters, temps, state); this.targetAddress = targetAddress; - this.state = state; - this.temps = temps; - assert temps != null; } @Override @@ -145,6 +102,50 @@ } } + public abstract static class RuntimeCallOp extends CallOp { + + protected final RuntimeCallTarget callTarget; + + public RuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(result, parameters, temps, state); + this.callTarget = callTarget; + } + + @Override + public boolean hasCall() { + return !callTarget.preservesRegisters(); + } + } + + @Opcode("CALL_NEAR_RUNTIME") + public static class DirectNearRuntimeCallOp extends RuntimeCallOp { + + public DirectNearRuntimeCallOp(RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(callTarget, result, parameters, temps, state); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + directCall(tasm, masm, callTarget, null, false, state); + } + } + + @Opcode("CALL_FAR_RUNTIME") + public static class DirectFarRuntimeCallOp extends RuntimeCallOp { + + @Temp({REG}) protected AllocatableValue callTemp; + + public DirectFarRuntimeCallOp(LIRGeneratorTool gen, RuntimeCallTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + super(callTarget, result, parameters, temps, state); + callTemp = gen.newVariable(Kind.Long); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + directCall(tasm, masm, callTarget, ((RegisterValue) callTemp).getRegister(), false, state); + } + } + public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) { if (align) { emitAlignmentForDirectCall(tasm, masm); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Sat Apr 20 12:23:29 2013 +0200 @@ -36,9 +36,9 @@ public enum PTXArithmetic { IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, - FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR, - DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR, - INEG, LNEG, + FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR, + DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR, + INEG, LNEG, FNEG, DNEG, I2L, L2I, I2B, I2C, I2S, F2D, D2F, I2F, I2D, F2I, D2I, @@ -46,6 +46,47 @@ MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; + /** + * Unary operation with separate source and destination operand. + */ + public static class Unary2Op extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + + public Unary2Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) { + this.opcode = opcode; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + PTXMove.move(tasm, masm, result, x); + emit(tasm, masm, opcode, result, x, null); + } + } + + /** + * Unary operation with single operand for source and destination. + */ + public static class Unary1Op extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + + public Unary1Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) { + this.opcode = opcode; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, result); + } + } + public static class Op1Reg extends PTXLIRInstruction { @Opcode private final PTXArithmetic opcode; @Def({REG, HINT}) protected Value result; @@ -213,23 +254,70 @@ } } - - @SuppressWarnings("unused") - protected static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) { + protected static void emit(@SuppressWarnings("unused") TargetMethodAssembler tasm, + PTXAssembler masm, PTXArithmetic opcode, Value result) { switch (opcode) { - default: throw GraalInternalError.shouldNotReachHere(); + case L2I: masm.and_b32(asIntReg(result), asIntReg(result), 0xFFFFFFFF); break; + case I2C: masm.and_b16(asIntReg(result), asIntReg(result), (short) 0xFFFF); break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) { int exceptionOffset = -1; if (isRegister(src)) { - Register a = asIntReg(src); - Register d = asIntReg(dst); switch (opcode) { - case INEG: masm.neg_s32(d, a); break; + case INEG: + masm.neg_s32(asIntReg(dst), asIntReg(src)); + break; + case I2L: + masm.cvt_s64_s32(asLongReg(dst), asIntReg(src)); + break; + case I2C: + masm.cvt_b16_s32(asIntReg(dst), asIntReg(src)); + break; + case I2B: + masm.cvt_s8_s32(asIntReg(dst), asIntReg(src)); + break; + case I2F: + masm.cvt_f32_s32(asFloatReg(dst), asIntReg(src)); + break; + case I2D: + masm.cvt_f64_s32(asDoubleReg(dst), asIntReg(src)); + break; + case FNEG: + masm.neg_f32(asFloatReg(dst), asFloatReg(src)); + break; + case DNEG: + masm.neg_f64(asDoubleReg(dst), asDoubleReg(src)); + break; + case F2I: + masm.cvt_s32_f32(asIntReg(dst), asFloatReg(src)); + break; + case F2L: + masm.cvt_s64_f32(asLongReg(dst), asFloatReg(src)); + break; + case F2D: + masm.cvt_f64_f32(asDoubleReg(dst), asFloatReg(src)); + break; + case D2I: + masm.cvt_s32_f64(asIntReg(dst), asDoubleReg(src)); + break; + case D2L: + masm.cvt_s64_f64(asLongReg(dst), asDoubleReg(src)); + break; + case D2F: + masm.cvt_f32_f64(asFloatReg(dst), asDoubleReg(src)); + break; + case LSHL: + masm.shl_s64(asLongReg(dst), asLongReg(dst), asIntReg(src)); + break; + case LSHR: + masm.shr_s64(asLongReg(dst), asLongReg(dst), asIntReg(src)); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } else if (isConstant(src)) { switch (opcode) { @@ -252,33 +340,74 @@ public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { int exceptionOffset = -1; if (isConstant(src1)) { - int a = tasm.asIntConst(src1); - Register b = asIntReg(src2); - Register d = asIntReg(dst); switch (opcode) { - case ISUB: masm.sub_s32(d, a, b); break; - case IAND: masm.and_b32(d, b, a); break; - default: throw GraalInternalError.shouldNotReachHere(); + case ISUB: masm.sub_s32(asIntReg(dst), tasm.asIntConst(src1), asIntReg(src2)); break; + case IAND: masm.and_b32(asIntReg(dst), asIntReg(src2), tasm.asIntConst(src1)); break; + case IDIV: masm.div_s32(asIntReg(dst), tasm.asIntConst(src1), asIntReg(src2)); break; + case FSUB: masm.sub_f32(asFloatReg(dst), tasm.asFloatConst(src1), asFloatReg(src2)); break; + case FDIV: masm.div_f32(asFloatReg(dst), tasm.asFloatConst(src1), asFloatReg(src2)); break; + case DSUB: masm.sub_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2)); break; + case DDIV: masm.div_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2)); break; + default: + throw GraalInternalError.shouldNotReachHere(); } } else if (isConstant(src2)) { - Register a = asIntReg(src1); - int b = tasm.asIntConst(src2); - Register d = asIntReg(dst); switch (opcode) { - case IADD: masm.add_s32(d, a, b); break; - case IAND: masm.and_b32(d, a, b); break; - case IUSHR: masm.shr_u32(d, a, b); break; - default: throw GraalInternalError.shouldNotReachHere(); + case IADD: masm.add_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case IMUL: masm.mul_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case IAND: masm.and_b32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case ISHL: masm.shl_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case ISHR: masm.shr_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case IUSHR: masm.shr_u32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case IXOR: masm.xor_b32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case LXOR: masm.xor_b64(asLongReg(dst), asLongReg(src1), tasm.asLongConst(src2)); break; + case LUSHR: masm.shr_u64(asLongReg(dst), asLongReg(src1), tasm.asLongConst(src2)); break; + case FADD: masm.add_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; + case FMUL: masm.mul_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; + case FDIV: masm.div_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; + case DADD: masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; + case DMUL: masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; + case DDIV: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; + default: + throw GraalInternalError.shouldNotReachHere(); } } else { - Register a = asIntReg(src1); - Register b = asIntReg(src2); - Register d = asIntReg(dst); switch (opcode) { - case IADD: masm.add_s32(d, a, b); break; - case ISUB: masm.sub_s32(d, a, b); break; - case IMUL: masm.mul_s32(d, a, b); break; - default: throw GraalInternalError.shouldNotReachHere(); + case IADD: masm.add_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IMUL: masm.mul_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IDIV: masm.div_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IAND: masm.and_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IOR: masm.or_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IXOR: masm.xor_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case ISHL: masm.shl_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case ISHR: masm.shr_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IUSHR: masm.shr_u32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IREM: masm.rem_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case LADD: masm.add_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LSUB: masm.sub_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LMUL: masm.mul_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LDIV: masm.div_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LAND: masm.and_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LOR: masm.or_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LXOR: masm.xor_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LSHL: masm.shl_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LSHR: masm.shr_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LUSHR: masm.shr_u64(asLongReg(dst), asLongReg(src1), asIntReg(src2)); break; + case LREM: masm.rem_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case FADD: masm.add_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case FSUB: masm.sub_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case FMUL: masm.mul_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case FDIV: masm.div_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case FREM: masm.div_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case DADD: masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + case DSUB: masm.sub_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + case DMUL: masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + case DDIV: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + case DREM: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } @@ -289,9 +418,11 @@ } private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) { - assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) + if (((opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) - || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double); + || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)) == false) { + throw GraalInternalError.shouldNotReachHere("opcode: " + opcode.name() + " x: " + x.getKind() + " y: " + y.getKind()); + } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Sat Apr 20 12:23:29 2013 +0200 @@ -65,11 +65,15 @@ public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXCompare opcode, Condition condition, Value x, Value y) { if (isConstant(x)) { - int a = tasm.asIntConst(x); - Register b = asIntReg(y); switch (opcode) { case ICMP: - emitCompareConstReg(masm, condition, a, b); + emitCompareConstReg(masm, condition, tasm.asIntConst(x), asIntReg(y)); + break; + case FCMP: + emitCompareConstReg(masm, condition, tasm.asFloatConst(x), asFloatReg(y)); + break; + case DCMP: + emitCompareConstReg(masm, condition, tasm.asDoubleConst(x), asDoubleReg(y)); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -101,18 +105,75 @@ throw GraalInternalError.shouldNotReachHere(); } } else { - Register a = asIntReg(x); - Register b = asIntReg(y); switch (opcode) { case ICMP: - emitCompareRegReg(masm, condition, a, b); + emitCompareRegReg(masm, condition, asIntReg(x), asIntReg(y)); + break; + case LCMP: + emitCompareRegReg(masm, condition, asLongReg(x), asLongReg(y)); + break; + case FCMP: + emitCompareRegReg(masm, condition, asFloatReg(x), asFloatReg(y)); + break; + case DCMP: + emitCompareRegReg(masm, condition, asDoubleReg(x), asDoubleReg(y)); break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } } + private static void emitCompareConstReg(PTXAssembler masm, Condition condition, float a, Register b) { + switch (condition) { + case EQ: + masm.setp_eq_f32(a, b); + break; + case NE: + masm.setp_ne_f32(a, b); + break; + case LT: + masm.setp_lt_f32(a, b); + break; + case LE: + masm.setp_le_f32(a, b); + break; + case GT: + masm.setp_gt_f32(a, b); + break; + case GE: + masm.setp_ge_f32(a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void emitCompareConstReg(PTXAssembler masm, Condition condition, double a, Register b) { + switch (condition) { + case EQ: + masm.setp_eq_f64(a, b); + break; + case NE: + masm.setp_ne_f64(a, b); + break; + case LT: + masm.setp_lt_f64(a, b); + break; + case LE: + masm.setp_le_f64(a, b); + break; + case GT: + masm.setp_gt_f64(a, b); + break; + case GE: + masm.setp_ge_f64(a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b) { switch (condition) { case EQ: diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,14 +22,28 @@ */ package com.oracle.graal.lir.ptx; +import static com.oracle.graal.api.code.ValueUtil.asIntReg; +import static com.oracle.graal.api.code.ValueUtil.asLongReg; +import static com.oracle.graal.api.code.ValueUtil.asObjectReg; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.asm.ptx.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.api.code.Register; +import com.oracle.graal.api.code.CompilationResult.JumpTable; +import com.oracle.graal.api.meta.Constant; +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.api.meta.Value; +import com.oracle.graal.asm.Buffer; +import com.oracle.graal.asm.Label; +import com.oracle.graal.asm.NumUtil; +import com.oracle.graal.asm.ptx.AbstractPTXAssembler; +import com.oracle.graal.asm.ptx.PTXAssembler; +import com.oracle.graal.graph.GraalInternalError; +import com.oracle.graal.lir.LabelRef; +import com.oracle.graal.lir.StandardOp; +import com.oracle.graal.lir.StandardOp.FallThroughOp; +import com.oracle.graal.lir.Variable; +import com.oracle.graal.lir.asm.TargetMethodAssembler; +import com.oracle.graal.nodes.calc.Condition; public class PTXControlFlow { @@ -64,7 +78,7 @@ public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { masm.at(); Label l = destination.label(); - l.addPatchAt(tasm.asm.codeBuffer.position()); + // l.addPatchAt(tasm.asm.codeBuffer.position()); String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET; masm.bra(target); } @@ -80,4 +94,176 @@ condition = condition.negate(); } } + + @SuppressWarnings("unused") + public static class CondMoveOp extends PTXLIRInstruction { + @Def({REG, HINT}) protected Value result; + @Alive({REG}) protected Value trueValue; + @Use({REG, STACK, CONST}) protected Value falseValue; + private final Condition condition; + + public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) { + this.result = result; + this.condition = condition; + this.trueValue = trueValue; + this.falseValue = falseValue; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + // cmove(tasm, masm, result, false, condition, false, trueValue, falseValue); + // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1 + throw new InternalError("NYI"); + } + } + + @SuppressWarnings("unused") + public static class FloatCondMoveOp extends PTXLIRInstruction { + @Def({REG}) protected Value result; + @Alive({REG}) protected Value trueValue; + @Alive({REG}) protected Value falseValue; + private final Condition condition; + private final boolean unorderedIsTrue; + + public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + this.result = result; + this.condition = condition; + this.unorderedIsTrue = unorderedIsTrue; + this.trueValue = trueValue; + this.falseValue = falseValue; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + // cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue); + // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1 + throw new InternalError("NYI"); + } + } + + public static class SequentialSwitchOp extends PTXLIRInstruction implements FallThroughOp { + @Use({CONST}) protected Constant[] keyConstants; + private final LabelRef[] keyTargets; + private LabelRef defaultTarget; + @Alive({REG}) protected Value key; + @Temp({REG, ILLEGAL}) protected Value scratch; + + public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, + Value key, Value scratch) { + assert keyConstants.length == keyTargets.length; + this.keyConstants = keyConstants; + this.keyTargets = keyTargets; + this.defaultTarget = defaultTarget; + this.key = key; + this.scratch = scratch; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + if (key.getKind() == Kind.Int) { + Register intKey = asIntReg(key); + for (int i = 0; i < keyConstants.length; i++) { + if (tasm.runtime.needsDataPatch(keyConstants[i])) { + tasm.recordDataReferenceInCode(keyConstants[i], 0, true); + } + long lc = keyConstants[i].asLong(); + assert NumUtil.isInt(lc); + masm.setp_eq_s32((int) lc, intKey); + masm.at(); + Label l = keyTargets[i].label(); + l.addPatchAt(tasm.asm.codeBuffer.position()); + String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET; + masm.bra(target); + } + } else if (key.getKind() == Kind.Long) { + Register longKey = asLongReg(key); + for (int i = 0; i < keyConstants.length; i++) { + masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]), longKey); + masm.at(); + Label l = keyTargets[i].label(); + l.addPatchAt(tasm.asm.codeBuffer.position()); + String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET; + masm.bra(target); + } + } else if (key.getKind() == Kind.Object) { + Register intKey = asObjectReg(key); + Register temp = asObjectReg(scratch); + for (int i = 0; i < keyConstants.length; i++) { + PTXMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]); + masm.setp_eq_u32(intKey, temp); + masm.at(); + masm.bra(keyTargets[i].label().toString()); + } + } else { + throw new GraalInternalError("sequential switch only supported for int, long and object"); + } + if (defaultTarget != null) { + masm.jmp(defaultTarget.label()); + } else { + // masm.hlt(); + } + } + + @Override + public LabelRef fallThroughTarget() { + return defaultTarget; + } + + @Override + public void setFallThroughTarget(LabelRef target) { + defaultTarget = target; + } + } + + public static class TableSwitchOp extends PTXLIRInstruction { + private final int lowKey; + private final LabelRef defaultTarget; + private final LabelRef[] targets; + @Alive protected Value index; + @Temp protected Value scratch; + + public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, + Variable index, Variable scratch) { + this.lowKey = lowKey; + this.defaultTarget = defaultTarget; + this.targets = targets; + this.index = index; + this.scratch = scratch; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch)); + } + } + + @SuppressWarnings("unused") + private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, + LabelRef defaultTarget, LabelRef[] targets, + Register value, Register scratch) { + Buffer buf = masm.codeBuffer; + // Compare index against jump table bounds + int highKey = lowKey + targets.length - 1; + if (lowKey != 0) { + // subtract the low value from the switch value + masm.sub_s32(value, value, lowKey); + masm.setp_gt_s32(value, highKey - lowKey); + } else { + masm.setp_gt_s32(value, highKey); + } + + // Jump to default target if index is not within the jump table + if (defaultTarget != null) { + masm.at(); + masm.bra(defaultTarget.label().toString()); + } + + // address of jump table + int tablePos = buf.position(); + + JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4); + tasm.compilationResult.addAnnotation(jt); + + // PTX: unimp: tableswitch extract + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Sat Apr 20 12:23:29 2013 +0200 @@ -133,9 +133,27 @@ public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { PTXAddress addr = address.toAddress(); switch (address.getKind()) { + case Byte: + masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Short: + masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Char: + masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; case Int: masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; + case Long: + masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Float: + masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Double: + masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; case Object: masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; @@ -162,11 +180,29 @@ assert isRegister(input); PTXAddress addr = address.toAddress(); switch (address.getKind()) { + case Byte: + masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Short: + masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; case Int: masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); break; + case Long: + masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Float: + masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Double: + masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Object: + masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind()); } } } @@ -250,11 +286,20 @@ case Int: masm.mov_s32(asRegister(result), asRegister(input)); break; + case Long: + masm.mov_s64(asRegister(result), asRegister(input)); + break; + case Float: + masm.mov_f32(asRegister(result), asRegister(input)); + break; + case Double: + masm.mov_f64(asRegister(result), asRegister(input)); + break; case Object: masm.mov_u64(asRegister(result), asRegister(input)); break; default: - throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind()); + throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind()); } } @@ -266,8 +311,24 @@ } masm.mov_s32(asRegister(result), input.asInt()); break; + case Long: + if (tasm.runtime.needsDataPatch(input)) { + tasm.recordDataReferenceInCode(input, 0, true); + } + masm.mov_s64(asRegister(result), input.asLong()); + break; + case Object: + if (input.isNull()) { + masm.mov_u64(asRegister(result), 0x0L); + } else if (tasm.target.inlineObjects) { + tasm.recordDataReferenceInCode(input, 0, true); + masm.mov_u64(asRegister(result), 0xDEADDEADDEADDEADL); + } else { + masm.mov_u64(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false)); + } + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind()); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,49 @@ +/* + * 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 static com.oracle.graal.lir.LIRInstruction.Opcode; + +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(TargetMethodAssembler tasm) { + tasm.recordInfopoint(tasm.asm.codeBuffer.position(), state, reason); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Sat Apr 20 12:23:29 2013 +0200 @@ -260,8 +260,8 @@ * Returns true when this instruction is a call instruction that destroys all caller-saved * registers. */ - public final boolean hasCall() { - return this instanceof StandardOp.CallOp; + public boolean hasCall() { + return false; } public final void forEachInput(ValueProcedure proc) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Sat Apr 20 12:23:29 2013 +0200 @@ -118,13 +118,6 @@ } /** - * Marker interface for a LIR operation that calls a method, i.e., destroys all caller-saved - * registers. - */ - public interface CallOp { - } - - /** * Meta-operation that defines the incoming method parameters. In the LIR, every register and * variable must be defined before it is used. This operation is the definition point of method * parameters, but is otherwise a no-op. In particular, it is not the actual method prologue. diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -27,6 +27,7 @@ import java.util.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.debug.*; @@ -99,11 +100,23 @@ } } - Debug.metric("TargetMethods").increment(); - Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize()); - Debug.metric("SafepointsEmitted").add(compilationResult.getSafepoints().size()); - Debug.metric("DataPatches").add(compilationResult.getDataReferences().size()); - Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); + if (Debug.isMeterEnabled()) { + List ldp = compilationResult.getDataReferences(); + DebugMetric[] dms = new DebugMetric[Kind.values().length]; + for (int i = 0; i < dms.length; i++) { + dms[i] = Debug.metric("DataPatches-" + Kind.values()[i].toString()); + } + + for (DataPatch dp : ldp) { + dms[dp.constant.getKind().ordinal()].add(1); + } + + Debug.metric("TargetMethods").increment(); + Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize()); + Debug.metric("SafepointsEmitted").add(compilationResult.getInfopoints().size()); + Debug.metric("DataPatches").add(ldp.size()); + Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); + } Debug.log("Finished target method %s, isStub %b", name, isStub); return compilationResult; } @@ -122,7 +135,7 @@ public void recordImplicitException(int pcOffset, LIRFrameState info) { // record an implicit exception point if (info != null) { - compilationResult.recordSafepoint(pcOffset, info.debugInfo()); + compilationResult.recordInfopoint(pcOffset, info.debugInfo(), InfopointReason.IMPLICIT_EXCEPTION); assert info.exceptionEdge == null; } } @@ -137,10 +150,10 @@ compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false); } - public void recordSafepoint(int pos, LIRFrameState info) { - // safepoints always need debug info + public void recordInfopoint(int pos, LIRFrameState info, InfopointReason reason) { + // infopoints always need debug info DebugInfo debugInfo = info.debugInfo(); - compilationResult.recordSafepoint(pos, debugInfo); + compilationResult.recordInfopoint(pos, debugInfo, reason); } public AbstractAddress recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { @@ -167,6 +180,36 @@ } /** + * Returns the float value of any constant that can be represented by a 32-bit float value. + */ + public float asFloatConst(Value value) { + assert (value.getKind().getStackKind() == Kind.Float && isConstant(value)); + Constant constant = (Constant) value; + assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; + return constant.asFloat(); + } + + /** + * Returns the long value of any constant that can be represented by a 64-bit long value. + */ + public long asLongConst(Value value) { + assert (value.getKind().getStackKind() == Kind.Long && isConstant(value)); + Constant constant = (Constant) value; + assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; + return constant.asLong(); + } + + /** + * Returns the double value of any constant that can be represented by a 64-bit float value. + */ + public double asDoubleConst(Value value) { + assert (value.getKind().getStackKind() == Kind.Double && isConstant(value)); + Constant constant = (Constant) value; + assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; + return constant.asDouble(); + } + + /** * Returns the address of a float constant that is embedded as a data references into the code. */ public AbstractAddress asFloatConstRef(Value value) { diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Sat Apr 20 12:23:29 2013 +0200 @@ -60,7 +60,7 @@ while (!loopBegin.isDeleted()) { int mark = graph.getMark(); peel(loop); - new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph); if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) { throw new BailoutException("FullUnroll : Graph seems to grow out of proportion"); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,31 +22,21 @@ */ package com.oracle.graal.loop.phases; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; -public class LoopFullUnrollPhase extends Phase { +public class LoopFullUnrollPhase extends BasePhase { private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls"); - private final GraalCodeCacheProvider runtime; - private final Assumptions assumptions; - private int unrollCount; - public LoopFullUnrollPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) { - this.runtime = runtime; - this.assumptions = assumptions; - } - - public int getUnrollCount() { - return unrollCount; + public LoopFullUnrollPhase() { } @Override - protected void run(StructuredGraph graph) { + protected void run(StructuredGraph graph, HighTierContext context) { if (graph.hasLoops()) { boolean peeled; do { @@ -56,11 +46,10 @@ for (LoopEx loop : dataCounted.countedLoops()) { if (LoopPolicies.shouldFullUnroll(loop)) { Debug.log("FullUnroll %s", loop); - LoopTransformations.fullUnroll(loop, runtime, assumptions); + LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions()); FULLY_UNROLLED_LOOPS.increment(); Debug.dump(graph, "After fullUnroll %s", loop); peeled = true; - unrollCount++; break; } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.type.*; - -public abstract class AbstractCallTargetNode extends CallTargetNode { - - private final Stamp returnStamp; - private final JavaType[] signature; - private final ResolvedJavaMethod target; - private final CallingConvention.Type callType; - - public AbstractCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType) { - super(arguments); - this.returnStamp = returnStamp; - this.signature = signature; - this.target = target; - this.callType = callType; - } - - @Override - public Stamp returnStamp() { - return returnStamp; - } - - public JavaType[] signature() { - return signature; - } - - public ResolvedJavaMethod target() { - return target; - } - - public CallingConvention.Type callType() { - return callType; - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -186,5 +186,5 @@ } @NodeIntrinsic - public static native T anchor(@ConstantNodeParameter Stamp stamp); + public static native BeginNode anchor(@ConstantNodeParameter Stamp stamp); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -29,7 +29,7 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") -public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable, DeoptimizingNode { +public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode { @Input private FrameState deoptState; @@ -51,6 +51,11 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.emitDeoptimize(action, this); } @@ -70,6 +75,7 @@ @Override public void setDeoptimizationState(FrameState f) { + updateUsages(deoptState, f); deoptState = f; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -49,6 +49,7 @@ @Override public void setDeoptimizationState(FrameState f) { + updateUsages(deoptState, f); deoptState = f; } diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.type.*; -public class DirectCallTargetNode extends AbstractCallTargetNode { +public class DirectCallTargetNode extends LoweredCallTargetNode { public DirectCallTargetNode(List arguments, Stamp returnStamp, JavaType[] signature, ResolvedJavaMethod target, CallingConvention.Type callType) { super(arguments, returnStamp, signature, target, callType); diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Sat Apr 20 12:23:29 2013 +0200 @@ -239,7 +239,7 @@ copy.remove(copy.size() - 1); } ValueNode lastSlot = copy.get(copy.size() - 1); - assert lastSlot.kind().getStackKind() == popKind.getStackKind() || (lastSlot instanceof BoxedVirtualObjectNode && popKind == Kind.Object); + assert lastSlot.kind().getStackKind() == popKind.getStackKind(); copy.remove(copy.size() - 1); } Collections.addAll(copy, pushedValues); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GenericArrayRangeWriteBarrier.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,56 @@ +/* + * 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.graph.*; +import com.oracle.graal.nodes.type.*; + +public final class GenericArrayRangeWriteBarrier extends FixedWithNextNode implements Node.IterableNodeType { + + @Input private ValueNode dstObject; + @Input private ValueNode dstPos; + @Input private ValueNode length; + + public ValueNode getDstObject() { + return dstObject; + } + + public ValueNode getDstPos() { + return dstPos; + } + + public ValueNode getLength() { + return length; + } + + public GenericArrayRangeWriteBarrier(ValueNode dstObject, ValueNode dstPos, ValueNode length) { + super(StampFactory.forVoid()); + this.dstObject = dstObject; + this.dstPos = dstPos; + this.length = length; + + } + + @NodeIntrinsic + public static native void insertWriteBarrier(Object dstObject, int dstPos, int length); +} diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.type.*; -public class IndirectCallTargetNode extends AbstractCallTargetNode { +public class IndirectCallTargetNode extends LoweredCallTargetNode { @Input protected ValueNode computedAddress; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,67 @@ +/* + * 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.Node.IterableNodeType; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Nodes of this type are inserted into the graph to denote points of interest to debugging. + */ +public class InfopointNode extends AbstractStateSplit implements LIRLowerable, IterableNodeType { + + public final InfopointReason reason; + + public InfopointNode(InfopointReason reason) { + super(StampFactory.forVoid()); + this.reason = reason; + } + + @Override + public void generate(LIRGeneratorTool generator) { + generator.visitInfopointNode(this); + } + + @Override + public boolean hasSideEffect() { + return false; + } + + @Override + public void setStateAfter(FrameState state) { + // shield this node from frame state removal + // TODO turn InfopointNode into a FixedWithNextNode subclass with a self-maintained + // FrameState that is correctly dealt with by scheduling and partial escape analysis + if (state != null) { + super.setStateAfter(state); + } + } + + @Override + public boolean verify() { + return stateAfter() != null && super.verify(); + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes; import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; public interface Invoke extends StateSplit, Lowerable, DeoptimizingNode { @@ -34,14 +33,9 @@ CallTargetNode callTarget(); - /** - * Utility method that returns the {@link #callTarget()} cast to a {@link MethodCallTargetNode}. - */ - MethodCallTargetNode methodCallTarget(); - int bci(); - FixedNode node(); + FixedNode asNode(); FrameState stateDuring(); @@ -51,8 +45,6 @@ void intrinsify(Node node); - Graph graph(); - double probability(); void setProbability(double value); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -38,6 +37,7 @@ public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint { @Input private final CallTargetNode callTarget; + @Input private FrameState deoptState; private final int bci; private boolean polymorphic; private boolean useForInlining; @@ -64,11 +64,6 @@ } @Override - public MethodCallTargetNode methodCallTarget() { - return (MethodCallTargetNode) callTarget; - } - - @Override public boolean isPolymorphic() { return polymorphic; } @@ -100,11 +95,7 @@ @Override public Map getDebugProperties(Map map) { Map debugProperties = super.getDebugProperties(map); - if (callTarget instanceof MethodCallTargetNode && methodCallTarget().targetMethod() != null) { - debugProperties.put("targetMethod", methodCallTarget().targetMethod()); - } else if (callTarget instanceof AbstractCallTargetNode) { - debugProperties.put("targetMethod", ((AbstractCallTargetNode) callTarget).target()); - } + debugProperties.put("targetMethod", callTarget.targetName()); return debugProperties; } @@ -139,13 +130,16 @@ } @Override - public FixedNode node() { + public FixedNode asNode() { return this; } @Override public FrameState stateDuring() { FrameState stateAfter = stateAfter(); + if (stateAfter == null) { + return null; + } FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), kind()); stateDuring.setDuringCall(true); return stateDuring; @@ -188,7 +182,12 @@ @Override public FrameState getDeoptimizationState() { - return stateDuring(); + if (deoptState == null) { + FrameState stateDuring = stateDuring(); + updateUsages(deoptState, stateDuring); + deoptState = stateDuring; + } + return deoptState; } @Override diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -37,6 +37,7 @@ @Successor private BeginNode next; @Successor private DispatchBeginNode exceptionEdge; @Input private final CallTargetNode callTarget; + @Input private FrameState deoptState; @Input private FrameState stateAfter; private final int bci; private boolean polymorphic; @@ -125,7 +126,7 @@ } @Override - public FixedNode node() { + public FixedNode asNode() { return this; } @@ -176,9 +177,7 @@ @Override public Map getDebugProperties(Map map) { Map debugProperties = super.getDebugProperties(map); - if (callTarget instanceof MethodCallTargetNode && methodCallTarget().targetMethod() != null) { - debugProperties.put("targetMethod", methodCallTarget().targetMethod()); - } + debugProperties.put("targetMethod", callTarget.targetName()); return debugProperties; } @@ -234,7 +233,12 @@ @Override public FrameState getDeoptimizationState() { - return stateDuring(); + if (deoptState == null) { + FrameState stateDuring = stateDuring(); + updateUsages(deoptState, stateDuring); + deoptState = stateDuring; + } + return deoptState; } @Override diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.type.*; + +public abstract class LoweredCallTargetNode extends CallTargetNode { + + 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); + this.returnStamp = returnStamp; + this.signature = signature; + this.target = target; + this.callType = callType; + } + + @Override + public Stamp returnStamp() { + return returnStamp; + } + + public JavaType[] signature() { + return signature; + } + + public ResolvedJavaMethod target() { + return target; + } + + public CallingConvention.Type callType() { + return callType; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,58 @@ +/* + * 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.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public final class SerialArrayRangeWriteBarrier extends FixedWithNextNode implements Lowerable { + + @Input private ValueNode object; + @Input private ValueNode startIndex; + @Input private ValueNode length; + + public ValueNode getObject() { + return object; + } + + public ValueNode getStartIndex() { + return startIndex; + } + + public ValueNode getLength() { + return length; + } + + public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { + super(StampFactory.forVoid()); + this.object = object; + this.startIndex = startIndex; + this.length = length; + + } + + public void lower(LoweringTool generator) { + generator.getRuntime().lower(this, generator); + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,58 @@ +/* + * 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.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public final class SerialWriteBarrier extends FixedWithNextNode implements Lowerable { + + @Input private ValueNode object; + @Input private LocationNode location; + private final boolean precise; + + public ValueNode getObject() { + return object; + } + + public LocationNode getLocation() { + return location; + } + + public boolean usePrecise() { + return precise; + } + + public SerialWriteBarrier(ValueNode object, LocationNode location, boolean precise) { + super(StampFactory.forVoid()); + this.object = object; + this.location = location; + this.precise = precise; + } + + @Override + public void lower(LoweringTool generator) { + generator.getRuntime().lower(this, generator); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -172,5 +172,15 @@ } @NodeIntrinsic - public static native S convert(@ConstantNodeParameter Op op, T value); + public static native float convert(@ConstantNodeParameter Op op, int value); + + @NodeIntrinsic + public static native int convert(@ConstantNodeParameter Op op, float value); + + @NodeIntrinsic + public static native double convert(@ConstantNodeParameter Op op, long value); + + @NodeIntrinsic + public static native long convert(@ConstantNodeParameter Op op, double value); + } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -81,8 +81,35 @@ // one of them is virtual: they can never be the same objects tool.replaceWithValue(LogicConstantNode.contradiction(graph())); } else if (xVirtual && yVirtual) { - // both are virtual: check if they refer to the same object - tool.replaceWithValue(LogicConstantNode.forBoolean(stateX == stateY, graph())); + boolean xIdentity = stateX.getVirtualObject().hasIdentity(); + boolean yIdentity = stateY.getVirtualObject().hasIdentity(); + if (xIdentity ^ yIdentity) { + /* + * One of the two objects has identity, the other doesn't. In code, this looks like + * "Integer.valueOf(a) == new Integer(b)", which is always false. + * + * In other words: an object created via valueOf can never be equal to one created + * by new in the same compilation unit. + */ + tool.replaceWithValue(LogicConstantNode.contradiction(graph())); + } else if (!xIdentity && !yIdentity) { + // both are virtual without identity: check contents + assert stateX.getVirtualObject().entryCount() == 1 && stateY.getVirtualObject().entryCount() == 1; + assert stateX.getVirtualObject().type() == stateY.getVirtualObject().type(); + assert stateX.getVirtualObject().entryKind(0) == Kind.Int || stateX.getVirtualObject().entryKind(0) == Kind.Long; + final IntegerEqualsNode equals = new IntegerEqualsNode(stateX.getEntry(0), stateY.getEntry(0)); + tool.customAction(new Runnable() { + + @Override + public void run() { + graph().add(equals); + } + }); + tool.replaceWithValue(equals); + } else { + // both are virtual with identity: check if they refer to the same object + tool.replaceWithValue(LogicConstantNode.forBoolean(stateX == stateY, graph())); + } } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -121,6 +121,9 @@ @Override public void lower(LoweringTool tool) { + if (!enabled) { + throw new GraalInternalError("counter nodes shouldn't exist when not enabled"); + } StructuredGraph graph = (StructuredGraph) graph(); if (excludedClassPrefix == null || !graph.method().getDeclaringClass().getName().startsWith(excludedClassPrefix)) { int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java Sat Apr 20 12:23:29 2013 +0200 @@ -33,5 +33,5 @@ void setNullCheck(boolean check); - Node node(); + Node asNode(); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -79,7 +79,7 @@ } @Override - public Node node() { + public Node asNode() { return this; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,80 +23,84 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -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.*; - -public final class BoxNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Canonicalizable { +import com.oracle.graal.nodes.virtual.*; - @Input private ValueNode source; - private final int bci; - private final Kind sourceKind; +/** + * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf + * methods in Integer, Long, etc. + */ +public class BoxNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Canonicalizable { - public BoxNode(ValueNode value, ResolvedJavaType type, Kind sourceKind, int bci) { - super(StampFactory.exactNonNull(type)); - this.source = value; - this.bci = bci; - this.sourceKind = sourceKind; - assert value.kind() != Kind.Object : "can only box from primitive type"; + @Input private ValueNode value; + private final Kind boxingKind; + + public BoxNode(ValueNode value, ResolvedJavaType resultType, Kind boxingKind) { + super(StampFactory.exactNonNull(resultType)); + this.value = value; + this.boxingKind = boxingKind; } - public ValueNode source() { - return source; - } - - public Kind getSourceKind() { - return sourceKind; + public Kind getBoxingKind() { + return boxingKind; } - public void expand(BoxingMethodPool pool) { - ResolvedJavaMethod boxingMethod = pool.getBoxingMethod(sourceKind); - MethodCallTargetNode callTarget = graph().add( - new MethodCallTargetNode(InvokeKind.Static, boxingMethod, new ValueNode[]{source}, boxingMethod.getSignature().getReturnType(boxingMethod.getDeclaringClass()))); - InvokeNode invokeNode = graph().add(new InvokeNode(callTarget, bci)); - invokeNode.setProbability(this.probability()); - invokeNode.setStateAfter(stateAfter()); - ((StructuredGraph) graph()).replaceFixedWithFixed(this, invokeNode); + public ValueNode getValue() { + return value; + } + + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); } @Override public ValueNode canonical(CanonicalizerTool tool) { + /* + * Constant values are not canonicalized into their constant boxing objects because this + * would mean that the information that they came from a valueOf is lost. + */ + if (usages().isEmpty()) { + return null; + } + return this; + } - if (source.isConstant()) { - Constant sourceConstant = source.asConstant(); - switch (sourceKind) { - case Boolean: - return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asBoolean()), tool.runtime(), graph()); - case Byte: - return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), tool.runtime(), graph()); - case Char: - return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), tool.runtime(), graph()); - case Short: - return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), tool.runtime(), graph()); - case Int: - return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), tool.runtime(), graph()); - case Long: - return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), tool.runtime(), graph()); - case Float: - return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), tool.runtime(), graph()); - case Double: - return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), tool.runtime(), graph()); - default: - assert false : "Unexpected source kind for boxing"; - break; + @Override + public void virtualize(VirtualizerTool tool) { + ValueNode v = tool.getReplacedValue(getValue()); + ResolvedJavaType type = objectStamp().type(); + + VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind); + assert newVirtual.getFields().length == 1; + + tool.createVirtualObject(newVirtual, new ValueNode[]{v}, 0); + tool.replaceWithVirtual(newVirtual); + } + + @NodeIntrinsic + public static native Boolean box(boolean value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native Byte box(byte value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - } - } + @NodeIntrinsic + public static native Character box(char value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native Double box(double value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native Float box(float value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - for (Node usage : usages()) { - if (usage != stateAfter()) { - return this; - } - } - replaceAtUsages(null); - return null; - } + @NodeIntrinsic + public static native Integer box(int value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native Long box(long value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native Short box(short value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.extended; - -import java.util.*; - -import com.oracle.graal.api.meta.*; - -public class BoxingMethodPool { - - private final Set specialMethods = new HashSet<>(); - private final MetaAccessProvider runtime; - private final ResolvedJavaMethod[] boxingMethods = new ResolvedJavaMethod[Kind.values().length]; - private final ResolvedJavaMethod[] unboxingMethods = new ResolvedJavaMethod[Kind.values().length]; - private final ResolvedJavaField[] boxFields = new ResolvedJavaField[Kind.values().length]; - - public BoxingMethodPool(MetaAccessProvider runtime) { - this.runtime = runtime; - - try { - initialize(Kind.Boolean, Boolean.class, "booleanValue"); - initialize(Kind.Byte, Byte.class, "byteValue"); - initialize(Kind.Char, Character.class, "charValue"); - initialize(Kind.Short, Short.class, "shortValue"); - initialize(Kind.Int, Integer.class, "intValue"); - initialize(Kind.Long, Long.class, "longValue"); - initialize(Kind.Float, Float.class, "floatValue"); - initialize(Kind.Double, Double.class, "doubleValue"); - } catch (SecurityException | NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - private void initialize(Kind kind, Class type, String unboxMethod) throws SecurityException, NoSuchMethodException { - // Get boxing method from runtime. - ResolvedJavaMethod boxingMethod = runtime.lookupJavaMethod(type.getDeclaredMethod("valueOf", kind.toJavaClass())); - specialMethods.add(boxingMethod); - boxingMethods[kind.ordinal()] = boxingMethod; - - // Get unboxing method from runtime. - ResolvedJavaMethod unboxingMethod = runtime.lookupJavaMethod(type.getDeclaredMethod(unboxMethod)); - unboxingMethods[kind.ordinal()] = unboxingMethod; - specialMethods.add(unboxingMethod); - - // Get the field that contains the boxed value. - ResolvedJavaField[] fields = runtime.lookupJavaType(type).getInstanceFields(false); - ResolvedJavaField boxField = fields[0]; - assert fields.length == 1 && boxField.getKind() == kind; - boxFields[kind.ordinal()] = boxField; - } - - public boolean isSpecialMethod(ResolvedJavaMethod method) { - return specialMethods.contains(method); - } - - public boolean isBoxingMethod(ResolvedJavaMethod method) { - return isSpecialMethod(method) && method.getSignature().getReturnKind() == Kind.Object; - } - - public boolean isUnboxingMethod(ResolvedJavaMethod method) { - return isSpecialMethod(method) && method.getSignature().getReturnKind() != Kind.Object; - } - - public ResolvedJavaMethod getBoxingMethod(Kind kind) { - return boxingMethods[kind.ordinal()]; - } - - public ResolvedJavaMethod getUnboxingMethod(Kind kind) { - return unboxingMethods[kind.ordinal()]; - } - - public ResolvedJavaField getBoxField(Kind kind) { - return boxFields[kind.ordinal()]; - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -76,7 +76,7 @@ } @Override - public Node node() { + public Node asNode() { return this; } @@ -97,6 +97,7 @@ @Override public void setDeoptimizationState(FrameState f) { + updateUsages(deoptState, f); deoptState = f; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -105,7 +105,7 @@ ResolvedJavaType fieldType = ((ResolvedJavaField) locId).getDeclaringClass(); ResolvedJavaType beforePiType = parent.object().objectStamp().type(); - if (fieldType.isAssignableFrom(beforePiType)) { + if (beforePiType != null && fieldType.isAssignableFrom(beforePiType)) { replaceFirstInput(parent, parent.object()); return true; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -81,7 +81,8 @@ if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) { stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind()); } - return stateDuring; + updateUsages(deoptState, stateDuring); + return deoptState = stateDuring; } return null; } @@ -91,6 +92,7 @@ if (deoptState != null) { throw new IllegalStateException(); } + updateUsages(deoptState, f); deoptState = f; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,47 +23,49 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public final class UnboxNode extends FixedWithNextNode implements Node.IterableNodeType, Canonicalizable { +public class UnboxNode extends FixedWithNextNode implements Virtualizable, Lowerable, Canonicalizable { - @Input private ValueNode source; - private Kind destinationKind; + @Input private ValueNode value; + private final Kind boxingKind; - public UnboxNode(Kind kind, ValueNode source) { - super(StampFactory.forKind(kind)); - this.source = source; - this.destinationKind = kind; - assert kind != Kind.Object : "can only unbox to primitive"; - assert source.kind() == Kind.Object : "can only unbox objects"; + public UnboxNode(ValueNode value, Kind boxingKind) { + super(StampFactory.forKind(boxingKind.getStackKind())); + this.value = value; + this.boxingKind = boxingKind; + } + + public Kind getBoxingKind() { + return boxingKind; } - public ValueNode source() { - return source; + public ValueNode getValue() { + return value; } - public Kind destinationKind() { - return destinationKind; + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); } - public void expand(BoxingMethodPool pool) { - ResolvedJavaField field = pool.getBoxField(kind()); - LoadFieldNode loadField = graph().add(new LoadFieldNode(source, field)); - loadField.setProbability(probability()); - ((StructuredGraph) graph()).replaceFixedWithFixed(this, loadField); + @Override + public void virtualize(VirtualizerTool tool) { + State state = tool.getObjectState(value); + if (state != null && state.getState() == EscapeState.Virtual) { + tool.replaceWithValue(state.getEntry(0)); + } } @Override public ValueNode canonical(CanonicalizerTool tool) { - if (source.isConstant()) { - Constant constant = source.asConstant(); + if (value.isConstant()) { + Constant constant = value.asConstant(); Object o = constant.asObject(); if (o != null) { - switch (destinationKind) { + switch (boxingKind) { case Boolean: return ConstantNode.forBoolean((Boolean) o, graph()); case Byte: @@ -84,7 +86,36 @@ ValueNodeUtil.shouldNotReachHere(); } } + } else if (value instanceof BoxNode) { + return ((BoxNode) value).getValue(); + } + if (usages().isEmpty()) { + return null; } return this; } + + @NodeIntrinsic + public static native boolean unbox(Boolean value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native byte unbox(Byte value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native char unbox(Character value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native double unbox(Double value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native float unbox(Float value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native int unbox(Integer value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native long unbox(Long value, @ConstantNodeParameter Kind kind); + + @NodeIntrinsic + public static native short unbox(Short value, @ConstantNodeParameter Kind kind); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -37,8 +37,8 @@ return length; } - public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp) { - super(object, stamp); + public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, ValueNode anchor) { + super(object, stamp, anchor); this.length = length; } @@ -51,5 +51,5 @@ } @NodeIntrinsic - public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp); + public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor); } diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,14 +25,34 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.graph.*; /** * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}. */ -public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint { +public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint, Node.IterableNodeType { @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; + private final WriteBarrierType barrierType; + + /* + * The types of write barriers attached to stores. + */ + public enum WriteBarrierType { + /* + * Primitive stores which do not necessitate write barriers. + */ + NONE, + /* + * Array object stores which necessitate precise write barriers. + */ + PRECISE, + /* + * Field object stores which necessitate imprecise write barriers. + */ + IMPRECISE + } public FrameState stateAfter() { return stateAfter; @@ -52,9 +72,14 @@ return value; } - public WriteNode(ValueNode object, ValueNode value, ValueNode location) { + public WriteBarrierType getWriteBarrierType() { + return barrierType; + } + + public WriteNode(ValueNode object, ValueNode value, ValueNode location, WriteBarrierType barrierType) { super(object, location, StampFactory.forVoid()); this.value = value; + this.barrierType = barrierType; } @Override @@ -63,7 +88,7 @@ } @NodeIntrinsic - public static native void writeMemory(Object object, Object value, Object location); + public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter boolean usePreciseWriteBarriers); @Override public Object[] getLocationIdentities() { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; /** * The {@code AccessMonitorNode} is the base class of both monitor acquisition and release. @@ -72,7 +73,7 @@ @Override public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object); - if (state != null && state.getState() == EscapeState.Virtual) { + if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().getClass() == VirtualInstanceNode.class) { Debug.log("monitor operation %s on %s\n", this, state); int newLockCount = state.getLockCount() + (this instanceof MonitorEnterNode ? 1 : -1); state.setLockCount(newLockCount); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -75,11 +75,20 @@ // checkcast. return object(); } + + // remove checkcast if the only usage is a more specific checkcast + if (usages().count() == 1) { + CheckCastNode ccn = usages().filter(CheckCastNode.class).first(); + if (ccn != null && ccn.type() != null && type.isAssignableFrom(ccn.type())) { + return object(); + } + } } if (object().objectStamp().alwaysNull()) { return object(); } + return this; } @@ -102,7 +111,9 @@ public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object); if (state != null && state.getState() == EscapeState.Virtual) { - tool.replaceWithVirtual(state.getVirtualObject()); + if (type.isAssignableFrom(state.getVirtualObject().type())) { + tool.replaceWithVirtual(state.getVirtualObject()); + } } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,8 +25,10 @@ import static com.oracle.graal.graph.UnsafeAccess.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.extended.WriteNode.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -34,13 +36,15 @@ * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the * value matched the expected value. */ -public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint { +public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, LIRLowerable, Lowerable, MemoryCheckpoint, Node.IterableNodeType { @Input private ValueNode object; @Input private ValueNode offset; @Input private ValueNode expected; @Input private ValueNode newValue; + @Input private LocationNode location; private final int displacement; + private WriteBarrierType barrierType; public ValueNode object() { return object; @@ -62,6 +66,23 @@ return displacement; } + public LocationNode getLocation() { + return location; + } + + public void setLocation(LocationNode location) { + updateUsages(this.location, location); + this.location = location; + } + + public WriteBarrierType getWriteBarrierType() { + return barrierType; + } + + public void setWriteBarrierType(WriteBarrierType type) { + this.barrierType = type; + } + public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) { super(StampFactory.forKind(Kind.Boolean.getStackKind())); assert expected.kind() == newValue.kind(); @@ -70,6 +91,7 @@ this.expected = expected; this.newValue = newValue; this.displacement = displacement; + this.barrierType = WriteBarrierType.NONE; } @Override diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -48,8 +48,15 @@ // } + private boolean isLowered() { + return (stamp() == StampFactory.forVoid()); + } + @Override public void lower(LoweringTool tool) { + if (isLowered()) { + return; + } StructuredGraph graph = (StructuredGraph) graph(); LoadExceptionObjectNode loadException = graph.add(new LoadExceptionObjectNode(stamp())); loadException.setStateAfter(stateAfter()); @@ -62,6 +69,9 @@ @Override public boolean verify() { + if (isLowered()) { + return true; + } assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state"); return super.verify(); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -63,7 +63,7 @@ ObjectStamp stamp = object().objectStamp(); ResolvedJavaType stampType = stamp.type(); - if (stamp.isExactType()) { + if (stamp.isExactType() || stampType != null) { boolean subType = type().isAssignableFrom(stampType); if (subType) { @@ -77,27 +77,15 @@ return graph().unique(new IsNullNode(object())); } } else { - // since this type check failed for an exact type we know that it can never succeed - // at run time. - // we also don't care about null values, since they will also make the check fail. - return LogicConstantNode.contradiction(graph()); - } - } else if (stampType != null) { - boolean subType = type().isAssignableFrom(stampType); - - if (subType) { - if (stamp.nonNull()) { - // the instanceOf matches, so return true - return LogicConstantNode.tautology(graph()); + if (stamp.isExactType()) { + // since this type check failed for an exact type we know that it can never + // succeed at run time. we also don't care about null values, since they will + // also make the check fail. + return LogicConstantNode.contradiction(graph()); } else { - // the instanceof matches if the object is non-null, so return true depending on - // the null-ness. - negateUsages(); - return graph().unique(new IsNullNode(object())); + // since the subtype comparison was only performed on a declared type we don't + // really know if it might be true at run time... } - } else { - // since the subtype comparison was only performed on a declared type we don't - // really know if it might be true at run time... } } if (object().objectStamp().alwaysNull()) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -65,7 +65,8 @@ } else if (stamp.type() != null && !stamp.type().hasFinalizableSubclass()) { // if either the declared type of receiver or the holder // can be assumed to have no finalizers - if (tool.assumptions().useOptimisticAssumptions() && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) { + if (tool.assumptions().useOptimisticAssumptions()) { + tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type()); needsCheck = false; } } @@ -97,6 +98,7 @@ @Override public void setDeoptimizationState(FrameState f) { + updateUsages(deoptState, f); deoptState = f; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.spi; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; /** @@ -30,5 +31,17 @@ */ public interface GraalCodeCacheProvider extends CodeCacheProvider { + /** + * Adds the given compilation result as an implementation of the given method without making it + * the default implementation. The graph might be inlined later on. + * + * @param method a method to which the executable code is begin added + * @param compResult the compilation result to be added + * @param graph the graph that represents the method + * @return a reference to the compiled and ready-to-run code or null if the code installation + * failed + */ + InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph); + void lower(Node n, LoweringTool tool); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Sat Apr 20 12:23:29 2013 +0200 @@ -137,4 +137,6 @@ */ public void beforeRegisterAllocation() { } + + public abstract void visitInfopointNode(InfopointNode i); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java Sat Apr 20 12:23:29 2013 +0200 @@ -61,9 +61,25 @@ String signature() default ""; /** + * Determines if the substitution is for a method that may not be part of the runtime. For + * example, a method introduced in a later JDK version. Substitutions for such methods are + * omitted if the original method cannot be found. + */ + boolean optional() default false; + + /** * The node class with which the method invocation should be replaced. It needs to be a subclass * of {@link FixedWithNextNode}, and it is expected to provide a public constructor that takes * an {@link InvokeNode} as a parameter. */ Class macro(); + + /** + * Determines if this method should be substituted in all cases, even if inlining thinks it is + * not important. + * + * Not that this is still depending on whether inlining sees the correct call target, so it's + * only a hard guarantee for static and special invocations. + */ + boolean forced() default false; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.spi; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -61,13 +63,30 @@ Assumptions getAssumptions(); /** - * Registers all the snippet methods defined by a given class. - */ - void registerSnippets(Class snippets); - - /** * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution * macro} substitutions defined by a given class. */ void registerSubstitutions(Class substitutions); + + /** + * Returns all methods that are currently registered as method/macro substitution or as a + * snippet. + */ + Collection getAllReplacements(); + + /** + * Determines whether the replacement of this method is flagged as being inlined always. + */ + boolean isForcedSubstitution(ResolvedJavaMethod methodAt); + + /** + * Register snippet templates. + */ + void registerSnippetTemplateCache(SnippetTemplateCache snippetTemplates); + + /** + * Get snippet templates that were registered with + * {@link Replacements#registerSnippetTemplateCache(SnippetTemplateCache)}. + */ + T getSnippetTemplateCache(Class templatesClass); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,10 +22,13 @@ */ package com.oracle.graal.nodes.spi; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + /** * Interface for service providers that register replacements with the compiler. */ public interface ReplacementsProvider { - void registerReplacements(Replacements replacements); + void registerReplacements(MetaAccessProvider runtime, Replacements replacements, TargetDescription target); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,12 +23,15 @@ package com.oracle.graal.nodes.type; import com.oracle.graal.api.code.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.type.GenericStamp.GenericStampType; public class StampFactory { + // JaCoCo Exclude + private static final Stamp[] stampCache = new Stamp[Kind.values().length]; private static final Stamp objectStamp = new ObjectStamp(null, false, false, false); private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false); diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Sat Apr 20 12:23:29 2013 +0200 @@ -202,7 +202,7 @@ while (n != null) { if (n instanceof MethodCallTargetNode) { elements.add(((MethodCallTargetNode) n).targetMethod().asStackTraceElement(-1)); - n = ((MethodCallTargetNode) n).invoke().node(); + n = ((MethodCallTargetNode) n).invoke().asNode(); } if (n instanceof StateSplit) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.virtual; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -public class BoxedVirtualObjectNode extends VirtualObjectNode implements LIRLowerable, Node.ValueNumberable { - - @Input ValueNode unboxedValue; - private final ResolvedJavaType type; - private final Kind kind; - - public BoxedVirtualObjectNode(ResolvedJavaType type, Kind kind, ValueNode unboxedValue) { - this.type = type; - this.kind = kind; - this.unboxedValue = unboxedValue; - } - - public ValueNode getUnboxedValue() { - return unboxedValue; - } - - @Override - public ResolvedJavaType type() { - return type; - } - - @Override - public int entryCount() { - return 1; - } - - @Override - public String fieldName(int index) { - assert index == 0; - return "value"; - } - - @Override - public int entryIndexForOffset(long constantOffset) { - // (lstadler) unsafe access to a newly created boxing object should only ever touch the - // value field - return 0; - } - - @Override - public Kind entryKind(int index) { - return kind; - } - - @Override - public BoxedVirtualObjectNode duplicate() { - return new BoxedVirtualObjectNode(type, kind, unboxedValue); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,10 +22,14 @@ */ package com.oracle.graal.nodes.virtual; +import java.util.*; + import sun.misc.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @NodeInfo(nameTemplate = "VirtualArray {p#componentType/s}[{p#length}]") @@ -137,4 +141,19 @@ public VirtualArrayNode duplicate() { return new VirtualArrayNode(componentType, length); } + + @Override + public void materializeAt(FixedWithNextNode materializeNode, List values, boolean defaultValuesOnly, int lockCount) { + StructuredGraph graph = (StructuredGraph) graph(); + ResolvedJavaType element = componentType(); + NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount(), graph), defaultValuesOnly, lockCount > 0)); + materializeNode.replaceAtUsages(newArray); + graph.addBeforeFixed(materializeNode, newArray); + if (!defaultValuesOnly) { + for (int i = 0; i < entryCount(); i++) { + graph.addBeforeFixed(materializeNode, graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.getKind(), values.get(i)))); + } + } + graph.removeFixed(materializeNode); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualBoxingNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,58 @@ +/* + * 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.virtual; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; + +public class VirtualBoxingNode extends VirtualInstanceNode { + + private final Kind boxingKind; + + public VirtualBoxingNode(ResolvedJavaType type, Kind boxingKind) { + super(type); + this.boxingKind = boxingKind; + } + + @Override + public VirtualBoxingNode duplicate() { + return new VirtualBoxingNode(type(), boxingKind); + } + + @Override + public boolean hasIdentity() { + return false; + } + + @Override + public void materializeAt(FixedWithNextNode materializeNode, List values, boolean defaultValuesOnly, int lockCount) { + assert values.size() == 1; + assert lockCount == 0; + StructuredGraph graph = (StructuredGraph) graph(); + BoxNode valueOf = graph.add(new BoxNode(values.get(0), type(), boxingKind)); + graph.replaceFixedWithFixed(materializeNode, valueOf); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,8 +22,12 @@ */ package com.oracle.graal.nodes.virtual; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; @NodeInfo(nameTemplate = "VirtualInstance {p#type}") public class VirtualInstanceNode extends VirtualObjectNode { @@ -93,4 +97,18 @@ public VirtualInstanceNode duplicate() { return new VirtualInstanceNode(type); } + + @Override + public void materializeAt(FixedWithNextNode materializeNode, List values, boolean defaultValuesOnly, int lockCount) { + StructuredGraph graph = (StructuredGraph) graph(); + NewInstanceNode newInstance = graph.add(new NewInstanceNode(type(), defaultValuesOnly, lockCount > 0)); + materializeNode.replaceAtUsages(newInstance); + graph.addBeforeFixed(materializeNode, newInstance); + if (!defaultValuesOnly) { + for (int i = 0; i < entryCount(); i++) { + graph.addBeforeFixed(materializeNode, graph.add(new StoreFieldNode(newInstance, field(i), values.get(i)))); + } + } + graph.removeFixed(materializeNode); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.virtual; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -46,13 +48,15 @@ public abstract String fieldName(int i); - public void materializeAt(@SuppressWarnings("unused") FixedNode fixed) { - // nothing to do in here - this method allows subclasses to respond to materialization - } + public abstract void materializeAt(FixedWithNextNode materializeNode, List values, boolean defaultValuesOnly, int lockCount); public abstract int entryIndexForOffset(long constantOffset); public abstract Kind entryKind(int index); public abstract VirtualObjectNode duplicate(); + + public boolean hasIdentity() { + return true; + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import static com.oracle.graal.graph.iterators.NodePredicates.*; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.iterators.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; - -public class BoxingEliminationPhase extends Phase { - - private final MetaAccessProvider metaAccess; - - public BoxingEliminationPhase(MetaAccessProvider metaAccess) { - this.metaAccess = metaAccess; - } - - @Override - protected void run(StructuredGraph graph) { - if (graph.getNodes(UnboxNode.class).isNotEmpty()) { - - Map phiReplacements = new HashMap<>(); - for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) { - tryEliminate(graph, unboxNode, phiReplacements); - } - - new DeadCodeEliminationPhase().apply(graph); - - for (BoxNode boxNode : graph.getNodes(BoxNode.class)) { - tryEliminate(boxNode); - } - } - } - - private void tryEliminate(StructuredGraph graph, UnboxNode unboxNode, Map phiReplacements) { - ValueNode unboxedValue = unboxedValue(unboxNode.source(), unboxNode.destinationKind(), phiReplacements); - if (unboxedValue != null) { - assert unboxedValue.kind() == unboxNode.kind(); - unboxNode.replaceAtUsages(unboxedValue); - graph.removeFixed(unboxNode); - } - } - - private PhiNode getReplacementPhi(PhiNode phiNode, Kind kind, Map phiReplacements) { - if (!phiReplacements.containsKey(phiNode)) { - PhiNode result = null; - ObjectStamp stamp = phiNode.objectStamp(); - if (stamp.nonNull() && stamp.isExactType()) { - ResolvedJavaType type = stamp.type(); - if (type != null && type.equals(metaAccess.lookupJavaType(kind.toBoxedJavaClass()))) { - StructuredGraph graph = (StructuredGraph) phiNode.graph(); - result = graph.add(new PhiNode(kind, phiNode.merge())); - phiReplacements.put(phiNode, result); - virtualizeUsages(phiNode, result, type, kind); - int i = 0; - for (ValueNode n : phiNode.values()) { - ValueNode unboxedValue = unboxedValue(n, kind, phiReplacements); - if (unboxedValue != null) { - assert unboxedValue.kind() == kind; - result.addInput(unboxedValue); - } else { - UnboxNode unboxNode = graph.add(new UnboxNode(kind, n)); - FixedNode pred = phiNode.merge().phiPredecessorAt(i); - graph.addBeforeFixed(pred, unboxNode); - result.addInput(unboxNode); - } - ++i; - } - } - } - } - return phiReplacements.get(phiNode); - } - - private ValueNode unboxedValue(ValueNode n, Kind kind, Map phiReplacements) { - if (n instanceof BoxNode) { - BoxNode boxNode = (BoxNode) n; - return boxNode.source(); - } else if (n instanceof PhiNode) { - PhiNode phiNode = (PhiNode) n; - return getReplacementPhi(phiNode, kind, phiReplacements); - } else { - return null; - } - } - - private static void tryEliminate(BoxNode boxNode) { - - assert boxNode.objectStamp().isExactType(); - virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type(), boxNode.getSourceKind()); - - if (boxNode.usages().filter(isNotA(VirtualState.class)).isNotEmpty()) { - // Elimination failed, because boxing object escapes. - return; - } - - FrameState stateAfter = boxNode.stateAfter(); - boxNode.setStateAfter(null); - stateAfter.safeDelete(); - - ((StructuredGraph) boxNode.graph()).removeFixed(boxNode); - } - - private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType, Kind sourceKind) { - ValueNode virtualValueNode = null; - VirtualObjectNode virtualObjectNode = null; - for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) { - if (virtualValueNode == null) { - virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, sourceKind, replacement)); - } - n.replaceFirstInput(boxNode, virtualObjectNode); - } - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -36,8 +36,9 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; -public class CanonicalizerPhase extends Phase { +public class CanonicalizerPhase extends BasePhase { private static final int MAX_ITERATION_PER_NODE = 10; private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes"); @@ -47,155 +48,171 @@ private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes"); public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits"); - private final int newNodesMark; - private final Assumptions assumptions; - private final MetaAccessProvider runtime; private final CustomCanonicalizer customCanonicalizer; - private final Iterable initWorkingSet; - - private NodeWorkList workList; - private Tool tool; - private List snapshotTemp; public interface CustomCanonicalizer { - ValueNode canonicalize(Node node); - } - - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions) { - this(runtime, assumptions, null, 0, null); + ValueNode canonicalize(ValueNode node); } - /** - * @param runtime - * @param assumptions - * @param workingSet the initial working set of nodes on which the canonicalizer works, should - * be an auto-grow node bitmap - * @param customCanonicalizer - */ - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { - this(runtime, assumptions, workingSet, 0, customCanonicalizer); + public CanonicalizerPhase() { + this(null); } - /** - * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by this - * mark are processed otherwise all nodes in the graph are processed - */ - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { - this(runtime, assumptions, null, newNodesMark, customCanonicalizer); - } - - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { - this.newNodesMark = newNodesMark; - this.assumptions = assumptions; - this.runtime = runtime; + public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) { this.customCanonicalizer = customCanonicalizer; - this.initWorkingSet = workingSet; - this.snapshotTemp = new ArrayList<>(); } @Override - protected void run(StructuredGraph graph) { - if (initWorkingSet == null) { - workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE); - } else { - workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE); - workList.addAll(initWorkingSet); - } - if (newNodesMark > 0) { - workList.addAll(graph.getNewNodes(newNodesMark)); - } - tool = new Tool(workList, runtime, assumptions); - processWorkSet(graph); + protected void run(StructuredGraph graph, PhaseContext context) { + new Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).run(graph); } - private void processWorkSet(StructuredGraph graph) { - graph.trackInputChange(new InputChangedListener() { + public static class Instance extends Phase { + + private final int newNodesMark; + private final Assumptions assumptions; + private final MetaAccessProvider runtime; + private final CustomCanonicalizer customCanonicalizer; + private final Iterable initWorkingSet; + + private NodeWorkList workList; + private Tool tool; + private List snapshotTemp; + + public Instance(MetaAccessProvider runtime, Assumptions assumptions) { + this(runtime, assumptions, null, 0, null); + } - @Override - public void inputChanged(Node node) { - workList.addAgain(node); - } - }); + /** + * @param runtime + * @param assumptions + * @param workingSet the initial working set of nodes on which the canonicalizer works, + * should be an auto-grow node bitmap + * @param customCanonicalizer + */ + public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, workingSet, 0, customCanonicalizer); + } - for (Node n : workList) { - processNode(n, graph); + /** + * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by + * this mark are processed otherwise all nodes in the graph are processed + */ + public Instance(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, null, newNodesMark, customCanonicalizer); + } + + public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + super("Canonicalizer"); + this.newNodesMark = newNodesMark; + this.assumptions = assumptions; + this.runtime = runtime; + this.customCanonicalizer = customCanonicalizer; + this.initWorkingSet = workingSet; + this.snapshotTemp = new ArrayList<>(); } - graph.stopTrackingInputChange(); - } - - private void processNode(Node node, StructuredGraph graph) { - if (node.isAlive()) { - METRIC_PROCESSED_NODES.increment(); - - if (tryGlobalValueNumbering(node, graph)) { - return; + @Override + protected void run(StructuredGraph graph) { + if (initWorkingSet == null) { + workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE); + } else { + workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE); + workList.addAll(initWorkingSet); + } + if (newNodesMark > 0) { + workList.addAll(graph.getNewNodes(newNodesMark)); } - int mark = graph.getMark(); - if (!tryKillUnused(node)) { - node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); - if (!tryCanonicalize(node, graph)) { - tryInferStamp(node, graph); - } else { - for (Node in : snapshotTemp) { - if (in.isAlive() && in.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(in); + tool = new Tool(workList, runtime, assumptions); + processWorkSet(graph); + } + + private void processWorkSet(StructuredGraph graph) { + graph.trackInputChange(new InputChangedListener() { + + @Override + public void inputChanged(Node node) { + workList.addAgain(node); + } + }); + + for (Node n : workList) { + processNode(n, graph); + } + + graph.stopTrackingInputChange(); + } + + private void processNode(Node node, StructuredGraph graph) { + if (node.isAlive()) { + METRIC_PROCESSED_NODES.increment(); + + if (tryGlobalValueNumbering(node, graph)) { + return; + } + int mark = graph.getMark(); + if (!tryKillUnused(node)) { + node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); + if (!tryCanonicalize(node, graph)) { + tryInferStamp(node, graph); + } else { + for (Node in : snapshotTemp) { + if (in.isAlive() && in.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(in); + } } } + snapshotTemp.clear(); } - snapshotTemp.clear(); - } - for (Node newNode : graph.getNewNodes(mark)) { - workList.add(newNode); + for (Node newNode : graph.getNewNodes(mark)) { + workList.add(newNode); + } } } - } - private static boolean tryKillUnused(Node node) { - if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(node); - return true; - } - return false; - } - - public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) { - if (node.getNodeClass().valueNumberable()) { - Node newNode = graph.findDuplicate(node); - if (newNode != null) { - assert !(node instanceof FixedNode || newNode instanceof FixedNode); - node.replaceAtUsages(newNode); - node.safeDelete(); - METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment(); - Debug.log("GVN applied and new node is %1s", newNode); + private static boolean tryKillUnused(Node node) { + if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(node); return true; } + return false; } - return false; - } - public boolean tryCanonicalize(final Node node, final StructuredGraph graph) { - boolean result = baseTryCanonicalize(node, graph); - if (!result && customCanonicalizer != null) { - ValueNode canonical = customCanonicalizer.canonicalize(node); - if (canonical == node && customCanonicalizer != null) { - canonical = customCanonicalizer.canonicalize(node); + public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) { + if (node.getNodeClass().valueNumberable()) { + Node newNode = graph.findDuplicate(node); + if (newNode != null) { + assert !(node instanceof FixedNode || newNode instanceof FixedNode); + node.replaceAtUsages(newNode); + node.safeDelete(); + METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment(); + Debug.log("GVN applied and new node is %1s", newNode); + return true; + } } - result = performReplacement(node, graph, canonical); + return false; } - return result; - } - public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) { - if (node instanceof Canonicalizable) { - assert !(node instanceof Simplifiable); - METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); - return Debug.scope("CanonicalizeNode", node, new Callable() { + public boolean tryCanonicalize(final Node node, final StructuredGraph graph) { + boolean result = baseTryCanonicalize(node, graph); + if (!result && customCanonicalizer != null && node instanceof ValueNode) { + ValueNode valueNode = (ValueNode) node; + ValueNode canonical = customCanonicalizer.canonicalize(valueNode); + result = performReplacement(node, graph, canonical); + } + return result; + } - public Boolean call() { - ValueNode canonical = ((Canonicalizable) node).canonical(tool); + public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) { + if (node instanceof Canonicalizable) { + assert !(node instanceof Simplifiable); + METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); + return Debug.scope("CanonicalizeNode", node, new Callable() { + + public Boolean call() { + ValueNode canonical = ((Canonicalizable) node).canonical(tool); // @formatter:off // cases: original node: // |Floating|Fixed-unconnected|Fixed-connected| @@ -211,137 +228,139 @@ // X: must not happen (checked with assertions) // @formatter:on - return performReplacement(node, graph, canonical); - } - }); - } else if (node instanceof Simplifiable) { - Debug.log("Canonicalizer: simplifying %s", node); - METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); - Debug.scope("SimplifyNode", node, new Runnable() { + return performReplacement(node, graph, canonical); + } + }); + } else if (node instanceof Simplifiable) { + Debug.log("Canonicalizer: simplifying %s", node); + METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); + Debug.scope("SimplifyNode", node, new Runnable() { - public void run() { - ((Simplifiable) node).simplify(tool); - } - }); + public void run() { + ((Simplifiable) node).simplify(tool); + } + }); + } + return node.isDeleted(); } - return node.isDeleted(); - } - private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) { - if (canonical == node) { - Debug.log("Canonicalizer: work on %s", node); - return false; - } else { - Debug.log("Canonicalizer: replacing %s with %s", node, canonical); - METRIC_CANONICALIZED_NODES.increment(); - if (node instanceof FloatingNode) { - if (canonical == null) { - // case 1 - graph.removeFloating((FloatingNode) node); + private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) { + if (canonical == node) { + Debug.log("Canonicalizer: work on %s", node); + return false; + } else { + Debug.log("Canonicalizer: replacing %s with %s", node, canonical); + METRIC_CANONICALIZED_NODES.increment(); + if (node instanceof FloatingNode) { + if (canonical == null) { + // case 1 + graph.removeFloating((FloatingNode) node); + } else { + // case 2 + assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + + " : replacement should be floating or fixed and connected"; + graph.replaceFloating((FloatingNode) node, canonical); + } } else { - // case 2 - assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + - " : replacement should be floating or fixed and connected"; - graph.replaceFloating((FloatingNode) node, canonical); - } - } else { - assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; - FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; + assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; + FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; - // When removing a fixed node, new canonicalization opportunities for its successor - // may arise - assert fixedWithNext.next() != null; - tool.addToWorkList(fixedWithNext.next()); + // When removing a fixed node, new canonicalization opportunities for its +// successor + // may arise + assert fixedWithNext.next() != null; + tool.addToWorkList(fixedWithNext.next()); - if (canonical == null) { - // case 3 - graph.removeFixed(fixedWithNext); - } else if (canonical instanceof FloatingNode) { - // case 4 - graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); - } else { - assert canonical instanceof FixedNode; - if (canonical.predecessor() == null) { - assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; - // case 5 - graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + if (canonical == null) { + // case 3 + graph.removeFixed(fixedWithNext); + } else if (canonical instanceof FloatingNode) { + // case 4 + graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); } else { - assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; - // case 6 - node.replaceAtUsages(canonical); - graph.removeFixed(fixedWithNext); + assert canonical instanceof FixedNode; + if (canonical.predecessor() == null) { + assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; + // case 5 + graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + } else { + assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; + // case 6 + node.replaceAtUsages(canonical); + graph.removeFixed(fixedWithNext); + } } } + return true; } - return true; } - } - /** - * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that - * the stamp has changed), re-queues the node's usages . If the stamp has changed then this - * method also checks if the stamp now describes a constant integer value, in which case the - * node is replaced with a constant. - */ - private void tryInferStamp(Node node, StructuredGraph graph) { - if (node.isAlive() && node instanceof ValueNode) { - ValueNode valueNode = (ValueNode) node; - METRIC_INFER_STAMP_CALLED.increment(); - if (valueNode.inferStamp()) { - METRIC_STAMP_CHANGED.increment(); - if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) { - ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph); - Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement); - valueNode.replaceAtUsages(replacement); - } else { - for (Node usage : valueNode.usages()) { - workList.addAgain(usage); + /** + * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means + * that the stamp has changed), re-queues the node's usages . If the stamp has changed then + * this method also checks if the stamp now describes a constant integer value, in which + * case the node is replaced with a constant. + */ + private void tryInferStamp(Node node, StructuredGraph graph) { + if (node.isAlive() && node instanceof ValueNode) { + ValueNode valueNode = (ValueNode) node; + METRIC_INFER_STAMP_CALLED.increment(); + if (valueNode.inferStamp()) { + METRIC_STAMP_CHANGED.increment(); + if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) { + ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph); + Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement); + valueNode.replaceAtUsages(replacement); + } else { + for (Node usage : valueNode.usages()) { + workList.addAgain(usage); + } } } } } - } - private static final class Tool implements SimplifierTool { + private static final class Tool implements SimplifierTool { - private final NodeWorkList nodeWorkSet; - private final MetaAccessProvider runtime; - private final Assumptions assumptions; + private final NodeWorkList nodeWorkSet; + private final MetaAccessProvider runtime; + private final Assumptions assumptions; - public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) { - this.nodeWorkSet = nodeWorkSet; - this.runtime = runtime; - this.assumptions = assumptions; - } + public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) { + this.nodeWorkSet = nodeWorkSet; + this.runtime = runtime; + this.assumptions = assumptions; + } - @Override - public void deleteBranch(FixedNode branch) { - branch.predecessor().replaceFirstSuccessor(branch, null); - GraphUtil.killCFG(branch); - } + @Override + public void deleteBranch(FixedNode branch) { + branch.predecessor().replaceFirstSuccessor(branch, null); + GraphUtil.killCFG(branch); + } - /** - * @return an object that can be used for recording assumptions or {@code null} if - * assumptions are not allowed in the current context. - */ - @Override - public Assumptions assumptions() { - return assumptions; - } + /** + * @return an object that can be used for recording assumptions or {@code null} if + * assumptions are not allowed in the current context. + */ + @Override + public Assumptions assumptions() { + return assumptions; + } - @Override - public MetaAccessProvider runtime() { - return runtime; - } + @Override + public MetaAccessProvider runtime() { + return runtime; + } - @Override - public void addToWorkList(Node node) { - nodeWorkSet.addAgain(node); - } + @Override + public void addToWorkList(Node node) { + nodeWorkSet.addAgain(node); + } - @Override - public void removeIfUnused(Node node) { - tryKillUnused(node); + @Override + public void removeIfUnused(Node node) { + tryKillUnused(node); + } } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -346,7 +346,7 @@ private static Scope createScope(Loop loop, HashMap processedLoops) { Scope parent = processedLoops.get(loop.parent); if (parent == null) { - parent = createScope(loop, processedLoops); + parent = createScope(loop.parent, processedLoops); } Scope result = new Scope(loop.loopBegin(), parent); processedLoops.put(loop, result); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandBoxingNodesPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandBoxingNodesPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.phases.*; - -public class ExpandBoxingNodesPhase extends Phase { - - private final BoxingMethodPool pool; - - public ExpandBoxingNodesPhase(BoxingMethodPool pool) { - this.pool = pool; - } - - @Override - protected void run(StructuredGraph graph) { - for (BoxNode boxNode : graph.getNodes(BoxNode.class)) { - boxNode.expand(pool); - } - - for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) { - unboxNode.expand(pool); - } - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -71,15 +71,20 @@ } } - private final Map> modifiedInLoops = new IdentityHashMap<>(); - @Override protected void run(StructuredGraph graph) { - ReentrantNodeIterator.apply(new CollectMemoryCheckpointsClosure(), graph.start(), new HashSet<>(), null); - ReentrantNodeIterator.apply(new FloatingReadClosure(), graph.start(), new MemoryMap(graph.start()), null); + Map> modifiedInLoops = new IdentityHashMap<>(); + ReentrantNodeIterator.apply(new CollectMemoryCheckpointsClosure(modifiedInLoops), graph.start(), new HashSet<>(), null); + ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops), graph.start(), new MemoryMap(graph.start()), null); } - private class CollectMemoryCheckpointsClosure extends NodeIteratorClosure> { + private static class CollectMemoryCheckpointsClosure extends NodeIteratorClosure> { + + private final Map> modifiedInLoops; + + public CollectMemoryCheckpointsClosure(Map> modifiedInLoops) { + this.modifiedInLoops = modifiedInLoops; + } @Override protected void processNode(FixedNode node, Set currentState) { @@ -122,7 +127,13 @@ } - private class FloatingReadClosure extends NodeIteratorClosure { + private static class FloatingReadClosure extends NodeIteratorClosure { + + private final Map> modifiedInLoops; + + public FloatingReadClosure(Map> modifiedInLoops) { + this.modifiedInLoops = modifiedInLoops; + } @Override protected void processNode(FixedNode node, MemoryMap state) { @@ -133,7 +144,7 @@ } } - private void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) { + private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) { for (Object identity : checkpoint.getLocationIdentities()) { if (identity == LocationNode.ANY_LOCATION) { state.lastMemorySnapshot.clear(); @@ -142,7 +153,7 @@ } } - private void processFloatable(FloatableAccessNode accessNode, MemoryMap state) { + private static void processFloatable(FloatableAccessNode accessNode, MemoryMap state) { StructuredGraph graph = (StructuredGraph) accessNode.graph(); assert accessNode.getNullCheck() == false; Object locationIdentity = accessNode.location().locationIdentity(); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013, 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.phases.common; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; + +public class FrameStateAssignmentPhase extends Phase { + + private static class FrameStateAssignmentState { + + private FrameState framestate; + + public FrameStateAssignmentState(FrameState framestate) { + this.framestate = framestate; + } + + public FrameState getFramestate() { + return framestate; + } + + public void setFramestate(FrameState framestate) { + assert framestate != null; + this.framestate = framestate; + } + + @Override + public String toString() { + return "FrameStateAssignementState: " + framestate; + } + } + + private static class FrameStateAssignementClosure extends BlockIteratorClosure { + + @Override + protected void processBlock(Block block, FrameStateAssignmentState currentState) { + FixedNode node = block.getBeginNode(); + while (node != null) { + if (node instanceof DeoptimizingNode) { + DeoptimizingNode deopt = (DeoptimizingNode) node; + if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) { + deopt.setDeoptimizationState(currentState.getFramestate()); + } + } + + if (node instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) node; + if (stateSplit.stateAfter() != null) { + currentState.setFramestate(stateSplit.stateAfter()); + stateSplit.setStateAfter(null); + } + } + + if (node instanceof FixedWithNextNode) { + node = ((FixedWithNextNode) node).next(); + } else { + node = null; + } + } + } + + @Override + protected FrameStateAssignmentState merge(Block mergeBlock, List states) { + MergeNode merge = (MergeNode) mergeBlock.getBeginNode(); + if (merge.stateAfter() != null) { + return new FrameStateAssignmentState(merge.stateAfter()); + } + return new FrameStateAssignmentState(singleFrameState(states)); + } + + @Override + protected FrameStateAssignmentState cloneState(FrameStateAssignmentState oldState) { + return new FrameStateAssignmentState(oldState.getFramestate()); + } + + @Override + protected List processLoop(Loop loop, FrameStateAssignmentState initialState) { + return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates; + } + + } + + @Override + protected void run(StructuredGraph graph) { + assert checkFixedDeopts(graph); + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false); + ReentrantBlockIterator.apply(new FrameStateAssignementClosure(), cfg.getStartBlock(), new FrameStateAssignmentState(null), null); + } + + private static boolean checkFixedDeopts(StructuredGraph graph) { + NodePredicate isFloatingNode = GraphUtil.isFloatingNode(); + for (Node n : graph.getNodes().filterInterface(DeoptimizingNode.class)) { + if (((DeoptimizingNode) n).canDeoptimize() && isFloatingNode.apply(n)) { + return false; + } + } + return true; + } + + private static FrameState singleFrameState(List states) { + Iterator it = states.iterator(); + assert it.hasNext(); + FrameState first = it.next().getFramestate(); + while (it.hasNext()) { + if (first != it.next().getFramestate()) { + return null; + } + } + return first; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -114,12 +114,12 @@ Access fixedAccess = access; if (access instanceof FloatingAccessNode) { fixedAccess = ((FloatingAccessNode) access).asFixedNode(); - replaceCurrent((FixedWithNextNode) fixedAccess.node()); + replaceCurrent((FixedWithNextNode) fixedAccess.asNode()); } assert fixedAccess instanceof FixedNode; fixedAccess.setNullCheck(true); LogicNode condition = guard.condition(); - guard.replaceAndDelete(fixedAccess.node()); + guard.replaceAndDelete(fixedAccess.asNode()); if (condition.usages().isEmpty()) { GraphUtil.killWithUnusedFloatingInputs(condition); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IdentifyBoxingPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IdentifyBoxingPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import java.lang.reflect.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.phases.*; - -public class IdentifyBoxingPhase extends Phase { - - private final BoxingMethodPool pool; - - public IdentifyBoxingPhase(BoxingMethodPool pool) { - this.pool = pool; - } - - @Override - protected void run(StructuredGraph graph) { - for (Invoke invoke : graph.getInvokes()) { - tryIntrinsify(invoke); - } - } - - public void tryIntrinsify(Invoke invoke) { - if (!(invoke.callTarget() instanceof MethodCallTargetNode)) { - return; - } - MethodCallTargetNode callTarget = invoke.methodCallTarget(); - ResolvedJavaMethod targetMethod = callTarget.targetMethod(); - if (pool.isSpecialMethod(targetMethod)) { - assert callTarget.arguments().size() == 1 : "boxing/unboxing method must have exactly one argument"; - Kind returnKind = callTarget.returnKind(); - ValueNode sourceValue = callTarget.arguments().get(0); - - // Check whether this is a boxing or an unboxing. - Node newNode = null; - if (returnKind == Kind.Object) { - // We have a boxing method here. - assert Modifier.isStatic(targetMethod.getModifiers()) : "boxing method must be static"; - Kind sourceKind = targetMethod.getSignature().getParameterKind(0); - newNode = invoke.graph().add(new BoxNode(sourceValue, targetMethod.getDeclaringClass(), sourceKind, invoke.bci())); - } else { - // We have an unboxing method here. - assert !Modifier.isStatic(targetMethod.getModifiers()) : "unboxing method must be an instance method"; - newNode = invoke.graph().add(new UnboxNode(returnKind, sourceValue)); - } - - // Intrinsify the invoke to the special node. - invoke.intrinsify(newNode); - } - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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.phases.common; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; +import com.oracle.graal.phases.tiers.*; + +public class IncrementalCanonicalizerPhase extends PhaseSuite { + + private final CustomCanonicalizer customCanonicalizer; + + public IncrementalCanonicalizerPhase() { + this(null); + } + + public IncrementalCanonicalizerPhase(CustomCanonicalizer customCanonicalizer) { + this.customCanonicalizer = customCanonicalizer; + } + + @Override + protected void run(StructuredGraph graph, C context) { + int mark = graph.getMark(); + super.run(graph, context); + new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), mark, customCanonicalizer).apply(graph); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; @@ -68,7 +69,8 @@ private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize"); private static final DebugMetric metricInliningRuns = Debug.metric("Runs"); - public InliningPhase(MetaAccessProvider runtime, Map hints, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) { + public InliningPhase(MetaAccessProvider runtime, Map hints, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan, + OptimisticOptimizations optimisticOpts) { this(runtime, replacements, assumptions, cache, plan, createInliningPolicy(runtime, replacements, assumptions, optimisticOpts, hints), optimisticOpts); } @@ -110,13 +112,13 @@ if (isWorthInlining) { int mark = graph.getMark(); try { - List invokeUsages = candidate.invoke().node().usages().snapshot(); + List invokeUsages = candidate.invoke().asNode().usages().snapshot(); candidate.inline(graph, runtime, replacements, this, assumptions); Debug.dump(graph, "after %s", candidate); Iterable newNodes = graph.getNewNodes(mark); inliningPolicy.scanInvokes(newNodes); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); } inliningCount++; metricInliningPerformed.increment(); @@ -160,7 +162,7 @@ new ComputeProbabilityPhase().apply(newGraph); } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(newGraph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph); } if (GraalOptions.CullFrameStates) { new CullFrameStatesPhase().apply(newGraph); @@ -200,8 +202,14 @@ * also getting queued in the compilation queue concurrently) */ - if (GraalOptions.AlwaysInlineIntrinsics && onlyIntrinsics(replacements, info)) { - return InliningUtil.logInlinedMethod(info, "intrinsic"); + if (GraalOptions.AlwaysInlineIntrinsics) { + if (onlyIntrinsics(replacements, info)) { + return InliningUtil.logInlinedMethod(info, "intrinsic"); + } + } else { + if (onlyForcedIntrinsics(replacements, info)) { + return InliningUtil.logInlinedMethod(info, "intrinsic"); + } } double bonus = 1; @@ -260,8 +268,9 @@ } private static int numberOfTransferredValues(InlineInfo info) { - Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature(); - int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers())); + MethodCallTargetNode methodCallTargetNode = ((MethodCallTargetNode) info.invoke().callTarget()); + Signature signature = methodCallTargetNode.targetMethod().getSignature(); + int transferredValues = signature.getParameterCount(!Modifier.isStatic(methodCallTargetNode.targetMethod().getModifiers())); if (signature.getReturnKind() != Kind.Void) { transferredValues++; } @@ -271,7 +280,7 @@ private static int countInvokeUsages(InlineInfo info) { // inlining calls with lots of usages simplifies the caller int usages = 0; - for (Node n : info.invoke().node().usages()) { + for (Node n : info.invoke().asNode().usages()) { if (!(n instanceof FrameState)) { usages++; } @@ -285,10 +294,11 @@ * argument simplifies the callee */ int moreSpecificArgumentInfo = 0; - boolean isStatic = info.invoke().methodCallTarget().isStatic(); + MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) info.invoke().callTarget(); + boolean isStatic = methodCallTarget.isStatic(); int signatureOffset = isStatic ? 0 : 1; - NodeInputList arguments = info.invoke().methodCallTarget().arguments(); - ResolvedJavaMethod targetMethod = info.invoke().methodCallTarget().targetMethod(); + NodeInputList arguments = methodCallTarget.arguments(); + ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod(); ResolvedJavaType methodHolderClass = targetMethod.getDeclaringClass(); Signature signature = targetMethod.getSignature(); @@ -347,6 +357,18 @@ } return true; } + + private static boolean onlyForcedIntrinsics(Replacements replacements, InlineInfo info) { + for (int i = 0; i < info.numberOfMethods(); i++) { + if (!InliningUtil.canIntrinsify(replacements, info.methodAt(i))) { + return false; + } + if (!replacements.isForcedSubstitution(info.methodAt(i))) { + return false; + } + } + return true; + } } private static class CFInliningPolicy implements InliningPolicy { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Sat Apr 20 12:23:29 2013 +0200 @@ -73,13 +73,47 @@ boolean isWorthInlining(InlineInfo info); } + /** + * Print a HotSpot-style inlining message to the console. + */ + private static void printInlining(final InlineInfo info, final boolean success, final String msg, final Object... args) { + printInlining(info.methodAt(0), info.invoke(), success, msg, args); + } + + /** + * Print a HotSpot-style inlining message to the console. + */ + private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final boolean success, final String msg, final Object... args) { + if (GraalOptions.HotSpotPrintInlining) { + final int mod = method.getModifiers(); + // 1234567 + TTY.print(" "); // print timestamp + // 1234 + TTY.print(" "); // print compilation number + // % s ! b n + TTY.print("%c%c%c%c%c ", ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' '); + TTY.print(" "); // more indent + TTY.print(" "); // initial inlining indent + final int level = computeInliningLevel(invoke); + for (int i = 0; i < level; i++) { + TTY.print(" "); + } + TTY.println(String.format("@ %d %s %s%s", invoke.bci(), methodName(method, null), success ? "" : "not inlining ", String.format(msg, args))); + } + } + + public static boolean logInlinedMethod(InlineInfo info, String msg, Object... args) { + logInliningDecision(info, true, msg, args); + return true; + } + public static boolean logNotInlinedMethod(InlineInfo info, String msg, Object... args) { - logInliningDecision(info, false, msg, args); return false; } public static void logInliningDecision(InlineInfo info, boolean success, String msg, final Object... args) { + printInlining(info, success, msg, args); if (shouldLogInliningDecision()) { logInliningDecision(methodName(info), success, msg, args); } @@ -94,11 +128,6 @@ }); } - public static boolean logInlinedMethod(InlineInfo info, String string, Object... args) { - logInliningDecision(info, true, string, args); - return true; - } - private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) { if (shouldLogInliningDecision()) { String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName()); @@ -112,6 +141,7 @@ } private static InlineInfo logNotInlinedMethodAndReturnNull(Invoke invoke, ResolvedJavaMethod method, String msg, Object... args) { + printInlining(method, invoke, false, msg, args); if (shouldLogInliningDecision()) { String methodString = methodName(method, invoke); logInliningDecision(methodString, false, msg, args); @@ -120,6 +150,7 @@ } private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, ResolvedJavaMethod method, String msg) { + printInlining(method, invoke, false, msg, new Object[0]); if (shouldLogInliningDecision()) { String methodString = methodName(method, invoke); logInliningDecision(methodString, false, msg, new Object[0]); @@ -221,15 +252,15 @@ protected static void inline(Invoke invoke, ResolvedJavaMethod concrete, InliningCallback callback, Replacements replacements, Assumptions assumptions, boolean receiverNullCheck) { Class macroNodeClass = getMacroNodeClass(replacements, concrete); - StructuredGraph graph = (StructuredGraph) invoke.graph(); + StructuredGraph graph = (StructuredGraph) invoke.asNode().graph(); if (macroNodeClass != null) { FixedWithNextNode macroNode; try { macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { - throw new GraalInternalError(e).addContext(invoke.node()).addContext("macroSubstitution", macroNodeClass); + throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass); } - macroNode.setProbability(invoke.node().probability()); + macroNode.setProbability(invoke.asNode().probability()); CallTargetNode callTarget = invoke.callTarget(); if (invoke instanceof InvokeNode) { graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode)); @@ -266,9 +297,9 @@ } protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) { - MethodCallTargetNode oldCallTarget = invoke.methodCallTarget(); + MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget(); MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); - invoke.node().replaceFirstInput(oldCallTarget, newCallTarget); + invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget); } } @@ -353,7 +384,7 @@ private void createGuard(StructuredGraph graph, MetaAccessProvider runtime) { InliningUtil.receiverNullCheck(invoke); - ValueNode receiver = invoke.methodCallTarget().receiver(); + ValueNode receiver = ((MethodCallTargetNode) invoke.callTarget()).receiver(); ConstantNode typeHub = ConstantNode.forConstant(type.getEncoding(Representation.ObjectHub), runtime, graph); LoadHubNode receiverHub = graph.add(new LoadHubNode(receiver, typeHub.kind())); CompareNode typeCheck = CompareNode.createCompareNode(Condition.EQ, receiverHub, typeHub); @@ -364,9 +395,9 @@ ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver, true); invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); - graph.addBeforeFixed(invoke.node(), receiverHub); - graph.addBeforeFixed(invoke.node(), guard); - graph.addBeforeFixed(invoke.node(), anchor); + graph.addBeforeFixed(invoke.asNode(), receiverHub); + graph.addBeforeFixed(invoke.asNode(), guard); + graph.addBeforeFixed(invoke.asNode(), anchor); } @Override @@ -432,15 +463,15 @@ int numberOfMethods = concretes.size(); FixedNode continuation = invoke.next(); - ValueNode originalReceiver = invoke.methodCallTarget().receiver(); + ValueNode originalReceiver = ((MethodCallTargetNode) invoke.callTarget()).receiver(); // setup merge and phi nodes for results and exceptions MergeNode returnMerge = graph.add(new MergeNode()); returnMerge.setProbability(invoke.probability()); returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci)); PhiNode returnValuePhi = null; - if (invoke.node().kind() != Kind.Void) { - returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge)); + if (invoke.asNode().kind() != Kind.Void) { + returnValuePhi = graph.unique(new PhiNode(invoke.asNode().kind(), returnMerge)); } MergeNode exceptionMerge = null; @@ -489,7 +520,7 @@ GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge()); } - assert invoke.node().isAlive(); + assert invoke.asNode().isAlive(); // replace the invoke with a switch on the type of the actual receiver createDispatchOnTypeBeforeInvoke(graph, successors, false); @@ -497,8 +528,8 @@ assert invoke.next() == continuation; invoke.setNext(null); returnMerge.setNext(continuation); - invoke.node().replaceAtUsages(returnValuePhi); - invoke.node().replaceAndDelete(null); + invoke.asNode().replaceAtUsages(returnValuePhi); + invoke.asNode().replaceAndDelete(null); ArrayList replacementNodes = new ArrayList<>(); @@ -508,7 +539,7 @@ Invoke invokeForInlining = (Invoke) node.next(); ResolvedJavaType commonType = getLeastCommonType(i); - ValueNode receiver = invokeForInlining.methodCallTarget().receiver(); + ValueNode receiver = ((MethodCallTargetNode) invokeForInlining.callTarget()).receiver(); boolean exact = getTypeCount(i) == 1; PiNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver, exact); invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver); @@ -528,7 +559,8 @@ FixedNode current = returnMerge; int opportunities = 0; do { - if (current instanceof InvokeNode && ((InvokeNode) current).methodCallTarget().receiver() == originalReceiver) { + if (current instanceof InvokeNode && ((InvokeNode) current).callTarget() instanceof MethodCallTargetNode && + ((MethodCallTargetNode) ((InvokeNode) current).callTarget()).receiver() == originalReceiver) { opportunities++; } else if (current.inputs().contains(originalReceiver)) { opportunities++; @@ -586,7 +618,7 @@ BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, false); - calleeEntryNode.setNext(invoke.node()); + calleeEntryNode.setNext(invoke.asNode()); ResolvedJavaMethod concrete = concretes.get(0); inline(invoke, concrete, callback, replacements, assumptions, false); @@ -595,9 +627,9 @@ private void createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor) { assert ptypes.size() > 1; - Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); - LoadHubNode hub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind)); - graph.addBeforeFixed(invoke.node(), hub); + Kind hubKind = ((MethodCallTargetNode) invoke.callTarget()).targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); + LoadHubNode hub = graph.add(new LoadHubNode(((MethodCallTargetNode) invoke.callTarget()).receiver(), hubKind)); + graph.addBeforeFixed(invoke.asNode(), hub); ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()]; double[] keyProbabilities = new double[ptypes.size() + 1]; @@ -612,7 +644,7 @@ keySuccessors[keySuccessors.length - 1] = successors.length - 1; TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors)); - FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor(); + FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor(); pred.setNext(typeSwitch); } @@ -620,7 +652,7 @@ double probability, boolean useForInlining) { Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining, probability); BeginNode calleeEntryNode = graph.add(new BeginNode()); - calleeEntryNode.setNext(duplicatedInvoke.node()); + calleeEntryNode.setNext(duplicatedInvoke.asNode()); calleeEntryNode.setProbability(probability); EndNode endNode = graph.add(new EndNode()); @@ -630,24 +662,24 @@ returnMerge.addForwardEnd(endNode); if (returnValuePhi != null) { - returnValuePhi.addInput(duplicatedInvoke.node()); + returnValuePhi.addInput(duplicatedInvoke.asNode()); } return calleeEntryNode; } private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining, double probability) { - Invoke result = (Invoke) invoke.node().copyWithInputs(); + Invoke result = (Invoke) invoke.asNode().copyWithInputs(); Node callTarget = result.callTarget().copyWithInputs(); - result.node().replaceFirstInput(result.callTarget(), callTarget); + result.asNode().replaceFirstInput(result.callTarget(), callTarget); result.setUseForInlining(useForInlining); result.setProbability(probability); result.setInliningRelevance(invoke.inliningRelevance() * probability); - Kind kind = invoke.node().kind(); + Kind kind = invoke.asNode().kind(); if (kind != Kind.Void) { FrameState stateAfter = invoke.stateAfter(); stateAfter = stateAfter.duplicate(stateAfter.bci); - stateAfter.replaceFirstInput(invoke.node(), result.node()); + stateAfter.replaceFirstInput(invoke.asNode(), result.asNode()); result.setStateAfter(stateAfter); } @@ -686,7 +718,7 @@ } private void tryToDevirtualizeMultipleMethods(StructuredGraph graph) { - MethodCallTargetNode methodCallTarget = invoke.methodCallTarget(); + MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget(); if (methodCallTarget.invokeKind() == InvokeKind.Interface) { ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod(); ResolvedJavaType leastCommonType = getLeastCommonType(); @@ -712,8 +744,8 @@ BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, true); - invocationEntry.setNext(invoke.node()); - ValueNode receiver = invoke.methodCallTarget().receiver(); + invocationEntry.setNext(invoke.asNode()); + ValueNode receiver = ((MethodCallTargetNode) invoke.callTarget()).receiver(); PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false); invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); replaceInvokeCallTarget(graph, kind, target); @@ -789,7 +821,7 @@ return null; } ResolvedJavaMethod caller = getCaller(invoke); - MethodCallTargetNode callTarget = invoke.methodCallTarget(); + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) { @@ -935,17 +967,18 @@ } private static boolean checkInvokeConditions(Invoke invoke) { - if (invoke.predecessor() == null || !invoke.node().isAlive()) { + if (invoke.predecessor() == null || !invoke.asNode().isAlive()) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code"); } else if (!(invoke.callTarget() instanceof MethodCallTargetNode)) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has already been lowered, or has been created as a low-level node"); - } else if (invoke.methodCallTarget().targetMethod() == null) { + } else if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() == null) { return logNotInlinedMethodAndReturnFalse(invoke, "target method is null"); } else if (invoke.stateAfter() == null) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has no after state"); } else if (!invoke.useForInlining()) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is marked to be not used for inlining"); - } else if (invoke.methodCallTarget().receiver() != null && invoke.methodCallTarget().receiver().isConstant() && invoke.methodCallTarget().receiver().asConstant().isNull()) { + } else if (((MethodCallTargetNode) invoke.callTarget()).receiver() != null && ((MethodCallTargetNode) invoke.callTarget()).receiver().isConstant() && + ((MethodCallTargetNode) invoke.callTarget()).receiver().asConstant().isNull()) { return logNotInlinedMethodAndReturnFalse(invoke, "receiver is null"); } else { return true; @@ -1017,7 +1050,7 @@ */ public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { NodeInputList parameters = invoke.callTarget().arguments(); - StructuredGraph graph = (StructuredGraph) invoke.node().graph(); + StructuredGraph graph = (StructuredGraph) invoke.asNode().graph(); FrameState stateAfter = invoke.stateAfter(); assert stateAfter.isAlive(); @@ -1045,17 +1078,17 @@ } } // ensure proper anchoring of things that were anchored to the StartNode - replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); + replacements.put(entryPointNode, BeginNode.prevBegin(invoke.asNode())); - assert invoke.node().successors().first() != null : invoke; - assert invoke.node().predecessor() != null; + assert invoke.asNode().successors().first() != null : invoke; + assert invoke.asNode().predecessor() != null; Map duplicates = graph.addDuplicates(nodes, replacements); FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); if (receiverNullCheck) { receiverNullCheck(invoke); } - invoke.node().replaceAtPredecessor(firstCFGNodeDuplicate); + invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate); FrameState stateAtExceptionEdge = null; if (invoke instanceof InvokeWithExceptionNode) { @@ -1094,7 +1127,7 @@ } FrameState outerFrameState = null; - double invokeProbability = invoke.node().probability(); + double invokeProbability = invoke.asNode().probability(); int callerLockDepth = stateAfter.nestedLockDepth(); for (Node node : duplicates.values()) { if (GraalOptions.ProbabilityAnalysis) { @@ -1117,7 +1150,7 @@ } if (node instanceof FrameState) { FrameState frameState = (FrameState) node; - assert frameState.bci != FrameState.BEFORE_BCI; + assert frameState.bci != FrameState.BEFORE_BCI : frameState; if (frameState.bci == FrameState.AFTER_BCI) { frameState.replaceAndDelete(stateAfter); } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) { @@ -1132,7 +1165,7 @@ if (frameState.outerFrameState() == null) { assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method() == inlineGraph.method(); if (outerFrameState == null) { - outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.node().kind()); + outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.asNode().kind()); outerFrameState.setDuringCall(true); } frameState.setOuterFrameState(outerFrameState); @@ -1152,7 +1185,7 @@ } else { returnValue = duplicates.get(returnNode.result()); } - invoke.node().replaceAtUsages(returnValue); + invoke.asNode().replaceAtUsages(returnValue); Node returnDuplicate = duplicates.get(returnNode); returnDuplicate.clearInputs(); Node n = invoke.next(); @@ -1160,19 +1193,19 @@ returnDuplicate.replaceAndDelete(n); } - invoke.node().replaceAtUsages(null); - GraphUtil.killCFG(invoke.node()); + invoke.asNode().replaceAtUsages(null); + GraphUtil.killCFG(invoke.asNode()); return duplicates; } public static void receiverNullCheck(Invoke invoke) { - MethodCallTargetNode callTarget = invoke.methodCallTarget(); - StructuredGraph graph = (StructuredGraph) invoke.graph(); + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + StructuredGraph graph = (StructuredGraph) callTarget.graph(); NodeInputList parameters = callTarget.arguments(); ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) { - graph.addBeforeFixed(invoke.node(), + graph.addBeforeFixed(invoke.asNode(), graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true))); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -24,27 +24,18 @@ import java.util.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Graph.InputChangedListener; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; - -public class IterativeConditionalEliminationPhase extends Phase { +import com.oracle.graal.phases.tiers.*; - private final MetaAccessProvider runtime; - private final Assumptions assumptions; - - public IterativeConditionalEliminationPhase(MetaAccessProvider runtime, Assumptions assumptions) { - this.runtime = runtime; - this.assumptions = assumptions; - } +public class IterativeConditionalEliminationPhase extends BasePhase { @Override - protected void run(StructuredGraph graph) { + protected void run(StructuredGraph graph, PhaseContext context) { Set canonicalizationRoots = new HashSet<>(); - ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(runtime); + ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(context.getRuntime()); Listener listener = new Listener(canonicalizationRoots); while (true) { graph.trackInputChange(listener); @@ -53,7 +44,7 @@ if (canonicalizationRoots.isEmpty()) { break; } - new CanonicalizerPhase(runtime, assumptions, canonicalizationRoots, null).apply(graph); + new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), canonicalizationRoots, null).apply(graph); canonicalizationRoots.clear(); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -151,7 +151,7 @@ deferred = false; processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed); Debug.dump(graph, "Lowering iteration %d", i++); - new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph); if (!deferred && !containsLowerable(graph.getNewNodes(mark))) { // No new lowerable nodes - done! diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushNodesThroughPi.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushNodesThroughPi.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +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.phases.common; - -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.phases.*; - -public class PushNodesThroughPi extends Phase { - - public static final DebugMetric PUSHED_NODES = Debug.metric("NodesPushedThroughPi"); - - @Override - protected void run(StructuredGraph graph) { - for (PiNode pi : graph.getNodes(PiNode.class)) { - for (Node n : pi.usages().snapshot()) { - if (n instanceof PiPushable) { - PiPushable pip = (PiPushable) n; - if (pip.push(pi)) { - PUSHED_NODES.add(1); - } - } - } - } - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushThroughPiPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/PushThroughPiPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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.phases.common; + +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; + +public class PushThroughPiPhase extends Phase { + + public static final DebugMetric PUSHED_NODES = Debug.metric("NodesPushedThroughPi"); + + @Override + protected void run(StructuredGraph graph) { + for (PiNode pi : graph.getNodes(PiNode.class)) { + for (Node n : pi.usages().snapshot()) { + if (n instanceof PiPushable) { + PiPushable pip = (PiPushable) n; + if (pip.push(pi)) { + PUSHED_NODES.add(1); + } + } + } + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.phases.common; -import java.util.*; - import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -32,11 +30,8 @@ public class ReadEliminationPhase extends Phase { - private Queue newPhis; - @Override protected void run(StructuredGraph graph) { - newPhis = new LinkedList<>(); for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) { if (isReadEliminable(n)) { NodeMap nodeMap = n.graph().createNodeMap(); @@ -47,11 +42,11 @@ } } - private boolean isReadEliminable(FloatingReadNode n) { + private static boolean isReadEliminable(FloatingReadNode n) { return isWrites(n, n.lastLocationAccess(), n.graph().createNodeBitMap()); } - private boolean isWrites(FloatingReadNode n, Node lastLocationAccess, NodeBitMap visited) { + private static boolean isWrites(FloatingReadNode n, Node lastLocationAccess, NodeBitMap visited) { if (lastLocationAccess == null) { return false; } @@ -77,7 +72,7 @@ return false; } - private ValueNode getValue(FloatingReadNode n, Node lastLocationAccess, NodeMap nodeMap) { + private static ValueNode getValue(FloatingReadNode n, Node lastLocationAccess, NodeMap nodeMap) { ValueNode exisiting = nodeMap.get(lastLocationAccess); if (exisiting != null) { return exisiting; @@ -97,7 +92,6 @@ for (ValueNode value : phi.values()) { newPhi.addInput(getValue(n, value, nodeMap)); } - newPhis.add(newPhi); return newPhi; } throw GraalInternalError.shouldNotReachHere(); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -46,7 +46,6 @@ /* * Various metrics on the circumstances in which tail duplication was/wasn't performed. */ - private static final DebugMetric metricDuplicationMonitors = Debug.metric("DuplicationMonitors"); private static final DebugMetric metricDuplicationEnd = Debug.metric("DuplicationEnd"); private static final DebugMetric metricDuplicationEndPerformed = Debug.metric("DuplicationEndPerformed"); private static final DebugMetric metricDuplicationOther = Debug.metric("DuplicationOther"); @@ -128,21 +127,13 @@ } }; - private int tailDuplicationCount; - - public int getTailDuplicationCount() { - return tailDuplicationCount; - } - @Override protected void run(StructuredGraph graph) { // A snapshot is taken here, so that new MergeNode instances aren't considered for tail // duplication. for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) { if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) { - if (tailDuplicate(merge, DEFAULT_DECISION, null)) { - tailDuplicationCount++; - } + tailDuplicate(merge, DEFAULT_DECISION, null); } } } @@ -168,20 +159,11 @@ assert replacements == null || replacements.size() == merge.forwardEndCount(); FixedNode fixed = merge; int fixedCount = 0; - boolean containsMonitor = false; while (fixed instanceof FixedWithNextNode) { - if (fixed instanceof MonitorEnterNode || fixed instanceof MonitorExitNode) { - containsMonitor = true; - } fixed = ((FixedWithNextNode) fixed).next(); fixedCount++; } - if (containsMonitor) { - // cannot currently be handled - // TODO (ls) re-evaluate this limitation after changes to the lock representation and - // the LIR generator - metricDuplicationMonitors.increment(); - } else if (fixedCount > 1) { + if (fixedCount > 1) { if (fixed instanceof EndNode && !(((EndNode) fixed).merge() instanceof LoopBeginNode)) { metricDuplicationEnd.increment(); if (decision.doTransform(merge, fixedCount)) { @@ -261,7 +243,6 @@ final HashSet duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter); mergeAfter.clearEnds(); expandDuplicated(duplicatedNodes, mergeAfter); - retargetDependencies(duplicatedNodes, anchor); List endSnapshot = merge.forwardEnds().snapshot(); List phiSnapshot = merge.phis().snapshot(); @@ -536,29 +517,6 @@ } /** - * Moves all depdendencies that point outside the duplicated area to the supplied value - * anchor node. - * - * @param duplicatedNodes The set of duplicated nodes. - * @param anchor The node that will be the new target for all dependencies that point - * outside the duplicated set of nodes. - */ - private static void retargetDependencies(HashSet duplicatedNodes, ValueAnchorNode anchor) { - for (Node node : duplicatedNodes) { - if (node instanceof ValueNode) { - NodeInputList dependencies = ((ValueNode) node).dependencies(); - for (int i = 0; i < dependencies.size(); i++) { - Node dependency = dependencies.get(i); - if (dependency != null && !duplicatedNodes.contains(dependency)) { - Debug.log("retargeting dependency %s to %s on %s", dependency, anchor, node); - dependencies.set(i, anchor); - } - } - } - } - } - - /** * Checks if the given node has usages that are not within the given set of nodes. * * @param node The node whose usages are checked. diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, 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.phases; + +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; + +/** + * Base class for all compiler phases. Subclasses should be stateless. There will be one global + * instance for each compiler phase that is shared for all compilations. VM-, target- and + * compilation-specific data can be passed with a context object. + */ +public abstract class BasePhase { + + private String name; + private static final DebugMetric metricPhaseRuns = Debug.metric("Runs"); + protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes"); + + protected BasePhase() { + this.name = this.getClass().getSimpleName(); + if (name.endsWith("Phase")) { + name = name.substring(0, name.length() - "Phase".length()); + } + } + + protected BasePhase(String name) { + this.name = name; + } + + protected String getDetailedName() { + return getName(); + } + + public final void apply(final StructuredGraph graph, final C context) { + apply(graph, context, true); + } + + public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { + Debug.scope(name, this, new Runnable() { + + public void run() { + BasePhase.this.run(graph, context); + metricPhaseRuns.increment(); + if (dumpGraph) { + Debug.dump(graph, "After phase %s", name); + } + assert graph.verify(); + } + }); + } + + public final String getName() { + return name; + } + + protected abstract void run(StructuredGraph graph, C context); +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Sat Apr 20 12:23:29 2013 +0200 @@ -36,6 +36,8 @@ public static int Threads = 4; + public static String CompilerConfiguration = "basic"; + // inlining settings public static boolean Inline = true; public static boolean AlwaysInlineIntrinsics = ____; @@ -88,6 +90,9 @@ public static int SlowQueueCutoff = 100000; public static boolean SlowCompileThreads = ____; public static boolean DynamicCompilePriority = ____; + public static String CompileTheWorld = null; + public static int CompileTheWorldStartAt = 1; + public static int CompileTheWorldStopAt = Integer.MAX_VALUE; // graph caching public static boolean CacheGraphs = true; @@ -109,13 +114,14 @@ // debugging settings public static boolean ZapStackOnMethodEntry = ____; public static boolean DeoptALot = ____; - public static boolean VerifyPhases = true; + public static boolean VerifyPhases = false; public static String PrintFilter = null; // Debug settings: public static boolean Debug = true; public static boolean DebugReplacements = ____; + public static boolean BootstrapReplacements = ____; public static boolean PerThreadDebugValues = ____; public static boolean SummarizeDebugValues = ____; public static boolean SummarizePerPhase = ____; @@ -127,7 +133,7 @@ public static String MethodFilter = null; public static boolean DumpOnError = ____; public static boolean GenericDynamicCounters = ____; - public static boolean BenchmarkDynamicCounters = ____; + public static String BenchmarkDynamicCounters = null; // Ideal graph visualizer output settings public static boolean PrintBinaryGraphs = true; @@ -151,6 +157,10 @@ public static boolean ExitVMOnBailout = ____; public static boolean ExitVMOnException = true; + // HotSpot command line options + public static boolean HotSpotPrintCompilation = ____; + public static boolean HotSpotPrintInlining = ____; + // Register allocator debugging public static String RegisterPressure = null; @@ -217,6 +227,7 @@ public static boolean IntrinsifyMathMethods = true; public static boolean IntrinsifyAESMethods = true; public static boolean IntrinsifyInstalledCodeMethods = true; + public static boolean IntrinsifyCallSiteTarget = true; /** * Counts the various paths taken through snippets. */ diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -22,28 +22,18 @@ */ package com.oracle.graal.phases; -import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; -public abstract class Phase { - - private String name; - private static final DebugMetric metricPhaseRuns = Debug.metric("Runs"); - protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes"); +/** + * Base class for compiler phases that don't need a context object. + */ +public abstract class Phase extends BasePhase { protected Phase() { - this.name = this.getClass().getSimpleName(); - if (name.endsWith("Phase")) { - name = name.substring(0, name.length() - "Phase".length()); - } } protected Phase(String name) { - this.name = name; - } - - protected String getDetailedName() { - return getName(); + super(name); } public final void apply(final StructuredGraph graph) { @@ -51,22 +41,13 @@ } public final void apply(final StructuredGraph graph, final boolean dumpGraph) { - Debug.scope(name, this, new Runnable() { - - public void run() { - Phase.this.run(graph); - metricPhaseRuns.increment(); - if (dumpGraph) { - Debug.dump(graph, "After phase %s", name); - } - assert graph.verify(); - } - }); - } - - public final String getName() { - return name; + apply(graph, null, dumpGraph); } protected abstract void run(StructuredGraph graph); + + @Override + protected final void run(StructuredGraph graph, Object context) { + run(graph); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,62 @@ +/* + * 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.phases; + +import java.util.*; + +import com.oracle.graal.nodes.*; + +public class PhaseSuite extends BasePhase { + + private final List> phases; + + public PhaseSuite() { + this.phases = new ArrayList<>(); + } + + public final void addPhase(BasePhase phase) { + phases.add(phase); + } + + public final ListIterator> findPhase(Class> phaseClass) { + ListIterator> it = phases.listIterator(); + findNextPhase(it, phaseClass); + return it; + } + + public static void findNextPhase(ListIterator> it, Class> phaseClass) { + while (it.hasNext()) { + BasePhase phase = it.next(); + if (phaseClass.isInstance(phase)) { + break; + } + } + } + + @Override + protected void run(StructuredGraph graph, C context) { + for (BasePhase phase : phases) { + phase.apply(graph, context); + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Sat Apr 20 12:23:29 2013 +0200 @@ -217,7 +217,7 @@ } protected void invoke(Invoke invoke) { - node(invoke.node()); + node(invoke.asNode()); } protected void finished() { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Sat Apr 20 12:23:29 2013 +0200 @@ -39,7 +39,7 @@ protected abstract void processBlock(Block block, StateT currentState); - protected abstract StateT merge(MergeNode merge, List states); + protected abstract StateT merge(Block merge, List states); protected abstract StateT cloneState(StateT oldState); @@ -161,12 +161,11 @@ assert current.getPredecessors().size() > 1; MergeNode merge = (MergeNode) current.getBeginNode(); ArrayList mergedStates = new ArrayList<>(merge.forwardEndCount()); - for (int i = 0; i < merge.forwardEndCount(); i++) { - StateT other = states.get(merge.forwardEndAt(i)); - assert other != null; - mergedStates.add(other); + for (Block predecessor : current.getPredecessors()) { + EndNode end = (EndNode) predecessor.getEndNode(); + mergedStates.add(states.get(end)); } - state = closure.merge(merge, mergedStates); + state = closure.merge(current, mergedStates); } assert state != null; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -39,6 +39,30 @@ public final class SchedulePhase extends Phase { + /** + * Error thrown when a graph cannot be scheduled. + */ + public static class SchedulingError extends Error { + + private static final long serialVersionUID = 1621001069476473145L; + + public SchedulingError() { + super(); + } + + /** + * This constructor creates a {@link SchedulingError} with a message assembled via + * {@link String#format(String, Object...)}. + * + * @param format a {@linkplain Formatter format} string + * @param args parameters to {@link String#format(String, Object...)} + */ + public SchedulingError(String format, Object... args) { + super(String.format(format, args)); + } + + } + public static enum SchedulingStrategy { EARLIEST, LATEST, LATEST_OUT_OF_LOOPS } @@ -91,7 +115,7 @@ } @Override - protected HashSet merge(MergeNode merge, List> states) { + protected HashSet merge(Block merge, List> states) { HashSet state = new HashSet<>(states.get(0)); for (int i = 1; i < states.size(); i++) { state.retainAll(states.get(i)); @@ -169,8 +193,8 @@ /** * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the - * scheduling built by @link {@link #run(StructuredGraph)}. This method should thus only be - * called when run has been successfully executed. + * scheduling built by {@link #run(StructuredGraph)}. This method should thus only be called + * when run has been successfully executed. */ public void scheduleGraph() { assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed"; @@ -207,7 +231,9 @@ private void assignBlockToNodes(StructuredGraph graph, SchedulingStrategy strategy) { for (Block block : cfg.getBlocks()) { List nodes = new ArrayList<>(); - assert blockToNodesMap.get(block) == null; + if (blockToNodesMap.get(block) != null) { + throw new SchedulingError(); + } blockToNodesMap.put(block, nodes); for (FixedNode node : block.getNodes()) { nodes.add(node); @@ -234,8 +260,9 @@ } // PhiNodes and FixedNodes should already have been placed in blocks by // ControlFlowGraph.identifyBlocks - assert !(node instanceof PhiNode) : node; - assert !(node instanceof FixedNode) : node; + if (node instanceof PhiNode || node instanceof FixedNode) { + throw new SchedulingError("%s should already have been placed in a block", node); + } Block block; switch (strategy) { @@ -251,8 +278,10 @@ // schedule at the latest position possible in the outermost loop possible Block earliestBlock = earliestBlock(node); block = scheduleOutOfLoops(node, block, earliestBlock); - assert earliestBlock.dominates(block) : "Graph cannot be scheduled : inconsistent for " + node + ", " + node.usages().count() + " usages, (" + earliestBlock + - " needs to dominate " + block + ")"; + if (!earliestBlock.dominates(block)) { + throw new SchedulingError("%s: Graph cannot be scheduled : inconsistent for %s, %d usages, (%s needs to dominate %s)", node.graph(), node, node.usages().count(), + earliestBlock, block); + } } break; default: @@ -271,7 +300,9 @@ private Block latestBlock(ScheduledNode node, SchedulingStrategy strategy) { CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null); for (Node succ : node.successors().nonNull()) { - assert cfg.getNodeToBlock().get(succ) != null; + if (cfg.getNodeToBlock().get(succ) == null) { + throw new SchedulingError(); + } cdbc.apply(cfg.getNodeToBlock().get(succ)); } ensureScheduledUsages(node, strategy); @@ -281,7 +312,9 @@ List usages = phantomUsages.get(node); if (usages != null) { for (FixedNode usage : usages) { - assert cfg.getNodeToBlock().get(usage) != null; + if (cfg.getNodeToBlock().get(usage) == null) { + throw new SchedulingError(); + } cdbc.apply(cfg.getNodeToBlock().get(usage)); } } @@ -331,7 +364,9 @@ */ BitSet dominators = new BitSet(cfg.getBlocks().length); - assert node.predecessor() == null; + if (node.predecessor() != null) { + throw new SchedulingError(); + } for (Node input : node.inputs().nonNull()) { assert input instanceof ValueNode; Block inputEarliest; @@ -356,7 +391,9 @@ } private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) { - assert latestBlock != null : "no latest : " + n; + if (latestBlock == null) { + throw new SchedulingError("no latest : %s", n); + } Block cur = latestBlock; Block result = latestBlock; while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) { @@ -378,7 +415,9 @@ * @param closure the closure that will be called for each block */ private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure, SchedulingStrategy strategy) { - assert !(node instanceof PhiNode); + if (node instanceof PhiNode) { + throw new SchedulingError(node.toString()); + } if (usage instanceof PhiNode) { // An input to a PhiNode is used at the end of the predecessor block that corresponds to @@ -388,7 +427,9 @@ PhiNode phi = (PhiNode) usage; MergeNode merge = phi.merge(); Block mergeBlock = cfg.getNodeToBlock().get(merge); - assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id); + if (mergeBlock == null) { + throw new SchedulingError("no block for merge %s", merge.toString(Verbosity.Id)); + } for (int i = 0; i < phi.valueCount(); ++i) { if (phi.valueAt(i) == node) { if (mergeBlock.getPredecessorCount() <= i) { @@ -412,7 +453,9 @@ blocksForUsage(node, unscheduledUsage, closure, strategy); } else if (unscheduledUsage instanceof MergeNode) { // Only FrameStates can be connected to MergeNodes. - assert usage instanceof FrameState; + if (!(usage instanceof FrameState)) { + throw new SchedulingError(usage.toString()); + } // If a FrameState belongs to a MergeNode then it's inputs will be placed at the // common dominator of all EndNodes. for (Node pred : unscheduledUsage.cfgPredecessors()) { @@ -420,8 +463,12 @@ } } else { // For the time being, only FrameStates can be connected to StateSplits. - assert usage instanceof FrameState; - assert unscheduledUsage instanceof StateSplit; + if (!(usage instanceof FrameState)) { + throw new SchedulingError(usage.toString()); + } + if (!(unscheduledUsage instanceof StateSplit || unscheduledUsage instanceof DeoptimizingNode)) { + throw new SchedulingError(unscheduledUsage.toString()); + } // Otherwise: Put the input into the same block as the usage. assignBlockToNode((ScheduledNode) unscheduledUsage, strategy); closure.apply(cfg.getNodeToBlock().get(unscheduledUsage)); @@ -459,8 +506,12 @@ } private void sortNodesWithinBlock(Block b, NodeBitMap visited, SchedulingStrategy strategy) { - assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b; - assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b; + if (visited.isMarked(b.getBeginNode()) || cfg.blockFor(b.getBeginNode()) != b) { + throw new SchedulingError(); + } + if (visited.isMarked(b.getEndNode()) || cfg.blockFor(b.getEndNode()) != b) { + throw new SchedulingError(); + } List sortedInstructions; switch (strategy) { @@ -520,7 +571,9 @@ private void addUnscheduledToLatestSorting(Block b, VirtualState state, List sortedInstructions, NodeBitMap visited) { if (state != null) { // UnscheduledNodes should never be marked as visited. - assert !visited.isMarked(state); + if (visited.isMarked(state)) { + throw new SchedulingError(); + } for (Node input : state.inputs()) { if (input instanceof VirtualState) { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,32 @@ +/* + * 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.phases.tiers; + +import com.oracle.graal.phases.*; + +public interface CompilerConfiguration { + + PhaseSuite createHighTier(); + + PhaseSuite createMidTier(); +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,33 @@ +/* + * 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.phases.tiers; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +public class HighTierContext extends PhaseContext { + + public HighTierContext(MetaAccessProvider runtime, Assumptions assumptions) { + super(runtime, assumptions); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/MidTierContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/MidTierContext.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,41 @@ +/* + * 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.phases.tiers; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.spi.*; + +public class MidTierContext extends PhaseContext { + + private final Replacements replacements; + + public MidTierContext(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements) { + super(runtime, assumptions); + this.replacements = replacements; + } + + public Replacements getReplacements() { + return replacements; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,45 @@ +/* + * 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.phases.tiers; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +public class PhaseContext { + + private final MetaAccessProvider runtime; + private final Assumptions assumptions; + + public PhaseContext(MetaAccessProvider runtime, Assumptions assumptions) { + this.runtime = runtime; + this.assumptions = assumptions; + } + + public MetaAccessProvider getRuntime() { + return runtime; + } + + public Assumptions getAssumptions() { + return assumptions; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,77 @@ +/* + * 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.phases.tiers; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.phases.*; + +public final class Suites { + + public static final Suites DEFAULT; + + private final PhaseSuite highTier; + private final PhaseSuite midTier; + + private static final Map configurations; + + public PhaseSuite getHighTier() { + return highTier; + } + + public PhaseSuite getMidTier() { + return midTier; + } + + static { + configurations = new HashMap<>(); + for (CompilerConfiguration config : ServiceLoader.loadInstalled(CompilerConfiguration.class)) { + String name = config.getClass().getSimpleName(); + if (name.endsWith("CompilerConfiguration")) { + name = name.substring(0, name.length() - "CompilerConfiguration".length()); + } + configurations.put(name.toLowerCase(), config); + } + + DEFAULT = createDefaultSuites(); + } + + private Suites(CompilerConfiguration config) { + highTier = config.createHighTier(); + midTier = config.createMidTier(); + } + + public static Suites createDefaultSuites() { + return createSuites(GraalOptions.CompilerConfiguration); + } + + public static Suites createSuites(String name) { + CompilerConfiguration config = configurations.get(name); + if (config == null) { + throw new GraalInternalError("unknown compiler configuration: " + name); + } + return new Suites(config); + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Sat Apr 20 12:23:29 2013 +0200 @@ -288,7 +288,9 @@ } void warning(int offset, String message) { + // CheckStyle: stop system..print check System.err.println("Warning: " + errorMessage(offset, message)); + // CheckStyle: resume system..print check } String errorMessage(int offset, String message) { @@ -316,8 +318,10 @@ int lineStart = input.lastIndexOf(HexCodeFile.NEW_LINE, index) + 1; String l = input.substring(lineStart, lineStart + 10); + // CheckStyle: stop system..print check System.out.println("YYY" + input.substring(index, index + 10) + "..."); System.out.println("XXX" + l + "..."); + // CheckStyle: resume system..print check int pos = input.indexOf(HexCodeFile.NEW_LINE, 0); int line = 1; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -23,18 +23,20 @@ package com.oracle.graal.replacements.amd64; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; +import java.util.*; + import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; /** * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match @@ -54,7 +56,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static int f2i(@Parameter("input") float input, @Parameter("result") int result) { + public static int f2i(float input, int result) { if (result == Integer.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { @@ -80,7 +82,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static long f2l(@Parameter("input") float input, @Parameter("result") long result) { + public static long f2l(float input, long result) { if (result == Long.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { @@ -106,7 +108,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static int d2i(@Parameter("input") double input, @Parameter("result") int result) { + public static int d2i(double input, int result) { if (result == Integer.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { @@ -132,7 +134,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static long d2l(@Parameter("input") double input, @Parameter("result") long result) { + public static long d2l(double input, long result) { if (result == Long.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { @@ -146,34 +148,26 @@ return result; } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod f2i; - private final ResolvedJavaMethod f2l; - private final ResolvedJavaMethod d2i; - private final ResolvedJavaMethod d2l; + private final EnumMap snippets; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, AMD64ConvertSnippets.class); - f2i = snippet("f2i", float.class, int.class); - f2l = snippet("f2l", float.class, long.class); - d2i = snippet("d2i", double.class, int.class); - d2l = snippet("d2l", double.class, long.class); + super(runtime, replacements, target); + + snippets = new EnumMap<>(Op.class); + snippets.put(Op.F2I, snippet(AMD64ConvertSnippets.class, "f2i")); + snippets.put(Op.F2L, snippet(AMD64ConvertSnippets.class, "f2l")); + snippets.put(Op.D2I, snippet(AMD64ConvertSnippets.class, "d2i")); + snippets.put(Op.D2L, snippet(AMD64ConvertSnippets.class, "d2l")); } public void lower(ConvertNode convert, LoweringTool tool) { - if (convert.opcode == Op.F2I) { - lower0(convert, tool, f2i); - } else if (convert.opcode == Op.F2L) { - lower0(convert, tool, f2l); - } else if (convert.opcode == Op.D2I) { - lower0(convert, tool, d2i); - } else if (convert.opcode == Op.D2L) { - lower0(convert, tool, d2l); + SnippetInfo key = snippets.get(convert.opcode); + if (key == null) { + return; } - } - private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) { StructuredGraph graph = (StructuredGraph) convert.graph(); // Insert a unique placeholder node in place of the Convert node so that the @@ -183,11 +177,13 @@ LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp())); convert.replaceAtUsages(replacee); - Key key = new Key(snippet); - Arguments arguments = arguments("input", convert.value()).add("result", convert); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments); - template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments); + Arguments args = new Arguments(key); + args.add("input", convert.value()); + args.add("result", convert); + + SnippetTemplate template = template(args); + Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args); + template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, args); } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CheckCastTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CheckCastTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.test.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; - -/** - * Tests the implementation of checkcast, allowing profiling information to be manually specified. - */ -public class CheckCastTest extends TypeCheckTest { - - @Override - protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { - CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); - if (ccn != null) { - CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile)); - graph.replaceFixedWithFixed(ccn, ccnNew); - } - } - - @LongTest - public void test1() { - test("asNumber", profile(), 111); - test("asNumber", profile(Integer.class), 111); - test("asNumber", profile(Long.class, Short.class), 111); - test("asNumberExt", profile(), 111); - test("asNumberExt", profile(Integer.class), 111); - test("asNumberExt", profile(Long.class, Short.class), 111); - } - - @LongTest - public void test2() { - test("asString", profile(), "111"); - test("asString", profile(String.class), "111"); - test("asString", profile(String.class), "111"); - - final String nullString = null; - test("asString", profile(), nullString); - test("asString", profile(String.class), nullString); - test("asString", profile(String.class), nullString); - - test("asStringExt", profile(), "111"); - test("asStringExt", profile(String.class), "111"); - test("asStringExt", profile(String.class), "111"); - } - - @LongTest - public void test3() { - test("asNumber", profile(), "111"); - } - - @LongTest - public void test4() { - test("asString", profile(String.class), 111); - } - - @LongTest - public void test5() { - test("asNumberExt", profile(), "111"); - } - - @LongTest - public void test6() { - test("asStringExt", profile(String.class), 111); - } - - @LongTest - public void test7() { - Throwable throwable = new Exception(); - test("asThrowable", profile(), throwable); - test("asThrowable", profile(Throwable.class), throwable); - test("asThrowable", profile(Exception.class, Error.class), throwable); - } - - @LongTest - public void test8() { - test("arrayStore", new Object[100], "111"); - } - - @LongTest - public void test8_1() { - test("arrayFill", new Object[100], "111"); - } - - public static Number asNumber(Object o) { - return (Number) o; - } - - public static String asString(Object o) { - return (String) o; - } - - public static Throwable asThrowable(Object o) { - return (Throwable) o; - } - - public static ValueNode asValueNode(Object o) { - return (ValueNode) o; - } - - public static Number asNumberExt(Object o) { - Number n = (Number) o; - return n.intValue() + 10; - } - - public static String asStringExt(Object o) { - String s = (String) o; - return "#" + s; - } - - public static Object[] arrayStore(Object[] arr, Object value) { - arr[15] = value; - return arr; - } - - public static Object[] arrayFill(Object[] arr, Object value) { - for (int i = 0; i < arr.length; i++) { - arr[i] = value; - } - return arr; - } - - static class Depth1 implements Cloneable { - } - - static class Depth2 extends Depth1 { - } - - static class Depth3 extends Depth2 { - } - - static class Depth4 extends Depth3 { - } - - static class Depth5 extends Depth4 { - } - - static class Depth6 extends Depth5 { - } - - static class Depth7 extends Depth6 { - } - - static class Depth8 extends Depth7 { - } - - static class Depth9 extends Depth8 { - } - - static class Depth10 extends Depth9 { - } - - static class Depth11 extends Depth10 { - } - - static class Depth12 extends Depth11 { - } - - static class Depth13 extends Depth12 { - } - - static class Depth14 extends Depth12 { - } - - public static Depth12 asDepth12(Object o) { - return (Depth12) o; - } - - public static Depth12[][] asDepth12Arr(Object o) { - return (Depth12[][]) o; - } - - public static Cloneable asCloneable(Object o) { - return (Cloneable) o; - } - - @LongTest - public void test9() { - Object o = new Depth13(); - test("asDepth12", profile(), o); - test("asDepth12", profile(Depth13.class), o); - test("asDepth12", profile(Depth13.class, Depth14.class), o); - } - - @LongTest - public void test10() { - Object o = new Depth13[3][]; - test("asDepth12Arr", o); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CompiledExceptionHandlerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/CompiledExceptionHandlerTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import java.lang.reflect.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; - -/** - * Tests compilation of a hot exception handler. - */ -public class CompiledExceptionHandlerTest extends GraalCompilerTest { - - @Override - protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) { - phasePlan.disablePhase(InliningPhase.class); - } - - @Override - protected StructuredGraph parse(Method m) { - StructuredGraph graph = super.parse(m); - int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count(); - Assert.assertEquals(1, handlers); - return graph; - } - - private static void raiseException(String s) { - throw new RuntimeException(s); - } - - @Test - public void test1() { - // Ensure the profile shows a hot exception - for (int i = 0; i < 10000; i++) { - test1Snippet(""); - test1Snippet(null); - } - - test("test1Snippet", "a string"); - } - - public static String test1Snippet(String message) { - if (message != null) { - try { - raiseException(message); - } catch (Exception e) { - return message; - } - } - return null; - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfDynamicTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfDynamicTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import com.oracle.graal.test.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.nodes.java.*; - -/** - * Tests for {@link InstanceOfDynamicNode}. - */ -public class InstanceOfDynamicTest extends GraalCompilerTest { - - public static int id(int value) { - return value; - } - - @LongTest - public void test100() { - final Object nul = null; - test("isStringDynamic", nul); - test("isStringDynamic", "object"); - test("isStringDynamic", Object.class); - } - - @LongTest - public void test101() { - final Object nul = null; - test("isStringIntDynamic", nul); - test("isStringIntDynamic", "object"); - test("isStringIntDynamic", Object.class); - } - - @LongTest - public void test103() { - test("isInstanceDynamic", String.class, null); - test("isInstanceDynamic", String.class, "object"); - test("isInstanceDynamic", String.class, Object.class); - test("isInstanceDynamic", int.class, null); - test("isInstanceDynamic", int.class, "Object"); - test("isInstanceDynamic", int.class, Object.class); - } - - @LongTest - public void test104() { - test("isInstanceIntDynamic", String.class, null); - test("isInstanceIntDynamic", String.class, "object"); - test("isInstanceIntDynamic", String.class, Object.class); - test("isInstanceIntDynamic", int.class, null); - test("isInstanceIntDynamic", int.class, "Object"); - test("isInstanceIntDynamic", int.class, Object.class); - } - - public static boolean isStringDynamic(Object o) { - return String.class.isInstance(o); - } - - public static int isStringIntDynamic(Object o) { - if (String.class.isInstance(o)) { - return o.toString().length(); - } - return o.getClass().getName().length(); - } - - public static boolean isInstanceDynamic(Class c, Object o) { - return c.isInstance(o); - } - - public static int isInstanceIntDynamic(Class c, Object o) { - if (c.isInstance(o)) { - return o.toString().length(); - } - return o.getClass().getName().length(); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InstanceOfTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,398 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import java.util.*; - - -import com.oracle.graal.api.code.CompilationResult.Call; -import com.oracle.graal.api.code.CompilationResult.Mark; -import com.oracle.graal.api.code.CompilationResult.Site; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.test.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; -import com.oracle.graal.replacements.CheckCastTest.*; - -/** - * Tests the implementation of instanceof, allowing profiling information to be manually specified. - */ -public class InstanceOfTest extends TypeCheckTest { - - @Override - protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) { - phasePlan.disablePhase(InliningPhase.class); - } - - @Override - protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { - InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first(); - if (ion != null) { - InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.type(), ion.object(), profile)); - graph.replaceFloating(ion, ionNew); - } - } - - @LongTest - public void test1() { - test("isString", profile(), "object"); - test("isString", profile(String.class), "object"); - - test("isString", profile(), Object.class); - test("isString", profile(String.class), Object.class); - } - - @LongTest - public void test2() { - test("isStringInt", profile(), "object"); - test("isStringInt", profile(String.class), "object"); - - test("isStringInt", profile(), Object.class); - test("isStringInt", profile(String.class), Object.class); - } - - @LongTest - public void test2_1() { - test("isStringIntComplex", profile(), "object"); - test("isStringIntComplex", profile(String.class), "object"); - - test("isStringIntComplex", profile(), Object.class); - test("isStringIntComplex", profile(String.class), Object.class); - } - - @LongTest - public void test3() { - Throwable throwable = new Exception(); - test("isThrowable", profile(), throwable); - test("isThrowable", profile(Throwable.class), throwable); - test("isThrowable", profile(Exception.class, Error.class), throwable); - - test("isThrowable", profile(), Object.class); - test("isThrowable", profile(Throwable.class), Object.class); - test("isThrowable", profile(Exception.class, Error.class), Object.class); - } - - @LongTest - public void test3_1() { - onlyFirstIsException(new Exception(), new Error()); - test("onlyFirstIsException", profile(), new Exception(), new Error()); - test("onlyFirstIsException", profile(), new Error(), new Exception()); - test("onlyFirstIsException", profile(), new Exception(), new Exception()); - test("onlyFirstIsException", profile(), new Error(), new Error()); - } - - @LongTest - public void test4() { - Throwable throwable = new Exception(); - test("isThrowableInt", profile(), throwable); - test("isThrowableInt", profile(Throwable.class), throwable); - test("isThrowableInt", profile(Exception.class, Error.class), throwable); - - test("isThrowableInt", profile(), Object.class); - test("isThrowableInt", profile(Throwable.class), Object.class); - test("isThrowableInt", profile(Exception.class, Error.class), Object.class); - } - - @LongTest - public void test5() { - Map map = new HashMap<>(); - test("isMap", profile(), map); - test("isMap", profile(HashMap.class), map); - test("isMap", profile(TreeMap.class, HashMap.class), map); - - test("isMap", profile(), Object.class); - test("isMap", profile(HashMap.class), Object.class); - test("isMap", profile(TreeMap.class, HashMap.class), Object.class); - } - - @LongTest - public void test6() { - Map map = new HashMap<>(); - test("isMapInt", profile(), map); - test("isMapInt", profile(HashMap.class), map); - test("isMapInt", profile(TreeMap.class, HashMap.class), map); - - test("isMapInt", profile(), Object.class); - test("isMapInt", profile(HashMap.class), Object.class); - test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class); - } - - @LongTest - public void test7() { - Object o = new Depth13(); - test("isDepth12", profile(), o); - test("isDepth12", profile(Depth13.class), o); - test("isDepth12", profile(Depth13.class, Depth14.class), o); - - o = "not a depth"; - test("isDepth12", profile(), o); - test("isDepth12", profile(Depth13.class), o); - test("isDepth12", profile(Depth13.class, Depth14.class), o); - } - - @LongTest - public void test8() { - Object o = new Depth13(); - test("isDepth12Int", profile(), o); - test("isDepth12Int", profile(Depth13.class), o); - test("isDepth12Int", profile(Depth13.class, Depth14.class), o); - - o = "not a depth"; - test("isDepth12Int", profile(), o); - test("isDepth12Int", profile(Depth13.class), o); - test("isDepth12Int", profile(Depth13.class, Depth14.class), o); - } - - public static boolean isString(Object o) { - return o instanceof String; - } - - public static int isStringInt(Object o) { - if (o instanceof String) { - return id(1); - } - return id(0); - } - - public static int isStringIntComplex(Object o) { - if (o instanceof String || o instanceof Integer) { - return id(o instanceof String ? 1 : 0); - } - return id(0); - } - - public static int id(int value) { - return value; - } - - public static boolean isThrowable(Object o) { - return ((Throwable) o) instanceof Exception; - } - - public static int onlyFirstIsException(Throwable t1, Throwable t2) { - if (t1 instanceof Exception ^ t2 instanceof Exception) { - return t1 instanceof Exception ? 1 : -1; - } - return -1; - } - - public static int isThrowableInt(Object o) { - int result = o instanceof Throwable ? 4 : 5; - if (o instanceof Throwable) { - return id(4); - } - return result; - } - - public static boolean isMap(Object o) { - return o instanceof Map; - } - - public static int isMapInt(Object o) { - if (o instanceof Map) { - return id(1); - } - return id(0); - } - - public static boolean isDepth12(Object o) { - return o instanceof Depth12; - } - - public static int isDepth12Int(Object o) { - if (o instanceof Depth12) { - return id(0); - } - return id(0); - } - - abstract static class MySite { - - final int offset; - - MySite(int offset) { - this.offset = offset; - } - } - - static class MyMark extends MySite { - - MyMark(int offset) { - super(offset); - } - } - - abstract static class MySafepoint extends MySite { - - MySafepoint(int offset) { - super(offset); - } - } - - static class MyCall extends MySafepoint { - - MyCall(int offset) { - super(offset); - } - } - - @LongTest - public void test9() { - MyCall callAt63 = new MyCall(63); - MyMark markAt63 = new MyMark(63); - test("compareMySites", callAt63, callAt63); - test("compareMySites", callAt63, markAt63); - test("compareMySites", markAt63, callAt63); - test("compareMySites", markAt63, markAt63); - } - - public static int compareMySites(MySite s1, MySite s2) { - if (s1.offset == s2.offset && (s1 instanceof MyMark ^ s2 instanceof MyMark)) { - return s1 instanceof MyMark ? -1 : 1; - } - return s1.offset - s2.offset; - } - - @LongTest - public void test10() { - Mark[] noMarks = {}; - Call callAt63 = new Call(null, 63, 5, true, null); - Mark markAt63 = new Mark(63, "1", noMarks); - test("compareSites", callAt63, callAt63); - test("compareSites", callAt63, markAt63); - test("compareSites", markAt63, callAt63); - test("compareSites", markAt63, markAt63); - } - - public static int compareSites(Site s1, Site s2) { - if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { - return s1 instanceof Mark ? -1 : 1; - } - return s1.pcOffset - s2.pcOffset; - } - - /** - * This test exists to show the kind of pattern that is be optimizable by - * {@code removeIntermediateMaterialization()} in {@link IfNode}. - *

- * The test exists in this source file as the transformation was originally motivated by the - * need to remove use of special JumpNodes in the {@code InstanceOfSnippets}. - */ - @LongTest - public void test_removeIntermediateMaterialization() { - List list = Arrays.asList("1", "2", "3", "4"); - test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no"); - test("removeIntermediateMaterialization", profile(), list, null, "yes", "no"); - test("removeIntermediateMaterialization", profile(), null, "2", "yes", "no"); - } - - public static String removeIntermediateMaterialization(List list, Object e, String a, String b) { - boolean test; - if (list == null || e == null) { - test = false; - } else { - test = false; - for (Object i : list) { - if (i.equals(e)) { - test = true; - break; - } - } - } - if (test) { - return a; - } - return b; - } - - abstract static class A { - } - - static class B extends A { - } - - static class C extends B { - } - - abstract static class D extends C { - } - - public static boolean isArrayOfA(Object o) { - return o instanceof A[]; - } - - public static boolean isArrayOfB(Object o) { - return o instanceof B[]; - } - - public static boolean isArrayOfC(Object o) { - return o instanceof C[]; - } - - public static boolean isArrayOfD(Object o) { - return o instanceof D[]; - } - - @LongTest - public void testArray() { - Object aArray = new A[10]; - test("isArrayOfA", aArray); - - Object bArray = new B[10]; - test("isArrayOfA", aArray); - test("isArrayOfA", bArray); - test("isArrayOfB", aArray); - test("isArrayOfB", bArray); - - Object cArray = new C[10]; - test("isArrayOfA", aArray); - test("isArrayOfA", bArray); - test("isArrayOfA", cArray); - test("isArrayOfB", aArray); - test("isArrayOfB", bArray); - test("isArrayOfB", cArray); - test("isArrayOfC", aArray); - test("isArrayOfC", bArray); - test("isArrayOfC", cArray); - - Object dArray = new D[10]; - test("isArrayOfA", aArray); - test("isArrayOfA", bArray); - test("isArrayOfA", cArray); - test("isArrayOfA", dArray); - test("isArrayOfB", aArray); - test("isArrayOfB", bArray); - test("isArrayOfB", cArray); - test("isArrayOfB", dArray); - test("isArrayOfC", aArray); - test("isArrayOfC", bArray); - test("isArrayOfC", cArray); - test("isArrayOfC", dArray); - test("isArrayOfD", aArray); - test("isArrayOfD", bArray); - test("isArrayOfD", cArray); - test("isArrayOfD", dArray); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InvokeTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/InvokeTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; - -/** - * Tests the implementation of the snippets for lowering the INVOKE* instructions. - */ -public class InvokeTest extends GraalCompilerTest { - - @Override - protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) { - phasePlan.disablePhase(InliningPhase.class); - } - - public interface I { - - String virtualMethod(String s); - } - - public static class A implements I { - - final String name = "A"; - - public String virtualMethod(String s) { - return name + s; - } - } - - @SuppressWarnings("static-method") - private String privateMethod(String s) { - return s; - } - - @Test - public void test1() { - test("invokestatic", "a string"); - test("invokespecialConstructor", "a string"); - test("invokespecial", this, "a string"); - test("invokevirtual", new A(), "a string"); - test("invokevirtual2", new A(), "a string"); - test("invokeinterface", new A(), "a string"); - Object[] args = {null}; - test("invokestatic", args); - test("invokespecialConstructor", args); - test("invokespecial", null, null); - test("invokevirtual", null, null); - test("invokevirtual2", null, null); - test("invokeinterface", null, null); - } - - public static String invokestatic(String s) { - return staticMethod(s); - } - - public static String staticMethod(String s) { - return s; - } - - public static String invokespecialConstructor(String s) { - return new A().virtualMethod(s); - } - - public static String invokespecial(InvokeTest a, String s) { - return a.privateMethod(s); - } - - public static String invokevirtual(A a, String s) { - return a.virtualMethod(s); - } - - public static String invokevirtual2(A a, String s) { - a.virtualMethod(s); - return a.virtualMethod(s); - } - - public static String invokeinterface(I i, String s) { - return i.virtualMethod(s); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MethodSubstitutionTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MethodSubstitutionTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import static org.junit.Assert.*; - -import java.util.concurrent.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; - -/** - * Tests if {@link MethodSubstitution}s are inlined correctly. Most test cases only assert that - * there are no remaining invocations in the graph. This is sufficient if the method that is being - * substituted is a native method. For Java methods, additional checks are necessary. - */ -public abstract class MethodSubstitutionTest extends GraalCompilerTest { - - protected StructuredGraph test(final String snippet) { - return Debug.scope("MethodSubstitutionTest", runtime.lookupJavaMethod(getMethod(snippet)), new Callable() { - - @Override - public StructuredGraph call() { - StructuredGraph graph = parse(snippet); - PhasePlan phasePlan = getDefaultPhasePlan(); - Assumptions assumptions = new Assumptions(true); - new ComputeProbabilityPhase().apply(graph); - Debug.dump(graph, "Graph"); - new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); - Debug.dump(graph, "Graph"); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - assertNotInGraph(graph, Invoke.class); - return graph; - } - }); - } - - protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class clazz) { - for (Node node : graph.getNodes()) { - if (clazz.isInstance(node)) { - fail(node.toString()); - } - } - return graph; - } - - protected static StructuredGraph assertInGraph(StructuredGraph graph, Class clazz) { - for (Node node : graph.getNodes()) { - if (clazz.isInstance(node)) { - return graph; - } - } - fail("Graph does not contain a node of class " + clazz.getName()); - return graph; - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MonitorTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/MonitorTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import org.junit.*; - -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.virtual.phases.ea.*; - -public class MonitorTest extends GraalCompilerTest { - - @Test - public void test0() { - test("lockObjectSimple", new Object(), new Object()); - test("lockObjectSimple", new Object(), null); - } - - @Test - public void test0_1() { - test("lockThisSimple", "test1", new Object()); - test("lockThisSimple", "test1", null); - } - - @Test - public void test0_2() { - test("lockObjectSimple", null, "test1"); - } - - @Test - public void test1_1() { - test("lockObject", new Object(), "test1", new String[1]); - } - - @Test - public void test1_2() { - test("lockObject", null, "test1_1", new String[1]); - } - - @Test - public void test2() { - test("lockThis", "test2", new String[1]); - } - - /** - * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}. - */ - @Test - public void test3() { - test("lockLocalObject", "test3", new String[1]); - } - - /** - * Tests recursive locking of objects which should be biasable. - */ - @Test - public void test4() { - Chars src = new Chars("1234567890".toCharArray()); - Chars dst = new Chars(src.data.length); - test("copyObj", src, dst, 100); - } - - /** - * Tests recursive locking of objects which do not appear to be biasable. - */ - @Test - public void test5() { - char[] src = "1234567890".toCharArray(); - char[] dst = new char[src.length]; - test("copyArr", src, dst, 100); - } - - /** - * Extends {@link #test4()} with contention. - */ - @Test - public void test6() { - Chars src = new Chars("1234567890".toCharArray()); - Chars dst = new Chars(src.data.length); - int n = Runtime.getRuntime().availableProcessors(); - testN(n, "copyObj", src, dst, 100); - } - - /** - * Extends {@link #test5()} with contention. - */ - @Test - public void test7() { - char[] src = "1234567890".toCharArray(); - char[] dst = new char[src.length]; - int n = Runtime.getRuntime().availableProcessors(); - testN(n, "copyArr", src, dst, 100); - } - - private static String setAndGet(String[] box, String value) { - synchronized (box) { - box[0] = null; - } - - // Do a GC while a object is locked (by the caller) - System.gc(); - - synchronized (box) { - box[0] = value; - } - return box[0]; - } - - public static Object lockObjectSimple(Object o, Object value) { - synchronized (o) { - value.hashCode(); - return value; - } - } - - public String lockThisSimple(String value, Object o) { - synchronized (this) { - synchronized (value) { - o.hashCode(); - return value; - } - } - } - - public static String lockObject(Object o, String value, String[] box) { - synchronized (o) { - return setAndGet(box, value); - } - } - - public String lockThis(String value, String[] box) { - synchronized (this) { - return setAndGet(box, value); - } - } - - public static String lockLocalObject(String value, String[] box) { - Object o = new Object(); - synchronized (o) { - return setAndGet(box, value); - } - } - - static class Chars { - - final char[] data; - - public Chars(int size) { - this.data = new char[size]; - } - - public Chars(char[] data) { - this.data = data; - } - } - - public static String copyObj(Chars src, Chars dst, int n) { - for (int j = 0; j < n; j++) { - for (int i = 0; i < src.data.length; i++) { - synchronized (src) { - synchronized (dst) { - synchronized (src) { - synchronized (dst) { - dst.data[i] = src.data[i]; - } - } - } - } - } - } - return new String(dst.data); - } - - public static String copyArr(char[] src, char[] dst, int n) { - for (int j = 0; j < n; j++) { - for (int i = 0; i < src.length; i++) { - synchronized (src) { - synchronized (dst) { - synchronized (src) { - synchronized (dst) { - dst[i] = src[i]; - } - } - } - } - } - } - return new String(dst); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewArrayTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewArrayTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import org.junit.*; - -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.test.*; - -/** - * Tests the implementation of {@code [A]NEWARRAY}. - */ -public class NewArrayTest extends GraalCompilerTest { - - @Override - protected void assertEquals(Object expected, Object actual) { - Assert.assertTrue(expected != null); - Assert.assertTrue(actual != null); - super.assertEquals(expected.getClass(), actual.getClass()); - if (expected instanceof int[]) { - Assert.assertArrayEquals((int[]) expected, (int[]) actual); - } else if (expected instanceof byte[]) { - Assert.assertArrayEquals((byte[]) expected, (byte[]) actual); - } else if (expected instanceof char[]) { - Assert.assertArrayEquals((char[]) expected, (char[]) actual); - } else if (expected instanceof short[]) { - Assert.assertArrayEquals((short[]) expected, (short[]) actual); - } else if (expected instanceof float[]) { - Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f); - } else if (expected instanceof long[]) { - Assert.assertArrayEquals((long[]) expected, (long[]) actual); - } else if (expected instanceof double[]) { - Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d); - } else if (expected instanceof Object[]) { - Assert.assertArrayEquals((Object[]) expected, (Object[]) actual); - } else { - Assert.fail("non-array value encountered: " + expected); - } - } - - @LongTest - public void test1() { - for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) { - test("new" + type + "Array7"); - test("new" + type + "ArrayMinus7"); - test("new" + type + "Array", 7); - test("new" + type + "Array", -7); - test("new" + type + "Array", Integer.MAX_VALUE); - test("new" + type + "Array", Integer.MIN_VALUE); - } - } - - public static Object newCharArray7() { - return new char[7]; - } - - public static Object newCharArrayMinus7() { - return new char[-7]; - } - - public static Object newCharArray(int length) { - return new char[length]; - } - - public static Object newShortArray7() { - return new short[7]; - } - - public static Object newShortArrayMinus7() { - return new short[-7]; - } - - public static Object newShortArray(int length) { - return new short[length]; - } - - public static Object newFloatArray7() { - return new float[7]; - } - - public static Object newFloatArrayMinus7() { - return new float[-7]; - } - - public static Object newFloatArray(int length) { - return new float[length]; - } - - public static Object newLongArray7() { - return new long[7]; - } - - public static Object newLongArrayMinus7() { - return new long[-7]; - } - - public static Object newLongArray(int length) { - return new long[length]; - } - - public static Object newDoubleArray7() { - return new double[7]; - } - - public static Object newDoubleArrayMinus7() { - return new double[-7]; - } - - public static Object newDoubleArray(int length) { - return new double[length]; - } - - public static Object newIntArray7() { - return new int[7]; - } - - public static Object newIntArrayMinus7() { - return new int[-7]; - } - - public static Object newIntArray(int length) { - return new int[length]; - } - - public static Object newByteArray7() { - return new byte[7]; - } - - public static Object newByteArrayMinus7() { - return new byte[-7]; - } - - public static Object newByteArray(int length) { - return new byte[length]; - } - - public static Object newStringArray7() { - return new String[7]; - } - - public static Object newStringArrayMinus7() { - return new String[-7]; - } - - public static Object newStringArray(int length) { - return new String[length]; - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewInstanceTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewInstanceTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.test.*; - -/** - * Tests the implementation of {@code NEW}. - */ -public class NewInstanceTest extends GraalCompilerTest { - - @Override - protected void assertEquals(Object expected, Object actual) { - Assert.assertTrue(expected != null); - Assert.assertTrue(actual != null); - super.assertEquals(expected.getClass(), actual.getClass()); - - if (expected instanceof Object[]) { - Assert.assertTrue(actual instanceof Object[]); - Object[] eArr = (Object[]) expected; - Object[] aArr = (Object[]) actual; - Assert.assertTrue(eArr.length == aArr.length); - for (int i = 0; i < eArr.length; i++) { - assertEquals(eArr[i], aArr[i]); - } - } else if (expected.getClass() != Object.class) { - try { - expected.getClass().getDeclaredMethod("equals", Object.class); - super.assertEquals(expected, actual); - } catch (Exception e) { - } - } - } - - @LongTest - public void test1() { - test("newObject"); - } - - @LongTest - public void test2() { - test("newObjectTwice"); - } - - public static Object newObject() { - return new Object(); - } - - @LongTest - public void test3() { - test("newObjectLoop", 100); - } - - @LongTest - public void test4() { - test("newBigObject"); - } - - @LongTest - public void test5() { - test("newSomeObject"); - } - - @LongTest - public void test6() { - test("newEmptyString"); - } - - @LongTest - public void test7() { - test("newString", "value"); - } - - @LongTest - public void test8() { - test("newHashMap", 31); - } - - @LongTest - public void test9() { - test("newRegression", true); - } - - public static Object[] newObjectTwice() { - Object[] res = {new Object(), new Object()}; - return res; - } - - public static Object[] newObjectLoop(int n) { - Object[] res = new Object[n]; - for (int i = 0; i < n; i++) { - res[i] = new Object(); - } - return res; - } - - public static BigObject newBigObject() { - return new BigObject(); - } - - public static SomeObject newSomeObject() { - return new SomeObject(); - } - - public static String newEmptyString() { - return new String(); - } - - public static String newString(String value) { - return new String(value); - } - - public static HashMap newHashMap(int initialCapacity) { - return new HashMap(initialCapacity); - } - - static class SomeObject { - - String name = "o1"; - HashMap map = new HashMap<>(); - - public SomeObject() { - map.put(name, this.getClass()); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof SomeObject) { - SomeObject so = (SomeObject) obj; - return so.name.equals(name) && so.map.equals(map); - } - return false; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - } - - static class BigObject { - - Object f01; - Object f02; - Object f03; - Object f04; - Object f05; - Object f06; - Object f07; - Object f08; - Object f09; - Object f10; - Object f12; - Object f13; - Object f14; - Object f15; - Object f16; - Object f17; - Object f18; - Object f19; - Object f20; - Object f21; - Object f22; - Object f23; - Object f24; - Object f25; - Object f26; - Object f27; - Object f28; - Object f29; - Object f30; - Object f31; - Object f32; - Object f33; - Object f34; - Object f35; - Object f36; - Object f37; - Object f38; - Object f39; - Object f40; - Object f41; - Object f42; - Object f43; - Object f44; - Object f45; - } - - /** - * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top' - * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the - * allocated B object in the true branch overwrote the allocated array. The cause is that - * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also - * floating. The fix was to make RegisterNode a fixed node (which it should have been in the - * first place). - */ - public static Object newRegression(boolean condition) { - Object result; - if (condition) { - Object[] arr = {0, 1, 2, 3, 4, 5}; - result = new B(); - for (int i = 0; i < arr.length; ++i) { - // If the bug exists, the values of arr will now be deadbeef values - // and the virtual dispatch will cause a segfault. This can result in - // either a VM crash or a spurious NullPointerException. - if (arr[i].equals(Integer.valueOf(i))) { - return false; - } - } - } else { - result = new B(); - } - return result; - } - - static class B { - - long f1 = 0xdeadbeefdeadbe01L; - long f2 = 0xdeadbeefdeadbe02L; - long f3 = 0xdeadbeefdeadbe03L; - long f4 = 0xdeadbeefdeadbe04L; - long f5 = 0xdeadbeefdeadbe05L; - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewMultiArrayTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/NewMultiArrayTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.test.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; - -/** - * Tests the lowering of the MULTIANEWARRAY instruction. - */ -public class NewMultiArrayTest extends GraalCompilerTest { - - private static int rank(ResolvedJavaType type) { - String name = type.getName(); - int dims = 0; - while (dims < name.length() && name.charAt(dims) == '[') { - dims++; - } - return dims; - } - - @Override - protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) { - boolean forceCompile = false; - if (bottomType != null) { - List snapshot = graph.getNodes().filter(NewMultiArrayNode.class).snapshot(); - assert snapshot != null; - assert snapshot.size() == 1; - - NewMultiArrayNode node = snapshot.get(0); - assert rank(arrayType) == dimensions.length; - int rank = dimensions.length; - ValueNode[] dimensionNodes = new ValueNode[rank]; - for (int i = 0; i < rank; i++) { - dimensionNodes[i] = graph.unique(ConstantNode.forInt(dimensions[i], graph)); - } - - NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes)); - graph.replaceFixedWithFixed(node, repl); - forceCompile = true; - } - return super.getCode(method, graph, forceCompile); - } - - @Override - protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - if (bottomType != null) { - try { - return Array.newInstance(bottomClass, dimensions); - } catch (Exception e) { - throw new InvocationTargetException(e); - } - } - return super.referenceInvoke(method, receiver, args); - } - - ResolvedJavaType arrayType; - ResolvedJavaType bottomType; - Class bottomClass; - int[] dimensions; - - @LongTest - public void test1() { - for (Class clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) { - bottomClass = clazz; - bottomType = runtime.lookupJavaType(clazz); - arrayType = bottomType; - for (int rank : new int[]{1, 2, 10, 50, 100, 200, 254, 255}) { - while (rank(arrayType) != rank) { - arrayType = arrayType.getArrayClass(); - } - - dimensions = new int[rank]; - for (int i = 0; i < rank; i++) { - dimensions[i] = 1; - } - - test("newMultiArray"); - } - } - bottomType = null; - arrayType = null; - } - - public static Object newMultiArray() { - // This is merely a template - the NewMultiArrayNode is replaced in getCode() above. - // This also means we need a separate test for correct handling of negative dimensions - // as deoptimization won't do what we want for a graph modified to be different from the - // source bytecode. - return new Object[10][9][8]; - } - - @LongTest - public void test2() { - test("newMultiArrayException"); - } - - public static Object newMultiArrayException() { - return new Object[10][9][-8]; - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/PointerTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,399 +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.replacements; - -import java.lang.reflect.*; - -import org.junit.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.word.*; - -/** - * Tests for the {@link Pointer} read and write operations. - */ -public class PointerTest extends GraalCompilerTest implements Snippets { - - private static final Object ID = new Object(); - private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}; - private final TargetDescription target; - private final ReplacementsImpl installer; - - public PointerTest() { - target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget(); - installer = new ReplacementsImpl(runtime, new Assumptions(false), target); - } - - private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); - - @Override - protected StructuredGraph parse(Method m) { - ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); - } - - @Test - public void test_read1() { - for (Kind kind : KINDS) { - assertRead(parse("read" + kind.name() + "1"), kind, false, ID); - } - } - - @Test - public void test_read2() { - for (Kind kind : KINDS) { - assertRead(parse("read" + kind.name() + "2"), kind, true, ID); - } - } - - @Test - public void test_read3() { - for (Kind kind : KINDS) { - assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION); - } - } - - @Test - public void test_write1() { - for (Kind kind : KINDS) { - assertWrite(parse("write" + kind.name() + "1"), kind, false, ID); - } - } - - @Test - public void test_write2() { - for (Kind kind : KINDS) { - assertWrite(parse("write" + kind.name() + "2"), kind, true, ID); - } - } - - @Test - public void test_write3() { - for (Kind kind : KINDS) { - assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION); - } - } - - private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) { - ReadNode read = (ReadNode) graph.start().next(); - Assert.assertEquals(kind.getStackKind(), read.kind()); - - UnsafeCastNode cast = (UnsafeCastNode) read.object(); - Assert.assertEquals(graph.getLocal(0), cast.object()); - Assert.assertEquals(target.wordKind, cast.kind()); - - IndexedLocationNode location = (IndexedLocationNode) read.location(); - Assert.assertEquals(kind, location.getValueKind()); - Assert.assertEquals(locationIdentity, location.locationIdentity()); - Assert.assertEquals(1, location.indexScaling()); - - if (indexConvert) { - ConvertNode convert = (ConvertNode) location.index(); - Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); - Assert.assertEquals(graph.getLocal(1), convert.value()); - } else { - Assert.assertEquals(graph.getLocal(1), location.index()); - } - - ReturnNode ret = (ReturnNode) read.next(); - Assert.assertEquals(read, ret.result()); - } - - private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) { - WriteNode write = (WriteNode) graph.start().next(); - Assert.assertEquals(graph.getLocal(2), write.value()); - Assert.assertEquals(Kind.Void, write.kind()); - Assert.assertEquals(FrameState.INVALID_FRAMESTATE_BCI, write.stateAfter().bci); - - UnsafeCastNode cast = (UnsafeCastNode) write.object(); - Assert.assertEquals(graph.getLocal(0), cast.object()); - Assert.assertEquals(target.wordKind, cast.kind()); - - IndexedLocationNode location = (IndexedLocationNode) write.location(); - Assert.assertEquals(kind, location.getValueKind()); - Assert.assertEquals(locationIdentity, location.locationIdentity()); - Assert.assertEquals(1, location.indexScaling()); - - if (indexConvert) { - ConvertNode convert = (ConvertNode) location.index(); - Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); - Assert.assertEquals(graph.getLocal(1), convert.value()); - } else { - Assert.assertEquals(graph.getLocal(1), location.index()); - } - - AbstractStateSplit stateSplit = (AbstractStateSplit) write.next(); - Assert.assertEquals(FrameState.AFTER_BCI, stateSplit.stateAfter().bci); - - ReturnNode ret = (ReturnNode) stateSplit.next(); - Assert.assertEquals(null, ret.result()); - } - - @Snippet - public static byte readByte1(Object o, int offset) { - return Word.fromObject(o).readByte(offset, ID); - } - - @Snippet - public static byte readByte2(Object o, int offset) { - return Word.fromObject(o).readByte(Word.signed(offset), ID); - } - - @Snippet - public static byte readByte3(Object o, int offset) { - return Word.fromObject(o).readByte(offset); - } - - @Snippet - public static void writeByte1(Object o, int offset, byte value) { - Word.fromObject(o).writeByte(offset, value, ID); - } - - @Snippet - public static void writeByte2(Object o, int offset, byte value) { - Word.fromObject(o).writeByte(Word.signed(offset), value, ID); - } - - @Snippet - public static void writeByte3(Object o, int offset, byte value) { - Word.fromObject(o).writeByte(offset, value); - } - - @Snippet - public static char readChar1(Object o, int offset) { - return Word.fromObject(o).readChar(offset, ID); - } - - @Snippet - public static char readChar2(Object o, int offset) { - return Word.fromObject(o).readChar(Word.signed(offset), ID); - } - - @Snippet - public static char readChar3(Object o, int offset) { - return Word.fromObject(o).readChar(offset); - } - - @Snippet - public static void writeChar1(Object o, int offset, char value) { - Word.fromObject(o).writeChar(offset, value, ID); - } - - @Snippet - public static void writeChar2(Object o, int offset, char value) { - Word.fromObject(o).writeChar(Word.signed(offset), value, ID); - } - - @Snippet - public static void writeChar3(Object o, int offset, char value) { - Word.fromObject(o).writeChar(offset, value); - } - - @Snippet - public static short readShort1(Object o, int offset) { - return Word.fromObject(o).readShort(offset, ID); - } - - @Snippet - public static short readShort2(Object o, int offset) { - return Word.fromObject(o).readShort(Word.signed(offset), ID); - } - - @Snippet - public static short readShort3(Object o, int offset) { - return Word.fromObject(o).readShort(offset); - } - - @Snippet - public static void writeShort1(Object o, int offset, short value) { - Word.fromObject(o).writeShort(offset, value, ID); - } - - @Snippet - public static void writeShort2(Object o, int offset, short value) { - Word.fromObject(o).writeShort(Word.signed(offset), value, ID); - } - - @Snippet - public static void writeShort3(Object o, int offset, short value) { - Word.fromObject(o).writeShort(offset, value); - } - - @Snippet - public static int readInt1(Object o, int offset) { - return Word.fromObject(o).readInt(offset, ID); - } - - @Snippet - public static int readInt2(Object o, int offset) { - return Word.fromObject(o).readInt(Word.signed(offset), ID); - } - - @Snippet - public static int readInt3(Object o, int offset) { - return Word.fromObject(o).readInt(offset); - } - - @Snippet - public static void writeInt1(Object o, int offset, int value) { - Word.fromObject(o).writeInt(offset, value, ID); - } - - @Snippet - public static void writeInt2(Object o, int offset, int value) { - Word.fromObject(o).writeInt(Word.signed(offset), value, ID); - } - - @Snippet - public static void writeInt3(Object o, int offset, int value) { - Word.fromObject(o).writeInt(offset, value); - } - - @Snippet - public static long readLong1(Object o, int offset) { - return Word.fromObject(o).readLong(offset, ID); - } - - @Snippet - public static long readLong2(Object o, int offset) { - return Word.fromObject(o).readLong(Word.signed(offset), ID); - } - - @Snippet - public static long readLong3(Object o, int offset) { - return Word.fromObject(o).readLong(offset); - } - - @Snippet - public static void writeLong1(Object o, int offset, long value) { - Word.fromObject(o).writeLong(offset, value, ID); - } - - @Snippet - public static void writeLong2(Object o, int offset, long value) { - Word.fromObject(o).writeLong(Word.signed(offset), value, ID); - } - - @Snippet - public static void writeLong3(Object o, int offset, long value) { - Word.fromObject(o).writeLong(offset, value); - } - - @Snippet - public static float readFloat1(Object o, int offset) { - return Word.fromObject(o).readFloat(offset, ID); - } - - @Snippet - public static float readFloat2(Object o, int offset) { - return Word.fromObject(o).readFloat(Word.signed(offset), ID); - } - - @Snippet - public static float readFloat3(Object o, int offset) { - return Word.fromObject(o).readFloat(offset); - } - - @Snippet - public static void writeFloat1(Object o, int offset, float value) { - Word.fromObject(o).writeFloat(offset, value, ID); - } - - @Snippet - public static void writeFloat2(Object o, int offset, float value) { - Word.fromObject(o).writeFloat(Word.signed(offset), value, ID); - } - - @Snippet - public static void writeFloat3(Object o, int offset, float value) { - Word.fromObject(o).writeFloat(offset, value); - } - - @Snippet - public static double readDouble1(Object o, int offset) { - return Word.fromObject(o).readDouble(offset, ID); - } - - @Snippet - public static double readDouble2(Object o, int offset) { - return Word.fromObject(o).readDouble(Word.signed(offset), ID); - } - - @Snippet - public static double readDouble3(Object o, int offset) { - return Word.fromObject(o).readDouble(offset); - } - - @Snippet - public static void writeDouble1(Object o, int offset, double value) { - Word.fromObject(o).writeDouble(offset, value, ID); - } - - @Snippet - public static void writeDouble2(Object o, int offset, double value) { - Word.fromObject(o).writeDouble(Word.signed(offset), value, ID); - } - - @Snippet - public static void writeDouble3(Object o, int offset, double value) { - Word.fromObject(o).writeDouble(offset, value); - } - - @Snippet - public static Object readObject1(Object o, int offset) { - return Word.fromObject(o).readObject(offset, ID); - } - - @Snippet - public static Object readObject2(Object o, int offset) { - return Word.fromObject(o).readObject(Word.signed(offset), ID); - } - - @Snippet - public static Object readObject3(Object o, int offset) { - return Word.fromObject(o).readObject(offset); - } - - @Snippet - public static void writeObject1(Object o, int offset, Object value) { - Word.fromObject(o).writeObject(offset, value, ID); - } - - @Snippet - public static void writeObject2(Object o, int offset, Object value) { - Word.fromObject(o).writeObject(Word.signed(offset), value, ID); - } - - @Snippet - public static void writeObject3(Object o, int offset, Object value) { - Word.fromObject(o).writeObject(offset, value); - } - -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/StandardMethodSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/StandardMethodSubstitutionsTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,453 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import static com.oracle.graal.graph.UnsafeAccess.*; -import static com.oracle.graal.replacements.UnsafeSubstitutions.*; - -import java.lang.reflect.*; -import java.util.concurrent.atomic.*; - -import org.junit.*; - -import sun.misc.*; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * Tests the VM independent {@link MethodSubstitution}s. - */ -public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest { - - static long off(Object o, String name) { - try { - return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name)); - } catch (Exception e) { - Assert.fail(e.toString()); - return 0L; - } - } - - static class Foo { - - boolean z; - byte b; - short s; - char c; - int i; - long l; - float f; - double d; - Object o; - - void testGet(Field field, long offset, String getName, Object value) throws Exception { - field.set(this, value); - Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class); - Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class); - Object expected = m1.invoke(unsafe, this, offset); - Object actual = m2.invoke(null, unsafe, this, offset); - Assert.assertEquals(expected, actual); - } - - void testDirect(Field field, long offset, String type, Object value) throws Exception { - if (type.equals("Boolean") || type.equals("Object")) { - // No direct memory access for these types - return; - } - - long address = unsafe.allocateMemory(offset + 16); - - String getName = "get" + type; - String putName = "put" + type; - Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType()); - Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class); - - Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); - Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class); - - m1.invoke(unsafe, address + offset, value); - Object expected = m2.invoke(unsafe, address + offset); - - m3.invoke(null, unsafe, address + offset, value); - Object actual = m4.invoke(null, unsafe, address + offset); - - unsafe.freeMemory(address); - Assert.assertEquals(expected, actual); - } - - void testPut(Field field, long offset, String putName, Object value) throws Exception { - Object initialValue = field.get(new Foo()); - field.set(this, initialValue); - - try { - Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); - Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType()); - m1.invoke(unsafe, this, offset, value); - Object expected = field.get(this); - m2.invoke(null, unsafe, this, offset, value); - Object actual = field.get(this); - Assert.assertEquals(expected, actual); - } catch (NoSuchMethodException e) { - if (!putName.startsWith("putOrdered")) { - throw e; - } - } - } - - void test(String fieldName, String typeSuffix, Object value) { - try { - Field field = Foo.class.getDeclaredField(fieldName); - long offset = unsafe.objectFieldOffset(field); - testGet(field, offset, "get" + typeSuffix, value); - testGet(field, offset, "get" + typeSuffix + "Volatile", value); - testPut(field, offset, "put" + typeSuffix, value); - testPut(field, offset, "put" + typeSuffix + "Volatile", value); - testPut(field, offset, "putOrdered" + typeSuffix, value); - testDirect(field, offset, typeSuffix, value); - } catch (Exception e) { - throw new AssertionError(e); - } - } - } - - @Test - public void testUnsafeSubstitutions() throws Exception { - test("unsafeCompareAndSwapInt"); - test("unsafeCompareAndSwapLong"); - test("unsafeCompareAndSwapObject"); - - test("unsafeGetBoolean"); - test("unsafeGetByte"); - test("unsafeGetShort"); - test("unsafeGetChar"); - test("unsafeGetInt"); - test("unsafeGetLong"); - test("unsafeGetFloat"); - test("unsafeGetDouble"); - test("unsafeGetObject"); - - test("unsafePutBoolean"); - test("unsafePutByte"); - test("unsafePutShort"); - test("unsafePutChar"); - test("unsafePutInt"); - test("unsafePutFloat"); - test("unsafePutDouble"); - test("unsafePutObject"); - - test("unsafeDirectMemoryRead"); - test("unsafeDirectMemoryWrite"); - - AtomicInteger a1 = new AtomicInteger(42); - AtomicInteger a2 = new AtomicInteger(42); - assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53)); - assertEquals(a1.get(), a2.get()); - - AtomicLong l1 = new AtomicLong(42); - AtomicLong l2 = new AtomicLong(42); - assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53)); - assertEquals(l1.get(), l2.get()); - - AtomicReference o1 = new AtomicReference<>("42"); - AtomicReference o2 = new AtomicReference<>("42"); - assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53")); - assertEquals(o1.get(), o2.get()); - - Foo f1 = new Foo(); - f1.test("z", "Boolean", Boolean.TRUE); - f1.test("b", "Byte", Byte.MIN_VALUE); - f1.test("s", "Short", Short.MAX_VALUE); - f1.test("c", "Char", '!'); - f1.test("i", "Int", 1010010); - f1.test("f", "Float", -34.5F); - f1.test("l", "Long", 99999L); - f1.test("d", "Double", 1234.5678D); - f1.test("o", "Object", "object"); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapInt(obj, offset, 0, 1); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapLong(obj, offset, 0, 1); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapObject(obj, offset, null, new Object()); - } - - @SuppressWarnings("all") - public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) { - return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) { - return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) { - return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) { - return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) { - return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) { - return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) { - return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) { - return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) { - return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) { - unsafe.putBoolean(obj, offset, value); - unsafe.putBooleanVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) { - unsafe.putByte(obj, offset, value); - unsafe.putByteVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) { - unsafe.putShort(obj, offset, value); - unsafe.putShortVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) { - unsafe.putChar(obj, offset, value); - unsafe.putCharVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) { - unsafe.putInt(obj, offset, value); - unsafe.putIntVolatile(obj, offset, value); - unsafe.putOrderedInt(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) { - unsafe.putLong(obj, offset, value); - unsafe.putLongVolatile(obj, offset, value); - unsafe.putOrderedLong(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) { - unsafe.putFloat(obj, offset, value); - unsafe.putFloatVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) { - unsafe.putDouble(obj, offset, value); - unsafe.putDoubleVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) { - unsafe.putObject(obj, offset, value); - unsafe.putObjectVolatile(obj, offset, value); - unsafe.putOrderedObject(obj, offset, value); - } - - @SuppressWarnings("all") - public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) { - // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist - return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address); - } - - @SuppressWarnings("all") - public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) { - // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist - unsafe.putByte(address, value); - unsafe.putShort(address, value); - unsafe.putChar(address, (char) value); - unsafe.putInt(address, value); - unsafe.putLong(address, value); - unsafe.putFloat(address, value); - unsafe.putDouble(address, value); - } - - @Test - public void testMathSubstitutions() { - assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class); // Java - test("math"); - - double value = 34567.891D; - assertEquals(Math.sqrt(value), MathSubstitutionsX86.sqrt(value)); - assertEquals(Math.log(value), MathSubstitutionsX86.log(value)); - assertEquals(Math.log10(value), MathSubstitutionsX86.log10(value)); - assertEquals(Math.sin(value), MathSubstitutionsX86.sin(value)); - assertEquals(Math.cos(value), MathSubstitutionsX86.cos(value)); - assertEquals(Math.tan(value), MathSubstitutionsX86.tan(value)); - } - - @SuppressWarnings("all") - public static double mathAbs(double value) { - return Math.abs(value); - } - - @SuppressWarnings("all") - public static double math(double value) { - return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value); - // Math.exp(value) + - // Math.pow(value, 13); - } - - @Test - public void testIntegerSubstitutions() { - assertInGraph(test("integerReverseBytes"), ReverseBytesNode.class); // Java - assertInGraph(test("integerNumberOfLeadingZeros"), BitScanReverseNode.class); // Java - assertInGraph(test("integerNumberOfTrailingZeros"), BitScanForwardNode.class); // Java - assertInGraph(test("integerBitCount"), BitCountNode.class); // Java - - for (int i : new int[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}) { - assertEquals(Integer.reverseBytes(i), IntegerSubstitutions.reverseBytes(i)); - assertEquals(Integer.numberOfLeadingZeros(i), IntegerSubstitutions.numberOfLeadingZeros(i)); - assertEquals(Integer.numberOfTrailingZeros(i), IntegerSubstitutions.numberOfTrailingZeros(i)); - assertEquals(Integer.bitCount(i), IntegerSubstitutions.bitCount(i)); - } - } - - @SuppressWarnings("all") - public static int integerReverseBytes(int value) { - return Integer.reverseBytes(value); - } - - @SuppressWarnings("all") - public static int integerNumberOfLeadingZeros(int value) { - return Integer.numberOfLeadingZeros(value); - } - - @SuppressWarnings("all") - public static int integerNumberOfTrailingZeros(int value) { - return Integer.numberOfTrailingZeros(value); - } - - @SuppressWarnings("all") - public static int integerBitCount(int value) { - return Integer.bitCount(value); - } - - @Test - public void testLongSubstitutions() { - assertInGraph(test("longReverseBytes"), ReverseBytesNode.class); // Java - assertInGraph(test("longNumberOfLeadingZeros"), BitScanReverseNode.class); // Java - assertInGraph(test("longNumberOfTrailingZeros"), BitScanForwardNode.class); // Java - assertInGraph(test("longBitCount"), BitCountNode.class); // Java - - for (long l : new long[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}) { - assertEquals(Long.reverseBytes(l), LongSubstitutions.reverseBytes(l)); - assertEquals(Long.numberOfLeadingZeros(l), LongSubstitutions.numberOfLeadingZeros(l)); - assertEquals(Long.numberOfTrailingZeros(l), LongSubstitutions.numberOfTrailingZeros(l)); - assertEquals(Long.bitCount(l), LongSubstitutions.bitCount(l)); - } - } - - @SuppressWarnings("all") - public static long longReverseBytes(long value) { - return Long.reverseBytes(value); - } - - @SuppressWarnings("all") - public static long longNumberOfLeadingZeros(long value) { - return Long.numberOfLeadingZeros(value); - } - - @SuppressWarnings("all") - public static long longNumberOfTrailingZeros(long value) { - return Long.numberOfTrailingZeros(value); - } - - @SuppressWarnings("all") - public static int longBitCount(long value) { - return Long.bitCount(value); - } - - @Test - public void testFloatSubstitutions() { - assertInGraph(test("floatToIntBits"), ConvertNode.class); // Java - test("intBitsToFloat"); - } - - @SuppressWarnings("all") - public static int floatToIntBits(float value) { - return Float.floatToIntBits(value); - } - - @SuppressWarnings("all") - public static float intBitsToFloat(int value) { - return Float.intBitsToFloat(value); - } - - @Test - public void testDoubleSubstitutions() { - assertInGraph(test("doubleToLongBits"), ConvertNode.class); // Java - test("longBitsToDouble"); - } - - @SuppressWarnings("all") - public static long doubleToLongBits(double value) { - return Double.doubleToLongBits(value); - } - - @SuppressWarnings("all") - public static double longBitsToDouble(long value) { - return Double.longBitsToDouble(value); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/TypeCheckTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/TypeCheckTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.nodes.*; - -/** - * Base class for checkcast and instanceof test classes. - */ -public abstract class TypeCheckTest extends GraalCompilerTest { - - protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile); - - protected JavaTypeProfile currentProfile; - - @Override - protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) { - boolean forceCompile = false; - if (currentProfile != null) { - replaceProfile(graph, currentProfile); - forceCompile = true; - } - return super.getCode(method, graph, forceCompile); - } - - protected JavaTypeProfile profile(Class... types) { - return profile(TriState.UNKNOWN, types); - } - - protected JavaTypeProfile profile(TriState nullSeen, Class... types) { - if (types.length == 0) { - return null; - } - ProfiledType[] ptypes = new ProfiledType[types.length]; - for (int i = 0; i < types.length; i++) { - ptypes[i] = new ProfiledType(runtime.lookupJavaType(types[i]), 1.0D / types.length); - } - return new JavaTypeProfile(nullSeen, 0.0D, ptypes); - } - - protected void test(String name, JavaTypeProfile profile, Object... args) { - assert currentProfile == null; - currentProfile = profile; - try { - super.test(name, args); - } finally { - currentProfile = null; - } - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/WordTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/WordTest.java Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import java.lang.reflect.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.test.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.word.*; - -/** - * Tests for the {@link Word} type. - */ -public class WordTest extends GraalCompilerTest implements Snippets { - - private final ReplacementsImpl installer; - - public WordTest() { - TargetDescription target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget(); - installer = new ReplacementsImpl(runtime, new Assumptions(false), target); - } - - private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); - - @Override - protected StructuredGraph parse(Method m) { - ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); - } - - @LongTest - public void construction() { - long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, - Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; - for (long word : words) { - test("unsigned_long", word); - test("unsigned_int", (int) word); - test("signed_long", word); - test("signed_int", (int) word); - } - } - - @LongTest - public void test_arithmetic() { - long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, - Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; - for (long word : words) { - test("unsigned_not", word); - test("signed_not", word); - for (long addend : words) { - test("unsigned_plus_int", word, (int) addend); - test("unsigned_minus_int", word, (int) addend); - test("unsigned_plus_int", word, -((int) addend)); - test("unsigned_minus_int", word, -((int) addend)); - test("unsigned_plus_long", word, addend); - test("unsigned_minus_long", word, addend); - test("unsigned_plus_long", word, -addend); - test("unsigned_minus_long", word, -addend); - test("signed_plus_int", word, (int) addend); - test("signed_minus_int", word, (int) addend); - test("signed_plus_int", word, -((int) addend)); - test("signed_minus_int", word, -((int) addend)); - test("signed_plus_long", word, addend); - test("signed_minus_long", word, addend); - test("signed_plus_long", word, -addend); - test("signed_minus_long", word, -addend); - - test("and_int", word, (int) addend); - test("or_int", word, (int) addend); - test("and_int", word, -((int) addend)); - test("or_int", word, -((int) addend)); - test("and_long", word, addend); - test("or_long", word, addend); - test("and_long", word, -addend); - test("or_long", word, -addend); - } - } - } - - @LongTest - public void test_compare() { - long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE}; - for (long word1 : words) { - for (long word2 : words) { - for (String method : new String[]{"aboveOrEqual", "above", "belowOrEqual", "below"}) { - test(method, word1, word2); - test(method, word2, word1); - } - } - } - } - - @Snippet - public static long unsigned_long(long word) { - return Word.unsigned(word).rawValue(); - } - - @Snippet - public static long unsigned_int(int word) { - return Word.unsigned(word).rawValue(); - } - - @Snippet - public static long signed_long(long word) { - return Word.signed(word).rawValue(); - } - - @Snippet - public static long signed_int(int word) { - return Word.signed(word).rawValue(); - } - - @Snippet - public static long unsigned_plus_int(long word, int addend) { - return Word.unsigned(word).add(addend).rawValue(); - } - - @Snippet - public static long unsigned_minus_int(long word, int addend) { - return Word.unsigned(word).subtract(addend).rawValue(); - } - - @Snippet - public static long unsigned_plus_long(long word, long addend) { - return Word.unsigned(word).add(Word.unsigned(addend)).rawValue(); - } - - @Snippet - public static long unsigned_minus_long(long word, long addend) { - return Word.unsigned(word).subtract(Word.unsigned(addend)).rawValue(); - } - - @Snippet - public static long signed_plus_int(long word, int addend) { - return Word.signed(word).add(addend).rawValue(); - } - - @Snippet - public static long signed_minus_int(long word, int addend) { - return Word.signed(word).subtract(addend).rawValue(); - } - - @Snippet - public static long signed_plus_long(long word, long addend) { - return Word.signed(word).add(Word.signed(addend)).rawValue(); - } - - @Snippet - public static long signed_minus_long(long word, long addend) { - return Word.signed(word).subtract(Word.signed(addend)).rawValue(); - } - - @Snippet - public static long signed_not(long word) { - return Word.signed(word).not().rawValue(); - } - - @Snippet - public static long unsigned_not(long word) { - return Word.unsigned(word).not().rawValue(); - } - - @Snippet - public static boolean aboveOrEqual(long word1, long word2) { - return Word.unsigned(word1).aboveOrEqual(Word.unsigned(word2)); - } - - @Snippet - public static boolean above(long word1, long word2) { - return Word.unsigned(word1).aboveThan(Word.unsigned(word2)); - } - - @Snippet - public static boolean belowOrEqual(long word1, long word2) { - return Word.unsigned(word1).belowOrEqual(Word.unsigned(word2)); - } - - @Snippet - public static boolean below(long word1, long word2) { - return Word.unsigned(word1).belowThan(Word.unsigned(word2)); - } - - @Snippet - public static long and_int(long word, int addend) { - return Word.unsigned(word).and(addend).rawValue(); - } - - @Snippet - public static long or_int(long word, int addend) { - return Word.unsigned(word).or(addend).rawValue(); - } - - @Snippet - public static long and_long(long word, long addend) { - return Word.unsigned(word).and(Word.unsigned(addend)).rawValue(); - } - - @Snippet - public static long or_long(long word, long addend) { - return Word.unsigned(word).or(Word.unsigned(addend)).rawValue(); - } -} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +/** + * Tests the implementation of checkcast, allowing profiling information to be manually specified. + */ +public class CheckCastTest extends TypeCheckTest { + + @Override + protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { + CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); + if (ccn != null) { + CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile)); + graph.replaceFixedWithFixed(ccn, ccnNew); + } + } + + @LongTest + public void test1() { + test("asNumber", profile(), 111); + test("asNumber", profile(Integer.class), 111); + test("asNumber", profile(Long.class, Short.class), 111); + test("asNumberExt", profile(), 111); + test("asNumberExt", profile(Integer.class), 111); + test("asNumberExt", profile(Long.class, Short.class), 111); + } + + @LongTest + public void test2() { + test("asString", profile(), "111"); + test("asString", profile(String.class), "111"); + test("asString", profile(String.class), "111"); + + final String nullString = null; + test("asString", profile(), nullString); + test("asString", profile(String.class), nullString); + test("asString", profile(String.class), nullString); + + test("asStringExt", profile(), "111"); + test("asStringExt", profile(String.class), "111"); + test("asStringExt", profile(String.class), "111"); + } + + @LongTest + public void test3() { + test("asNumber", profile(), "111"); + } + + @LongTest + public void test4() { + test("asString", profile(String.class), 111); + } + + @LongTest + public void test5() { + test("asNumberExt", profile(), "111"); + } + + @LongTest + public void test6() { + test("asStringExt", profile(String.class), 111); + } + + @LongTest + public void test7() { + Throwable throwable = new Exception(); + test("asThrowable", profile(), throwable); + test("asThrowable", profile(Throwable.class), throwable); + test("asThrowable", profile(Exception.class, Error.class), throwable); + } + + @LongTest + public void test8() { + test("arrayStore", new Object[100], "111"); + } + + @LongTest + public void test8_1() { + test("arrayFill", new Object[100], "111"); + } + + public static Number asNumber(Object o) { + return (Number) o; + } + + public static String asString(Object o) { + return (String) o; + } + + public static Throwable asThrowable(Object o) { + return (Throwable) o; + } + + public static ValueNode asValueNode(Object o) { + return (ValueNode) o; + } + + public static Number asNumberExt(Object o) { + Number n = (Number) o; + return n.intValue() + 10; + } + + public static String asStringExt(Object o) { + String s = (String) o; + return "#" + s; + } + + public static Object[] arrayStore(Object[] arr, Object value) { + arr[15] = value; + return arr; + } + + public static Object[] arrayFill(Object[] arr, Object value) { + for (int i = 0; i < arr.length; i++) { + arr[i] = value; + } + return arr; + } + + static class Depth1 implements Cloneable { + } + + static class Depth2 extends Depth1 { + } + + static class Depth3 extends Depth2 { + } + + static class Depth4 extends Depth3 { + } + + static class Depth5 extends Depth4 { + } + + static class Depth6 extends Depth5 { + } + + static class Depth7 extends Depth6 { + } + + static class Depth8 extends Depth7 { + } + + static class Depth9 extends Depth8 { + } + + static class Depth10 extends Depth9 { + } + + static class Depth11 extends Depth10 { + } + + static class Depth12 extends Depth11 { + } + + static class Depth13 extends Depth12 { + } + + static class Depth14 extends Depth12 { + } + + public static Depth12 asDepth12(Object o) { + return (Depth12) o; + } + + public static Depth12[][] asDepth12Arr(Object o) { + return (Depth12[][]) o; + } + + public static Cloneable asCloneable(Object o) { + return (Cloneable) o; + } + + @LongTest + public void test9() { + Object o = new Depth13(); + test("asDepth12", profile(), o); + test("asDepth12", profile(Depth13.class), o); + test("asDepth12", profile(Depth13.class, Depth14.class), o); + } + + @LongTest + public void test10() { + Object o = new Depth13[3][]; + test("asDepth12Arr", o); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +/** + * Tests compilation of a hot exception handler. + */ +public class CompiledExceptionHandlerTest extends GraalCompilerTest { + + @Override + protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) { + phasePlan.disablePhase(InliningPhase.class); + } + + @Override + protected StructuredGraph parse(Method m) { + StructuredGraph graph = super.parse(m); + int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count(); + Assert.assertEquals(1, handlers); + return graph; + } + + private static void raiseException(String s) { + throw new RuntimeException(s); + } + + @Test + public void test1() { + // Ensure the profile shows a hot exception + for (int i = 0; i < 10000; i++) { + test1Snippet(""); + test1Snippet(null); + } + + test("test1Snippet", "a string"); + } + + public static String test1Snippet(String message) { + if (message != null) { + try { + raiseException(message); + } catch (Exception e) { + return message; + } + } + return null; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import com.oracle.graal.test.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.java.*; + +/** + * Tests for {@link InstanceOfDynamicNode}. + */ +public class InstanceOfDynamicTest extends GraalCompilerTest { + + public static int id(int value) { + return value; + } + + @LongTest + public void test100() { + final Object nul = null; + test("isStringDynamic", nul); + test("isStringDynamic", "object"); + test("isStringDynamic", Object.class); + } + + @LongTest + public void test101() { + final Object nul = null; + test("isStringIntDynamic", nul); + test("isStringIntDynamic", "object"); + test("isStringIntDynamic", Object.class); + } + + @LongTest + public void test103() { + test("isInstanceDynamic", String.class, null); + test("isInstanceDynamic", String.class, "object"); + test("isInstanceDynamic", String.class, Object.class); + test("isInstanceDynamic", int.class, null); + test("isInstanceDynamic", int.class, "Object"); + test("isInstanceDynamic", int.class, Object.class); + } + + @LongTest + public void test104() { + test("isInstanceIntDynamic", String.class, null); + test("isInstanceIntDynamic", String.class, "object"); + test("isInstanceIntDynamic", String.class, Object.class); + test("isInstanceIntDynamic", int.class, null); + test("isInstanceIntDynamic", int.class, "Object"); + test("isInstanceIntDynamic", int.class, Object.class); + } + + public static boolean isStringDynamic(Object o) { + return String.class.isInstance(o); + } + + public static int isStringIntDynamic(Object o) { + if (String.class.isInstance(o)) { + return o.toString().length(); + } + return o.getClass().getName().length(); + } + + public static boolean isInstanceDynamic(Class c, Object o) { + return c.isInstance(o); + } + + public static int isInstanceIntDynamic(Class c, Object o) { + if (c.isInstance(o)) { + return o.toString().length(); + } + return o.getClass().getName().length(); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import java.util.*; + +import com.oracle.graal.api.code.CompilationResult.Call; +import com.oracle.graal.api.code.CompilationResult.Mark; +import com.oracle.graal.api.code.CompilationResult.Site; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.replacements.test.CheckCastTest.Depth12; +import com.oracle.graal.replacements.test.CheckCastTest.Depth13; +import com.oracle.graal.replacements.test.CheckCastTest.Depth14; +import com.oracle.graal.test.*; + +/** + * Tests the implementation of instanceof, allowing profiling information to be manually specified. + */ +public class InstanceOfTest extends TypeCheckTest { + + @Override + protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) { + phasePlan.disablePhase(InliningPhase.class); + } + + @Override + protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { + InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first(); + if (ion != null) { + InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.type(), ion.object(), profile)); + graph.replaceFloating(ion, ionNew); + } + } + + @LongTest + public void test1() { + test("isString", profile(), "object"); + test("isString", profile(String.class), "object"); + + test("isString", profile(), Object.class); + test("isString", profile(String.class), Object.class); + } + + @LongTest + public void test2() { + test("isStringInt", profile(), "object"); + test("isStringInt", profile(String.class), "object"); + + test("isStringInt", profile(), Object.class); + test("isStringInt", profile(String.class), Object.class); + } + + @LongTest + public void test2_1() { + test("isStringIntComplex", profile(), "object"); + test("isStringIntComplex", profile(String.class), "object"); + + test("isStringIntComplex", profile(), Object.class); + test("isStringIntComplex", profile(String.class), Object.class); + } + + @LongTest + public void test3() { + Throwable throwable = new Exception(); + test("isThrowable", profile(), throwable); + test("isThrowable", profile(Throwable.class), throwable); + test("isThrowable", profile(Exception.class, Error.class), throwable); + + test("isThrowable", profile(), Object.class); + test("isThrowable", profile(Throwable.class), Object.class); + test("isThrowable", profile(Exception.class, Error.class), Object.class); + } + + @LongTest + public void test3_1() { + onlyFirstIsException(new Exception(), new Error()); + test("onlyFirstIsException", profile(), new Exception(), new Error()); + test("onlyFirstIsException", profile(), new Error(), new Exception()); + test("onlyFirstIsException", profile(), new Exception(), new Exception()); + test("onlyFirstIsException", profile(), new Error(), new Error()); + } + + @LongTest + public void test4() { + Throwable throwable = new Exception(); + test("isThrowableInt", profile(), throwable); + test("isThrowableInt", profile(Throwable.class), throwable); + test("isThrowableInt", profile(Exception.class, Error.class), throwable); + + test("isThrowableInt", profile(), Object.class); + test("isThrowableInt", profile(Throwable.class), Object.class); + test("isThrowableInt", profile(Exception.class, Error.class), Object.class); + } + + @LongTest + public void test5() { + Map map = new HashMap<>(); + test("isMap", profile(), map); + test("isMap", profile(HashMap.class), map); + test("isMap", profile(TreeMap.class, HashMap.class), map); + + test("isMap", profile(), Object.class); + test("isMap", profile(HashMap.class), Object.class); + test("isMap", profile(TreeMap.class, HashMap.class), Object.class); + test("isMap", profile(String.class, HashMap.class), Object.class); + } + + @LongTest + public void test6() { + Map map = new HashMap<>(); + test("isMapInt", profile(), map); + test("isMapInt", profile(HashMap.class), map); + test("isMapInt", profile(TreeMap.class, HashMap.class), map); + + test("isMapInt", profile(), Object.class); + test("isMapInt", profile(HashMap.class), Object.class); + test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class); + } + + @LongTest + public void test7() { + Object o = new Depth13(); + test("isDepth12", profile(), o); + test("isDepth12", profile(Depth13.class), o); + test("isDepth12", profile(Depth13.class, Depth14.class), o); + + o = "not a depth"; + test("isDepth12", profile(), o); + test("isDepth12", profile(Depth13.class), o); + test("isDepth12", profile(Depth13.class, Depth14.class), o); + test("isDepth12", profile(String.class, HashMap.class), o); + } + + @LongTest + public void test8() { + Object o = new Depth13(); + test("isDepth12Int", profile(), o); + test("isDepth12Int", profile(Depth13.class), o); + test("isDepth12Int", profile(Depth13.class, Depth14.class), o); + + o = "not a depth"; + test("isDepth12Int", profile(), o); + test("isDepth12Int", profile(Depth13.class), o); + test("isDepth12Int", profile(Depth13.class, Depth14.class), o); + } + + public static boolean isString(Object o) { + return o instanceof String; + } + + public static int isStringInt(Object o) { + if (o instanceof String) { + return id(1); + } + return id(0); + } + + public static int isStringIntComplex(Object o) { + if (o instanceof String || o instanceof Integer) { + return id(o instanceof String ? 1 : 0); + } + return id(0); + } + + public static int id(int value) { + return value; + } + + public static boolean isThrowable(Object o) { + return ((Throwable) o) instanceof Exception; + } + + public static int onlyFirstIsException(Throwable t1, Throwable t2) { + if (t1 instanceof Exception ^ t2 instanceof Exception) { + return t1 instanceof Exception ? 1 : -1; + } + return -1; + } + + public static int isThrowableInt(Object o) { + int result = o instanceof Throwable ? 4 : 5; + if (o instanceof Throwable) { + return id(4); + } + return result; + } + + public static boolean isMap(Object o) { + return o instanceof Map; + } + + public static int isMapInt(Object o) { + if (o instanceof Map) { + return id(1); + } + return id(0); + } + + public static boolean isDepth12(Object o) { + return o instanceof Depth12; + } + + public static int isDepth12Int(Object o) { + if (o instanceof Depth12) { + return id(0); + } + return id(0); + } + + abstract static class MySite { + + final int offset; + + MySite(int offset) { + this.offset = offset; + } + } + + static class MyMark extends MySite { + + MyMark(int offset) { + super(offset); + } + } + + abstract static class MySafepoint extends MySite { + + MySafepoint(int offset) { + super(offset); + } + } + + static class MyCall extends MySafepoint { + + MyCall(int offset) { + super(offset); + } + } + + @LongTest + public void test9() { + MyCall callAt63 = new MyCall(63); + MyMark markAt63 = new MyMark(63); + test("compareMySites", callAt63, callAt63); + test("compareMySites", callAt63, markAt63); + test("compareMySites", markAt63, callAt63); + test("compareMySites", markAt63, markAt63); + } + + public static int compareMySites(MySite s1, MySite s2) { + if (s1.offset == s2.offset && (s1 instanceof MyMark ^ s2 instanceof MyMark)) { + return s1 instanceof MyMark ? -1 : 1; + } + return s1.offset - s2.offset; + } + + @LongTest + public void test10() { + Mark[] noMarks = {}; + Call callAt63 = new Call(null, 63, 5, true, null); + Mark markAt63 = new Mark(63, "1", noMarks); + test("compareSites", callAt63, callAt63); + test("compareSites", callAt63, markAt63); + test("compareSites", markAt63, callAt63); + test("compareSites", markAt63, markAt63); + } + + public static int compareSites(Site s1, Site s2) { + if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { + return s1 instanceof Mark ? -1 : 1; + } + return s1.pcOffset - s2.pcOffset; + } + + /** + * This test exists to show the kind of pattern that is be optimizable by + * {@code removeIntermediateMaterialization()} in {@link IfNode}. + *

+ * The test exists in this source file as the transformation was originally motivated by the + * need to remove use of special JumpNodes in the {@code InstanceOfSnippets}. + */ + @LongTest + public void test_removeIntermediateMaterialization() { + List list = Arrays.asList("1", "2", "3", "4"); + test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no"); + test("removeIntermediateMaterialization", profile(), list, null, "yes", "no"); + test("removeIntermediateMaterialization", profile(), null, "2", "yes", "no"); + } + + public static String removeIntermediateMaterialization(List list, Object e, String a, String b) { + boolean test; + if (list == null || e == null) { + test = false; + } else { + test = false; + for (Object i : list) { + if (i.equals(e)) { + test = true; + break; + } + } + } + if (test) { + return a; + } + return b; + } + + abstract static class A { + } + + static class B extends A { + } + + static class C extends B { + } + + abstract static class D extends C { + } + + public static boolean isArrayOfA(Object o) { + return o instanceof A[]; + } + + public static boolean isArrayOfB(Object o) { + return o instanceof B[]; + } + + public static boolean isArrayOfC(Object o) { + return o instanceof C[]; + } + + public static boolean isArrayOfD(Object o) { + return o instanceof D[]; + } + + @LongTest + public void testArray() { + Object aArray = new A[10]; + test("isArrayOfA", aArray); + + Object bArray = new B[10]; + test("isArrayOfA", aArray); + test("isArrayOfA", bArray); + test("isArrayOfB", aArray); + test("isArrayOfB", bArray); + + Object cArray = new C[10]; + test("isArrayOfA", aArray); + test("isArrayOfA", bArray); + test("isArrayOfA", cArray); + test("isArrayOfB", aArray); + test("isArrayOfB", bArray); + test("isArrayOfB", cArray); + test("isArrayOfC", aArray); + test("isArrayOfC", bArray); + test("isArrayOfC", cArray); + + Object dArray = new D[10]; + test("isArrayOfA", aArray); + test("isArrayOfA", bArray); + test("isArrayOfA", cArray); + test("isArrayOfA", dArray); + test("isArrayOfB", aArray); + test("isArrayOfB", bArray); + test("isArrayOfB", cArray); + test("isArrayOfB", dArray); + test("isArrayOfC", aArray); + test("isArrayOfC", bArray); + test("isArrayOfC", cArray); + test("isArrayOfC", dArray); + test("isArrayOfD", aArray); + test("isArrayOfD", bArray); + test("isArrayOfD", cArray); + test("isArrayOfD", dArray); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +/** + * Tests the implementation of the snippets for lowering the INVOKE* instructions. + */ +public class InvokeTest extends GraalCompilerTest { + + @Override + protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) { + phasePlan.disablePhase(InliningPhase.class); + } + + public interface I { + + String virtualMethod(String s); + } + + public static class A implements I { + + final String name = "A"; + + public String virtualMethod(String s) { + return name + s; + } + } + + @SuppressWarnings("static-method") + private String privateMethod(String s) { + return s; + } + + @Test + public void test1() { + test("invokestatic", "a string"); + test("invokespecialConstructor", "a string"); + test("invokespecial", this, "a string"); + test("invokevirtual", new A(), "a string"); + test("invokevirtual2", new A(), "a string"); + test("invokeinterface", new A(), "a string"); + Object[] args = {null}; + test("invokestatic", args); + test("invokespecialConstructor", args); + test("invokespecial", null, null); + test("invokevirtual", null, null); + test("invokevirtual2", null, null); + test("invokeinterface", null, null); + } + + public static String invokestatic(String s) { + return staticMethod(s); + } + + public static String staticMethod(String s) { + return s; + } + + public static String invokespecialConstructor(String s) { + return new A().virtualMethod(s); + } + + public static String invokespecial(InvokeTest a, String s) { + return a.privateMethod(s); + } + + public static String invokevirtual(A a, String s) { + return a.virtualMethod(s); + } + + public static String invokevirtual2(A a, String s) { + a.virtualMethod(s); + return a.virtualMethod(s); + } + + public static String invokeinterface(I i, String s) { + return i.virtualMethod(s); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import static org.junit.Assert.*; + +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +/** + * Tests if {@link MethodSubstitution}s are inlined correctly. Most test cases only assert that + * there are no remaining invocations in the graph. This is sufficient if the method that is being + * substituted is a native method. For Java methods, additional checks are necessary. + */ +public abstract class MethodSubstitutionTest extends GraalCompilerTest { + + protected StructuredGraph test(final String snippet) { + return Debug.scope("MethodSubstitutionTest", runtime.lookupJavaMethod(getMethod(snippet)), new Callable() { + + @Override + public StructuredGraph call() { + StructuredGraph graph = parse(snippet); + PhasePlan phasePlan = getDefaultPhasePlan(); + Assumptions assumptions = new Assumptions(true); + new ComputeProbabilityPhase().apply(graph); + Debug.dump(graph, "Graph"); + new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); + Debug.dump(graph, "Graph"); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + assertNotInGraph(graph, Invoke.class); + return graph; + } + }); + } + + protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class clazz) { + for (Node node : graph.getNodes()) { + if (clazz.isInstance(node)) { + fail(node.toString()); + } + } + return graph; + } + + protected static StructuredGraph assertInGraph(StructuredGraph graph, Class clazz) { + for (Node node : graph.getNodes()) { + if (clazz.isInstance(node)) { + return graph; + } + } + fail("Graph does not contain a node of class " + clazz.getName()); + return graph; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import org.junit.*; + +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.virtual.phases.ea.*; + +public class MonitorTest extends GraalCompilerTest { + + @Test + public void test0() { + test("lockObjectSimple", new Object(), new Object()); + test("lockObjectSimple", new Object(), null); + } + + @Test + public void test0_1() { + test("lockThisSimple", "test1", new Object()); + test("lockThisSimple", "test1", null); + } + + @Test + public void test0_2() { + test("lockObjectSimple", null, "test1"); + } + + @Test + public void test1_1() { + test("lockObject", new Object(), "test1", new String[1]); + } + + @Test + public void test1_2() { + test("lockObject", null, "test1_1", new String[1]); + } + + @Test + public void test2() { + test("lockThis", "test2", new String[1]); + } + + /** + * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}. + */ + @Test + public void test3() { + test("lockLocalObject", "test3", new String[1]); + } + + /** + * Tests recursive locking of objects which should be biasable. + */ + @Test + public void test4() { + Chars src = new Chars("1234567890".toCharArray()); + Chars dst = new Chars(src.data.length); + test("copyObj", src, dst, 100); + } + + /** + * Tests recursive locking of objects which do not appear to be biasable. + */ + @Test + public void test5() { + char[] src = "1234567890".toCharArray(); + char[] dst = new char[src.length]; + test("copyArr", src, dst, 100); + } + + /** + * Extends {@link #test4()} with contention. + */ + @Test + public void test6() { + Chars src = new Chars("1234567890".toCharArray()); + Chars dst = new Chars(src.data.length); + int n = Runtime.getRuntime().availableProcessors(); + testN(n, "copyObj", src, dst, 100); + } + + /** + * Extends {@link #test5()} with contention. + */ + @Test + public void test7() { + char[] src = "1234567890".toCharArray(); + char[] dst = new char[src.length]; + int n = Runtime.getRuntime().availableProcessors(); + testN(n, "copyArr", src, dst, 100); + } + + private static String setAndGet(String[] box, String value) { + synchronized (box) { + box[0] = null; + } + + // Do a GC while a object is locked (by the caller) + System.gc(); + + synchronized (box) { + box[0] = value; + } + return box[0]; + } + + public static Object lockObjectSimple(Object o, Object value) { + synchronized (o) { + value.hashCode(); + return value; + } + } + + public String lockThisSimple(String value, Object o) { + synchronized (this) { + synchronized (value) { + o.hashCode(); + return value; + } + } + } + + public static String lockObject(Object o, String value, String[] box) { + synchronized (o) { + return setAndGet(box, value); + } + } + + public String lockThis(String value, String[] box) { + synchronized (this) { + return setAndGet(box, value); + } + } + + public static String lockLocalObject(String value, String[] box) { + Object o = new Object(); + synchronized (o) { + return setAndGet(box, value); + } + } + + static class Chars { + + final char[] data; + + public Chars(int size) { + this.data = new char[size]; + } + + public Chars(char[] data) { + this.data = data; + } + } + + public static String copyObj(Chars src, Chars dst, int n) { + for (int j = 0; j < n; j++) { + for (int i = 0; i < src.data.length; i++) { + synchronized (src) { + synchronized (dst) { + synchronized (src) { + synchronized (dst) { + dst.data[i] = src.data[i]; + } + } + } + } + } + } + return new String(dst.data); + } + + public static String copyArr(char[] src, char[] dst, int n) { + for (int j = 0; j < n; j++) { + for (int i = 0; i < src.length; i++) { + synchronized (src) { + synchronized (dst) { + synchronized (src) { + synchronized (dst) { + dst[i] = src[i]; + } + } + } + } + } + } + return new String(dst); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import org.junit.*; + +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.test.*; + +/** + * Tests the implementation of {@code [A]NEWARRAY}. + */ +public class NewArrayTest extends GraalCompilerTest { + + @Override + protected void assertEquals(Object expected, Object actual) { + Assert.assertTrue(expected != null); + Assert.assertTrue(actual != null); + super.assertEquals(expected.getClass(), actual.getClass()); + if (expected instanceof int[]) { + Assert.assertArrayEquals((int[]) expected, (int[]) actual); + } else if (expected instanceof byte[]) { + Assert.assertArrayEquals((byte[]) expected, (byte[]) actual); + } else if (expected instanceof char[]) { + Assert.assertArrayEquals((char[]) expected, (char[]) actual); + } else if (expected instanceof short[]) { + Assert.assertArrayEquals((short[]) expected, (short[]) actual); + } else if (expected instanceof float[]) { + Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f); + } else if (expected instanceof long[]) { + Assert.assertArrayEquals((long[]) expected, (long[]) actual); + } else if (expected instanceof double[]) { + Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d); + } else if (expected instanceof Object[]) { + Assert.assertArrayEquals((Object[]) expected, (Object[]) actual); + } else { + Assert.fail("non-array value encountered: " + expected); + } + } + + @LongTest + public void test1() { + for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) { + test("new" + type + "Array7"); + test("new" + type + "ArrayMinus7"); + test("new" + type + "Array", 7); + test("new" + type + "Array", -7); + test("new" + type + "Array", Integer.MAX_VALUE); + test("new" + type + "Array", Integer.MIN_VALUE); + } + } + + public static Object newCharArray7() { + return new char[7]; + } + + public static Object newCharArrayMinus7() { + return new char[-7]; + } + + public static Object newCharArray(int length) { + return new char[length]; + } + + public static Object newShortArray7() { + return new short[7]; + } + + public static Object newShortArrayMinus7() { + return new short[-7]; + } + + public static Object newShortArray(int length) { + return new short[length]; + } + + public static Object newFloatArray7() { + return new float[7]; + } + + public static Object newFloatArrayMinus7() { + return new float[-7]; + } + + public static Object newFloatArray(int length) { + return new float[length]; + } + + public static Object newLongArray7() { + return new long[7]; + } + + public static Object newLongArrayMinus7() { + return new long[-7]; + } + + public static Object newLongArray(int length) { + return new long[length]; + } + + public static Object newDoubleArray7() { + return new double[7]; + } + + public static Object newDoubleArrayMinus7() { + return new double[-7]; + } + + public static Object newDoubleArray(int length) { + return new double[length]; + } + + public static Object newIntArray7() { + return new int[7]; + } + + public static Object newIntArrayMinus7() { + return new int[-7]; + } + + public static Object newIntArray(int length) { + return new int[length]; + } + + public static Object newByteArray7() { + return new byte[7]; + } + + public static Object newByteArrayMinus7() { + return new byte[-7]; + } + + public static Object newByteArray(int length) { + return new byte[length]; + } + + public static Object newStringArray7() { + return new String[7]; + } + + public static Object newStringArrayMinus7() { + return new String[-7]; + } + + public static Object newStringArray(int length) { + return new String[length]; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.test.*; + +/** + * Tests the implementation of {@code NEW}. + */ +public class NewInstanceTest extends GraalCompilerTest { + + @Override + protected void assertEquals(Object expected, Object actual) { + Assert.assertTrue(expected != null); + Assert.assertTrue(actual != null); + super.assertEquals(expected.getClass(), actual.getClass()); + + if (expected instanceof Object[]) { + Assert.assertTrue(actual instanceof Object[]); + Object[] eArr = (Object[]) expected; + Object[] aArr = (Object[]) actual; + Assert.assertTrue(eArr.length == aArr.length); + for (int i = 0; i < eArr.length; i++) { + assertEquals(eArr[i], aArr[i]); + } + } else if (expected.getClass() != Object.class) { + try { + expected.getClass().getDeclaredMethod("equals", Object.class); + super.assertEquals(expected, actual); + } catch (Exception e) { + } + } + } + + @LongTest + public void test1() { + test("newObject"); + } + + @LongTest + public void test2() { + test("newObjectTwice"); + } + + public static Object newObject() { + return new Object(); + } + + @LongTest + public void test3() { + test("newObjectLoop", 100); + } + + @LongTest + public void test4() { + test("newBigObject"); + } + + @LongTest + public void test5() { + test("newSomeObject"); + } + + @LongTest + public void test6() { + test("newEmptyString"); + } + + @LongTest + public void test7() { + test("newString", "value"); + } + + @LongTest + public void test8() { + test("newHashMap", 31); + } + + @LongTest + public void test9() { + test("newRegression", true); + } + + public static Object[] newObjectTwice() { + Object[] res = {new Object(), new Object()}; + return res; + } + + public static Object[] newObjectLoop(int n) { + Object[] res = new Object[n]; + for (int i = 0; i < n; i++) { + res[i] = new Object(); + } + return res; + } + + public static BigObject newBigObject() { + return new BigObject(); + } + + public static SomeObject newSomeObject() { + return new SomeObject(); + } + + public static String newEmptyString() { + return new String(); + } + + public static String newString(String value) { + return new String(value); + } + + public static HashMap newHashMap(int initialCapacity) { + return new HashMap(initialCapacity); + } + + static class SomeObject { + + String name = "o1"; + HashMap map = new HashMap<>(); + + public SomeObject() { + map.put(name, this.getClass()); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SomeObject) { + SomeObject so = (SomeObject) obj; + return so.name.equals(name) && so.map.equals(map); + } + return false; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + } + + static class BigObject { + + Object f01; + Object f02; + Object f03; + Object f04; + Object f05; + Object f06; + Object f07; + Object f08; + Object f09; + Object f10; + Object f12; + Object f13; + Object f14; + Object f15; + Object f16; + Object f17; + Object f18; + Object f19; + Object f20; + Object f21; + Object f22; + Object f23; + Object f24; + Object f25; + Object f26; + Object f27; + Object f28; + Object f29; + Object f30; + Object f31; + Object f32; + Object f33; + Object f34; + Object f35; + Object f36; + Object f37; + Object f38; + Object f39; + Object f40; + Object f41; + Object f42; + Object f43; + Object f44; + Object f45; + } + + /** + * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB 'top' + * and 'end' values was being GVN'ed from each branch of the 'if' statement. This meant that the + * allocated B object in the true branch overwrote the allocated array. The cause is that + * RegisterNode was a floating node and the reads from it were UnsafeLoads which are also + * floating. The fix was to make RegisterNode a fixed node (which it should have been in the + * first place). + */ + public static Object newRegression(boolean condition) { + Object result; + if (condition) { + Object[] arr = {0, 1, 2, 3, 4, 5}; + result = new B(); + for (int i = 0; i < arr.length; ++i) { + // If the bug exists, the values of arr will now be deadbeef values + // and the virtual dispatch will cause a segfault. This can result in + // either a VM crash or a spurious NullPointerException. + if (arr[i].equals(Integer.valueOf(i))) { + return false; + } + } + } else { + result = new B(); + } + return result; + } + + static class B { + + long f1 = 0xdeadbeefdeadbe01L; + long f2 = 0xdeadbeefdeadbe02L; + long f3 = 0xdeadbeefdeadbe03L; + long f4 = 0xdeadbeefdeadbe04L; + long f5 = 0xdeadbeefdeadbe05L; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +/** + * Tests the lowering of the MULTIANEWARRAY instruction. + */ +public class NewMultiArrayTest extends GraalCompilerTest { + + private static int rank(ResolvedJavaType type) { + String name = type.getName(); + int dims = 0; + while (dims < name.length() && name.charAt(dims) == '[') { + dims++; + } + return dims; + } + + @Override + protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) { + boolean forceCompile = false; + if (bottomType != null) { + List snapshot = graph.getNodes().filter(NewMultiArrayNode.class).snapshot(); + assert snapshot != null; + assert snapshot.size() == 1; + + NewMultiArrayNode node = snapshot.get(0); + assert rank(arrayType) == dimensions.length; + int rank = dimensions.length; + ValueNode[] dimensionNodes = new ValueNode[rank]; + for (int i = 0; i < rank; i++) { + dimensionNodes[i] = graph.unique(ConstantNode.forInt(dimensions[i], graph)); + } + + NewMultiArrayNode repl = graph.add(new NewMultiArrayNode(arrayType, dimensionNodes)); + graph.replaceFixedWithFixed(node, repl); + forceCompile = true; + } + return super.getCode(method, graph, forceCompile); + } + + @Override + protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + if (bottomType != null) { + try { + return Array.newInstance(bottomClass, dimensions); + } catch (Exception e) { + throw new InvocationTargetException(e); + } + } + return super.referenceInvoke(method, receiver, args); + } + + ResolvedJavaType arrayType; + ResolvedJavaType bottomType; + Class bottomClass; + int[] dimensions; + + @LongTest + public void test1() { + for (Class clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) { + bottomClass = clazz; + bottomType = runtime.lookupJavaType(clazz); + arrayType = bottomType; + for (int rank : new int[]{1, 2, 10, 50, 100, 200, 254, 255}) { + while (rank(arrayType) != rank) { + arrayType = arrayType.getArrayClass(); + } + + dimensions = new int[rank]; + for (int i = 0; i < rank; i++) { + dimensions[i] = 1; + } + + test("newMultiArray"); + } + } + bottomType = null; + arrayType = null; + } + + public static Object newMultiArray() { + // This is merely a template - the NewMultiArrayNode is replaced in getCode() above. + // This also means we need a separate test for correct handling of negative dimensions + // as deoptimization won't do what we want for a graph modified to be different from the + // source bytecode. + return new Object[10][9][8]; + } + + @LongTest + public void test2() { + test("newMultiArrayException"); + } + + public static Object newMultiArrayException() { + return new Object[10][9][-8]; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,400 @@ +/* + * 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.replacements.test; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.word.*; + +/** + * Tests for the {@link Pointer} read and write operations. + */ +public class PointerTest extends GraalCompilerTest implements Snippets { + + private static final Object ID = new Object(); + private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}; + private final TargetDescription target; + private final ReplacementsImpl installer; + + public PointerTest() { + target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget(); + installer = new ReplacementsImpl(runtime, new Assumptions(false), target); + } + + private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); + + @Override + protected StructuredGraph parse(Method m) { + ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); + return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); + } + + @Test + public void test_read1() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "1"), kind, false, ID); + } + } + + @Test + public void test_read2() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "2"), kind, true, ID); + } + } + + @Test + public void test_read3() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION); + } + } + + @Test + public void test_write1() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "1"), kind, false, ID); + } + } + + @Test + public void test_write2() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "2"), kind, true, ID); + } + } + + @Test + public void test_write3() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION); + } + } + + private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) { + ReadNode read = (ReadNode) graph.start().next(); + Assert.assertEquals(kind.getStackKind(), read.kind()); + + UnsafeCastNode cast = (UnsafeCastNode) read.object(); + Assert.assertEquals(graph.getLocal(0), cast.object()); + Assert.assertEquals(target.wordKind, cast.kind()); + + IndexedLocationNode location = (IndexedLocationNode) read.location(); + Assert.assertEquals(kind, location.getValueKind()); + Assert.assertEquals(locationIdentity, location.locationIdentity()); + Assert.assertEquals(1, location.indexScaling()); + + if (indexConvert) { + ConvertNode convert = (ConvertNode) location.index(); + Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(graph.getLocal(1), convert.value()); + } else { + Assert.assertEquals(graph.getLocal(1), location.index()); + } + + ReturnNode ret = (ReturnNode) read.next(); + Assert.assertEquals(read, ret.result()); + } + + private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) { + WriteNode write = (WriteNode) graph.start().next(); + Assert.assertEquals(graph.getLocal(2), write.value()); + Assert.assertEquals(Kind.Void, write.kind()); + Assert.assertEquals(FrameState.INVALID_FRAMESTATE_BCI, write.stateAfter().bci); + + UnsafeCastNode cast = (UnsafeCastNode) write.object(); + Assert.assertEquals(graph.getLocal(0), cast.object()); + Assert.assertEquals(target.wordKind, cast.kind()); + + IndexedLocationNode location = (IndexedLocationNode) write.location(); + Assert.assertEquals(kind, location.getValueKind()); + Assert.assertEquals(locationIdentity, location.locationIdentity()); + Assert.assertEquals(1, location.indexScaling()); + + if (indexConvert) { + ConvertNode convert = (ConvertNode) location.index(); + Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(graph.getLocal(1), convert.value()); + } else { + Assert.assertEquals(graph.getLocal(1), location.index()); + } + + AbstractStateSplit stateSplit = (AbstractStateSplit) write.next(); + Assert.assertEquals(FrameState.AFTER_BCI, stateSplit.stateAfter().bci); + + ReturnNode ret = (ReturnNode) stateSplit.next(); + Assert.assertEquals(null, ret.result()); + } + + @Snippet + public static byte readByte1(Object o, int offset) { + return Word.fromObject(o).readByte(offset, ID); + } + + @Snippet + public static byte readByte2(Object o, int offset) { + return Word.fromObject(o).readByte(Word.signed(offset), ID); + } + + @Snippet + public static byte readByte3(Object o, int offset) { + return Word.fromObject(o).readByte(offset); + } + + @Snippet + public static void writeByte1(Object o, int offset, byte value) { + Word.fromObject(o).writeByte(offset, value, ID); + } + + @Snippet + public static void writeByte2(Object o, int offset, byte value) { + Word.fromObject(o).writeByte(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeByte3(Object o, int offset, byte value) { + Word.fromObject(o).writeByte(offset, value); + } + + @Snippet + public static char readChar1(Object o, int offset) { + return Word.fromObject(o).readChar(offset, ID); + } + + @Snippet + public static char readChar2(Object o, int offset) { + return Word.fromObject(o).readChar(Word.signed(offset), ID); + } + + @Snippet + public static char readChar3(Object o, int offset) { + return Word.fromObject(o).readChar(offset); + } + + @Snippet + public static void writeChar1(Object o, int offset, char value) { + Word.fromObject(o).writeChar(offset, value, ID); + } + + @Snippet + public static void writeChar2(Object o, int offset, char value) { + Word.fromObject(o).writeChar(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeChar3(Object o, int offset, char value) { + Word.fromObject(o).writeChar(offset, value); + } + + @Snippet + public static short readShort1(Object o, int offset) { + return Word.fromObject(o).readShort(offset, ID); + } + + @Snippet + public static short readShort2(Object o, int offset) { + return Word.fromObject(o).readShort(Word.signed(offset), ID); + } + + @Snippet + public static short readShort3(Object o, int offset) { + return Word.fromObject(o).readShort(offset); + } + + @Snippet + public static void writeShort1(Object o, int offset, short value) { + Word.fromObject(o).writeShort(offset, value, ID); + } + + @Snippet + public static void writeShort2(Object o, int offset, short value) { + Word.fromObject(o).writeShort(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeShort3(Object o, int offset, short value) { + Word.fromObject(o).writeShort(offset, value); + } + + @Snippet + public static int readInt1(Object o, int offset) { + return Word.fromObject(o).readInt(offset, ID); + } + + @Snippet + public static int readInt2(Object o, int offset) { + return Word.fromObject(o).readInt(Word.signed(offset), ID); + } + + @Snippet + public static int readInt3(Object o, int offset) { + return Word.fromObject(o).readInt(offset); + } + + @Snippet + public static void writeInt1(Object o, int offset, int value) { + Word.fromObject(o).writeInt(offset, value, ID); + } + + @Snippet + public static void writeInt2(Object o, int offset, int value) { + Word.fromObject(o).writeInt(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeInt3(Object o, int offset, int value) { + Word.fromObject(o).writeInt(offset, value); + } + + @Snippet + public static long readLong1(Object o, int offset) { + return Word.fromObject(o).readLong(offset, ID); + } + + @Snippet + public static long readLong2(Object o, int offset) { + return Word.fromObject(o).readLong(Word.signed(offset), ID); + } + + @Snippet + public static long readLong3(Object o, int offset) { + return Word.fromObject(o).readLong(offset); + } + + @Snippet + public static void writeLong1(Object o, int offset, long value) { + Word.fromObject(o).writeLong(offset, value, ID); + } + + @Snippet + public static void writeLong2(Object o, int offset, long value) { + Word.fromObject(o).writeLong(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeLong3(Object o, int offset, long value) { + Word.fromObject(o).writeLong(offset, value); + } + + @Snippet + public static float readFloat1(Object o, int offset) { + return Word.fromObject(o).readFloat(offset, ID); + } + + @Snippet + public static float readFloat2(Object o, int offset) { + return Word.fromObject(o).readFloat(Word.signed(offset), ID); + } + + @Snippet + public static float readFloat3(Object o, int offset) { + return Word.fromObject(o).readFloat(offset); + } + + @Snippet + public static void writeFloat1(Object o, int offset, float value) { + Word.fromObject(o).writeFloat(offset, value, ID); + } + + @Snippet + public static void writeFloat2(Object o, int offset, float value) { + Word.fromObject(o).writeFloat(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeFloat3(Object o, int offset, float value) { + Word.fromObject(o).writeFloat(offset, value); + } + + @Snippet + public static double readDouble1(Object o, int offset) { + return Word.fromObject(o).readDouble(offset, ID); + } + + @Snippet + public static double readDouble2(Object o, int offset) { + return Word.fromObject(o).readDouble(Word.signed(offset), ID); + } + + @Snippet + public static double readDouble3(Object o, int offset) { + return Word.fromObject(o).readDouble(offset); + } + + @Snippet + public static void writeDouble1(Object o, int offset, double value) { + Word.fromObject(o).writeDouble(offset, value, ID); + } + + @Snippet + public static void writeDouble2(Object o, int offset, double value) { + Word.fromObject(o).writeDouble(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeDouble3(Object o, int offset, double value) { + Word.fromObject(o).writeDouble(offset, value); + } + + @Snippet + public static Object readObject1(Object o, int offset) { + return Word.fromObject(o).readObject(offset, ID); + } + + @Snippet + public static Object readObject2(Object o, int offset) { + return Word.fromObject(o).readObject(Word.signed(offset), ID); + } + + @Snippet + public static Object readObject3(Object o, int offset) { + return Word.fromObject(o).readObject(offset); + } + + @Snippet + public static void writeObject1(Object o, int offset, Object value) { + Word.fromObject(o).writeObject(offset, value, ID); + } + + @Snippet + public static void writeObject2(Object o, int offset, Object value) { + Word.fromObject(o).writeObject(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeObject3(Object o, int offset, Object value) { + Word.fromObject(o).writeObject(offset, value); + } + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.replacements.UnsafeSubstitutions.*; + +import java.lang.reflect.*; +import java.util.concurrent.atomic.*; + +import org.junit.*; + +import sun.misc.*; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Tests the VM independent {@link MethodSubstitution}s. + */ +public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest { + + static long off(Object o, String name) { + try { + return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name)); + } catch (Exception e) { + Assert.fail(e.toString()); + return 0L; + } + } + + static class Foo { + + boolean z; + byte b; + short s; + char c; + int i; + long l; + float f; + double d; + Object o; + + void testGet(Field field, long offset, String getName, Object value) throws Exception { + field.set(this, value); + Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class); + Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class); + Object expected = m1.invoke(unsafe, this, offset); + Object actual = m2.invoke(null, unsafe, this, offset); + Assert.assertEquals(expected, actual); + } + + void testDirect(Field field, long offset, String type, Object value) throws Exception { + if (type.equals("Boolean") || type.equals("Object")) { + // No direct memory access for these types + return; + } + + long address = unsafe.allocateMemory(offset + 16); + + String getName = "get" + type; + String putName = "put" + type; + Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType()); + Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class); + + Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); + Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class); + + m1.invoke(unsafe, address + offset, value); + Object expected = m2.invoke(unsafe, address + offset); + + m3.invoke(null, unsafe, address + offset, value); + Object actual = m4.invoke(null, unsafe, address + offset); + + unsafe.freeMemory(address); + Assert.assertEquals(expected, actual); + } + + void testPut(Field field, long offset, String putName, Object value) throws Exception { + Object initialValue = field.get(new Foo()); + field.set(this, initialValue); + + try { + Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); + Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType()); + m1.invoke(unsafe, this, offset, value); + Object expected = field.get(this); + m2.invoke(null, unsafe, this, offset, value); + Object actual = field.get(this); + Assert.assertEquals(expected, actual); + } catch (NoSuchMethodException e) { + if (!putName.startsWith("putOrdered")) { + throw e; + } + } + } + + void test(String fieldName, String typeSuffix, Object value) { + try { + Field field = Foo.class.getDeclaredField(fieldName); + long offset = unsafe.objectFieldOffset(field); + testGet(field, offset, "get" + typeSuffix, value); + testGet(field, offset, "get" + typeSuffix + "Volatile", value); + testPut(field, offset, "put" + typeSuffix, value); + testPut(field, offset, "put" + typeSuffix + "Volatile", value); + testPut(field, offset, "putOrdered" + typeSuffix, value); + testDirect(field, offset, typeSuffix, value); + } catch (Exception e) { + throw new AssertionError(e); + } + } + } + + @Test + public void testUnsafeSubstitutions() throws Exception { + test("unsafeCompareAndSwapInt"); + test("unsafeCompareAndSwapLong"); + test("unsafeCompareAndSwapObject"); + + test("unsafeGetBoolean"); + test("unsafeGetByte"); + test("unsafeGetShort"); + test("unsafeGetChar"); + test("unsafeGetInt"); + test("unsafeGetLong"); + test("unsafeGetFloat"); + test("unsafeGetDouble"); + test("unsafeGetObject"); + + test("unsafePutBoolean"); + test("unsafePutByte"); + test("unsafePutShort"); + test("unsafePutChar"); + test("unsafePutInt"); + test("unsafePutFloat"); + test("unsafePutDouble"); + test("unsafePutObject"); + + test("unsafeDirectMemoryRead"); + test("unsafeDirectMemoryWrite"); + + AtomicInteger a1 = new AtomicInteger(42); + AtomicInteger a2 = new AtomicInteger(42); + assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53)); + assertEquals(a1.get(), a2.get()); + + AtomicLong l1 = new AtomicLong(42); + AtomicLong l2 = new AtomicLong(42); + assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53)); + assertEquals(l1.get(), l2.get()); + + AtomicReference o1 = new AtomicReference<>("42"); + AtomicReference o2 = new AtomicReference<>("42"); + assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53")); + assertEquals(o1.get(), o2.get()); + + Foo f1 = new Foo(); + f1.test("z", "Boolean", Boolean.TRUE); + f1.test("b", "Byte", Byte.MIN_VALUE); + f1.test("s", "Short", Short.MAX_VALUE); + f1.test("c", "Char", '!'); + f1.test("i", "Int", 1010010); + f1.test("f", "Float", -34.5F); + f1.test("l", "Long", 99999L); + f1.test("d", "Double", 1234.5678D); + f1.test("o", "Object", "object"); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapInt(obj, offset, 0, 1); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapLong(obj, offset, 0, 1); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapObject(obj, offset, null, new Object()); + } + + @SuppressWarnings("all") + public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) { + return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) { + return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) { + return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) { + return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) { + return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) { + return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) { + return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) { + return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) { + return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) { + unsafe.putBoolean(obj, offset, value); + unsafe.putBooleanVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) { + unsafe.putByte(obj, offset, value); + unsafe.putByteVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) { + unsafe.putShort(obj, offset, value); + unsafe.putShortVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) { + unsafe.putChar(obj, offset, value); + unsafe.putCharVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) { + unsafe.putInt(obj, offset, value); + unsafe.putIntVolatile(obj, offset, value); + unsafe.putOrderedInt(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) { + unsafe.putLong(obj, offset, value); + unsafe.putLongVolatile(obj, offset, value); + unsafe.putOrderedLong(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) { + unsafe.putFloat(obj, offset, value); + unsafe.putFloatVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) { + unsafe.putDouble(obj, offset, value); + unsafe.putDoubleVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) { + unsafe.putObject(obj, offset, value); + unsafe.putObjectVolatile(obj, offset, value); + unsafe.putOrderedObject(obj, offset, value); + } + + @SuppressWarnings("all") + public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) { + // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist + return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address); + } + + @SuppressWarnings("all") + public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) { + // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist + unsafe.putByte(address, value); + unsafe.putShort(address, value); + unsafe.putChar(address, (char) value); + unsafe.putInt(address, value); + unsafe.putLong(address, value); + unsafe.putFloat(address, value); + unsafe.putDouble(address, value); + } + + @Test + public void testMathSubstitutions() { + assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class); // Java + test("math"); + + double value = 34567.891D; + assertEquals(Math.sqrt(value), MathSubstitutionsX86.sqrt(value)); + assertEquals(Math.log(value), MathSubstitutionsX86.log(value)); + assertEquals(Math.log10(value), MathSubstitutionsX86.log10(value)); + assertEquals(Math.sin(value), MathSubstitutionsX86.sin(value)); + assertEquals(Math.cos(value), MathSubstitutionsX86.cos(value)); + assertEquals(Math.tan(value), MathSubstitutionsX86.tan(value)); + } + + @SuppressWarnings("all") + public static double mathAbs(double value) { + return Math.abs(value); + } + + @SuppressWarnings("all") + public static double math(double value) { + return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value); + // Math.exp(value) + + // Math.pow(value, 13); + } + + @Test + public void testIntegerSubstitutions() { + assertInGraph(test("integerReverseBytes"), ReverseBytesNode.class); // Java + assertInGraph(test("integerNumberOfLeadingZeros"), BitScanReverseNode.class); // Java + assertInGraph(test("integerNumberOfTrailingZeros"), BitScanForwardNode.class); // Java + assertInGraph(test("integerBitCount"), BitCountNode.class); // Java + + for (int i : new int[]{Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE}) { + assertEquals(Integer.reverseBytes(i), IntegerSubstitutions.reverseBytes(i)); + assertEquals(Integer.numberOfLeadingZeros(i), IntegerSubstitutions.numberOfLeadingZeros(i)); + assertEquals(Integer.numberOfTrailingZeros(i), IntegerSubstitutions.numberOfTrailingZeros(i)); + assertEquals(Integer.bitCount(i), IntegerSubstitutions.bitCount(i)); + } + } + + @SuppressWarnings("all") + public static int integerReverseBytes(int value) { + return Integer.reverseBytes(value); + } + + @SuppressWarnings("all") + public static int integerNumberOfLeadingZeros(int value) { + return Integer.numberOfLeadingZeros(value); + } + + @SuppressWarnings("all") + public static int integerNumberOfTrailingZeros(int value) { + return Integer.numberOfTrailingZeros(value); + } + + @SuppressWarnings("all") + public static int integerBitCount(int value) { + return Integer.bitCount(value); + } + + @Test + public void testLongSubstitutions() { + assertInGraph(test("longReverseBytes"), ReverseBytesNode.class); // Java + assertInGraph(test("longNumberOfLeadingZeros"), BitScanReverseNode.class); // Java + assertInGraph(test("longNumberOfTrailingZeros"), BitScanForwardNode.class); // Java + assertInGraph(test("longBitCount"), BitCountNode.class); // Java + + for (long l : new long[]{Long.MIN_VALUE, -1L, 0L, 1L, Long.MAX_VALUE}) { + assertEquals(Long.reverseBytes(l), LongSubstitutions.reverseBytes(l)); + assertEquals(Long.numberOfLeadingZeros(l), LongSubstitutions.numberOfLeadingZeros(l)); + assertEquals(Long.numberOfTrailingZeros(l), LongSubstitutions.numberOfTrailingZeros(l)); + assertEquals(Long.bitCount(l), LongSubstitutions.bitCount(l)); + } + } + + @SuppressWarnings("all") + public static long longReverseBytes(long value) { + return Long.reverseBytes(value); + } + + @SuppressWarnings("all") + public static long longNumberOfLeadingZeros(long value) { + return Long.numberOfLeadingZeros(value); + } + + @SuppressWarnings("all") + public static long longNumberOfTrailingZeros(long value) { + return Long.numberOfTrailingZeros(value); + } + + @SuppressWarnings("all") + public static int longBitCount(long value) { + return Long.bitCount(value); + } + + @Test + public void testFloatSubstitutions() { + assertInGraph(test("floatToIntBits"), ConvertNode.class); // Java + test("intBitsToFloat"); + } + + @SuppressWarnings("all") + public static int floatToIntBits(float value) { + return Float.floatToIntBits(value); + } + + @SuppressWarnings("all") + public static float intBitsToFloat(int value) { + return Float.intBitsToFloat(value); + } + + @Test + public void testDoubleSubstitutions() { + assertInGraph(test("doubleToLongBits"), ConvertNode.class); // Java + test("longBitsToDouble"); + } + + @SuppressWarnings("all") + public static long doubleToLongBits(double value) { + return Double.doubleToLongBits(value); + } + + @SuppressWarnings("all") + public static double longBitsToDouble(long value) { + return Double.longBitsToDouble(value); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/TypeCheckTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/TypeCheckTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; + +/** + * Base class for checkcast and instanceof test classes. + */ +public abstract class TypeCheckTest extends GraalCompilerTest { + + protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile); + + protected JavaTypeProfile currentProfile; + + @Override + protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) { + boolean forceCompile = false; + if (currentProfile != null) { + replaceProfile(graph, currentProfile); + forceCompile = true; + } + return super.getCode(method, graph, forceCompile); + } + + protected JavaTypeProfile profile(Class... types) { + return profile(TriState.UNKNOWN, types); + } + + protected JavaTypeProfile profile(TriState nullSeen, Class... types) { + if (types.length == 0) { + return null; + } + ProfiledType[] ptypes = new ProfiledType[types.length]; + for (int i = 0; i < types.length; i++) { + ptypes[i] = new ProfiledType(runtime.lookupJavaType(types[i]), 1.0D / types.length); + } + return new JavaTypeProfile(nullSeen, 0.0D, ptypes); + } + + protected void test(String name, JavaTypeProfile profile, Object... args) { + assert currentProfile == null; + currentProfile = profile; + try { + super.test(name, args); + } finally { + currentProfile = null; + } + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.word.*; + +/** + * Tests for the {@link Word} type. + */ +public class WordTest extends GraalCompilerTest implements Snippets { + + private final ReplacementsImpl installer; + + public WordTest() { + TargetDescription target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget(); + installer = new ReplacementsImpl(runtime, new Assumptions(false), target); + } + + private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); + + @Override + protected StructuredGraph parse(Method m) { + ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); + return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); + } + + @LongTest + public void construction() { + long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, + Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; + for (long word : words) { + test("unsigned_long", word); + test("unsigned_int", (int) word); + test("signed_long", word); + test("signed_int", (int) word); + } + } + + @LongTest + public void test_arithmetic() { + long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, + Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; + for (long word : words) { + test("unsigned_not", word); + test("signed_not", word); + for (long addend : words) { + test("unsigned_plus_int", word, (int) addend); + test("unsigned_minus_int", word, (int) addend); + test("unsigned_plus_int", word, -((int) addend)); + test("unsigned_minus_int", word, -((int) addend)); + test("unsigned_plus_long", word, addend); + test("unsigned_minus_long", word, addend); + test("unsigned_plus_long", word, -addend); + test("unsigned_minus_long", word, -addend); + test("signed_plus_int", word, (int) addend); + test("signed_minus_int", word, (int) addend); + test("signed_plus_int", word, -((int) addend)); + test("signed_minus_int", word, -((int) addend)); + test("signed_plus_long", word, addend); + test("signed_minus_long", word, addend); + test("signed_plus_long", word, -addend); + test("signed_minus_long", word, -addend); + + test("and_int", word, (int) addend); + test("or_int", word, (int) addend); + test("and_int", word, -((int) addend)); + test("or_int", word, -((int) addend)); + test("and_long", word, addend); + test("or_long", word, addend); + test("and_long", word, -addend); + test("or_long", word, -addend); + } + } + } + + @LongTest + public void test_compare() { + long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE}; + for (long word1 : words) { + for (long word2 : words) { + for (String method : new String[]{"aboveOrEqual", "above", "belowOrEqual", "below"}) { + test(method, word1, word2); + test(method, word2, word1); + } + } + } + } + + @Snippet + public static long unsigned_long(long word) { + return Word.unsigned(word).rawValue(); + } + + @Snippet + public static long unsigned_int(int word) { + return Word.unsigned(word).rawValue(); + } + + @Snippet + public static long signed_long(long word) { + return Word.signed(word).rawValue(); + } + + @Snippet + public static long signed_int(int word) { + return Word.signed(word).rawValue(); + } + + @Snippet + public static long unsigned_plus_int(long word, int addend) { + return Word.unsigned(word).add(addend).rawValue(); + } + + @Snippet + public static long unsigned_minus_int(long word, int addend) { + return Word.unsigned(word).subtract(addend).rawValue(); + } + + @Snippet + public static long unsigned_plus_long(long word, long addend) { + return Word.unsigned(word).add(Word.unsigned(addend)).rawValue(); + } + + @Snippet + public static long unsigned_minus_long(long word, long addend) { + return Word.unsigned(word).subtract(Word.unsigned(addend)).rawValue(); + } + + @Snippet + public static long signed_plus_int(long word, int addend) { + return Word.signed(word).add(addend).rawValue(); + } + + @Snippet + public static long signed_minus_int(long word, int addend) { + return Word.signed(word).subtract(addend).rawValue(); + } + + @Snippet + public static long signed_plus_long(long word, long addend) { + return Word.signed(word).add(Word.signed(addend)).rawValue(); + } + + @Snippet + public static long signed_minus_long(long word, long addend) { + return Word.signed(word).subtract(Word.signed(addend)).rawValue(); + } + + @Snippet + public static long signed_not(long word) { + return Word.signed(word).not().rawValue(); + } + + @Snippet + public static long unsigned_not(long word) { + return Word.unsigned(word).not().rawValue(); + } + + @Snippet + public static boolean aboveOrEqual(long word1, long word2) { + return Word.unsigned(word1).aboveOrEqual(Word.unsigned(word2)); + } + + @Snippet + public static boolean above(long word1, long word2) { + return Word.unsigned(word1).aboveThan(Word.unsigned(word2)); + } + + @Snippet + public static boolean belowOrEqual(long word1, long word2) { + return Word.unsigned(word1).belowOrEqual(Word.unsigned(word2)); + } + + @Snippet + public static boolean below(long word1, long word2) { + return Word.unsigned(word1).belowThan(Word.unsigned(word2)); + } + + @Snippet + public static long and_int(long word, int addend) { + return Word.unsigned(word).and(addend).rawValue(); + } + + @Snippet + public static long or_int(long word, int addend) { + return Word.unsigned(word).or(addend).rawValue(); + } + + @Snippet + public static long and_long(long word, long addend) { + return Word.unsigned(word).and(Word.unsigned(addend)).rawValue(); + } + + @Snippet + public static long or_long(long word, long addend) { + return Word.unsigned(word).or(Word.unsigned(addend)).rawValue(); + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import static com.oracle.graal.replacements.SnippetTemplate.*; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.replacements.Snippet.Fold; +import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.word.*; + +public class BoxingSnippets implements Snippets { + + /** + * This snippet inlining policy differs from the default one in that it does normal inlining of + * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution). + */ + public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy { + + @Override + public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { + if (Modifier.isNative(method.getModifiers())) { + return false; + } + if (method.getAnnotation(Fold.class) != null) { + return false; + } + if (method.getAnnotation(NodeIntrinsic.class) != null) { + return false; + } + if (method.getAnnotation(Word.Operation.class) != null) { + return false; + } + return true; + } + + @Override + public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) { + return false; + } + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Boolean booleanValueOf(boolean value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Byte byteValueOf(byte value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Character charValueOf(char value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Double doubleValueOf(double value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Float floatValueOf(float value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Integer intValueOf(int value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Long longValueOf(long value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Short shortValueOf(short value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static boolean booleanValue(Boolean value) { + valueOfCounter.inc(); + return value.booleanValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static byte byteValue(Byte value) { + valueOfCounter.inc(); + return value.byteValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static char charValue(Character value) { + valueOfCounter.inc(); + return value.charValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static double doubleValue(Double value) { + valueOfCounter.inc(); + return value.doubleValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static float floatValue(Float value) { + valueOfCounter.inc(); + return value.floatValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static int intValue(Integer value) { + valueOfCounter.inc(); + return value.intValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static long longValue(Long value) { + valueOfCounter.inc(); + return value.longValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static short shortValue(Short value) { + valueOfCounter.inc(); + return value.shortValue(); + } + + public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) { + ValueNode value = box.getValue(); + if (value.isConstant()) { + Constant sourceConstant = value.asConstant(); + switch (box.getBoxingKind()) { + case Boolean: + return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph()); + case Byte: + return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph()); + case Char: + return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph()); + case Short: + return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph()); + case Int: + return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph()); + case Long: + return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph()); + case Float: + return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph()); + case Double: + return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph()); + default: + assert false : "Unexpected source kind for boxing"; + break; + } + } + return null; + } + + public static class Templates extends AbstractTemplates { + + private final EnumMap boxSnippets = new EnumMap<>(Kind.class); + private final EnumMap unboxSnippets = new EnumMap<>(Kind.class); + + public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); + for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) { + boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf")); + unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value")); + } + } + + public void lower(BoxNode box) { + FloatingNode canonical = canonicalizeBoxing(box, runtime); + if (canonical != null) { + ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical); + } else { + Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind())); + args.add("value", box.getValue()); + + SnippetTemplate template = template(args); + Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args); + template.instantiate(runtime, box, DEFAULT_REPLACER, args); + } + } + + public void lower(UnboxNode unbox) { + Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind())); + args.add("value", unbox.getValue()); + + SnippetTemplate template = template(args); + Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args); + template.instantiate(runtime, unbox, DEFAULT_REPLACER, args); + } + } + + private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null; + private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification"); + +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.extended.*; + +public class BoxingSubstitutions { + + @ClassSubstitution(Boolean.class) + private static class BooleanSubstitutions { + + @MethodSubstitution(forced = true) + public static Boolean valueOf(boolean value) { + return BoxNode.box(value, Boolean.class, Kind.Boolean); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static boolean booleanValue(Boolean value) { + return UnboxNode.unbox(value, Kind.Boolean); + } + } + + @ClassSubstitution(Byte.class) + private static class ByteSubstitutions { + + @MethodSubstitution(forced = true) + public static Byte valueOf(byte value) { + return BoxNode.box(value, Byte.class, Kind.Byte); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static byte byteValue(Byte value) { + return UnboxNode.unbox(value, Kind.Byte); + } + } + + @ClassSubstitution(Character.class) + private static class CharacterSubstitutions { + + @MethodSubstitution(forced = true) + public static Character valueOf(char value) { + return BoxNode.box(value, Character.class, Kind.Char); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static char charValue(Character value) { + return UnboxNode.unbox(value, Kind.Char); + } + } + + @ClassSubstitution(Double.class) + private static class DoubleSubstitutions { + + @MethodSubstitution(forced = true) + public static Double valueOf(double value) { + return BoxNode.box(value, Double.class, Kind.Double); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static double doubleValue(Double value) { + return UnboxNode.unbox(value, Kind.Double); + } + } + + @ClassSubstitution(Float.class) + private static class FloatSubstitutions { + + @MethodSubstitution(forced = true) + public static Float valueOf(float value) { + return BoxNode.box(value, Float.class, Kind.Float); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static float floatValue(Float value) { + return UnboxNode.unbox(value, Kind.Float); + } + } + + @ClassSubstitution(Integer.class) + private static class IntegerSubstitutions { + + @MethodSubstitution(forced = true) + public static Integer valueOf(int value) { + return BoxNode.box(value, Integer.class, Kind.Int); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static int intValue(Integer value) { + return UnboxNode.unbox(value, Kind.Int); + } + } + + @ClassSubstitution(Long.class) + private static class LongSubstitutions { + + @MethodSubstitution(forced = true) + public static Long valueOf(long value) { + return BoxNode.box(value, Long.class, Kind.Long); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static long longValue(Long value) { + return UnboxNode.unbox(value, Kind.Long); + } + } + + @ClassSubstitution(Short.class) + private static class ShortSubstitutions { + + @MethodSubstitution(forced = true) + public static Short valueOf(short value) { + return BoxNode.box(value, Short.class, Kind.Short); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static short shortValue(Short value) { + return UnboxNode.unbox(value, Kind.Short); + } + } + + public static Class[] getClasses() { + return new Class[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class, + LongSubstitutions.class, ShortSubstitutions.class}; + } +} diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.replacements; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -32,7 +34,11 @@ @ServiceProvider(ReplacementsProvider.class) public class GraalMethodSubstitutions implements ReplacementsProvider { - public void registerReplacements(Replacements replacements) { + public void registerReplacements(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + for (Class clazz : BoxingSubstitutions.getClasses()) { + replacements.registerSubstitutions(clazz); + } + if (GraalOptions.Intrinsify) { replacements.registerSubstitutions(MathSubstitutionsX86.class); replacements.registerSubstitutions(DoubleSubstitutions.class); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Sat Apr 20 12:23:29 2013 +0200 @@ -34,7 +34,9 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.UsageReplacer; /** * Helper class for lowering {@link InstanceOfNode}s with snippets. The majority of the complexity @@ -49,31 +51,16 @@ * {@link IfNode}. This avoids materializing the instanceof test as a boolean which is then retested * by the {@link IfNode}. */ -public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { +public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { - public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class snippetsClass) { - super(runtime, replacements, target, snippetsClass); + public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); } /** - * The key and arguments used to retrieve and instantiate an instanceof snippet template. + * Gets the arguments used to retrieve and instantiate an instanceof snippet template. */ - public static class KeyAndArguments { - - public final Key key; - public final Arguments arguments; - - public KeyAndArguments(Key key, Arguments arguments) { - this.key = key; - this.arguments = arguments; - } - - } - - /** - * Gets the key and arguments used to retrieve and instantiate an instanceof snippet template. - */ - protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); + protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); public void lower(FloatingNode instanceOf, LoweringTool tool) { assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode; @@ -90,9 +77,8 @@ // No need to re-instantiate the snippet - just re-use its result replacer.replaceUsingInstantiation(); } else { - KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool); - SnippetTemplate template = cache.get(keyAndArguments.key); - template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments); + Arguments args = makeArguments(replacer, tool); + template(args).instantiate(runtime, instanceOf, replacer, tool, args); } } @@ -105,11 +91,14 @@ /** * Gets the specific replacer object used to replace the usage of an instanceof node with the * result of an instantiated instanceof snippet. + * + * @param nUsages + * @param tool */ protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, LoweringTool tool, int nUsages, Instantiation instantiation, Node usage, final StructuredGraph graph) { InstanceOfUsageReplacer replacer; if (usage instanceof IfNode) { - replacer = new IfUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, (IfNode) usage, nUsages == 1, tool); + replacer = new IfUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, (IfNode) usage); } else { assert usage instanceof ConditionalNode : "unexpected usage of " + instanceOf + ": " + usage; ConditionalNode c = (ConditionalNode) usage; @@ -204,14 +193,10 @@ */ public static class IfUsageReplacer extends InstanceOfUsageReplacer { - private final boolean solitaryUsage; private final IfNode usage; - private final boolean sameBlock; - public IfUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, FloatingNode instanceOf, IfNode usage, boolean solitaryUsage, LoweringTool tool) { + public IfUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, FloatingNode instanceOf, IfNode usage) { super(instantiation, instanceOf, trueValue, falseValue); - this.sameBlock = tool.getBlockFor(usage) == tool.getBlockFor(instanceOf); - this.solitaryUsage = solitaryUsage; this.usage = usage; } @@ -220,84 +205,13 @@ usage.replaceFirstInput(instanceOf, instantiation.asCondition(trueValue)); } - private boolean usageFollowsInstantiation() { - return instantiation.result != null && instantiation.result.merge().next() == usage; - } - @Override public void replace(ValueNode oldNode, ValueNode newNode) { assert newNode instanceof PhiNode; assert oldNode == instanceOf; - if (sameBlock && solitaryUsage && usageFollowsInstantiation()) { - removeIntermediateMaterialization(newNode); - } else { - newNode.inferStamp(); - instantiation.initialize((PhiNode) newNode, trueValue, falseValue); - usage.replaceFirstInput(oldNode, instantiation.asCondition(trueValue)); - } - } - - /** - * Directly wires the incoming edges of the merge at the end of the snippet to the outgoing - * edges of the IfNode that uses the materialized result. - */ - private void removeIntermediateMaterialization(ValueNode newNode) { - IfNode ifNode = usage; - PhiNode phi = (PhiNode) newNode; - MergeNode merge = phi.merge(); - assert merge.stateAfter() == null; - - List mergePredecessors = merge.cfgPredecessors().snapshot(); - assert phi.valueCount() == mergePredecessors.size(); - - List falseEnds = new ArrayList<>(mergePredecessors.size()); - List trueEnds = new ArrayList<>(mergePredecessors.size()); - - int endIndex = 0; - for (EndNode end : mergePredecessors) { - ValueNode endValue = phi.valueAt(endIndex++); - if (endValue == trueValue) { - trueEnds.add(end); - } else { - assert endValue == falseValue; - falseEnds.add(end); - } - } - - BeginNode trueSuccessor = ifNode.trueSuccessor(); - BeginNode falseSuccessor = ifNode.falseSuccessor(); - ifNode.setTrueSuccessor(null); - ifNode.setFalseSuccessor(null); - - connectEnds(merge, trueEnds, trueSuccessor); - connectEnds(merge, falseEnds, falseSuccessor); - - GraphUtil.killCFG(merge); - GraphUtil.killCFG(ifNode); - - assert !merge.isAlive() : merge; - assert !phi.isAlive() : phi; - } - - private static void connectEnds(MergeNode merge, List ends, BeginNode successor) { - if (ends.size() == 0) { - // InstanceOf has been lowered to always true or always false - this successor is - // therefore unreachable. - GraphUtil.killCFG(successor); - } else if (ends.size() == 1) { - EndNode end = ends.get(0); - ((FixedWithNextNode) end.predecessor()).setNext(successor); - merge.removeEnd(end); - GraphUtil.killCFG(end); - } else { - assert ends.size() > 1; - MergeNode newMerge = merge.graph().add(new MergeNode()); - - for (EndNode end : ends) { - newMerge.addForwardEnd(end); - } - newMerge.setNext(successor); - } + newNode.inferStamp(); + instantiation.initialize((PhiNode) newNode, trueValue, falseValue); + usage.replaceFirstInput(oldNode, instantiation.asCondition(trueValue)); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,22 +22,22 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.meta.MetaUtil.*; - import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.Fold; /** * Replaces calls to {@link NodeIntrinsic}s with nodes and calls to methods annotated with @@ -46,93 +46,78 @@ public class NodeIntrinsificationPhase extends Phase { private final MetaAccessProvider runtime; - private final BoxingMethodPool pool; - public NodeIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool) { + public NodeIntrinsificationPhase(MetaAccessProvider runtime) { this.runtime = runtime; - this.pool = pool; } @Override protected void run(StructuredGraph graph) { - for (Invoke i : graph.getInvokes()) { - if (i.callTarget() instanceof MethodCallTargetNode) { - tryIntrinsify(i); - } + ArrayList cleanUpReturnList = new ArrayList<>(); + for (MethodCallTargetNode node : graph.getNodes(MethodCallTargetNode.class)) { + tryIntrinsify(node, cleanUpReturnList); + } + + for (Node node : cleanUpReturnList) { + cleanUpReturnCheckCast(node); } } - public static Class[] signatureToTypes(Signature signature, JavaType receiverType, ResolvedJavaType accessingClass) { - int count = signature.getParameterCount(receiverType != null); - Class[] result = new Class[count]; - int j = 0; - if (receiverType != null) { - result[0] = getMirrorOrFail(receiverType.resolve(accessingClass), Thread.currentThread().getContextClassLoader()); - j = 1; - } - for (int i = 0; i + j < result.length; ++i) { - result[i + j] = getMirrorOrFail(signature.getParameterType(i, accessingClass).resolve(accessingClass), Thread.currentThread().getContextClassLoader()); - } - return result; - } - - private boolean tryIntrinsify(Invoke invoke) { - ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod(); + private boolean tryIntrinsify(MethodCallTargetNode methodCallTargetNode, List cleanUpReturnList) { + ResolvedJavaMethod target = methodCallTargetNode.targetMethod(); NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class); ResolvedJavaType declaringClass = target.getDeclaringClass(); - JavaType receiverType = invoke.methodCallTarget().isStatic() ? null : declaringClass; if (intrinsic != null) { assert target.getAnnotation(Fold.class) == null; + assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target; - // TODO mjj non-static intrinsic? - Class[] parameterTypes = signatureToTypes(target.getSignature(), null, declaringClass); + ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass); ResolvedJavaType returnType = target.getSignature().getReturnType(declaringClass).resolve(declaringClass); // Prepare the arguments for the reflective constructor call on the node class. - Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false); + Constant[] nodeConstructorArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false); if (nodeConstructorArguments == null) { return false; } // Create the new node instance. - Class c = getNodeClass(target, intrinsic); - Node newInstance = createNodeInstance(runtime, c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments); + ResolvedJavaType c = getNodeClass(target, intrinsic); + Node newInstance = createNodeInstance(c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments); // Replace the invoke with the new node. - invoke.node().graph().add(newInstance); - invoke.intrinsify(newInstance); + methodCallTargetNode.graph().add(newInstance); + methodCallTargetNode.invoke().intrinsify(newInstance); // Clean up checkcast instructions inserted by javac if the return type is generic. - cleanUpReturnCheckCast(newInstance); + cleanUpReturnList.add(newInstance); } else if (target.getAnnotation(Fold.class) != null) { - Class[] parameterTypes = signatureToTypes(target.getSignature(), receiverType, declaringClass); + ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass); // Prepare the arguments for the reflective method call - Object[] arguments = prepareArguments(invoke, parameterTypes, target, true); + Constant[] arguments = prepareArguments(methodCallTargetNode, parameterTypes, target, true); if (arguments == null) { return false; } - Object receiver = null; - if (!invoke.methodCallTarget().isStatic()) { + Constant receiver = null; + if (!methodCallTargetNode.isStatic()) { receiver = arguments[0]; - arguments = Arrays.asList(arguments).subList(1, arguments.length).toArray(); - parameterTypes = Arrays.asList(parameterTypes).subList(1, parameterTypes.length).toArray(new Class[parameterTypes.length - 1]); + arguments = Arrays.copyOfRange(arguments, 1, arguments.length); + parameterTypes = Arrays.copyOfRange(parameterTypes, 1, parameterTypes.length); } // Call the method - Constant constant = callMethod(target.getSignature().getReturnKind(), getMirrorOrFail(declaringClass, Thread.currentThread().getContextClassLoader()), target.getName(), parameterTypes, - receiver, arguments); + Constant constant = target.invoke(receiver, arguments); if (constant != null) { // Replace the invoke with the result of the call - ConstantNode node = ConstantNode.forConstant(constant, runtime, invoke.node().graph()); - invoke.intrinsify(node); + ConstantNode node = ConstantNode.forConstant(constant, runtime, methodCallTargetNode.graph()); + methodCallTargetNode.invoke().intrinsify(node); // Clean up checkcast instructions inserted by javac if the return type is generic. - cleanUpReturnCheckCast(node); + cleanUpReturnList.add(node); } else { // Remove the invoke - invoke.intrinsify(null); + methodCallTargetNode.invoke().intrinsify(null); } } return true; @@ -146,15 +131,15 @@ * @return the arguments for the reflective invocation or null if an argument of {@code invoke} * that is expected to be constant isn't */ - private Object[] prepareArguments(Invoke invoke, Class[] parameterTypes, ResolvedJavaMethod target, boolean folding) { - NodeInputList arguments = invoke.callTarget().arguments(); - Object[] reflectionCallArguments = new Object[arguments.size()]; + private Constant[] prepareArguments(MethodCallTargetNode methodCallTargetNode, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) { + NodeInputList arguments = methodCallTargetNode.arguments(); + Constant[] reflectionCallArguments = new Constant[arguments.size()]; for (int i = 0; i < reflectionCallArguments.length; ++i) { int parameterIndex = i; - if (!invoke.methodCallTarget().isStatic()) { + if (!methodCallTargetNode.isStatic()) { parameterIndex--; } - ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i)); + ValueNode argument = arguments.get(i); if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) { if (!(argument instanceof ConstantNode)) { return null; @@ -163,171 +148,63 @@ Constant constant = constantNode.asConstant(); Object o = constant.asBoxedValue(); if (o instanceof Class) { - reflectionCallArguments[i] = runtime.lookupJavaType((Class) o); - parameterTypes[i] = ResolvedJavaType.class; + reflectionCallArguments[i] = Constant.forObject(runtime.lookupJavaType((Class) o)); + parameterTypes[i] = runtime.lookupJavaType(ResolvedJavaType.class); } else { - if (parameterTypes[i] == boolean.class) { - reflectionCallArguments[i] = Boolean.valueOf(constant.asInt() != 0); - } else if (parameterTypes[i] == byte.class) { - reflectionCallArguments[i] = Byte.valueOf((byte) constant.asInt()); - } else if (parameterTypes[i] == short.class) { - reflectionCallArguments[i] = Short.valueOf((short) constant.asInt()); - } else if (parameterTypes[i] == char.class) { - reflectionCallArguments[i] = Character.valueOf((char) constant.asInt()); + if (parameterTypes[i].getKind() == Kind.Boolean) { + reflectionCallArguments[i] = Constant.forObject(Boolean.valueOf(constant.asInt() != 0)); + } else if (parameterTypes[i].getKind() == Kind.Byte) { + reflectionCallArguments[i] = Constant.forObject(Byte.valueOf((byte) constant.asInt())); + } else if (parameterTypes[i].getKind() == Kind.Short) { + reflectionCallArguments[i] = Constant.forObject(Short.valueOf((short) constant.asInt())); + } else if (parameterTypes[i].getKind() == Kind.Char) { + reflectionCallArguments[i] = Constant.forObject(Character.valueOf((char) constant.asInt())); } else { - reflectionCallArguments[i] = o; + reflectionCallArguments[i] = constant; } } } else { - reflectionCallArguments[i] = argument; - parameterTypes[i] = ValueNode.class; + reflectionCallArguments[i] = Constant.forObject(argument); + parameterTypes[i] = runtime.lookupJavaType(ValueNode.class); } } return reflectionCallArguments; } - private static Class getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { - Class result = intrinsic.value(); - if (result == NodeIntrinsic.class) { - return getMirrorOrFail(target.getDeclaringClass(), Thread.currentThread().getContextClassLoader()); + private ResolvedJavaType getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { + ResolvedJavaType result; + if (intrinsic.value() == NodeIntrinsic.class) { + result = target.getDeclaringClass(); + } else { + result = runtime.lookupJavaType(intrinsic.value()); } - assert Node.class.isAssignableFrom(result); + assert runtime.lookupJavaType(ValueNode.class).isAssignableFrom(result); return result; } - private ValueNode tryBoxingElimination(int parameterIndex, ResolvedJavaMethod target, ValueNode node) { - if (parameterIndex >= 0) { - Type type = target.getGenericParameterTypes()[parameterIndex]; - if (type instanceof TypeVariable) { - TypeVariable typeVariable = (TypeVariable) type; - if (typeVariable.getBounds().length == 1) { - Type boundType = typeVariable.getBounds()[0]; - if (boundType instanceof Class && ((Class) boundType).getSuperclass() == null) { - // Unbound generic => try boxing elimination - if (node.usages().count() == 2) { - if (node instanceof Invoke) { - Invoke invokeNode = (Invoke) node; - MethodCallTargetNode callTarget = invokeNode.methodCallTarget(); - if (pool.isBoxingMethod(callTarget.targetMethod())) { - FrameState stateAfter = invokeNode.stateAfter(); - assert stateAfter.usages().count() == 1; - invokeNode.node().replaceAtUsages(null); - ValueNode result = callTarget.arguments().get(0); - StructuredGraph graph = (StructuredGraph) node.graph(); - if (invokeNode instanceof InvokeWithExceptionNode) { - // Destroy exception edge & clear stateAfter. - InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode; + private Node createNodeInstance(ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType, Constant[] nodeConstructorArguments) { + ResolvedJavaMethod constructor = null; + Constant[] arguments = null; - invokeWithExceptionNode.killExceptionEdge(); - graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next()); - } else { - graph.removeFixed((InvokeNode) invokeNode); - } - stateAfter.safeDelete(); - GraphUtil.propagateKill(callTarget); - return result; - } - } - } - } - } - } - } - return node; - } - - private static Class asBoxedType(Class type) { - if (!type.isPrimitive()) { - return type; - } + for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) { + Constant[] match = match(c, parameterTypes, nodeConstructorArguments); - if (Boolean.TYPE == type) { - return Boolean.class; - } - if (Character.TYPE == type) { - return Character.class; - } - if (Byte.TYPE == type) { - return Byte.class; - } - if (Short.TYPE == type) { - return Short.class; - } - if (Integer.TYPE == type) { - return Integer.class; - } - if (Long.TYPE == type) { - return Long.class; - } - if (Float.TYPE == type) { - return Float.class; - } - assert Double.TYPE == type; - return Double.class; - } - - static final int VARARGS = 0x00000080; - - private static Node createNodeInstance(MetaAccessProvider runtime, Class nodeClass, Class[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType, - Object[] nodeConstructorArguments) { - Object[] arguments = null; - Constructor constructor = null; - boolean needsMetaAccessProviderArgument = false; - nextConstructor: for (Constructor c : nodeClass.getDeclaredConstructors()) { - needsMetaAccessProviderArgument = false; - Class[] signature = c.getParameterTypes(); - if (signature.length != 0 && signature[0] == MetaAccessProvider.class) { - // Chop off the MetaAccessProvider first parameter - signature = Arrays.copyOfRange(signature, 1, signature.length); - needsMetaAccessProviderArgument = true; - } - if ((c.getModifiers() & VARARGS) != 0) { - int fixedArgs = signature.length - 1; - if (parameterTypes.length < fixedArgs) { - continue nextConstructor; + if (match != null) { + if (constructor == null) { + constructor = c; + arguments = match; + } else { + throw new GraalInternalError("Found multiple constructors in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes) + ": " + constructor + ", " + c); } - - for (int i = 0; i < fixedArgs; i++) { - if (!parameterTypes[i].equals(signature[i])) { - continue nextConstructor; - } - } - - Class componentType = signature[fixedArgs].getComponentType(); - assert componentType != null : "expected last parameter of varargs constructor " + c + " to be an array type"; - Class boxedType = asBoxedType(componentType); - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { - if (!boxedType.isInstance(nodeConstructorArguments[i])) { - continue nextConstructor; - } - } - arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1); - int varargsLength = nodeConstructorArguments.length - fixedArgs; - Object varargs = Array.newInstance(componentType, varargsLength); - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { - Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i]); - } - arguments[fixedArgs] = varargs; - constructor = c; - break; - } else if (Arrays.equals(parameterTypes, signature)) { - arguments = nodeConstructorArguments; - constructor = c; - break; } } if (constructor == null) { throw new GraalInternalError("Could not find constructor in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes)); } - if (needsMetaAccessProviderArgument) { - Object[] copy = new Object[arguments.length + 1]; - System.arraycopy(arguments, 0, copy, 1, arguments.length); - copy[0] = runtime; - arguments = copy; - } - constructor.setAccessible(true); + try { - ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments); + ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments).asObject(); + if (setStampFromReturnType) { if (returnType.getKind() == Kind.Object) { intrinsicNode.setStamp(StampFactory.declared(returnType)); @@ -341,26 +218,58 @@ } } - /** - * Calls a Java method via reflection. - */ - private static Constant callMethod(Kind returnKind, Class holder, String name, Class[] parameterTypes, Object receiver, Object[] arguments) { - Method method; - try { - method = holder.getDeclaredMethod(name, parameterTypes); - method.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); + private Constant[] match(ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Constant[] nodeConstructorArguments) { + Constant[] arguments = null; + boolean needsMetaAccessProviderArgument = false; + + ResolvedJavaType[] signature = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(c.getSignature(), null), c.getDeclaringClass()); + if (signature.length != 0 && signature[0].equals(runtime.lookupJavaType(MetaAccessProvider.class))) { + // Chop off the MetaAccessProvider first parameter + signature = Arrays.copyOfRange(signature, 1, signature.length); + needsMetaAccessProviderArgument = true; } - try { - Object result = method.invoke(receiver, arguments); - if (result == null) { + + if (Arrays.equals(parameterTypes, signature)) { + // Exact match + arguments = nodeConstructorArguments; + + } else if (signature.length > 0 && signature[signature.length - 1].isArray()) { + // Last constructor parameter is an array, so check if we have a vararg match + int fixedArgs = signature.length - 1; + if (parameterTypes.length < fixedArgs) { return null; } - return Constant.forBoxed(returnKind, result); - } catch (Exception e) { - throw new RuntimeException(e); + for (int i = 0; i < fixedArgs; i++) { + if (!parameterTypes[i].equals(signature[i])) { + return null; + } + } + + ResolvedJavaType componentType = signature[fixedArgs].getComponentType(); + assert componentType != null; + for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { + if (!parameterTypes[i].equals(componentType)) { + return null; + } + } + arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1); + arguments[fixedArgs] = componentType.newArray(nodeConstructorArguments.length - fixedArgs); + + Object varargs = arguments[fixedArgs].asObject(); + for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { + Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i].asBoxedValue()); + } + } else { + return null; } + + if (needsMetaAccessProviderArgument) { + Constant[] copy = new Constant[arguments.length + 1]; + System.arraycopy(arguments, 0, copy, 1, arguments.length); + copy[0] = Constant.forObject(runtime); + arguments = copy; + } + return arguments; } private static String sourceLocation(Node n) { @@ -379,32 +288,25 @@ if (checkCastUsage instanceof ValueAnchorNode) { ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage; graph.removeFixed(valueAnchorNode); + } else if (checkCastUsage instanceof UnboxNode) { + UnboxNode unbox = (UnboxNode) checkCastUsage; + unbox.replaceAtUsages(newInstance); + graph.removeFixed(unbox); } else if (checkCastUsage instanceof MethodCallTargetNode) { MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage; - if (pool.isUnboxingMethod(checkCastCallTarget.targetMethod())) { - Invoke invokeNode = checkCastCallTarget.invoke(); - invokeNode.node().replaceAtUsages(newInstance); - if (invokeNode instanceof InvokeWithExceptionNode) { - // Destroy exception edge & clear stateAfter. - InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode; - - invokeWithExceptionNode.killExceptionEdge(); - graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next()); - } else { - graph.removeFixed((InvokeNode) invokeNode); - } - checkCastCallTarget.safeDelete(); - } else { - assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(checkCastNode) + - " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " + - checkCastCallTarget.targetMethod(); - checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object()); - } + assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(checkCastNode) + + " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " + + checkCastCallTarget.targetMethod(); + checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object()); } else if (checkCastUsage instanceof FrameState) { checkCastUsage.replaceFirstInput(checkCastNode, null); } else if (checkCastUsage instanceof ReturnNode && checkCastNode.object().stamp() == StampFactory.forNodeIntrinsic()) { checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object()); + } else if (checkCastUsage instanceof IsNullNode) { + assert checkCastUsage.usages().count() == 1 && checkCastUsage.usages().first().predecessor() == checkCastNode; + graph.replaceFloating((FloatingNode) checkCastUsage, LogicConstantNode.contradiction(graph)); } else { + Debug.dump(graph, "exception"); assert false : sourceLocation(checkCastUsage) + " has unexpected usage " + checkCastUsage + " of checkcast at " + sourceLocation(checkCastNode); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -42,20 +42,18 @@ @Override protected void run(StructuredGraph graph) { - for (Invoke i : graph.getInvokes()) { - if (i.callTarget() instanceof MethodCallTargetNode) { - checkInvoke(i); - } + for (MethodCallTargetNode n : graph.getNodes(MethodCallTargetNode.class)) { + checkInvoke(n); } } - private static void checkInvoke(Invoke invoke) { - ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod(); + private static void checkInvoke(MethodCallTargetNode n) { + ResolvedJavaMethod target = n.targetMethod(); NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class); if (intrinsic != null) { - throw new GraalInternalError("Illegal call to node intrinsic in " + invoke.graph() + ": " + invoke); + throw new GraalInternalError("Illegal call to node intrinsic in " + n.graph() + ": " + n.invoke()); } else if (target.getAnnotation(Fold.class) != null) { - throw new GraalInternalError("Illegal call to foldable method in " + invoke.graph() + ": " + invoke); + throw new GraalInternalError("Illegal call to foldable method in " + n.graph() + ": " + n.invoke()); } } } diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -37,7 +37,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; -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.*; @@ -53,8 +52,6 @@ protected final TargetDescription target; protected final Assumptions assumptions; - private BoxingMethodPool pool; - /** * The preprocessed replacement graphs. */ @@ -63,8 +60,9 @@ // These data structures are all fully initialized during single-threaded // compiler startup and so do not need to be concurrent. private final Map registeredMethodSubstitutions; - private final Set registeredSnippets; private final Map> registerMacroSubstitutions; + private final Set forcedSubstitutions; + private final Map, SnippetTemplateCache> snippetTemplateCache; public ReplacementsImpl(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target) { this.runtime = runtime; @@ -72,35 +70,21 @@ this.assumptions = assumptions; this.graphs = new ConcurrentHashMap<>(); this.registeredMethodSubstitutions = new HashMap<>(); - this.registeredSnippets = new HashSet<>(); this.registerMacroSubstitutions = new HashMap<>(); - } - - public void registerSnippets(Class snippets) { - assert Snippets.class.isAssignableFrom(snippets); - for (Method method : snippets.getDeclaredMethods()) { - if (method.getAnnotation(Snippet.class) != null) { - int modifiers = method.getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native"); - } - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); - registeredSnippets.add(snippet); - } - } + this.forcedSubstitutions = new HashSet<>(); + this.snippetTemplateCache = new HashMap<>(); } public StructuredGraph getSnippet(ResolvedJavaMethod method) { - if (!registeredSnippets.contains(method)) { - return null; - } + assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); + assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native"; + StructuredGraph graph = graphs.get(method); if (graph == null) { graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method))); graph = graphs.get(method); } return graph; - } public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) { @@ -147,17 +131,23 @@ } String originalName = originalName(substituteMethod, methodSubstitution.value()); Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic()); - Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters); + Member originalMethod = originalMethod(classSubstitution, methodSubstitution.optional(), originalName, originalParameters); if (originalMethod != null) { - registerMethodSubstitution(originalMethod, substituteMethod); + ResolvedJavaMethod original = registerMethodSubstitution(originalMethod, substituteMethod); + if (original != null && methodSubstitution.forced()) { + forcedSubstitutions.add(original); + } } } if (macroSubstitution != null) { String originalName = originalName(substituteMethod, macroSubstitution.value()); Class[] originalParameters = originalParameters(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic()); - Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters); + Member originalMethod = originalMethod(classSubstitution, macroSubstitution.optional(), originalName, originalParameters); if (originalMethod != null) { - registerMacroSubstitution(originalMethod, macroSubstitution.macro()); + ResolvedJavaMethod original = registerMacroSubstitution(originalMethod, macroSubstitution.macro()); + if (original != null && macroSubstitution.forced()) { + forcedSubstitutions.add(original); + } } } } @@ -168,8 +158,9 @@ * * @param originalMember a method or constructor being substituted * @param substituteMethod the substitute method + * @return the original method */ - protected void registerMethodSubstitution(Member originalMember, Method substituteMethod) { + protected ResolvedJavaMethod registerMethodSubstitution(Member originalMember, Method substituteMethod) { ResolvedJavaMethod substitute = runtime.lookupJavaMethod(substituteMethod); ResolvedJavaMethod original; if (originalMember instanceof Method) { @@ -180,6 +171,7 @@ Debug.log("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute)); registeredMethodSubstitutions.put(original, substitute); + return original; } /** @@ -187,8 +179,9 @@ * * @param originalMethod a method or constructor being substituted * @param macro the substitute macro node class + * @return the original method */ - protected void registerMacroSubstitution(Member originalMethod, Class macro) { + protected ResolvedJavaMethod registerMacroSubstitution(Member originalMethod, Class macro) { ResolvedJavaMethod originalJavaMethod; if (originalMethod instanceof Method) { originalJavaMethod = runtime.lookupJavaMethod((Method) originalMethod); @@ -196,6 +189,7 @@ originalJavaMethod = runtime.lookupJavaConstructor((Constructor) originalMethod); } registerMacroSubstitutions.put(originalJavaMethod, macro); + return originalJavaMethod; } private SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) { @@ -205,7 +199,7 @@ policyClass = snippet.inlining(); } if (policyClass == SnippetInliningPolicy.class) { - return new DefaultSnippetInliningPolicy(runtime, pool()); + return new DefaultSnippetInliningPolicy(runtime); } try { return policyClass.getConstructor().newInstance(); @@ -284,7 +278,7 @@ * Does final processing of a snippet graph. */ protected void finalizeGraph(StructuredGraph graph) { - new NodeIntrinsificationPhase(runtime, pool()).apply(graph); + new NodeIntrinsificationPhase(runtime).apply(graph); assert SnippetTemplate.hasConstantParameter(method) || NodeIntrinsificationVerificationPhase.verify(graph); if (original == null) { @@ -318,7 +312,6 @@ Debug.dump(graph, "%s: %s", methodToParse.getName(), GraphBuilderPhase.class.getSimpleName()); new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); - new NodeIntrinsificationPhase(runtime, pool()).apply(graph); return graph; } @@ -332,7 +325,7 @@ protected void afterInline(StructuredGraph caller, StructuredGraph callee) { if (GraalOptions.OptCanonicalizer) { new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller); - new CanonicalizerPhase(runtime, assumptions).apply(caller); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(caller); } } @@ -340,13 +333,13 @@ * Called after all inlining for a given graph is complete. */ protected void afterInlining(StructuredGraph graph) { - new NodeIntrinsificationPhase(runtime, pool()).apply(graph); + new NodeIntrinsificationPhase(runtime).apply(graph); new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); } } @@ -354,21 +347,26 @@ assert !Modifier.isAbstract(methodToParse.getModifiers()) && !Modifier.isNative(methodToParse.getModifiers()) : methodToParse; final StructuredGraph graph = buildInitialGraph(methodToParse); - for (Invoke invoke : graph.getInvokes()) { - MethodCallTargetNode callTarget = invoke.methodCallTarget(); + for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.class)) { ResolvedJavaMethod callee = callTarget.targetMethod(); if (callee == method) { final StructuredGraph originalGraph = new StructuredGraph(original); new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph); - InliningUtil.inline(invoke, originalGraph, true); + InliningUtil.inline(callTarget.invoke(), originalGraph, true); Debug.dump(graph, "after inlining %s", callee); afterInline(graph, originalGraph); substituteCallsOriginal = true; } else { if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, methodToParse)) { - StructuredGraph targetGraph = parseGraph(callee, policy); - InliningUtil.inline(invoke, targetGraph, true); + StructuredGraph targetGraph; + StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee); + if (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)) { + targetGraph = intrinsicGraph; + } else { + targetGraph = parseGraph(callee, policy); + } + InliningUtil.inline(callTarget.invoke(), targetGraph, true); Debug.dump(graph, "after inlining %s", callee); afterInline(graph, targetGraph); } @@ -448,7 +446,7 @@ return parameters; } - private static Member originalMethod(ClassSubstitution classSubstitution, String name, Class[] parameters) { + private static Member originalMethod(ClassSubstitution classSubstitution, boolean optional, String name, Class[] parameters) { Class originalClass = classSubstitution.value(); if (originalClass == ClassSubstitution.class) { originalClass = resolveType(classSubstitution.className(), classSubstitution.optional()); @@ -464,15 +462,35 @@ return originalClass.getDeclaredMethod(name, parameters); } } catch (NoSuchMethodException | SecurityException e) { + if (optional) { + return null; + } throw new GraalInternalError(e); } } - protected BoxingMethodPool pool() { - if (pool == null) { - // A race to create the pool is ok - pool = new BoxingMethodPool(runtime); - } - return pool; + @Override + public Collection getAllReplacements() { + HashSet result = new HashSet<>(); + result.addAll(registeredMethodSubstitutions.keySet()); + result.addAll(registerMacroSubstitutions.keySet()); + return result; + } + + @Override + public boolean isForcedSubstitution(ResolvedJavaMethod method) { + return forcedSubstitutions.contains(method); + } + + @Override + public void registerSnippetTemplateCache(SnippetTemplateCache templates) { + assert snippetTemplateCache.get(templates.getClass()) == null; + snippetTemplateCache.put(templates.getClass(), templates); + } + + @Override + public T getSnippetTemplateCache(Class templatesClass) { + SnippetTemplateCache ret = snippetTemplateCache.get(templatesClass); + return templatesClass.cast(ret); } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Sat Apr 20 12:23:29 2013 +0200 @@ -27,8 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -55,6 +53,13 @@ * Determines if {@code method} should be inlined into {@code caller}. */ boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller); + + /** + * Determines if {@code method} should be inlined using its replacement graph. + * + * @return true if the replacement graph should be used, false for normal inlining. + */ + boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse); } /** @@ -70,11 +75,9 @@ public static class DefaultSnippetInliningPolicy implements SnippetInliningPolicy { private final MetaAccessProvider metaAccess; - private final BoxingMethodPool pool; - public DefaultSnippetInliningPolicy(MetaAccessProvider metaAccess, BoxingMethodPool pool) { + public DefaultSnippetInliningPolicy(MetaAccessProvider metaAccess) { this.metaAccess = metaAccess; - this.pool = pool; } @Override @@ -89,16 +92,18 @@ return false; } if (metaAccess.lookupJavaType(Throwable.class).isAssignableFrom(method.getDeclaringClass())) { - if (method.getName().equals("")) { + if (method.isConstructor()) { return false; } } if (method.getAnnotation(Word.Operation.class) != null) { return false; } - if (pool.isSpecialMethod(method)) { - return false; - } + return true; + } + + @Override + public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) { return true; } } @@ -116,20 +121,6 @@ } /** - * Denotes a snippet parameter that will be bound during snippet template - * {@linkplain SnippetTemplate#instantiate instantiation}. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.PARAMETER) - public @interface Parameter { - - /** - * The name of this parameter. - */ - String value(); - } - - /** * Denotes a snippet parameter representing 0 or more arguments that will be bound during * snippet template {@linkplain SnippetTemplate#instantiate instantiation}. During snippet * template creation, its value must be an array whose length specifies the number of arguments @@ -143,11 +134,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface VarargsParameter { - - /** - * The name of this parameter. - */ - String value(); } /** @@ -157,61 +143,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface ConstantParameter { - - /** - * The name of this constant. - */ - String value(); - } - - /** - * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter. - */ - public static class Varargs { - - private final Object args; - private final Class argType; - private final int length; - private final Stamp argStamp; - - public static Varargs vargargs(Object array, Stamp argStamp) { - return new Varargs(array, argStamp); - } - - public Varargs(Object array, Stamp argStamp) { - assert array != null; - this.argType = array.getClass().getComponentType(); - this.argStamp = argStamp; - assert this.argType != null; - this.length = java.lang.reflect.Array.getLength(array); - this.args = array; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Varargs) { - Varargs other = (Varargs) obj; - return other.argType == argType && other.length == length; - } - return false; - } - - public Object getArray() { - return args; - } - - public Stamp getArgStamp() { - return argStamp; - } - - @Override - public int hashCode() { - return argType.hashCode() ^ length; - } - - @Override - public String toString() { - return argType.getName() + "[" + length + "]"; - } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,29 +22,24 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.meta.MetaUtil.*; - import java.lang.reflect.*; import java.util.*; -import java.util.Map.Entry; import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.Snippet.Varargs; import com.oracle.graal.replacements.Snippet.VarargsParameter; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -54,174 +49,274 @@ * A snippet template is a graph created by parsing a snippet method and then specialized by binding * constants to the snippet's {@link ConstantParameter} parameters. * - * Snippet templates can be managed in a {@link Cache}. + * Snippet templates can be managed in a cache maintained by {@link AbstractTemplates}. */ public class SnippetTemplate { /** - * A snippet template key encapsulates the method from which a snippet was built and the - * arguments used to specialize the snippet. - * - * @see Cache + * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the + * method that needs to be computed only once. The {@link SnippetInfo} should be created once + * per snippet an then cached. */ - public static class Key implements Iterable> { + public static class SnippetInfo { + + protected final ResolvedJavaMethod method; + protected final boolean[] constantParameters; + protected final boolean[] varargsParameters; + + /** + * The parameter names, taken from the local variables table. Only used for assertion + * checking, so use only within an assert statement. + */ + protected final String[] names; + + protected SnippetInfo(ResolvedJavaMethod method) { + this.method = method; - public final ResolvedJavaMethod method; - private final HashMap map = new HashMap<>(); - private int hash; + assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); + int count = method.getSignature().getParameterCount(false); + constantParameters = new boolean[count]; + varargsParameters = new boolean[count]; + for (int i = 0; i < count; i++) { + constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method) != null; + varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method) != null; + + assert !isConstantParameter(i) || !isVarargsParameter(i) : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" + + VarargsParameter.class.getSimpleName(); + } - public Key(ResolvedJavaMethod method) { - this.method = method; - this.hash = method.hashCode(); + names = new String[count]; + // Retrieve the names only when assertions are turned on. + assert initNames(); + } + + private boolean initNames() { + int slotIdx = 0; + for (int i = 0; i < names.length; i++) { + names[i] = method.getLocalVariableTable().getLocal(slotIdx, 0).getName(); + + Kind kind = method.getSignature().getParameterKind(i); + slotIdx += kind == Kind.Long || kind == Kind.Double ? 2 : 1; + } + return true; } - public Key add(String name, Object value) { - assert !map.containsKey(name); - map.put(name, value); - hash = hash ^ name.hashCode(); - if (value != null) { - hash *= (value.hashCode() + 1); - } + public ResolvedJavaMethod getMethod() { + return method; + } + + public int getParameterCount() { + return constantParameters.length; + } + + public boolean isConstantParameter(int paramIdx) { + return constantParameters[paramIdx]; + } + + public boolean isVarargsParameter(int paramIdx) { + return varargsParameters[paramIdx]; + } + } + + /** + * Values that are bound to the snippet method parameters. The methods {@link #add}, + * {@link #addConst}, and {@link #addVarargs} must be called in the same order as in the + * signature of the snippet method. The parameter name is passed to the add methods for + * assertion checking, i.e., to enforce that the order matches. Which method needs to be called + * depends on the annotation of the snippet method parameter: + *
    + *
  • Use {@link #add} for a parameter without an annotation. The value is bound when the + * {@link SnippetTemplate} is {@link SnippetTemplate#instantiate instantiated}. + *
  • Use {@link #addConst} for a parameter annotated with {@link ConstantParameter}. The value + * is bound when the {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created}. + *
  • Use {@link #addVarargs} for an array parameter annotated with {@link VarargsParameter}. A + * separate {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created} for every + * distinct array length. The actual values are bound when the {@link SnippetTemplate} is + * {@link SnippetTemplate#instantiate instantiated} + *
+ */ + public static class Arguments { + + protected final SnippetInfo info; + protected final CacheKey cacheKey; + protected final Object[] values; + + protected int nextParamIdx; + + public Arguments(SnippetInfo info) { + this.info = info; + this.cacheKey = new CacheKey(info); + this.values = new Object[info.getParameterCount()]; + } + + public Arguments add(String name, Object value) { + assert check(name, false, false); + values[nextParamIdx] = value; + nextParamIdx++; return this; } - public int length() { - return map.size(); + public Arguments addConst(String name, Object value) { + assert check(name, true, false); + values[nextParamIdx] = value; + cacheKey.setParam(nextParamIdx, value); + nextParamIdx++; + return this; } - public Object get(String name) { - return map.get(name); + public Arguments addVarargs(String name, Class componentType, Stamp argStamp, Object value) { + assert check(name, false, true); + Varargs varargs = new Varargs(componentType, argStamp, value); + values[nextParamIdx] = varargs; + // A separate template is necessary for every distinct array length + cacheKey.setParam(nextParamIdx, varargs.length); + nextParamIdx++; + return this; + } + + private boolean check(String name, boolean constParam, boolean varargsParam) { + assert nextParamIdx < info.getParameterCount() : "too many parameters: " + name + " " + this; + assert info.names[nextParamIdx].equals(name) : "wrong parameter name: " + name + " " + this; + assert constParam == info.isConstantParameter(nextParamIdx) : "Parameter " + (constParam ? "not " : "") + "annotated with @" + ConstantParameter.class.getSimpleName() + ": " + name + + " " + this; + assert varargsParam == info.isVarargsParameter(nextParamIdx) : "Parameter " + (varargsParam ? "not " : "") + "annotated with @" + VarargsParameter.class.getSimpleName() + ": " + name + + " " + this; + return true; } @Override - public Iterator> iterator() { - return map.entrySet().iterator(); + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("Parameters<").append(MetaUtil.format("%H.%n", info.method)).append(" ["); + String sep = ""; + for (int i = 0; i < info.getParameterCount(); i++) { + result.append(sep); + if (info.isConstantParameter(i)) { + result.append("const "); + } else if (info.isVarargsParameter(i)) { + result.append("varargs "); + } + result.append(info.names[i]).append(" = ").append(values[i]); + sep = ", "; + } + result.append(">"); + return result.toString(); + } + } + + /** + * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter. + */ + static class Varargs { + + protected final Class componentType; + protected final Stamp stamp; + protected final Object value; + protected final int length; + + protected Varargs(Class componentType, Stamp stamp, Object value) { + this.componentType = componentType; + this.stamp = stamp; + this.value = value; + if (value instanceof List) { + this.length = ((List) value).size(); + } else { + this.length = Array.getLength(value); + } + } + } + + static class CacheKey { + + private final ResolvedJavaMethod method; + private final Object[] values; + private int hash; + + protected CacheKey(SnippetInfo info) { + this.method = info.method; + this.values = new Object[info.getParameterCount()]; + this.hash = info.method.hashCode(); + } + + protected void setParam(int paramIdx, Object value) { + values[paramIdx] = value; + hash = (hash * 31) ^ (value == null ? 0 : value.hashCode()); } @Override public boolean equals(Object obj) { - if (obj instanceof Key) { - Key other = (Key) obj; - return other.method == method && other.map.equals(map); + if (!(obj instanceof CacheKey)) { + return false; + } + CacheKey other = (CacheKey) obj; + if (method != other.method) { + return false; } - return false; + for (int i = 0; i < values.length; i++) { + if (values[i] != null && !values[i].equals(other.values[i])) { + return false; + } + } + return true; } @Override public int hashCode() { return hash; } - - @Override - public String toString() { - return MetaUtil.format("%h.%n", method) + map.toString(); - } - - public Set names() { - return map.keySet(); - } } /** - * Arguments used to instantiate a template. + * Base class for snippet classes. It provides a cache for {@link SnippetTemplate}s. */ - public static class Arguments implements Iterable> { - - private final HashMap map = new HashMap<>(); - - public static Arguments arguments(String name, Object value) { - return new Arguments().add(name, value); - } - - public Arguments add(String name, Object value) { - assert !map.containsKey(name); - map.put(name, value); - return this; - } - - public int length() { - return map.size(); - } + public abstract static class AbstractTemplates implements SnippetTemplateCache { - @Override - public Iterator> iterator() { - return map.entrySet().iterator(); - } - - @Override - public String toString() { - return map.toString(); - } - } + protected final MetaAccessProvider runtime; + protected final Replacements replacements; + protected final TargetDescription target; + private final ConcurrentHashMap templates; - /** - * A collection of snippet templates accessed by a {@link Key} instance. - */ - public static class Cache { - - private final ConcurrentHashMap templates = new ConcurrentHashMap<>(); - private final MetaAccessProvider runtime; - private final TargetDescription target; - private final Replacements replacements; - - public Cache(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + protected AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { this.runtime = runtime; this.replacements = replacements; this.target = target; + this.templates = new ConcurrentHashMap<>(); + } + + protected SnippetInfo snippet(Class declaringClass, String methodName) { + Method found = null; + for (Method method : declaringClass.getDeclaredMethods()) { + if (method.getAnnotation(Snippet.class) != null && method.getName().equals(methodName)) { + assert found == null : "found more than one @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass; + found = method; + } + } + assert found != null : "did not find @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass; + + return new SnippetInfo(runtime.lookupJavaMethod(found)); } /** * Gets a template for a given key, creating it first if necessary. */ - public SnippetTemplate get(final SnippetTemplate.Key key) { - SnippetTemplate template = templates.get(key); + protected SnippetTemplate template(final Arguments args) { + SnippetTemplate template = templates.get(args.cacheKey); if (template == null) { - template = Debug.scope("SnippetSpecialization", key.method, new Callable() { + template = Debug.scope("SnippetSpecialization", args.info.method, new Callable() { @Override public SnippetTemplate call() throws Exception { - return new SnippetTemplate(runtime, replacements, target, key); + return new SnippetTemplate(runtime, replacements, target, args); } }); - // System.out.println(key + " -> " + template); - templates.put(key, template); + templates.put(args.cacheKey, template); } return template; } } - public abstract static class AbstractTemplates { - - protected final Cache cache; - protected final MetaAccessProvider runtime; - protected final Replacements replacements; - protected Class snippetsClass; - - public AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class snippetsClass) { - this.runtime = runtime; - this.replacements = replacements; - if (snippetsClass == null) { - assert this instanceof Snippets; - this.snippetsClass = getClass(); - } else { - this.snippetsClass = snippetsClass; - } - this.cache = new Cache(runtime, replacements, target); - replacements.registerSnippets(this.snippetsClass); - } - - protected ResolvedJavaMethod snippet(String name, Class... parameterTypes) { - try { - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(snippetsClass.getDeclaredMethod(name, parameterTypes)); - assert snippet.getAnnotation(Snippet.class) != null : "snippet is not annotated with @" + Snippet.class.getSimpleName(); - return snippet; - } catch (NoSuchMethodException e) { - throw new GraalInternalError(e); - } - } - } - private static final Object UNUSED_PARAMETER = "DEAD PARAMETER"; + private static final Object CONSTANT_PARAMETER = "CONSTANT"; /** * Determines if any parameter of a given method is annotated with {@link ConstantParameter}. @@ -238,31 +333,25 @@ /** * Creates a snippet template. */ - public SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, SnippetTemplate.Key key) { - ResolvedJavaMethod method = key.method; - assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + method; + protected SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Arguments args) { + StructuredGraph snippetGraph = replacements.getSnippet(args.info.method); + + ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); // Copy snippet graph, replacing constant parameters with given arguments - StructuredGraph snippetGraph = replacements.getSnippet(method); - if (snippetGraph == null) { - throw new GraalInternalError("Snippet has not been registered: %s", format("%H.%n(%p)", method)); - } StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); IdentityHashMap nodeReplacements = new IdentityHashMap<>(); nodeReplacements.put(snippetGraph.start(), snippetCopy.start()); - int parameterCount = signature.getParameterCount(false); - assert checkTemplate(runtime, key, parameterCount, method, signature); + assert checkTemplate(runtime, args, method, signature); - Parameter[] parameterAnnotations = new Parameter[parameterCount]; - VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount]; + int parameterCount = args.info.getParameterCount(); ConstantNode[] placeholders = new ConstantNode[parameterCount]; + for (int i = 0; i < parameterCount; i++) { - ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - if (c != null) { - String name = c.value(); - Object arg = key.get(name); + if (args.info.isConstantParameter(i)) { + Object arg = args.values[i]; Kind kind = signature.getParameterKind(i); Constant constantArg; if (arg instanceof Constant) { @@ -271,19 +360,12 @@ constantArg = Constant.forBoxed(kind, arg); } nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy)); - } else { - VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); - if (vp != null) { - String name = vp.value(); - Varargs varargs = (Varargs) key.get(name); - Object array = varargs.getArray(); - ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); - nodeReplacements.put(snippetGraph.getLocal(i), placeholder); - placeholders[i] = placeholder; - varargsParameterAnnotations[i] = vp; - } else { - parameterAnnotations[i] = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - } + } else if (args.info.isVarargsParameter(i)) { + Varargs varargs = (Varargs) args.values[i]; + Object array = Array.newInstance(varargs.componentType, varargs.length); + ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); + nodeReplacements.put(snippetGraph.getLocal(i), placeholder); + placeholders[i] = placeholder; } } snippetCopy.addDuplicates(snippetGraph.getNodes(), nodeReplacements); @@ -291,31 +373,31 @@ Debug.dump(snippetCopy, "Before specialization"); if (!nodeReplacements.isEmpty()) { // Do deferred intrinsification of node intrinsics - new NodeIntrinsificationPhase(runtime, new BoxingMethodPool(runtime)).apply(snippetCopy); + new NodeIntrinsificationPhase(runtime).apply(snippetCopy); new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); - new CanonicalizerPhase(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy); + new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy); } assert NodeIntrinsificationVerificationPhase.verify(snippetCopy); // Gather the template parameters - parameters = new HashMap<>(); + parameters = new Object[parameterCount]; for (int i = 0; i < parameterCount; i++) { - VarargsParameter vp = varargsParameterAnnotations[i]; - if (vp != null) { + if (args.info.isConstantParameter(i)) { + parameters[i] = CONSTANT_PARAMETER; + } else if (args.info.isVarargsParameter(i)) { assert snippetCopy.getLocal(i) == null; - Varargs varargs = (Varargs) key.get(vp.value()); - Object array = varargs.getArray(); - int length = Array.getLength(array); + Varargs varargs = (Varargs) args.values[i]; + int length = varargs.length; LocalNode[] locals = new LocalNode[length]; - Stamp stamp = varargs.getArgStamp(); + Stamp stamp = varargs.stamp; for (int j = 0; j < length; j++) { assert (parameterCount & 0xFFFF) == parameterCount; int idx = i << 16 | j; LocalNode local = snippetCopy.unique(new LocalNode(idx, stamp)); locals[j] = local; } - parameters.put(vp.value(), locals); + parameters[i] = locals; ConstantNode placeholder = placeholders[i]; assert placeholder != null; @@ -329,15 +411,12 @@ } } } else { - Parameter p = parameterAnnotations[i]; - if (p != null) { - LocalNode local = snippetCopy.getLocal(i); - if (local == null) { - // Parameter value was eliminated - parameters.put(p.value(), UNUSED_PARAMETER); - } else { - parameters.put(p.value(), local); - } + LocalNode local = snippetCopy.getLocal(i); + if (local == null) { + // Parameter value was eliminated + parameters[i] = UNUSED_PARAMETER; + } else { + parameters[i] = local; } } } @@ -354,7 +433,7 @@ LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); int mark = snippetCopy.getMark(); LoopTransformations.fullUnroll(loop, runtime, null); - new CanonicalizerPhase(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy); + new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy); } FixedNode explodeLoopNext = explodeLoop.next(); explodeLoop.clearSuccessors(); @@ -436,11 +515,11 @@ return true; } - private static boolean checkVarargs(final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { - Object arg = varargs.getArray(); + private static boolean checkVarargs(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); assert type.isArray() : "varargs parameter must be an array type"; - assert type.isInstance(Constant.forObject(arg)) : "value for " + name + " is not a " + MetaUtil.toJavaName(type) + " instance: " + arg; + assert type.getComponentType().isAssignableFrom(runtime.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + MetaUtil.toJavaName(type) + " instance: " + + varargs.componentType; return true; } @@ -455,7 +534,7 @@ * {@link LocalNode} instance or a {@link LocalNode} array. For an eliminated parameter, the * value is identical to the key. */ - private final Map parameters; + private final Object[] parameters; /** * The return node (if any) of the snippet. @@ -483,33 +562,33 @@ * * @return the map that will be used to bind arguments to parameters when inlining this template */ - private IdentityHashMap bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, SnippetTemplate.Arguments args) { + private IdentityHashMap bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, Arguments args) { IdentityHashMap replacements = new IdentityHashMap<>(); - assert args.length() == parameters.size() : "number of args (" + args.length() + ") != number of parameters (" + parameters.size() + ")"; - for (Map.Entry e : args) { - String name = e.getKey(); - Object parameter = parameters.get(name); - assert parameter != null : this + " has no parameter named " + name; - Object argument = e.getValue(); + assert args.info.getParameterCount() == parameters.length : "number of args (" + args.info.getParameterCount() + ") != number of parameters (" + parameters.length + ")"; + for (int i = 0; i < parameters.length; i++) { + Object parameter = parameters[i]; + assert parameter != null : this + " has no parameter named " + args.info.names[i]; + Object argument = args.values[i]; if (parameter instanceof LocalNode) { if (argument instanceof ValueNode) { replacements.put((LocalNode) parameter, (ValueNode) argument); } else { Kind kind = ((LocalNode) parameter).kind(); - assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + name; - Constant constant = Constant.forBoxed(kind, argument); + assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.names[i]; + Constant constant = forBoxed(argument, kind); replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph)); } } else if (parameter instanceof LocalNode[]) { LocalNode[] locals = (LocalNode[]) parameter; + Varargs varargs = (Varargs) argument; int length = locals.length; List list = null; Object array = null; - if (argument instanceof List) { - list = (List) argument; + if (varargs.value instanceof List) { + list = (List) varargs.value; assert list.size() == length : length + " != " + list.size(); } else { - array = argument; + array = varargs.value; assert array != null && array.getClass().isArray(); assert Array.getLength(array) == length : length + " != " + Array.getLength(array); } @@ -521,19 +600,45 @@ if (value instanceof ValueNode) { replacements.put(local, (ValueNode) value); } else { - Constant constant = Constant.forBoxed(local.kind(), value); + Constant constant = forBoxed(value, local.kind()); ConstantNode element = ConstantNode.forConstant(constant, runtime, replaceeGraph); replacements.put(local, element); } } } else { - assert parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + name + " -> " + parameter; + assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.names[i] + " -> " + parameter; } } return replacements; } /** + * Converts a Java boxed value to a {@link Constant} of the right kind. This adjusts for the + * limitation that a {@link Local}'s kind is a {@linkplain Kind#getStackKind() stack kind} and + * so cannot be used for re-boxing primitives smaller than an int. + * + * @param argument a Java boxed value + * @param localKind the kind of the {@link Local} to which {@code argument} will be bound + */ + protected Constant forBoxed(Object argument, Kind localKind) { + assert localKind == localKind.getStackKind(); + if (localKind == Kind.Int && !(argument instanceof Integer)) { + if (argument instanceof Boolean) { + return Constant.forBoxed(Kind.Boolean, argument); + } + if (argument instanceof Byte) { + return Constant.forBoxed(Kind.Byte, argument); + } + if (argument instanceof Short) { + return Constant.forBoxed(Kind.Short, argument); + } + assert argument instanceof Character; + return Constant.forBoxed(Kind.Char, argument); + } + return Constant.forBoxed(localKind, argument); + } + + /** * Logic for replacing a snippet-lowered node at its usages with the return value of the * snippet. An alternative to the {@linkplain SnippetTemplate#DEFAULT_REPLACER default} * replacement logic can be used to handle mismatches between the stamp of the node being @@ -568,7 +673,7 @@ * @param args the arguments to be bound to the flattened positional parameters of the snippet * @return the map of duplicated nodes (original -> duplicate) */ - public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) { + public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -644,7 +749,7 @@ * @param replacer object that replaces the usages of {@code replacee} * @param args the arguments to be bound to the flattened positional parameters of the snippet */ - public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) { + public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -703,13 +808,17 @@ public String toString() { StringBuilder buf = new StringBuilder(snippet.toString()).append('('); String sep = ""; - for (Map.Entry e : parameters.entrySet()) { - String name = e.getKey(); - Object value = e.getValue(); + for (int i = 0; i < parameters.length; i++) { + String name = "[" + i + "]"; + Object value = parameters[i]; buf.append(sep); sep = ", "; - if (value == UNUSED_PARAMETER) { + if (value == null) { + buf.append(" ").append(name); + } else if (value == UNUSED_PARAMETER) { buf.append(" ").append(name); + } else if (value == CONSTANT_PARAMETER) { + buf.append(" ").append(name); } else if (value instanceof LocalNode) { LocalNode local = (LocalNode) value; buf.append(local.kind().getJavaName()).append(' ').append(name); @@ -722,42 +831,18 @@ return buf.append(')').toString(); } - private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) { - Set expected = new HashSet<>(); - for (int i = 0; i < parameterCount; i++) { - ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); - Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - if (c != null) { - assert vp == null && p == null; - String name = c.value(); - expected.add(name); + private static boolean checkTemplate(MetaAccessProvider runtime, Arguments args, ResolvedJavaMethod method, Signature signature) { + for (int i = 0; i < args.info.getParameterCount(); i++) { + if (args.info.isConstantParameter(i)) { Kind kind = signature.getParameterKind(i); - assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind); - } else if (vp != null) { - assert p == null; - String name = vp.value(); - expected.add(name); - assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert key.get(name) instanceof Varargs; - Varargs varargs = (Varargs) key.get(name); - assert checkVarargs(method, signature, i, name, varargs); - } else { - assert p != null : method + ": parameter " + i + " must be annotated with exactly one of " + "@" + ConstantParameter.class.getSimpleName() + " or " + "@" + - VarargsParameter.class.getSimpleName() + " or " + "@" + Parameter.class.getSimpleName(); + assert checkConstantArgument(runtime, method, signature, i, args.info.names[i], args.values[i], kind); + + } else if (args.info.isVarargsParameter(i)) { + assert args.values[i] instanceof Varargs; + Varargs varargs = (Varargs) args.values[i]; + assert checkVarargs(runtime, method, signature, i, args.info.names[i], varargs); } } - if (!key.names().containsAll(expected)) { - expected.removeAll(key.names()); - assert false : expected + " missing from key " + key; - } - if (!expected.containsAll(key.names())) { - Set namesCopy = new HashSet<>(key.names()); - namesCopy.removeAll(expected); - assert false : "parameter(s) " + namesCopy + " should be annotated with @" + ConstantParameter.class.getSimpleName() + " or @" + VarargsParameter.class.getSimpleName() + " in " + - MetaUtil.format("%H.%n(%p)", method); - } return true; } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.extended.WriteNode.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; @@ -63,7 +64,7 @@ public void lower(LoweringTool tool) { StructuredGraph graph = (StructuredGraph) this.graph(); IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, 1); - WriteNode write = graph.add(new WriteNode(object, value, location)); + WriteNode write = graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE)); graph.replaceFixedWithFixed(this, write); } } diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -41,11 +41,12 @@ private final JavaType returnType; protected MacroNode(Invoke invoke) { - super(invoke.node().stamp(), invoke.stateAfter()); - this.arguments = new NodeInputList<>(this, invoke.methodCallTarget().arguments()); + super(invoke.asNode().stamp(), invoke.stateAfter()); + MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget(); + this.arguments = new NodeInputList<>(this, methodCallTarget.arguments()); this.bci = invoke.bci(); - this.targetMethod = invoke.methodCallTarget().targetMethod(); - this.returnType = invoke.methodCallTarget().returnType(); + this.targetMethod = methodCallTarget.targetMethod(); + this.returnType = methodCallTarget.returnType(); } public int getBci() { @@ -92,11 +93,11 @@ protected void replaceSnippetInvokes(StructuredGraph snippetGraph) { for (InvokeNode invoke : snippetGraph.getNodes(InvokeNode.class)) { - if (invoke.methodCallTarget().targetMethod() != getTargetMethod()) { + if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != getTargetMethod()) { throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName()); } if (invoke.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) { - InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.methodCallTarget(), getBci())); + InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci())); newInvoke.setStateAfter(snippetGraph.add(new FrameState(FrameState.AFTER_BCI))); snippetGraph.replaceFixedWithFixed(invoke, newInvoke); } else { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -107,6 +107,8 @@ return ConstantNode.forDouble(Math.cos(value), graph()); case TAN: return ConstantNode.forDouble(Math.tan(value), graph()); + default: + throw GraalInternalError.shouldNotReachHere(); } } return this; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java --- a/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java Sat Apr 20 12:23:29 2013 +0200 @@ -38,38 +38,7 @@ @SupportedAnnotationTypes("com.oracle.graal.api.runtime.ServiceProvider") public class ServiceProviderProcessor extends AbstractProcessor { - private Map> serviceMap; - - public ServiceProviderProcessor() { - serviceMap = new HashMap<>(); - } - - private void addProvider(String serviceName, TypeElement serviceProvider) { - Set providers = serviceMap.get(serviceName); - if (providers == null) { - providers = new HashSet<>(); - serviceMap.put(serviceName, providers); - } - providers.add(serviceProvider); - } - - private void generateServicesFiles() { - Filer filer = processingEnv.getFiler(); - for (Map.Entry> entry : serviceMap.entrySet()) { - String filename = "META-INF/services/" + entry.getKey(); - TypeElement[] providers = entry.getValue().toArray(new TypeElement[0]); - try { - FileObject servicesFile = filer.createResource(StandardLocation.CLASS_OUTPUT, "", filename, providers); - PrintWriter writer = new PrintWriter(new OutputStreamWriter(servicesFile.openOutputStream(), "UTF-8")); - for (TypeElement provider : providers) { - writer.println(provider.getQualifiedName()); - } - writer.close(); - } catch (IOException e) { - processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage()); - } - } - } + private final Set processed = new HashSet<>(); private boolean verifyAnnotation(TypeMirror serviceInterface, TypeElement serviceProvider) { if (!processingEnv.getTypeUtils().isSubtype(serviceProvider.asType(), serviceInterface)) { @@ -81,27 +50,49 @@ return true; } + private void processElement(TypeElement serviceProvider) { + if (processed.contains(serviceProvider)) { + return; + } + + processed.add(serviceProvider); + ServiceProvider annotation = serviceProvider.getAnnotation(ServiceProvider.class); + if (annotation != null) { + try { + annotation.value(); + } catch (MirroredTypeException ex) { + TypeMirror serviceInterface = ex.getTypeMirror(); + if (verifyAnnotation(serviceInterface, serviceProvider)) { + String interfaceName = ex.getTypeMirror().toString(); + createProviderFile(serviceProvider, interfaceName); + } + } + } + } + + private void createProviderFile(TypeElement serviceProvider, String interfaceName) { + String filename = "META-INF/providers/" + serviceProvider.getQualifiedName(); + try { + FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, serviceProvider); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); + writer.println(interfaceName); + writer.close(); + } catch (IOException e) { + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), serviceProvider); + } + } + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (roundEnv.processingOver()) { - generateServicesFiles(); return true; } for (Element element : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) { assert element.getKind().isClass(); - ServiceProvider annotation = element.getAnnotation(ServiceProvider.class); - try { - annotation.value(); - } catch (MirroredTypeException ex) { - TypeMirror serviceInterface = ex.getTypeMirror(); - TypeElement serviceProvider = (TypeElement) element; - if (verifyAnnotation(serviceInterface, serviceProvider)) { - String interfaceName = ex.getTypeMirror().toString(); - addProvider(interfaceName, serviceProvider); - } - } + processElement((TypeElement) element); } + return true; } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -30,9 +30,6 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; -/** - * The {@code StoreFieldNode} represents a write to a static or instance field. - */ @NodeInfo(nameTemplate = "MaterializeStore#{p#target/s}") public final class CyclicMaterializeStoreNode extends FixedWithNextNode implements Lowerable, Virtualizable { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; @@ -44,10 +43,18 @@ this.values = new NodeInputList<>(this, virtualObject.entryCount()); } - public NodeInputList values() { + public NodeInputList getValues() { return values; } + public VirtualObjectNode getVirtualObject() { + return virtualObject; + } + + public int getLockCount() { + return lockCount; + } + @Override public ValueNode length() { assert virtualObject.type().isArray(); @@ -73,38 +80,7 @@ @Override public void lower(LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) graph(); - - boolean defaultValuesOnly = isDefault(); - - if (virtualObject instanceof VirtualInstanceNode) { - VirtualInstanceNode virtual = (VirtualInstanceNode) virtualObject; - - NewInstanceNode newInstance = graph.add(new NewInstanceNode(virtual.type(), defaultValuesOnly, lockCount > 0)); - this.replaceAtUsages(newInstance); - graph.addBeforeFixed(this, newInstance); - - if (!defaultValuesOnly) { - for (int i = 0; i < virtual.entryCount(); i++) { - graph.addBeforeFixed(this, graph.add(new StoreFieldNode(newInstance, virtual.field(i), values.get(i)))); - } - } - } else { - assert virtualObject instanceof VirtualArrayNode; - VirtualArrayNode virtual = (VirtualArrayNode) virtualObject; - - ResolvedJavaType element = virtual.componentType(); - NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0)); - this.replaceAtUsages(newArray); - graph.addBeforeFixed(this, newArray); - - if (!defaultValuesOnly) { - for (int i = 0; i < virtual.entryCount(); i++) { - graph.addBeforeFixed(this, graph.add(new StoreIndexedNode(newArray, ConstantNode.forInt(i, graph), element.getKind(), values.get(i)))); - } - } - } - graph.removeFixed(this); + virtualObject.materializeAt(this, values, isDefault(), lockCount); } @Override diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Sat Apr 20 12:23:29 2013 +0200 @@ -40,7 +40,7 @@ private final IdentityHashMap objectStates = new IdentityHashMap<>(); private final IdentityHashMap objectAliases; private final IdentityHashMap scalarAliases; - private final HashMap readCache; + final HashMap readCache; static class ReadCacheEntry { @@ -167,8 +167,6 @@ ValueNode[] fieldState = obj.getEntries(); - // some entries are not default constants - do the materialization - virtual.materializeAt(fixed); MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.getLockCount()); ValueNode[] values = new ValueNode[obj.getEntries().length]; materialize.setProbability(fixed.probability()); @@ -249,70 +247,13 @@ return objectStates.values(); } - public Iterable getVirtualObjects() { + public Collection getVirtualObjects() { return objectAliases.values(); } @Override public String toString() { - return objectStates.toString(); - } - - public void mergeReadCache(List states, MergeNode merge, GraphEffectList effects) { - for (Map.Entry entry : states.get(0).readCache.entrySet()) { - ReadCacheEntry key = entry.getKey(); - ValueNode value = entry.getValue(); - boolean phi = false; - for (int i = 1; i < states.size(); i++) { - ValueNode otherValue = states.get(i).readCache.get(key); - if (otherValue == null) { - value = null; - phi = false; - break; - } - if (!phi && otherValue != value) { - phi = true; - } - } - if (phi) { - PhiNode phiNode = new PhiNode(value.kind(), merge); - effects.addFloatingNode(phiNode); - for (int i = 0; i < states.size(); i++) { - effects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity)); - } - readCache.put(key, phiNode); - } else if (value != null) { - readCache.put(key, value); - } - } - for (PhiNode phi : merge.phis()) { - if (phi.kind() == Kind.Object) { - for (Map.Entry entry : states.get(0).readCache.entrySet()) { - if (entry.getKey().object == phi.valueAt(0)) { - mergeReadCachePhi(phi, entry.getKey().identity, states, merge, effects); - } - } - - } - } - } - - private void mergeReadCachePhi(PhiNode phi, Object identity, List states, MergeNode merge, GraphEffectList effects) { - ValueNode[] values = new ValueNode[phi.valueCount()]; - for (int i = 0; i < phi.valueCount(); i++) { - ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity); - if (value == null) { - return; - } - values[i] = value; - } - - PhiNode phiNode = new PhiNode(values[0].kind(), merge); - effects.addFloatingNode(phiNode); - for (int i = 0; i < values.length; i++) { - effects.addPhiInput(phiNode, values[i]); - } - readCache.put(new ReadCacheEntry(identity, phi), phiNode); + return objectStates + " " + readCache; } public static BlockState meetAliases(List states) { @@ -349,4 +290,38 @@ return readCache; } + public boolean equivalentTo(BlockState other) { + if (this == other) { + return true; + } + boolean objectAliasesEqual = compareMaps(objectAliases, other.objectAliases); + boolean objectStatesEqual = compareMaps(objectStates, other.objectStates); + boolean readCacheEqual = compareMapsNoSize(readCache, other.readCache); + boolean scalarAliasesEqual = scalarAliases.equals(other.scalarAliases); + return objectAliasesEqual && objectStatesEqual && readCacheEqual && scalarAliasesEqual; + } + + private static boolean compareMaps(Map left, Map right) { + if (left.size() != right.size()) { + return false; + } + return compareMapsNoSize(left, right); + } + + private static boolean compareMapsNoSize(Map left, Map right) { + if (left == right) { + return true; + } + for (Map.Entry entry : right.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + assert value != null; + V otherValue = left.get(key); + if (otherValue != value && !value.equals(otherValue)) { + return false; + } + } + return true; + } + } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java Sat Apr 20 12:23:29 2013 +0200 @@ -73,48 +73,47 @@ public abstract void apply(StructuredGraph graph, ArrayList obsoleteNodes); } - private Effect[] effects = new Effect[16]; - private int[] level = new int[16]; + private static final Effect[] EMPTY_ARRAY = new Effect[0]; + + private Effect[] effects = EMPTY_ARRAY; private int size; - private int currentLevel; + + private void enlarge(int elements) { + int length = effects.length; + if (size + elements > length) { + while (size + elements > length) { + length = Math.max(length * 2, 4); + } + effects = Arrays.copyOf(effects, length); + } + } public void add(Effect effect) { - if (effects.length == size) { - effects = Arrays.copyOf(effects, effects.length * 2); - level = Arrays.copyOf(level, effects.length); - } - level[size] = currentLevel; + assert effect != null; + enlarge(1); effects[size++] = effect; } public void addAll(Collection list) { - int length = effects.length; - if (size + list.size() > length) { - while (size + list.size() > length) { - length *= 2; - } - effects = Arrays.copyOf(effects, length); - level = Arrays.copyOf(level, effects.length); - } + enlarge(list.size()); for (Effect effect : list) { - level[size] = currentLevel; + assert effect != null; effects[size++] = effect; } } public void addAll(EffectList list) { - int length = effects.length; - if (size + list.size > length) { - while (size + list.size > length) { - length *= 2; - } - effects = Arrays.copyOf(effects, length); - level = Arrays.copyOf(level, effects.length); - } - for (Effect effect : list) { - level[size] = currentLevel; - effects[size++] = effect; - } + enlarge(list.size); + System.arraycopy(list.effects, 0, effects, size, list.size); + size += list.size; + } + + public void insertAll(EffectList list, int position) { + assert position >= 0 && position <= size; + enlarge(list.size); + System.arraycopy(effects, position, effects, position + list.size, size - position); + System.arraycopy(list.effects, 0, effects, position, list.size); + size += list.size; } public int checkpoint() { @@ -154,14 +153,6 @@ }; } - public void incLevel() { - currentLevel++; - } - - public void decLevel() { - currentLevel--; - } - public Effect get(int index) { if (index >= size) { throw new IndexOutOfBoundsException(); @@ -169,13 +160,6 @@ return effects[index]; } - public int levelAt(int index) { - if (index >= size) { - throw new IndexOutOfBoundsException(); - } - return level[index]; - } - public void clear() { size = 0; } @@ -190,9 +174,6 @@ for (int i = 0; i < size(); i++) { Effect effect = get(i); if (effect.isVisible()) { - for (int i2 = 0; i2 < levelAt(i); i2++) { - str.append(" "); - } str.append(effect).append('\n'); } } diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Sat Apr 20 12:23:29 2013 +0200 @@ -104,17 +104,17 @@ * * @param node The floating node to be added. */ - public void addFloatingNode(final ValueNode node) { + public void addFloatingNode(final ValueNode node, final String cause) { add(new Effect() { @Override public String name() { - return "addFloatingNode"; + return "addFloatingNode " + cause; } @Override public void apply(StructuredGraph graph, ArrayList obsoleteNodes) { - assert !node.isAlive() && !node.isDeleted(); + assert !node.isAlive() && !node.isDeleted() : node + " " + cause; graph.add(node); } }); @@ -142,7 +142,7 @@ graph.addBeforeFixed(position, graph.add(node)); node.setProbability(position.probability()); for (int i = 0; i < values.length; i++) { - node.values().set(i, values[i]); + node.getValues().set(i, values[i]); } } }); @@ -164,7 +164,7 @@ @Override public void apply(StructuredGraph graph, ArrayList obsoleteNodes) { - assert node.isAlive() && value.isAlive(); + assert node.isAlive() && value.isAlive() : node + " " + value; node.addInput(value); } }); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,28 +25,24 @@ import java.util.*; import java.util.concurrent.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; -public class IterativeInliningPhase extends Phase { +public class IterativeInliningPhase extends BasePhase { private final PhasePlan plan; - private final GraalCodeCacheProvider runtime; private final Replacements replacements; - private final Assumptions assumptions; private final GraphCache cache; private final OptimisticOptimizations optimisticOpts; private final boolean readElimination; - public IterativeInliningPhase(GraalCodeCacheProvider runtime, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) { - this.runtime = runtime; + public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) { this.replacements = replacements; - this.assumptions = assumptions; this.cache = cache; this.plan = plan; this.optimisticOpts = optimisticOpts; @@ -60,12 +56,12 @@ } @Override - protected void run(final StructuredGraph graph) { - runIterations(graph, true); - runIterations(graph, false); + protected void run(final StructuredGraph graph, final HighTierContext context) { + runIterations(graph, true, context); + runIterations(graph, false, context); } - private void runIterations(final StructuredGraph graph, final boolean simple) { + private void runIterations(final StructuredGraph graph, final boolean simple, final HighTierContext context) { Boolean continueIteration = true; for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) { continueIteration = Debug.scope("iteration " + iteration, new Callable() { @@ -73,13 +69,13 @@ @Override public Boolean call() { boolean progress = false; - PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(runtime, assumptions, false, readElimination); - ea.apply(graph); - progress |= ea.hasChanged(); + PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination); + boolean eaResult = ea.runAnalysis(graph, context); + progress |= eaResult; Map hints = GraalOptions.PEAInliningHints ? PartialEscapeAnalysisPhase.getHints(graph) : null; - InliningPhase inlining = new InliningPhase(runtime, hints, replacements, assumptions, cache, plan, optimisticOpts); + InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, replacements, context.getAssumptions(), cache, plan, optimisticOpts); inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE); inlining.apply(graph); progress |= inlining.getInliningCount() > 0; @@ -87,8 +83,8 @@ new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase().apply(graph, context); + new IterativeConditionalEliminationPhase().apply(graph, context); } return progress; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.virtual.phases.ea; +import java.util.*; + import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; @@ -144,4 +146,48 @@ return str.append('}').toString(); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(entries); + result = prime * result + lockCount; + result = prime * result + ((materializedValue == null) ? 0 : materializedValue.hashCode()); + result = prime * result + ((state == null) ? 0 : state.hashCode()); + result = prime * result + ((virtual == null) ? 0 : virtual.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + ObjectState other = (ObjectState) obj; + if (!Arrays.equals(entries, other.entries)) { + return false; + } + if (lockCount != other.lockCount) { + return false; + } + if (materializedValue == null) { + if (other.materializedValue != null) { + return false; + } + } else if (!materializedValue.equals(other.materializedValue)) { + return false; + } + if (state != other.state) { + return false; + } + assert virtual != null && other.virtual != null; + if (!virtual.equals(other.virtual)) { + return false; + } + return true; + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -25,12 +25,10 @@ import java.util.*; import java.util.concurrent.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -38,34 +36,25 @@ import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.nodes.*; -import com.oracle.graal.virtual.phases.ea.EffectList.Effect; -public class PartialEscapeAnalysisPhase extends Phase { +public class PartialEscapeAnalysisPhase extends BasePhase { - private final MetaAccessProvider runtime; - private final Assumptions assumptions; - private CustomCanonicalizer customCanonicalizer; + private final CustomCanonicalizer customCanonicalizer; private final boolean iterative; private final boolean readElimination; - private boolean changed; + public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination) { + this(null, iterative, readElimination); + } - public PartialEscapeAnalysisPhase(MetaAccessProvider runtime, Assumptions assumptions, boolean iterative, boolean readElimination) { - this.runtime = runtime; - this.assumptions = assumptions; + public PartialEscapeAnalysisPhase(CustomCanonicalizer customCanonicalizer, boolean iterative, boolean readElimination) { + this.customCanonicalizer = customCanonicalizer; this.iterative = iterative; this.readElimination = readElimination; } - public boolean hasChanged() { - return changed; - } - - public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) { - this.customCanonicalizer = customCanonicalizer; - } - public static final void trace(String format, Object... obj) { if (GraalOptions.TraceEscapeAnalysis) { Debug.log(format, obj); @@ -73,9 +62,13 @@ } @Override - protected void run(final StructuredGraph graph) { + protected void run(StructuredGraph graph, HighTierContext context) { + runAnalysis(graph, context); + } + + public boolean runAnalysis(final StructuredGraph graph, final HighTierContext context) { if (!matches(graph, GraalOptions.EscapeAnalyzeOnly)) { - return; + return false; } if (!readElimination) { @@ -87,33 +80,29 @@ } } if (!analyzableNodes) { - return; + return false; } } - Boolean continueIteration = true; + boolean continueIteration = true; + boolean changed = false; for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) { - continueIteration = Debug.scope("iteration " + iteration, new Callable() { + boolean currentChanged = Debug.scope("iteration " + iteration, new Callable() { @Override public Boolean call() { SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph, false); - PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime, assumptions); + PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, context.getRuntime(), context.getAssumptions()); ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null); if (!closure.hasChanged()) { return false; } - changed = true; // apply the effects collected during the escape analysis iteration - ArrayList obsoleteNodes = new ArrayList<>(); - for (Effect effect : closure.getEffects()) { - effect.apply(graph, obsoleteNodes); - } - trace("%s\n", closure.getEffects()); + List obsoleteNodes = closure.applyEffects(graph); Debug.dump(graph, "after PartialEscapeAnalysis iteration"); assert noObsoleteNodes(graph, obsoleteNodes); @@ -121,21 +110,17 @@ new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions, null, customCanonicalizer).apply(graph); + new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).apply(graph); } - return iterative; + return true; } }); + continueIteration = currentChanged && iterative; + changed |= currentChanged; } - if (DynamicCounterNode.enabled && readElimination) { - for (Node node : graph.getNodes()) { - if (node instanceof LoadFieldNode) { - DynamicCounterNode.addCounterBefore("load non-elim", 1, false, (FixedNode) node); - } - } - } + return changed; } private static boolean matches(StructuredGraph graph, String filter) { @@ -146,7 +131,7 @@ return true; } - static boolean noObsoleteNodes(StructuredGraph graph, ArrayList obsoleteNodes) { + static boolean noObsoleteNodes(StructuredGraph graph, List obsoleteNodes) { // helper code that determines the paths that keep obsolete nodes alive: NodeFlood flood = graph.createNodeFlood(); @@ -196,14 +181,13 @@ } } } - boolean success = true; for (Node node : obsoleteNodes) { if (flood.isMarked(node)) { - System.out.print("offending node path:"); + TTY.print("offending node path:"); Node current = node; while (current != null) { - System.out.println(current.toString()); + TTY.println(current.toString()); current = path.get(current); if (current != null && current instanceof FixedNode && !obsoleteNodes.contains(current)) { break; diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Sat Apr 20 12:23:29 2013 +0200 @@ -46,6 +46,7 @@ import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.BlockState.ReadCacheEntry; +import com.oracle.graal.virtual.phases.ea.EffectList.Effect; class PartialEscapeClosure extends BlockIteratorClosure { @@ -65,7 +66,8 @@ private final NodeBitMap usages; private final SchedulePhase schedule; - private final GraphEffectList effects = new GraphEffectList(); + private final BlockMap blockEffects; + private final IdentityHashMap loopMergeEffects = new IdentityHashMap<>(); private final VirtualizerToolImpl tool; @@ -76,19 +78,57 @@ public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider metaAccess, Assumptions assumptions) { this.usages = usages; this.schedule = schedule; - tool = new VirtualizerToolImpl(effects, usages, metaAccess, assumptions); + this.tool = new VirtualizerToolImpl(usages, metaAccess, assumptions); + this.blockEffects = new BlockMap<>(schedule.getCFG()); + for (Block block : schedule.getCFG().getBlocks()) { + blockEffects.put(block, new GraphEffectList()); + } } public boolean hasChanged() { return changed; } - public GraphEffectList getEffects() { - return effects; - } + public List applyEffects(final StructuredGraph graph) { + final ArrayList obsoleteNodes = new ArrayList<>(); + BlockIteratorClosure closure = new BlockIteratorClosure() { + + private void apply(GraphEffectList effects, Object context) { + if (!effects.isEmpty()) { + Debug.log(" ==== effects for %s", context); + for (Effect effect : effects) { + effect.apply(graph, obsoleteNodes); + if (effect.isVisible()) { + Debug.log(" %s", effect); + } + } + } + } - public int getNewVirtualObjectCount() { - return tool.getNewVirtualObjectCount(); + @Override + protected void processBlock(Block block, Object currentState) { + apply(blockEffects.get(block), block); + } + + @Override + protected Object merge(Block merge, List states) { + return new Object(); + } + + @Override + protected Object cloneState(Object oldState) { + return oldState; + } + + @Override + protected List processLoop(Loop loop, Object initialState) { + LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, initialState); + apply(loopMergeEffects.get(loop), loop); + return info.exitStates; + } + }; + ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new Object(), null); + return obsoleteNodes; } public Map getHints() { @@ -97,6 +137,9 @@ @Override protected void processBlock(Block block, BlockState state) { + GraphEffectList effects = blockEffects.get(block); + tool.setEffects(effects); + trace("\nBlock: %s (", block); List nodeList = schedule.getBlockToNodesMap().get(block); @@ -105,7 +148,7 @@ boolean deleted; if (usages.isMarked(node) || node instanceof VirtualizableAllocation) { trace("[[%s]] ", node); - deleted = processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state); + deleted = processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state, effects); } else { trace("%s ", node); deleted = false; @@ -119,7 +162,6 @@ state.killReadCache(store.field()); if (cachedValue == store.value()) { - effects.addCounterBefore("store elim", 1, false, lastFixedNode.next()); effects.deleteFixedNode(store); changed = true; } else { @@ -130,7 +172,6 @@ ValueNode cachedValue = state.getReadCache(load.object(), load.field()); if (cachedValue != null) { METRIC_LOADFIELD_ELIMINATED.increment(); - effects.addCounterBefore("load elim", 1, false, lastFixedNode.next()); effects.replaceAtUsages(load, cachedValue); state.addScalarAlias(load, cachedValue); changed = true; @@ -154,7 +195,7 @@ trace(")\n end state: %s\n", state); } - private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockState state) { + private boolean processNode(final ValueNode node, FixedNode insertBefore, final BlockState state, final GraphEffectList effects) { tool.reset(state, node); if (node instanceof Virtualizable) { ((Virtualizable) node).virtualize(tool); @@ -250,13 +291,13 @@ hints.put(invoke, 5d); } trace("replacing input %s at %s: %s", input, node, obj); - replaceWithMaterialized(input, node, insertBefore, state, obj, METRIC_MATERIALIZATIONS_UNHANDLED); + replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED); } } return false; } - private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, DebugMetric metric) { + private static void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore, GraphEffectList effects, DebugMetric metric) { assert obj != null; if (obj.getState() == EscapeState.Virtual) { metric.increment(); @@ -267,34 +308,204 @@ assert !obj.isVirtual(); } - private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, DebugMetric metric) { - ensureMaterialized(state, obj, materializeBefore, metric); + private static void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj, GraphEffectList effects, DebugMetric metric) { + ensureMaterialized(state, obj, materializeBefore, effects, metric); effects.replaceFirstInput(usage, value, obj.getMaterializedValue()); } @Override - protected BlockState merge(MergeNode merge, List states) { - BlockState newState = BlockState.meetAliases(states); + protected BlockState merge(Block merge, List states) { + assert blockEffects.get(merge).isEmpty(); + MergeProcessor processor = new MergeProcessor(merge, usages, blockEffects); + processor.merge(states); + blockEffects.get(merge).addAll(processor.mergeEffects); + blockEffects.get(merge).addAll(processor.afterMergeEffects); + return processor.newState; + + } + + @Override + protected BlockState cloneState(BlockState oldState) { + return oldState.cloneState(); + } + + @Override + protected List processLoop(Loop loop, BlockState initialState) { + BlockState loopEntryState = initialState; + BlockState lastMergedState = initialState; + MergeProcessor mergeProcessor = new MergeProcessor(loop.header, usages, blockEffects); + for (int iteration = 0; iteration < 10; iteration++) { + LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, lastMergedState.cloneState()); + + List states = new ArrayList<>(); + states.add(initialState); + states.addAll(info.endStates); + mergeProcessor.merge(states); - // Iterative processing: - // Merging the materialized/virtual state of virtual objects can lead to new - // materializations, which can - // lead to new materializations because of phis, and so on. + Debug.log("================== %s", loop.header); + Debug.log("%s", mergeProcessor.newState); + Debug.log("===== vs."); + Debug.log("%s", lastMergedState); + + if (mergeProcessor.newState.equivalentTo(lastMergedState)) { + blockEffects.get(loop.header).insertAll(mergeProcessor.mergeEffects, 0); + loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects); + + assert info.exitStates.size() == loop.exits.size(); + for (int i = 0; i < loop.exits.size(); i++) { + BlockState exitState = info.exitStates.get(i); + assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header; + processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), loopEntryState, exitState, blockEffects.get(loop.exits.get(i))); + } + + return info.exitStates; + } else { + lastMergedState = mergeProcessor.newState; + for (Block block : loop.blocks) { + blockEffects.get(block).clear(); + } + } + } + throw new GraalInternalError("too many iterations at %s", loop); + } + + private static void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState, GraphEffectList effects) { + HashMap proxies = new HashMap<>(); - boolean materialized; - do { - materialized = false; - // use a hash set to make the values distinct... - for (VirtualObjectNode object : newState.getVirtualObjects()) { - ObjectState resultState = newState.getObjectStateOptional(object); - if (resultState == null || resultState.isVirtual()) { + for (ProxyNode proxy : exitNode.proxies()) { + ObjectState obj = exitState.getObjectState(proxy.value()); + if (obj != null) { + proxies.put(obj.virtual, proxy); + } + } + for (ObjectState obj : exitState.getStates()) { + ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual); + if (obj.isVirtual()) { + for (int i = 0; i < obj.getEntries().length; i++) { + ValueNode value = obj.getEntry(i); + ObjectState valueObj = exitState.getObjectState(value); + if (valueObj == null) { + if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) { + ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null); + obj.setEntry(i, proxy); + effects.addFloatingNode(proxy, "virtualProxy"); + } + } + } + } else { + if (initialObj == null || initialObj.isVirtual()) { + ProxyNode proxy = proxies.get(obj.virtual); + if (proxy == null) { + proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value, null); + effects.addFloatingNode(proxy, "proxy"); + } else { + effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue()); + // nothing to do - will be handled in processNode + } + obj.updateMaterializedValue(proxy); + } else { + if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) { + Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode); + } + } + } + } + + for (Map.Entry entry : exitState.getReadCache().entrySet()) { + if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) { + ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null); + effects.addFloatingNode(proxy, "readCacheProxy"); + entry.setValue(proxy); + } + } + } + + private static class MergeProcessor { + + private final Block mergeBlock; + private final MergeNode merge; + private final NodeBitMap usages; + private final BlockMap blockEffects; + private final GraphEffectList mergeEffects; + private final GraphEffectList afterMergeEffects; + + private final HashMap materializedPhis = new HashMap<>(); + private final IdentityHashMap valuePhis = new IdentityHashMap<>(); + private final IdentityHashMap valueObjectMergePhis = new IdentityHashMap<>(); + private final IdentityHashMap valueObjectVirtuals = new IdentityHashMap<>(); + private BlockState newState; + + public MergeProcessor(Block mergeBlock, NodeBitMap usages, BlockMap blockEffects) { + this.usages = usages; + this.mergeBlock = mergeBlock; + this.blockEffects = blockEffects; + this.merge = (MergeNode) mergeBlock.getBeginNode(); + this.mergeEffects = new GraphEffectList(); + this.afterMergeEffects = new GraphEffectList(); + } + + private PhiNode getCachedPhi(T virtual, Kind kind) { + PhiNode result = materializedPhis.get(virtual); + if (result == null) { + result = new PhiNode(kind, merge); + materializedPhis.put(virtual, result); + } + return result; + } + + private PhiNode[] getValuePhis(VirtualObjectNode virtual) { + PhiNode[] result = valuePhis.get(virtual); + if (result == null) { + result = new PhiNode[virtual.entryCount()]; + valuePhis.put(virtual, result); + } + return result; + } + + private PhiNode[] getValueObjectMergePhis(PhiNode phi, int entryCount) { + PhiNode[] result = valueObjectMergePhis.get(phi); + if (result == null) { + result = new PhiNode[entryCount]; + valueObjectMergePhis.put(phi, result); + } + return result; + } + + private VirtualObjectNode getValueObjectVirtual(PhiNode phi, VirtualObjectNode virtual) { + VirtualObjectNode result = valueObjectVirtuals.get(phi); + if (result == null) { + result = virtual.duplicate(); + valueObjectVirtuals.put(phi, result); + } + return result; + } + + private void merge(List states) { + newState = BlockState.meetAliases(states); + + /* + * Iterative processing: Merging the materialized/virtual state of virtual objects can + * lead to new materializations, which can lead to new materializations because of phis, + * and so on. + */ + + HashSet virtualObjects = new HashSet<>(newState.getVirtualObjects()); + boolean materialized; + do { + mergeEffects.clear(); + afterMergeEffects.clear(); + materialized = false; + for (VirtualObjectNode object : virtualObjects) { + ObjectState[] objStates = new ObjectState[states.size()]; + for (int i = 0; i < states.size(); i++) { + objStates[i] = states.get(i).getObjectState(object); + } int virtual = 0; - ObjectState startObj = states.get(0).getObjectState(object); + ObjectState startObj = objStates[0]; int lockCount = startObj.getLockCount(); boolean locksMatch = true; ValueNode singleValue = startObj.isVirtual() ? null : startObj.getMaterializedValue(); - for (BlockState state : states) { - ObjectState obj = state.getObjectState(object); + for (ObjectState obj : objStates) { if (obj.isVirtual()) { virtual++; singleValue = null; @@ -310,14 +521,15 @@ if (virtual < states.size()) { if (singleValue == null) { - PhiNode materializedValuePhi = new PhiNode(Kind.Object, merge); - effects.addFloatingNode(materializedValuePhi); + PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object); + mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi"); for (int i = 0; i < states.size(); i++) { BlockState state = states.get(i); - ObjectState obj = state.getObjectState(object); + ObjectState obj = objStates[i]; materialized |= obj.isVirtual(); - ensureMaterialized(state, obj, merge.forwardEndAt(i), METRIC_MATERIALIZATIONS_MERGE); - effects.addPhiInput(materializedValuePhi, obj.getMaterializedValue()); + Block predecessor = mergeBlock.getPredecessors().get(i); + ensureMaterialized(state, obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE); + afterMergeEffects.addPhiInput(materializedValuePhi, obj.getMaterializedValue()); } newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Global, lockCount)); } else { @@ -326,428 +538,188 @@ } else { assert virtual == states.size(); ValueNode[] values = startObj.getEntries().clone(); - PhiNode[] phis = new PhiNode[values.length]; - int mismatch = 0; - for (int i = 1; i < states.size(); i++) { - BlockState state = states.get(i); - ValueNode[] fields = state.getObjectState(object).getEntries(); - for (int index = 0; index < values.length; index++) { + PhiNode[] phis = getValuePhis(object); + for (int index = 0; index < values.length; index++) { + for (int i = 1; i < states.size(); i++) { + ValueNode[] fields = objStates[i].getEntries(); if (phis[index] == null && values[index] != fields[index]) { - mismatch++; phis[index] = new PhiNode(values[index].kind(), merge); - effects.addFloatingNode(phis[index]); } } } - if (mismatch > 0) { - for (int i = 0; i < states.size(); i++) { - BlockState state = states.get(i); - ValueNode[] fields = state.getObjectState(object).getEntries(); - for (int index = 0; index < values.length; index++) { - if (phis[index] != null) { - ObjectState obj = state.getObjectState(fields[index]); - if (obj != null) { - materialized |= obj.isVirtual(); - ensureMaterialized(state, obj, merge.forwardEndAt(i), METRIC_MATERIALIZATIONS_MERGE); - fields[index] = obj.getMaterializedValue(); - } - effects.addPhiInput(phis[index], fields[index]); + outer: for (int index = 0; index < values.length; index++) { + if (phis[index] != null) { + mergeEffects.addFloatingNode(phis[index], "virtualMergePhi"); + for (int i = 0; i < states.size(); i++) { + if (!objStates[i].isVirtual()) { + break outer; } + ValueNode[] fields = objStates[i].getEntries(); + ObjectState obj = states.get(i).getObjectState(fields[index]); + if (obj != null) { + materialized |= obj.isVirtual(); + Block predecessor = mergeBlock.getPredecessors().get(i); + ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE); + fields[index] = obj.getMaterializedValue(); + } + afterMergeEffects.addPhiInput(phis[index], fields[index]); } - } - for (int index = 0; index < values.length; index++) { - if (phis[index] != null) { - values[index] = phis[index]; - } + values[index] = phis[index]; } } newState.addObject(object, new ObjectState(object, values, EscapeState.Virtual, lockCount)); } } - } - - for (PhiNode phi : merge.phis()) { - if (usages.isMarked(phi) && phi.type() == PhiType.Value) { - materialized |= processPhi(newState, merge, phi, states); - } - } - } while (materialized); - - newState.mergeReadCache(states, merge, effects); - - return newState; - } - private boolean processPhi(BlockState newState, MergeNode merge, PhiNode phi, List states) { - assert states.size() == phi.valueCount(); - int virtualInputs = 0; - boolean materialized = false; - VirtualObjectNode sameObject = null; - ResolvedJavaType sameType = null; - int sameEntryCount = -1; - for (int i = 0; i < phi.valueCount(); i++) { - ValueNode value = phi.valueAt(i); - ObjectState obj = states.get(i).getObjectState(value); - if (obj != null) { - if (obj.isVirtual()) { - virtualInputs++; - if (i == 0) { - sameObject = obj.virtual; - sameType = obj.virtual.type(); - sameEntryCount = obj.virtual.entryCount(); - } else { - if (sameObject != obj.virtual) { - sameObject = null; - } - if (sameType != obj.virtual.type()) { - sameType = null; - } - if (sameEntryCount != obj.virtual.entryCount()) { - sameEntryCount = -1; - } + for (PhiNode phi : merge.phis()) { + if (usages.isMarked(phi) && phi.type() == PhiType.Value) { + materialized |= processPhi(phi, states); } - } else { - effects.setPhiInput(phi, i, obj.getMaterializedValue()); } - } - } - boolean materialize = false; - if (virtualInputs == 0) { - // nothing to do... - } else if (virtualInputs == phi.valueCount()) { - if (sameObject != null) { - newState.addAndMarkAlias(sameObject, phi, usages); - } else if (sameType != null && sameEntryCount != -1) { - materialize = true; - // throw new GraalInternalError("merge required for %s", sameType); - } else { - materialize = true; - } - } else { - materialize = true; + } while (materialized); + + mergeReadCache(states); } - if (materialize) { + private boolean processPhi(PhiNode phi, List states) { + assert states.size() == phi.valueCount(); + int virtualInputs = 0; + boolean materialized = false; + VirtualObjectNode sameObject = null; + ResolvedJavaType sameType = null; + int sameEntryCount = -1; + boolean hasIdentity = false; for (int i = 0; i < phi.valueCount(); i++) { ValueNode value = phi.valueAt(i); ObjectState obj = states.get(i).getObjectState(value); if (obj != null) { - materialized |= obj.isVirtual(); - replaceWithMaterialized(value, phi, merge.forwardEndAt(i), states.get(i), obj, METRIC_MATERIALIZATIONS_PHI); - } - } - } - return materialized; - } - - @Override - protected BlockState cloneState(BlockState oldState) { - return oldState.cloneState(); - } - - @Override - protected List processLoop(Loop loop, BlockState initialState) { - GraphEffectList successEffects = new GraphEffectList(); - HashSet phis = new HashSet<>(); - for (int iteration = 0; iteration < 10; iteration++) { - BlockState state = initialState.cloneState(); - int checkpoint = effects.checkpoint(); - - for (PhiDesc desc : phis) { - ObjectState obj = state.getObjectState(desc.virtualObject); - if (obj.isVirtual()) { - ValueNode value = obj.getEntry(desc.fieldIndex); - ObjectState valueObj = state.getObjectState(value); - if (valueObj != null) { - assert !valueObj.isVirtual(); - value = valueObj.getMaterializedValue(); - } - - PhiNode phiNode = new PhiNode(value.kind(), loop.loopBegin()); - effects.addFloatingNode(phiNode); - effects.addPhiInput(phiNode, value); - obj.setEntry(desc.fieldIndex, phiNode); - } - } - - for (PhiNode phi : loop.loopBegin().phis()) { - if (usages.isMarked(phi) && phi.type() == PhiType.Value) { - ObjectState initialObj = initialState.getObjectState(phi.valueAt(0)); - if (initialObj != null) { - if (initialObj.isVirtual()) { - state.addAndMarkAlias(initialObj.virtual, phi, usages); + if (obj.isVirtual()) { + virtualInputs++; + if (i == 0) { + sameObject = obj.virtual; + sameType = obj.virtual.type(); + sameEntryCount = obj.virtual.entryCount(); } else { - successEffects.setPhiInput(phi, 0, initialObj.getMaterializedValue()); + if (sameObject != obj.virtual) { + sameObject = null; + } + if (sameType != obj.virtual.type()) { + sameType = null; + } + if (sameEntryCount != obj.virtual.entryCount()) { + sameEntryCount = -1; + } + hasIdentity |= obj.virtual.hasIdentity(); } + } else { + afterMergeEffects.setPhiInput(phi, i, obj.getMaterializedValue()); } } } - - effects.incLevel(); - LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, state.cloneState()); - - List loopEndStates = info.endStates; - List predecessors = loop.header.getPredecessors(); - HashSet additionalMaterializations = new HashSet<>(); - HashSet additionalKilledReads = new HashSet<>(); - int oldPhiCount = phis.size(); - for (int i = 1; i < predecessors.size(); i++) { - processLoopEnd(loop.loopBegin(), (LoopEndNode) predecessors.get(i).getEndNode(), state, loopEndStates.get(i - 1), successEffects, additionalMaterializations, additionalKilledReads, - phis); - } - if (additionalMaterializations.isEmpty() && additionalKilledReads.isEmpty() && oldPhiCount == phis.size()) { - effects.addAll(successEffects); + boolean materialize = false; + if (virtualInputs == 0) { + // nothing to do... + } else if (virtualInputs == phi.valueCount()) { + if (sameObject != null) { + newState.addAndMarkAlias(sameObject, phi, usages); + } else if (sameType != null && sameEntryCount != -1) { + if (!hasIdentity) { + VirtualObjectNode virtual = getValueObjectVirtual(phi, states.get(0).getObjectState(phi.valueAt(0)).virtual); - assert info.exitStates.size() == loop.exits.size(); - for (int i = 0; i < loop.exits.size(); i++) { - BlockState exitState = info.exitStates.get(i); - assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header; - processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), state, exitState); + PhiNode[] phis = getValueObjectMergePhis(phi, virtual.entryCount()); + for (int i = 0; i < virtual.entryCount(); i++) { + assert virtual.entryKind(i) != Kind.Object; + if (phis[i] == null) { + phis[i] = new PhiNode(virtual.entryKind(i), merge); + } + mergeEffects.addFloatingNode(phis[i], "valueObjectPhi"); + for (int i2 = 0; i2 < phi.valueCount(); i2++) { + afterMergeEffects.addPhiInput(phis[i], states.get(i2).getObjectState(phi.valueAt(i2)).getEntry(i)); + } + } + mergeEffects.addFloatingNode(virtual, "valueObjectNode"); + newState.addObject(virtual, new ObjectState(virtual, Arrays.copyOf(phis, phis.length, ValueNode[].class), EscapeState.Virtual, 0)); + newState.addAndMarkAlias(virtual, virtual, usages); + newState.addAndMarkAlias(virtual, phi, usages); + } else { + materialize = true; + } + } else { + materialize = true; } - - effects.decLevel(); - return info.exitStates; } else { - successEffects.clear(); - effects.backtrack(checkpoint); - effects.decLevel(); - for (VirtualObjectNode virtualObject : additionalMaterializations) { - ObjectState obj = initialState.getObjectState(virtualObject); - if (obj.isVirtual()) { - METRIC_MATERIALIZATIONS_LOOP_REITERATION.increment(); - initialState.materializeBefore(loop.loopBegin().forwardEnd(), virtualObject, EscapeState.Global, effects); - } else { - assert obj.getState() == EscapeState.Global; + materialize = true; + } + + if (materialize) { + for (int i = 0; i < phi.valueCount(); i++) { + ValueNode value = phi.valueAt(i); + ObjectState obj = states.get(i).getObjectState(value); + if (obj != null) { + materialized |= obj.isVirtual(); + Block predecessor = mergeBlock.getPredecessors().get(i); + replaceWithMaterialized(value, phi, predecessor.getEndNode(), states.get(i), obj, blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_PHI); } } - for (ReadCacheEntry entry : additionalKilledReads) { - initialState.getReadCache().remove(entry); + } + return materialized; + } + + private void mergeReadCache(List states) { + for (Map.Entry entry : states.get(0).readCache.entrySet()) { + ReadCacheEntry key = entry.getKey(); + ValueNode value = entry.getValue(); + boolean phi = false; + for (int i = 1; i < states.size(); i++) { + ValueNode otherValue = states.get(i).readCache.get(key); + if (otherValue == null) { + value = null; + phi = false; + break; + } + if (!phi && otherValue != value) { + phi = true; + } + } + if (phi) { + PhiNode phiNode = getCachedPhi(entry, value.kind()); + mergeEffects.addFloatingNode(phiNode, "mergeReadCache"); + for (int i = 0; i < states.size(); i++) { + afterMergeEffects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity)); + } + newState.readCache.put(key, phiNode); + } else if (value != null) { + newState.readCache.put(key, value); + } + } + for (PhiNode phi : merge.phis()) { + if (phi.kind() == Kind.Object) { + for (Map.Entry entry : states.get(0).readCache.entrySet()) { + if (entry.getKey().object == phi.valueAt(0)) { + mergeReadCachePhi(phi, entry.getKey().identity, states); + } + } + } } } - throw new GraalInternalError("too many iterations at %s", loop); - } - - private void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState) { - HashMap proxies = new HashMap<>(); - - for (ProxyNode proxy : exitNode.proxies()) { - ObjectState obj = exitState.getObjectState(proxy.value()); - if (obj != null) { - proxies.put(obj.virtual, proxy); - } - } - for (ObjectState obj : exitState.getStates()) { - ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual); - if (obj.isVirtual()) { - for (int i = 0; i < obj.getEntries().length; i++) { - ValueNode value = obj.getEntry(i); - ObjectState valueObj = exitState.getObjectState(value); - if (valueObj == null) { - if ((value instanceof PhiNode && ((PhiNode) value).merge() == exitNode.loopBegin()) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) { - ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null); - obj.setEntry(i, proxy); - effects.addFloatingNode(proxy); - } - } + private void mergeReadCachePhi(PhiNode phi, Object identity, List states) { + ValueNode[] values = new ValueNode[phi.valueCount()]; + for (int i = 0; i < phi.valueCount(); i++) { + ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity); + if (value == null) { + return; } - } else { - if (initialObj == null || initialObj.isVirtual()) { - ProxyNode proxy = proxies.get(obj.virtual); - if (proxy == null) { - proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value, null); - effects.addFloatingNode(proxy); - } else { - effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue()); - // nothing to do - will be handled in processNode - } - obj.updateMaterializedValue(proxy); - } else { - assert initialObj.getMaterializedValue() == obj.getMaterializedValue() : "materialized value is not allowed to change within loops: " + initialObj.getMaterializedValue() + - " vs. " + obj.getMaterializedValue() + " at " + exitNode; - } - } - } - - for (Map.Entry entry : exitState.getReadCache().entrySet()) { - if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) { - ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null); - effects.addFloatingNode(proxy); - entry.setValue(proxy); + values[i] = value; } - } - } - - private final class PhiDesc { - - public final VirtualObjectNode virtualObject; - public final int fieldIndex; - - public PhiDesc(VirtualObjectNode virtualObject, int fieldIndex) { - this.virtualObject = virtualObject; - this.fieldIndex = fieldIndex; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = fieldIndex; - result = prime * result + ((virtualObject == null) ? 0 : virtualObject.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - PhiDesc other = (PhiDesc) obj; - return virtualObject == other.virtualObject && fieldIndex == other.fieldIndex; - } - } - - private void processLoopEnd(LoopBeginNode loopBegin, LoopEndNode loopEnd, BlockState initialState, BlockState loopEndState, GraphEffectList successEffects, - Set additionalMaterializations, HashSet additionalKilledReads, HashSet phis) { - assert loopEnd.loopBegin() == loopBegin; - boolean materialized; - do { - materialized = false; - for (ObjectState state : initialState.getStates()) { - ObjectState endState = loopEndState.getObjectState(state.virtual); - if (state.isVirtual()) { - if (endState.isVirtual()) { - assert state.getEntries().length == endState.getEntries().length; - for (int i = 0; endState.isVirtual() && i < state.getEntries().length; i++) { - ValueNode value = state.getEntry(i); - ValueNode endValue = endState.getEntry(i); - ObjectState valueObj = initialState.getObjectState(value); - ObjectState endValueObj = loopEndState.getObjectState(endValue); - if (valueObj != null) { - if (valueObj.isVirtual()) { - if (endValueObj == null || !endValueObj.isVirtual() || valueObj.virtual != endValueObj.virtual) { - additionalMaterializations.add(valueObj.virtual); - } else { - // endValue is also virtual and refers to the same virtual - // object, so we're - // good. - } - } - } else { - if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) { - if (endValueObj != null) { - if (endValueObj.isVirtual()) { - METRIC_MATERIALIZATIONS_LOOP_END.increment(); - loopEndState.materializeBefore(loopEnd, endValueObj.virtual, EscapeState.Global, successEffects); - materialized = true; - } - } - } - } - } - } else { - additionalMaterializations.add(state.virtual); - } - } - } - for (PhiNode phi : loopBegin.phis()) { - if (usages.isMarked(phi) && phi.type() == PhiType.Value) { - ObjectState initialObj = initialState.getObjectState(phi.valueAt(0)); - boolean initialMaterialized = initialObj == null || !initialObj.isVirtual(); - - ObjectState loopEndObj = loopEndState.getObjectState(phi.valueAt(loopEnd)); - if (loopEndObj == null || !loopEndObj.isVirtual()) { - if (loopEndObj != null) { - successEffects.setPhiInput(phi, loopBegin.phiPredecessorIndex(loopEnd), loopEndObj.getMaterializedValue()); - } - if (!initialMaterialized) { - additionalMaterializations.add(initialObj.virtual); - } - } else { - if (initialMaterialized) { - loopEndState.materializeBefore(loopEnd, loopEndObj.virtual, EscapeState.Global, successEffects); - materialized = true; - } else { - if (loopEndObj.virtual != initialObj.virtual) { - additionalMaterializations.add(initialObj.virtual); - } - } - } - } + PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].kind()); + mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi"); + for (int i = 0; i < values.length; i++) { + afterMergeEffects.addPhiInput(phiNode, values[i]); } - } while (materialized); - - for (ObjectState state : initialState.getStates()) { - ObjectState endState = loopEndState.getObjectState(state.virtual); - if (state.isVirtual()) { - if (endState.isVirtual()) { - assert state.getEntries().length == endState.getEntries().length; - for (int i = 0; i < state.getEntries().length; i++) { - ValueNode value = state.getEntry(i); - ValueNode endValue = endState.getEntry(i); - ObjectState valueObj = initialState.getObjectState(value); - ObjectState endValueObj = loopEndState.getObjectState(endValue); - - if (valueObj != null) { - if (valueObj.isVirtual()) { - if (endValueObj == null || !endValueObj.isVirtual() || valueObj.virtual != endValueObj.virtual) { - assert !additionalMaterializations.isEmpty(); - } else { - // endValue is also virtual and refers to the same virtual - // object, so we're - // good. - } - } else { - if ((endValueObj != null && endValueObj.getMaterializedValue() != valueObj.getMaterializedValue()) || - (endValueObj == null && valueObj.getMaterializedValue() != endValue)) { - phis.add(new PhiDesc(state.virtual, i)); - } else { - // either endValue has the same materialized value as value or - // endValue is the - // same as the materialized value, so we're good. - } - } - } else { - if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) { - if (endValueObj != null) { - if (endValueObj.isVirtual()) { - assert !additionalMaterializations.isEmpty(); - } - successEffects.addPhiInput((PhiNode) value, endValueObj.getMaterializedValue()); - } else { - successEffects.addPhiInput((PhiNode) value, endValue); - } - } else if (value != endValue) { - phis.add(new PhiDesc(state.virtual, i)); - } - } - } - } else { - // endState.materializedValue != null - assert !additionalMaterializations.isEmpty(); - } - } else { - // state.materializedValue != null - if (endState.isVirtual()) { - // throw new GraalInternalError("un-materialized object state at %s", loopEnd); - } else { - if (state.getMaterializedValue() != endState.getMaterializedValue()) { - // throw new - // GraalInternalError("changed materialized value during loop: %s vs %s", - // state.materializedValue, endState.materializedValue); - } - } - } - } - - for (Map.Entry entry : initialState.getReadCache().entrySet()) { - if (loopEndState.getReadCache().get(entry.getKey()) != entry.getValue()) { - additionalKilledReads.add(entry.getKey()); - } + newState.readCache.put(new ReadCacheEntry(identity, phi), phiNode); } } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Sat Apr 20 12:23:29 2013 +0200 @@ -36,13 +36,12 @@ class VirtualizerToolImpl implements VirtualizerTool { - private final GraphEffectList effects; private final NodeBitMap usages; private final MetaAccessProvider metaAccess; private final Assumptions assumptions; + private GraphEffectList effects; - VirtualizerToolImpl(GraphEffectList effects, NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) { - this.effects = effects; + VirtualizerToolImpl(NodeBitMap usages, MetaAccessProvider metaAccess, Assumptions assumptions) { this.usages = usages; this.metaAccess = metaAccess; this.assumptions = assumptions; @@ -52,7 +51,6 @@ private boolean customAction; private BlockState state; private ValueNode current; - private int newVirtualObjectCount = 0; @Override public MetaAccessProvider getMetaAccessProvider() { @@ -64,6 +62,10 @@ return assumptions; } + public void setEffects(GraphEffectList effects) { + this.effects = effects; + } + public void reset(BlockState newState, ValueNode newCurrent) { deleted = false; customAction = false; @@ -79,10 +81,6 @@ return customAction; } - public int getNewVirtualObjectCount() { - return newVirtualObjectCount; - } - @Override public State getObjectState(ValueNode value) { return state.getObjectState(value); @@ -155,7 +153,7 @@ if (virtualObject.isAlive()) { state.addAndMarkAlias(virtualObject, virtualObject, usages); } else { - effects.addFloatingNode(virtualObject); + effects.addFloatingNode(virtualObject, "newVirtualObject"); } for (int i = 0; i < entryState.length; i++) { entryState[i] = state.getScalarAlias(entryState[i]); @@ -163,7 +161,6 @@ state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, lockCount)); state.addAndMarkAlias(virtualObject, virtualObject, usages); PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment(); - newVirtualObjectCount++; } @Override diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.extended.WriteNode.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @@ -183,7 +184,7 @@ case TO_OBJECT: assert arguments.size() == 1; - replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.node().stamp()))); + replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.asNode().stamp()))); break; default: @@ -227,7 +228,7 @@ Constructor constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class); ValueNode result = graph.add(constructor.newInstance(wordKind, left, right)); if (result instanceof FixedWithNextNode) { - graph.addBeforeFixed(invoke.node(), (FixedWithNextNode) result); + graph.addBeforeFixed(invoke.asNode(), (FixedWithNextNode) result); } return result; } catch (Throwable ex) { @@ -267,28 +268,28 @@ private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Kind readKind, Object locationIdentity) { IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1); - ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp())); - graph.addBeforeFixed(invoke.node(), read); + ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp())); + graph.addBeforeFixed(invoke.asNode(), read); // The read must not float outside its block otherwise it may float above an explicit zero // check on its base address - read.dependencies().add(BeginNode.prevBegin(invoke.node())); + read.dependencies().add(BeginNode.prevBegin(invoke.asNode())); return read; } private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Kind writeKind, Object locationIdentity) { IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, writeKind, 0, offset, graph, 1); - WriteNode write = graph.add(new WriteNode(base, value, location)); + WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE)); write.setStateAfter(invoke.stateAfter()); - graph.addBeforeFixed(invoke.node(), write); + graph.addBeforeFixed(invoke.asNode(), write); return write; } private static void replace(Invoke invoke, ValueNode value) { FixedNode next = invoke.next(); invoke.setNext(null); - invoke.node().replaceAtPredecessor(next); - invoke.node().replaceAtUsages(value); - GraphUtil.killCFG(invoke.node()); + invoke.asNode().replaceAtPredecessor(next); + invoke.asNode().replaceAtUsages(value); + GraphUtil.killCFG(invoke.asNode()); } public boolean isWord(ValueNode node) { diff -r b69312e4eceb -r 9d29e5aa54d2 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 Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Sat Apr 20 12:23:29 2013 +0200 @@ -80,9 +80,9 @@ ValueNode receiver = arguments.get(argc); if (receiver == node && isWord(node)) { ResolvedJavaMethod resolvedMethod = wordAccess.getWordImplType().resolveMethod(method); - verify(resolvedMethod != null, node, invoke.node(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method)); + verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method)); Operation operation = resolvedMethod.getAnnotation(Word.Operation.class); - verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); + verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); } argc++; } @@ -91,7 +91,7 @@ ValueNode argument = arguments.get(argc); if (argument == node) { ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); - verify(isWord(type) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); + verify(isWord(type) == isWord(argument), node, invoke.asNode(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); } argc++; } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Sat Apr 20 12:23:29 2013 +0200 @@ -61,7 +61,7 @@ dom = db.newDocument(); } catch (ParserConfigurationException ex) { - System.out.println("Error while trying to instantiate DocumentBuilder " + ex); + throw new RuntimeException(ex); } graphDocument = dom.createElement("graphDocument"); diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java Sat Apr 20 12:23:29 2013 +0200 @@ -103,19 +103,29 @@ return annotations; } - /* Support JDK8 langtools. */ - @SuppressWarnings("unused") + /** + * Support JDK8 langtools. + * + * @param annotationType + */ public A[] getAnnotationsByType(Class annotationType) { throw new UnsupportedOperationException(); } - /* Support for some JDK8 builds. (remove after jdk8 is released) */ - @SuppressWarnings("unused") + /** + * Support for some JDK8 builds. (remove after jdk8 is released) + * + * @param annotationType + */ public A[] getAnnotations(Class annotationType) { throw new UnsupportedOperationException(); } - @Override + /** + * Support for some JDK8 builds. (remove after jdk8 is released) + * + * @param annotationType + */ public A getAnnotation(Class annotationType) { throw new UnsupportedOperationException(); } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Sat Apr 20 12:23:29 2013 +0200 @@ -225,4 +225,7 @@ return copy; } + public TypeMirror getReceiverType() { + throw new UnsupportedOperationException(); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Sat Apr 20 12:23:29 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.codegen.processor.ast; +import java.lang.annotation.*; import java.util.*; import javax.lang.model.element.*; @@ -98,4 +99,21 @@ } + public List getAnnotationMirrors() { + throw new UnsupportedOperationException(); + } + + /** + * @param annotationType + */ + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException(); + } + + /** + * @param annotationType + */ + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException(); + } } diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Sat Apr 20 12:23:29 2013 +0200 @@ -61,7 +61,6 @@ if (node != null) { String dump = parsed.dump(); log.message(Kind.ERROR, null, null, null, dump); - System.out.println(dump); } } } finally { diff -r b69312e4eceb -r 9d29e5aa54d2 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java Sat Apr 20 12:22:54 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java Sat Apr 20 12:23:29 2013 +0200 @@ -37,7 +37,9 @@ public static void run(InputStream input, PrintStream printOutput, int repeats, boolean log) { if (log) { + // CheckStyle: stop system..print check System.out.printf("== running on %s\n", Truffle.getRuntime().getName()); + // CheckStyle: resume system..print check } NodeFactory factory = new NodeFactory(printOutput); @@ -63,7 +65,9 @@ printOutput.println(result); } if (log) { + // CheckStyle: stop system..print check System.out.printf("== iteration %d: %.3f ms\n", (i + 1), (end - start) / 1000000.0); + // CheckStyle: resume system..print check } } diff -r b69312e4eceb -r 9d29e5aa54d2 make/Makefile --- a/make/Makefile Sat Apr 20 12:22:54 2013 +0200 +++ b/make/Makefile Sat Apr 20 12:23:29 2013 +0200 @@ -19,7 +19,7 @@ # 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. -# +# # # Top level gnumake file for hotspot builds @@ -86,18 +86,19 @@ # Directory for shared code (e.g. graal.jar) SHARED_DIR=$(OUTPUTDIR)/shared +BUILD_GRAAL_JAR ?= true # Typical C1/C2 targets made available with this Makefile -C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1 -C2_VM_TARGETS=product fastdebug optimized jvmg -ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero jvmgzero -SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark jvmgshark -MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 jvmgminimal1 -GRAAL_VM_TARGETS=productgraal fastdebuggraal optimizedgraal jvmggraal +C1_VM_TARGETS=product1 fastdebug1 optimized1 debug1 +C2_VM_TARGETS=product fastdebug optimized debug +ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero debugzero +SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark debugshark +MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 debugminimal1 +GRAAL_VM_TARGETS=productgraal fastdebuggraal optimizedgraal debuggraal COMMON_VM_PRODUCT_TARGETS=product product1 docs export_product COMMON_VM_FASTDEBUG_TARGETS=fastdebug fastdebug1 docs export_fastdebug -COMMON_VM_DEBUG_TARGETS=jvmg jvmg1 docs export_debug +COMMON_VM_DEBUG_TARGETS=debug debug1 docs export_debug # JDK directory list JDK_DIRS=bin include jre lib demo @@ -107,13 +108,13 @@ ifeq ($(JVM_VARIANT_MINIMAL1),true) all_product: productminimal1 all_fastdebug: fastdebugminimal1 -all_debug: jvmgminimal1 +all_debug: debugminimal1 endif ifdef BUILD_CLIENT_ONLY all_product: product1 docs export_product all_fastdebug: fastdebug1 docs export_fastdebug -all_debug: jvmg1 docs export_debug +all_debug: debug1 docs export_debug else ifeq ($(MACOSX_UNIVERSAL),true) all_product: universal_product @@ -131,19 +132,19 @@ allzero: all_productzero all_fastdebugzero all_productzero: productzero docs export_product all_fastdebugzero: fastdebugzero docs export_fastdebug -all_debugzero: jvmgzero docs export_debug +all_debugzero: debugzero docs export_debug all_optimizedzero: optimizedzero docs export_optimized allshark: all_productshark all_fastdebugshark all_productshark: productshark docs export_product all_fastdebugshark: fastdebugshark docs export_fastdebug -all_debugshark: jvmgshark docs export_debug +all_debugshark: debugshark docs export_debug all_optimizedshark: optimizedshark docs export_optimized allgraal: all_productgraal all_fastdebuggraal all_productgraal: productgraal docs export_product all_fastdebuggraal: fastdebuggraal docs export_fastdebug -all_debuggraal: jvmggraal docs export_debug +all_debuggraal: debuggraal docs export_debug all_optimizedgraal: optimizedgraal docs export_optimized # Do everything @@ -238,7 +239,7 @@ $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ $(MAKE) -f $(ABS_OS_MAKEFILE) \ - $(MAKE_ARGS) $(VM_TARGET) + $(MAKE_ARGS) $(VM_TARGET) generic_buildminimal1: ifeq ($(JVM_VARIANT_MINIMAL1),true) @@ -267,9 +268,12 @@ $(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE_ARGS) $(VM_TARGET) + # Builds code that can be shared among different build flavors buildshared: +ifeq ($(BUILD_GRAAL_JAR),true) $(REMOTE) $(ANT) -f $(GAMMADIR)/make/build-graal.xml -Dgamma.dir=$(GAMMADIR) -Dshared.dir=$(SHARED_DIR) +endif # Export file rule generic_export: $(EXPORT_LIST) @@ -281,7 +285,7 @@ EXPORT_SUBDIR=/$(@:export_%=%) \ generic_export export_debug: - $(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=${VM_DEBUG} \ + $(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ EXPORT_SUBDIR=/$(@:export_%=%) \ generic_export export_optimized: @@ -302,7 +306,7 @@ ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) \ generic_export export_debug_jdk:: - $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) VM_SUBDIR=${VM_DEBUG} \ + $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) VM_SUBDIR=$(@:export_%_jdk=%) \ ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) \ generic_export @@ -346,7 +350,7 @@ # Bin files (windows) ifeq ($(OSNAME),windows) -# Get jvm.lib +# Get jvm.lib $(EXPORT_LIB_DIR)/%.lib: $(MISC_DIR)/%.lib $(install-file) @@ -591,11 +595,11 @@ @$(RUN_JVM) -XXaltjvm=$(ALTJVM_DIR) -showversion -help # C2 test targets -test_product test_optimized test_fastdebug test_jvmg: +test_product test_optimized test_fastdebug test_debug: @$(MAKE) generic_test ALTJVM_DIR="$(C2_DIR)/$(@:test_%=%)" # C1 test targets -test_product1 test_optimized1 test_fastdebug1 test_jvmg1: +test_product1 test_optimized1 test_fastdebug1 test_debug1: ifeq ($(ARCH_DATA_MODEL), 32) @$(MAKE) generic_test ALTJVM_DIR="$(C1_DIR)/$(@:test_%1=%)" else @@ -603,15 +607,15 @@ endif # Zero test targets -test_productzero test_optimizedzero test_fastdebugzero test_jvmgzero: +test_productzero test_optimizedzero test_fastdebugzero test_debugzero: @$(MAKE) generic_test ALTJVM_DIR="$(ZERO_DIR)/$(@:test_%zero=%)" # Shark test targets -test_productshark test_optimizedshark test_fastdebugshark test_jvmgshark: +test_productshark test_optimizedshark test_fastdebugshark test_debugshark: @$(MAKE) generic_test ALTJVM_DIR="$(SHARK_DIR)/$(@:test_%shark=%)" # Minimal1 test targets -test_productminimal1 test_optimizedminimal1 test_fastdebugminimal1 test_jvmgminimal1: +test_productminimal1 test_optimizedminimal1 test_fastdebugminimal1 test_debugminimal1: @$(MAKE) generic_test ALTJVM_DIR="$(MINIMAL1_DIR)/$(@:test_%minimal1=%)" @@ -676,7 +680,7 @@ # Intro help message intro_help: @$(ECHO) \ -"Makefile for the Hotspot workspace." +"Makefile for the Hotspot workspace." @$(ECHO) \ "Default behavior is to build and create an export area for the j2se builds." @@ -687,7 +691,7 @@ @$(ECHO) "world: Same as: all create_jdk" @$(ECHO) "all_product: Same as: product product1 export_product" @$(ECHO) "all_fastdebug: Same as: fastdebug fastdebug1 export_fastdebug" - @$(ECHO) "all_debug: Same as: jvmg jvmg1 export_debug" + @$(ECHO) "all_debug: Same as: debug debug1 export_debug" @$(ECHO) "all_optimized: Same as: optimized optimized1 export_optimized" @$(ECHO) "clean: Clean all areas" @$(ECHO) "export_product: Export product files to EXPORT_PATH" @@ -780,7 +784,7 @@ @$(ECHO) \ " $(MAKE) world" @$(ECHO) \ -" $(MAKE) ALT_BOOTDIR=/opt/java/jdk$(PREVIOUS_JDK_VERSION)" +" $(MAKE) ALT_BOOTDIR=/opt/java/jdk$(PREVIOUS_JDK_VERSION)" @$(ECHO) \ " $(MAKE) ALT_JDK_IMPORT_PATH=/opt/java/jdk$(JDK_VERSION)" @@ -791,6 +795,25 @@ endif endif +# Compatibility for transition to new naming +warn_jvmg_deprecated: + echo "Warning: The jvmg target has been replaced with debug" + echo "Warning: Please update your usage" + +jvmg: warn_jvmg_deprecated debug + +jvmg1: warn_jvmg_deprecated debug1 + +jvmgminimal1: warn_jvmg_deprecated debugminimal1 + +jvmgcore: warn_jvmg_deprecated debugcore + +jvmgzero: warn_jvmg_deprecated debugzero + +jvmgshark: warn_jvmg_deprecated debugshark + +jvmggraal: warn_jvmg_deprecated debuggraal + # JPRT rule to build this workspace include $(GAMMADIR)/make/jprt.gmk diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/Makefile --- a/make/bsd/Makefile Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/Makefile Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -142,55 +142,43 @@ # # debug compiler2 __compiler2/debug # fastdebug compiler2 __compiler2/fastdebug -# jvmg compiler2 __compiler2/jvmg # optimized compiler2 __compiler2/optimized -# profiled compiler2 __compiler2/profiled # product compiler2 __compiler2/product # # debug1 compiler1 __compiler1/debug # fastdebug1 compiler1 __compiler1/fastdebug -# jvmg1 compiler1 __compiler1/jvmg # optimized1 compiler1 __compiler1/optimized -# profiled1 compiler1 __compiler1/profiled # product1 compiler1 __compiler1/product # # debugcore core __core/debug # fastdebugcore core __core/fastdebug -# jvmgcore core __core/jvmg # optimizedcore core __core/optimized -# profiledcore core __core/profiled # productcore core __core/product # # debugzero zero __zero/debug # fastdebugzero zero __zero/fastdebug -# jvmgzero zero __zero/jvmg # optimizedzero zero __zero/optimized -# profiledzero zero __zero/profiled # productzero zero __zero/product # # debugshark shark __shark/debug # fastdebugshark shark __shark/fastdebug -# jvmgshark shark __shark/jvmg # optimizedshark shark __shark/optimized -# profiledshark shark __shark/profiled # productshark shark __shark/product # # fastdebugminimal1 minimal1 __minimal1/fastdebug -# jvmgminimal1 minimal1 __minimal1/jvmg +# debugminimal1 minimal1 __minimal1/debug # productminimal1 minimal1 __minimal1/product # # What you get with each target: # -# debug* - "thin" libjvm - debug info linked into the gamma launcher +# debug* - debug compile with asserts enabled # fastdebug* - optimized compile, but with asserts enabled -# jvmg* - "fat" libjvm - debug info linked into libjvm.so # optimized* - optimized compile, no asserts -# profiled* - gprof # product* - the shippable thing: optimized compile, no asserts, -DPRODUCT # This target list needs to be coordinated with the usage message # in the build.sh script: -TARGETS = debug jvmg fastdebug optimized profiled product +TARGETS = debug fastdebug optimized product ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) SUBDIR_DOCS = $(OSNAME)_$(VARIANTARCH)_docs @@ -368,15 +356,29 @@ $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs # Synonyms for win32-like targets. -compiler2: jvmg product +compiler2: debug product + +compiler1: debug1 product1 -compiler1: jvmg1 product1 +core: debugcore productcore + +zero: debugzero productzero + +shark: debugshark productshark -core: jvmgcore productcore +warn_jvmg_deprecated: + echo "Warning: The jvmg target has been replaced with debug" + echo "Warning: Please update your usage" + +jvmg: warn_jvmg_deprecated debug -zero: jvmgzero productzero +jvmg1: warn_jvmg_deprecated debug1 + +jvmgcore: warn_jvmg_deprecated debugcore -shark: jvmgshark productshark +jvmgzero: warn_jvmg_deprecated debugzero + +jvmgshark: warn_jvmg_deprecated debugshark clean_docs: rm -rf $(SUBDIR_DOCS) diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/buildtree.make --- a/make/bsd/makefiles/buildtree.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/makefiles/buildtree.make Sat Apr 20 12:23:29 2013 +0200 @@ -19,7 +19,7 @@ # 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. -# +# # # Usage: @@ -46,11 +46,11 @@ # Makefile - for "make foo" # flags.make - with macro settings # vm.make - to support making "$(MAKE) -v vm.make" in makefiles -# adlc.make - +# adlc.make - # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives # env.[ck]sh - environment settings -# +# # The makefiles are split this way so that "make foo" will run faster by not # having to read the dependency files for the vm. @@ -122,7 +122,7 @@ $(PLATFORM_DIR)/generated/jvmtifiles \ $(PLATFORM_DIR)/generated/dtracefiles -TARGETS = debug fastdebug jvmg optimized product profiled +TARGETS = debug fastdebug optimized product SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) # For dependencies and recursive makes. @@ -186,8 +186,8 @@ $(QUIETLY) mkdir -p $@ # Convenience macro which takes a source relative path, applies $(1) to the -# absolute path, and then replaces $(GAMMADIR) in the result with a -# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile. +# absolute path, and then replaces $(GAMMADIR) in the result with a +# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile. gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2))) # This bit is needed to enable local rebuilds. @@ -279,8 +279,6 @@ $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ echo; \ - [ "$(TARGET)" = profiled ] && \ - echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/optimized.make"; \ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ ) > $@ @@ -381,7 +379,7 @@ $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ echo "JDK=${JAVA_HOME}"; \ - ) > $@ + ) > $@ FORCE: diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/compiler1.make --- a/make/bsd/makefiles/compiler1.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/makefiles/compiler1.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER1 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = client-nograal endif \ No newline at end of file diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/compiler2.make --- a/make/bsd/makefiles/compiler2.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/makefiles/compiler2.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER2 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif \ No newline at end of file diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/debug.make --- a/make/bsd/makefiles/debug.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/makefiles/debug.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # Sets make macros for making debug version of VM @@ -27,17 +27,16 @@ # Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS) DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)) -CFLAGS += $(DEBUG_CFLAGS/BYFILE) + +# _NMT_NOINLINE_ informs NMT that no inlining by Compiler +CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_ + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. # Linker mapfile MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug -_JUNK_ := $(shell echo -e >&2 ""\ - "----------------------------------------------------------------------\n" \ - "WARNING: 'make debug' is deprecated. It will be removed in the future.\n" \ - "Please use 'make jvmg' to build debug JVM. \n" \ - "----------------------------------------------------------------------\n") - VERSION = debug -SYSDEFS += -DASSERT -DDEBUG +SYSDEFS += -DASSERT PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/defs.make --- a/make/bsd/makefiles/defs.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/makefiles/defs.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # The common definitions for hotspot bsd builds. @@ -86,7 +86,7 @@ VM_PLATFORM = bsd_i486 HS_ARCH = x86 # We have to reset ARCH to i386 since SRCARCH relies on it - ARCH = i386 + ARCH = i386 endif endif @@ -146,9 +146,6 @@ LIBRARY_SUFFIX=so endif -# FIXUP: The subdirectory for a debug build is NOT the same on all platforms -VM_DEBUG=jvmg - EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html # client and server subdirectories have symbolic links to ../libjsig.so @@ -177,7 +174,7 @@ else EXPORT_LIST += $(EXPORT_MINIMAL_DIR)/libjvm.debuginfo endif - endif + endif endif # Serviceability Binaries diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/fastdebug.make --- a/make/bsd/makefiles/fastdebug.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/makefiles/fastdebug.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # Sets make macros for making debug version of VM @@ -59,5 +59,5 @@ MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug VERSION = optimized -SYSDEFS += -DASSERT -DFASTDEBUG +SYSDEFS += -DASSERT PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/jvmg.make --- a/make/bsd/makefiles/jvmg.make Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -# -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - -# Sets make macros for making debug version of VM - -# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make -DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS) -DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)) - -# _NMT_NOINLINE_ informs NMT that no inlining by Compiler -CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_ - -# Set the environment variable HOTSPARC_GENERIC to "true" -# to inhibit the effect of the previous line on CFLAGS. - -# Linker mapfile -MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug - -VERSION = debug -SYSDEFS += -DASSERT -DDEBUG -PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/profiled.make --- a/make/bsd/makefiles/profiled.make Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -# -# Copyright (c) 1999, 2008, 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. -# -# - -# Sets make macros for making profiled version of Gamma VM -# (It is also optimized.) - -CFLAGS += -pg -AOUT_FLAGS += -pg -LDNOMAP = true diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/tiered.make --- a/make/bsd/makefiles/tiered.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/makefiles/tiered.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER2 -DCOMPILER1 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif diff -r b69312e4eceb -r 9d29e5aa54d2 make/bsd/makefiles/vm.make --- a/make/bsd/makefiles/vm.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/bsd/makefiles/vm.make Sat Apr 20 12:23:29 2013 +0200 @@ -196,7 +196,7 @@ SHARK_SPECIFIC_FILES := shark ZERO_SPECIFIC_FILES := zero -ifdef OMIT_GRAAL +ifneq ($(INCLUDE_GRAAL), true) GRAAL_SPECIFIC_FILES := graal\* else GRAAL_SPECIFIC_FILES := diff -r b69312e4eceb -r 9d29e5aa54d2 make/build-graal.xml --- a/make/build-graal.xml Sat Apr 20 12:22:54 2013 +0200 +++ b/make/build-graal.xml Sat Apr 20 12:23:29 2013 +0200 @@ -32,6 +32,7 @@ + @@ -49,7 +50,6 @@ - @@ -74,7 +74,16 @@ - + + + + + + + + + + diff -r b69312e4eceb -r 9d29e5aa54d2 make/hotspot_version --- a/make/hotspot_version Sat Apr 20 12:22:54 2013 +0200 +++ b/make/hotspot_version Sat Apr 20 12:23:29 2013 +0200 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=26 +HS_BUILD_NUMBER=29 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r b69312e4eceb -r 9d29e5aa54d2 make/jprt.properties --- a/make/jprt.properties Sat Apr 20 12:22:54 2013 +0200 +++ b/make/jprt.properties Sat Apr 20 12:23:29 2013 +0200 @@ -133,15 +133,15 @@ # Standard list of jprt build targets for this source tree jprt.build.targets.standard= \ - ${jprt.my.solaris.sparc}-{product|fastdebug|debug}, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug|debug}, \ - ${jprt.my.solaris.i586}-{product|fastdebug|debug}, \ - ${jprt.my.solaris.x64}-{product|fastdebug|debug}, \ - ${jprt.my.linux.i586}-{product|fastdebug|debug}, \ + ${jprt.my.solaris.sparc}-{product|fastdebug}, \ + ${jprt.my.solaris.sparcv9}-{product|fastdebug}, \ + ${jprt.my.solaris.i586}-{product|fastdebug}, \ + ${jprt.my.solaris.x64}-{product|fastdebug}, \ + ${jprt.my.linux.i586}-{product|fastdebug}, \ ${jprt.my.linux.x64}-{product|fastdebug}, \ - ${jprt.my.macosx.x64}-{product|fastdebug|debug}, \ - ${jprt.my.windows.i586}-{product|fastdebug|debug}, \ - ${jprt.my.windows.x64}-{product|fastdebug|debug}, \ + ${jprt.my.macosx.x64}-{product|fastdebug}, \ + ${jprt.my.windows.i586}-{product|fastdebug}, \ + ${jprt.my.windows.x64}-{product|fastdebug}, \ ${jprt.my.linux.armvh}-{product|fastdebug} jprt.build.targets.open= \ @@ -150,7 +150,7 @@ ${jprt.my.linux.x64}-{productOpen} jprt.build.targets.embedded= \ - ${jprt.my.linux.i586}-{productEmb|fastdebugEmb|debugEmb}, \ + ${jprt.my.linux.i586}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.ppc}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.ppcv2}-{productEmb|fastdebugEmb}, \ ${jprt.my.linux.ppcsflt}-{productEmb|fastdebugEmb}, \ @@ -174,21 +174,18 @@ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese, \ ${jprt.my.solaris.sparc}-fastdebug-c1-runThese_Xshare, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_default, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_G1, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_default, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_SerialGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParallelGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParNewGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_CMS, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_G1, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParOldGC, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_default, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jbb_default_nontiered, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \ @@ -201,21 +198,18 @@ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98_nontiered, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \ ${jprt.my.solaris.sparcv9}-product-c2-runThese, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_SerialGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_CMS, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_G1, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_CMS, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParOldGC, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default_nontiered, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_SerialGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParallelGC, \ @@ -229,21 +223,18 @@ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-scimark, \ ${jprt.my.solaris.x64}-product-c2-runThese, \ ${jprt.my.solaris.x64}-product-c2-runThese_Xcomp, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_G1, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_CMS, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default_nontiered, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_SerialGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ @@ -258,28 +249,24 @@ ${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \ ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp, \ ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xshare, \ - ${jprt.my.solaris.i586}-product-c1-GCBasher_default, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_SerialGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_ParallelGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_ParNewGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_CMS, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_G1, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_ParOldGC, \ - ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_default, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_SerialGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParallelGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParNewGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_CMS, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_G1, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParOldGC, \ - ${jprt.my.solaris.i586}-product-c1-GCOld_default, \ ${jprt.my.solaris.i586}-product-c1-GCOld_SerialGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParallelGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParNewGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_CMS, \ ${jprt.my.solaris.i586}-product-c1-GCOld_G1, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParOldGC, \ - ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default_nontiered, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \ @@ -293,21 +280,19 @@ ${jprt.my.linux.i586}-product-c1-runThese_Xcomp, \ ${jprt.my.linux.i586}-fastdebug-c1-runThese_Xshare, \ ${jprt.my.linux.i586}-fastdebug-c2-runThese_Xcomp, \ - ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_default, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_G1, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \ - ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_default, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_SerialGC, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParallelGC, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParNewGC, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_CMS, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_G1, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParOldGC, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_default, \ + ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_SerialGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-c2-jbb_default_nontiered, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParallelGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \ @@ -318,21 +303,18 @@ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98_nontiered, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark, \ - ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_G1, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ - ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_CMS, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ - ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default_nontiered, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_G1, \ @@ -342,21 +324,18 @@ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jvm98, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jvm98_nontiered, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-scimark, \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_G1, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_CMS, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_default, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_default_nontiered, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_G1, \ @@ -369,14 +348,12 @@ ${jprt.my.windows.i586}-product-{c1|c2}-runThese, \ ${jprt.my.windows.i586}-product-{c1|c2}-runThese_Xcomp, \ ${jprt.my.windows.i586}-fastdebug-c1-runThese_Xshare, \ - ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_default, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_G1, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \ - ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_default, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_SerialGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParallelGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParNewGC, \ @@ -396,14 +373,12 @@ ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark, \ ${jprt.my.windows.x64}-product-c2-runThese, \ ${jprt.my.windows.x64}-product-c2-runThese_Xcomp, \ - ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_G1, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ - ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ @@ -419,7 +394,7 @@ # Some basic "smoke" tests for OpenJDK builds jprt.test.targets.open = \ - ${jprt.my.solaris.x64}-{productOpen|debugOpen|fastdebugOpen}-c2-jvm98, \ + ${jprt.my.solaris.x64}-{productOpen|fastdebugOpen}-c2-jvm98, \ ${jprt.my.solaris.i586}-{productOpen|fastdebugOpen}-c2-jvm98, \ ${jprt.my.linux.x64}-{productOpen|fastdebugOpen}-c2-jvm98 @@ -520,5 +495,5 @@ jprt.make.rule.test.targets=${jprt.make.rule.test.targets.${jprt.tools.default.release}} # 7155453: Work-around to prevent popups on OSX from blocking test completion -# but the work-around is added to all platforms to be consistent +# but the work-around is added to all platforms to be consistent jprt.jbb.options=-Djava.awt.headless=true diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/Makefile --- a/make/linux/Makefile Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/Makefile Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -142,55 +142,42 @@ # # debug compiler2 __compiler2/debug # fastdebug compiler2 __compiler2/fastdebug -# jvmg compiler2 __compiler2/jvmg # optimized compiler2 __compiler2/optimized -# profiled compiler2 __compiler2/profiled # product compiler2 __compiler2/product # # debug1 compiler1 __compiler1/debug # fastdebug1 compiler1 __compiler1/fastdebug -# jvmg1 compiler1 __compiler1/jvmg # optimized1 compiler1 __compiler1/optimized -# profiled1 compiler1 __compiler1/profiled # product1 compiler1 __compiler1/product # # debugcore core __core/debug # fastdebugcore core __core/fastdebug -# jvmgcore core __core/jvmg # optimizedcore core __core/optimized -# profiledcore core __core/profiled # productcore core __core/product # # debugzero zero __zero/debug # fastdebugzero zero __zero/fastdebug -# jvmgzero zero __zero/jvmg # optimizedzero zero __zero/optimized -# profiledzero zero __zero/profiled # productzero zero __zero/product # # debugshark shark __shark/debug # fastdebugshark shark __shark/fastdebug -# jvmgshark shark __shark/jvmg # optimizedshark shark __shark/optimized -# profiledshark shark __shark/profiled # productshark shark __shark/product # # fastdebugminimal1 minimal1 __minimal1/fastdebug -# jvmgminimal1 minimal1 __minimal1/jvmg # productminimal1 minimal1 __minimal1/product # # What you get with each target: # -# debug* - "thin" libjvm - debug info linked into the gamma launcher +# debug* - debug compile with asserts enabled # fastdebug* - optimized compile, but with asserts enabled -# jvmg* - "fat" libjvm - debug info linked into libjvm.so # optimized* - optimized compile, no asserts -# profiled* - gprof # product* - the shippable thing: optimized compile, no asserts, -DPRODUCT # This target list needs to be coordinated with the usage message # in the build.sh script: -TARGETS = debug jvmg fastdebug optimized profiled product +TARGETS = debug fastdebug optimized product ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) SUBDIR_DOCS = $(OSNAME)_$(VARIANTARCH)_docs @@ -370,15 +357,29 @@ $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) BUILD_FLAVOR=product jvmtidocs # Synonyms for win32-like targets. -compiler2: jvmg product +compiler2: debug product + +compiler1: debug1 product1 -compiler1: jvmg1 product1 +core: debugcore productcore + +zero: debugzero productzero + +shark: debugshark productshark -core: jvmgcore productcore +warn_jvmg_deprecated: + echo "Warning: The jvmg target has been replaced with debug" + echo "Warning: Please update your usage" + +jvmg: warn_jvmg_deprecated debug -zero: jvmgzero productzero +jvmg1: warn_jvmg_deprecated debug1 + +jvmgcore: warn_jvmg_deprecated debugcore -shark: jvmgshark productshark +jvmgzero: warn_jvmg_deprecated debugzero + +jvmgshark: warn_jvmg_deprecated debugshark clean_docs: rm -rf $(SUBDIR_DOCS) diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/buildtree.make --- a/make/linux/makefiles/buildtree.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/buildtree.make Sat Apr 20 12:23:29 2013 +0200 @@ -19,7 +19,7 @@ # 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. -# +# # # Usage: @@ -46,11 +46,11 @@ # Makefile - for "make foo" # flags.make - with macro settings # vm.make - to support making "$(MAKE) -v vm.make" in makefiles -# adlc.make - +# adlc.make - # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives # env.[ck]sh - environment settings -# +# # The makefiles are split this way so that "make foo" will run faster by not # having to read the dependency files for the vm. @@ -117,7 +117,7 @@ $(PLATFORM_DIR)/generated/adfiles \ $(PLATFORM_DIR)/generated/jvmtifiles -TARGETS = debug fastdebug jvmg optimized product profiled +TARGETS = debug fastdebug optimized product SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) # For dependencies and recursive makes. @@ -179,8 +179,8 @@ $(QUIETLY) mkdir -p $@ # Convenience macro which takes a source relative path, applies $(1) to the -# absolute path, and then replaces $(GAMMADIR) in the result with a -# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile. +# absolute path, and then replaces $(GAMMADIR) in the result with a +# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile. gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2))) # This bit is needed to enable local rebuilds. @@ -284,8 +284,6 @@ $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ echo; \ - [ "$(TARGET)" = profiled ] && \ - echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/optimized.make"; \ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ ) > $@ @@ -376,7 +374,7 @@ $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ echo "JDK=${JAVA_HOME}"; \ - ) > $@ + ) > $@ FORCE: diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/compiler1.make --- a/make/linux/makefiles/compiler1.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/compiler1.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER1 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = client-nograal endif \ No newline at end of file diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/compiler2.make --- a/make/linux/makefiles/compiler2.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/compiler2.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER2 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif \ No newline at end of file diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/debug.make --- a/make/linux/makefiles/debug.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/debug.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # Sets make macros for making debug version of VM @@ -27,17 +27,16 @@ # Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS) DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)) -CFLAGS += $(DEBUG_CFLAGS/BYFILE) + +# _NMT_NOINLINE_ informs NMT that no inlining by Compiler +CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_ + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. # Linker mapfile MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug -_JUNK_ := $(shell echo -e >&2 ""\ - "----------------------------------------------------------------------\n" \ - "WARNING: 'make debug' is deprecated. It will be removed in the future.\n" \ - "Please use 'make jvmg' to build debug JVM. \n" \ - "----------------------------------------------------------------------\n") - VERSION = debug -SYSDEFS += -DASSERT -DDEBUG +SYSDEFS += -DASSERT PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/defs.make --- a/make/linux/makefiles/defs.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/defs.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # The common definitions for hotspot linux builds. @@ -92,7 +92,7 @@ VM_PLATFORM = linux_i486 HS_ARCH = x86 # We have to reset ARCH to i686 since SRCARCH relies on it - ARCH = i686 + ARCH = i686 endif endif @@ -240,9 +240,6 @@ # Library suffix LIBRARY_SUFFIX=so -# FIXUP: The subdirectory for a debug build is NOT the same on all platforms -VM_DEBUG=jvmg - EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html # client and server subdirectories have symbolic links to ../libjsig.so @@ -279,7 +276,7 @@ else EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo endif - endif + endif endif ifeq ($(JVM_VARIANT_MINIMAL1),true) @@ -292,15 +289,15 @@ else EXPORT_LIST += $(EXPORT_MINIMAL_DIR)/libjvm.debuginfo endif - endif + endif endif # Serviceability Binaries # No SA Support for PPC, IA64, ARM or zero ADD_SA_BINARIES/x86 = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \ - $(EXPORT_LIB_DIR)/sa-jdi.jar + $(EXPORT_LIB_DIR)/sa-jdi.jar ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \ - $(EXPORT_LIB_DIR)/sa-jdi.jar + $(EXPORT_LIB_DIR)/sa-jdi.jar ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) ifeq ($(ZIP_DEBUGINFO_FILES),1) ADD_SA_BINARIES/x86 += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.diz @@ -310,10 +307,10 @@ ADD_SA_BINARIES/sparc += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo endif endif -ADD_SA_BINARIES/ppc = -ADD_SA_BINARIES/ia64 = -ADD_SA_BINARIES/arm = -ADD_SA_BINARIES/zero = +ADD_SA_BINARIES/ppc = +ADD_SA_BINARIES/ia64 = +ADD_SA_BINARIES/arm = +ADD_SA_BINARIES/zero = -include $(HS_ALT_MAKE)/linux/makefiles/defs.make diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/fastdebug.make --- a/make/linux/makefiles/fastdebug.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/fastdebug.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # Sets make macros for making debug version of VM @@ -59,5 +59,5 @@ MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug VERSION = optimized -SYSDEFS += -DASSERT -DFASTDEBUG +SYSDEFS += -DASSERT PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/gcc.make --- a/make/linux/makefiles/gcc.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/gcc.make Sat Apr 20 12:23:29 2013 +0200 @@ -126,14 +126,12 @@ # Compiler warnings are treated as errors WARNINGS_ARE_ERRORS = -Werror -# Except for a few acceptable ones +WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function + # Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit -# conversions which might affect the values. To avoid that, we need to turn -# it off explicitly. -ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" -WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -else -WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef +# conversions which might affect the values. Only enable it in earlier versions. +ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" +WARNING_FLAGS += -Wconversion endif CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS) diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/jvmg.make --- a/make/linux/makefiles/jvmg.make Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -# -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - -# Sets make macros for making debug version of VM - -# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make -DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS) -DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)) - -# _NMT_NOINLINE_ informs NMT that no inlining by Compiler -CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_ - -# Set the environment variable HOTSPARC_GENERIC to "true" -# to inhibit the effect of the previous line on CFLAGS. - -# Linker mapfile -MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug - -VERSION = debug -SYSDEFS += -DASSERT -DDEBUG -PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/profiled.make --- a/make/linux/makefiles/profiled.make Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -# -# Copyright (c) 1999, 2008, 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. -# -# - -# Sets make macros for making profiled version of Gamma VM -# (It is also optimized.) - -CFLAGS += -pg -AOUT_FLAGS += -pg -LDNOMAP = true diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/tiered.make --- a/make/linux/makefiles/tiered.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/tiered.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER2 -DCOMPILER1 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif \ No newline at end of file diff -r b69312e4eceb -r 9d29e5aa54d2 make/linux/makefiles/vm.make --- a/make/linux/makefiles/vm.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/linux/makefiles/vm.make Sat Apr 20 12:23:29 2013 +0200 @@ -198,7 +198,7 @@ SHARK_SPECIFIC_FILES := shark ZERO_SPECIFIC_FILES := zero -ifdef OMIT_GRAAL +ifneq ($(INCLUDE_GRAAL), true) GRAAL_SPECIFIC_FILES := graal\* else GRAAL_SPECIFIC_FILES := diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/Makefile --- a/make/solaris/Makefile Sat Apr 20 12:22:54 2013 +0200 +++ b/make/solaris/Makefile Sat Apr 20 12:23:29 2013 +0200 @@ -120,37 +120,29 @@ # # debug compiler2 __compiler2/debug # fastdebug compiler2 __compiler2/fastdebug -# jvmg compiler2 __compiler2/jvmg # optimized compiler2 __compiler2/optimized -# profiled compiler2 __compiler2/profiled # product compiler2 __compiler2/product # # debug1 compiler1 __compiler1/debug # fastdebug1 compiler1 __compiler1/fastdebug -# jvmg1 compiler1 __compiler1/jvmg # optimized1 compiler1 __compiler1/optimized -# profiled1 compiler1 __compiler1/profiled # product1 compiler1 __compiler1/product # # debugcore core __core/debug # fastdebugcore core __core/fastdebug -# jvmgcore core __core/jvmg # optimizedcore core __core/optimized -# profiledcore core __core/profiled # productcore core __core/product # # What you get with each target: # -# debug* - "thin" libjvm - debug info linked into the gamma launcher +# debug* - debug compile with asserts enabled # fastdebug* - optimized compile, but with asserts enabled -# jvmg* - "fat" libjvm - debug info linked into libjvm.so # optimized* - optimized compile, no asserts -# profiled* - gprof # product* - the shippable thing: optimized compile, no asserts, -DPRODUCT # This target list needs to be coordinated with the usage message # in the build.sh script: -TARGETS = debug jvmg fastdebug optimized profiled product +TARGETS = debug fastdebug optimized product SUBDIR_DOCS = $(OSNAME)_$(BUILDARCH)_docs SUBDIRS_C1 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler1/,$(TARGETS)) @@ -281,11 +273,21 @@ $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) BUILD_FLAVOR=product jvmtidocs # Synonyms for win32-like targets. -compiler2: jvmg product +compiler2: debug product + +compiler1: debug1 product1 + +core: debugcore productcore -compiler1: jvmg1 product1 +warn_jvmg_deprecated: + echo "Warning: The jvmg target has been replaced with debug" + echo "Warning: Please update your usage" -core: jvmgcore productcore +jvmg: warn_jvmg_deprecated debug + +jvmg1: warn_jvmg_deprecated debug1 + +jvmgcore: warn_jvmg_deprecated debugcore clean_docs: rm -rf $(SUBDIR_DOCS) diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/buildtree.make --- a/make/solaris/makefiles/buildtree.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/solaris/makefiles/buildtree.make Sat Apr 20 12:23:29 2013 +0200 @@ -19,7 +19,7 @@ # 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. -# +# # # Usage: @@ -46,11 +46,11 @@ # Makefile - for "make foo" # flags.make - with macro settings # vm.make - to support making "$(MAKE) -v vm.make" in makefiles -# adlc.make - +# adlc.make - # jvmti.make - generate JVMTI bindings from the spec (JSR-163) # sa.make - generate SA jar file and natives # env.[ck]sh - environment settings -# +# # The makefiles are split this way so that "make foo" will run faster by not # having to read the dependency files for the vm. @@ -69,7 +69,7 @@ GCC_LIB = /usr/local/lib else PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH) -GCC_LIB = +GCC_LIB = endif ifdef FORCE_TIERED @@ -110,7 +110,7 @@ $(PLATFORM_DIR)/generated/adfiles \ $(PLATFORM_DIR)/generated/jvmtifiles -TARGETS = debug fastdebug jvmg optimized product profiled +TARGETS = debug fastdebug optimized product SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) # For dependencies and recursive makes. @@ -153,7 +153,7 @@ endif endif -BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HS_BUILD_VER) HOTSPOT_BUILD_VERSION= JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) +BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HS_BUILD_VER) HOTSPOT_BUILD_VERSION= JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) BUILDTREE = \ $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_TARGETS) $(BUILDTREE_VARS) @@ -172,8 +172,8 @@ $(QUIETLY) mkdir -p $@ # Convenience macro which takes a source relative path, applies $(1) to the -# absolute path, and then replaces $(GAMMADIR) in the result with a -# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile. +# absolute path, and then replaces $(GAMMADIR) in the result with a +# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile. gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2))) # This bit is needed to enable local rebuilds. @@ -274,8 +274,6 @@ $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ echo; \ - [ "$(TARGET)" = profiled ] && \ - echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/optimized.make"; \ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ ) > $@ @@ -366,7 +364,7 @@ $(QUIETLY) ( \ $(BUILDTREE_COMMENT); \ echo "JDK=${JAVA_HOME}"; \ - ) > $@ + ) > $@ FORCE: diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/compiler1.make --- a/make/solaris/makefiles/compiler1.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/solaris/makefiles/compiler1.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER1 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = client-nograal endif diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/compiler2.make --- a/make/solaris/makefiles/compiler2.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/solaris/makefiles/compiler2.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER2 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/debug.make --- a/make/solaris/makefiles/debug.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/solaris/makefiles/debug.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # Sets make macros for making debug version of VM @@ -37,7 +37,11 @@ endif endif -CFLAGS += $(DEBUG_CFLAGS/BYFILE) +# _NMT_NOINLINE_ informs NMT that no inlining by Compiler +CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_ + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. # Linker mapfiles MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ @@ -46,16 +50,10 @@ MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL #endif -# This mapfile is only needed when compiling with dtrace support, +# This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) -_JUNK_ := $(shell echo >&2 ""\ - "-------------------------------------------------------------------------\n" \ - "WARNING: 'gnumake debug' is deprecated. It will be removed in the future.\n" \ - "Please use 'gnumake jvmg' to build debug JVM. \n" \ - "-------------------------------------------------------------------------\n") - VERSION = debug -SYSDEFS += -DASSERT -DDEBUG +SYSDEFS += -DASSERT PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/defs.make --- a/make/solaris/makefiles/defs.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/solaris/makefiles/defs.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # The common definitions for hotspot solaris builds. @@ -172,9 +172,6 @@ # Library suffix LIBRARY_SUFFIX=so -# FIXUP: The subdirectory for a debug build is NOT the same on all platforms -VM_DEBUG=jvmg - EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html # client and server subdirectories have symbolic links to ../libjsig.$(LIBRARY_SUFFIX) @@ -221,8 +218,8 @@ endif ifeq ($(JVM_VARIANT_CLIENT),true) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.$(LIBRARY_SUFFIX) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.$(LIBRARY_SUFFIX) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX) ifeq ($(ARCH_DATA_MODEL),32) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX) @@ -257,4 +254,4 @@ EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo endif endif -EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar +EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/fastdebug.make --- a/make/solaris/makefiles/fastdebug.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/solaris/makefiles/fastdebug.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 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 @@ -19,7 +19,7 @@ # 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. -# +# # # Sets make macros for making debug version of VM @@ -121,10 +121,10 @@ MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL #endif -# This mapfile is only needed when compiling with dtrace support, +# This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) VERSION = optimized -SYSDEFS += -DASSERT -DFASTDEBUG -DCHECK_UNHANDLED_OOPS +SYSDEFS += -DASSERT -DCHECK_UNHANDLED_OOPS PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/jvmg.make --- a/make/solaris/makefiles/jvmg.make Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -# -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - -# Sets make macros for making debug version of VM - -# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make -DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS) -DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)) - -ifeq ("${Platform_compiler}", "sparcWorks") - -ifeq ($(COMPILER_REV_NUMERIC),508) - # SS11 SEGV when compiling with -g and -xarch=v8, using different backend - DEBUG_CFLAGS/compileBroker.o = $(DEBUG_CFLAGS) -xO0 - DEBUG_CFLAGS/jvmtiTagMap.o = $(DEBUG_CFLAGS) -xO0 -endif -endif - -# _NMT_NOINLINE_ informs NMT that no inlining by Compiler -CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_ - -# Set the environment variable HOTSPARC_GENERIC to "true" -# to inhibit the effect of the previous line on CFLAGS. - -# Linker mapfiles -MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug -#ifdef GRAAL -MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL -#endif - -# This mapfile is only needed when compiling with dtrace support, -# and mustn't be otherwise. -MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) - -VERSION = debug -SYSDEFS += -DASSERT -DDEBUG -PICFLAGS = DEFAULT diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/profiled.make --- a/make/solaris/makefiles/profiled.make Sat Apr 20 12:22:54 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -# -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - -# Sets make macros for making profiled version of Gamma VM -# (It is also optimized.) - -CFLAGS += -pg - -# On x86 Solaris 2.6, 7, and 8 if LD_LIBRARY_PATH has /usr/lib in it then -# adlc linked with -pg puts out empty header files. To avoid linking adlc -# with -pg the profile flag is split out separately and used in rules.make - -PROF_AOUT_FLAGS += -pg - -# To do a profiled build of the product, such as for generating the -# reordering file, set PROFILE_PRODUCT. Otherwise the reordering file will -# contain references to functions which are not defined in the PRODUCT build. - -ifdef PROFILE_PRODUCT - SYSDEFS += -DPRODUCT -endif - -LDNOMAP = true diff -r b69312e4eceb -r 9d29e5aa54d2 make/solaris/makefiles/tiered.make --- a/make/solaris/makefiles/tiered.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/solaris/makefiles/tiered.make Sat Apr 20 12:23:29 2013 +0200 @@ -30,6 +30,8 @@ CFLAGS += -DCOMPILER2 -DCOMPILER1 -ifndef OMIT_GRAAL +ifeq ($(INCLUDE_GRAAL), true) CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif diff -r b69312e4eceb -r 9d29e5aa54d2 make/windows/build.make --- a/make/windows/build.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/windows/build.make Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 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 @@ -237,18 +237,14 @@ cd $(variantDir) nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=product ARCH=$(ARCH) -# The debug or jvmg (all the same thing) is an optional build -debug jvmg: checks $(variantDir) $(variantDir)\local.make sanity +# The debug build is an optional build +debug: checks $(variantDir) $(variantDir)\local.make sanity cd $(variantDir) nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=debug ARCH=$(ARCH) fastdebug: checks $(variantDir) $(variantDir)\local.make sanity cd $(variantDir) nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=fastdebug ARCH=$(ARCH) -develop: checks $(variantDir) $(variantDir)\local.make sanity - cd $(variantDir) - nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=product DEVELOP=1 ARCH=$(ARCH) - # target to create just the directory structure tree: checks $(variantDir) $(variantDir)\local.make sanity mkdir $(variantDir)\product diff -r b69312e4eceb -r 9d29e5aa54d2 make/windows/create.bat --- a/make/windows/create.bat Sat Apr 20 12:22:54 2013 +0200 +++ b/make/windows/create.bat Sat Apr 20 12:23:29 2013 +0200 @@ -37,10 +37,14 @@ REM that "grep" be accessible on the PATH. An MKS install does this. REM -cl 2>NUL >NUL -if %errorlevel% == 0 goto nexttest -echo Make sure cl.exe is in your PATH before running this script. -goto end + + +REM (cwirth) does not return a proper error code, so build fails all the time +REM +REM cl 2>NUL >NUL +REM if %errorlevel% == 0 goto nexttest +REM echo Make sure cl.exe is in your PATH before running this script. +REM goto end :nexttest grep -V 2>NUL >NUL diff -r b69312e4eceb -r 9d29e5aa54d2 make/windows/makefiles/defs.make --- a/make/windows/makefiles/defs.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/windows/makefiles/defs.make Sat Apr 20 12:23:29 2013 +0200 @@ -19,7 +19,7 @@ # 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. -# +# # # The common definitions for hotspot windows builds. @@ -209,8 +209,6 @@ ifneq (,$(findstring MINGW,$(SYSTEM_UNAME))) USING_MINGW=true endif -# FIXUP: The subdirectory for a debug build is NOT the same on all platforms -VM_DEBUG=debug # Windows wants particular paths due to nmake (must be after macros defined) # It is important that gnumake invokes nmake with C:\\...\\ formated @@ -292,7 +290,7 @@ MAKE_ARGS += BUILD_WIN_SA=1 endif -# Propagate compiler and tools paths from configure to nmake. +# Propagate compiler and tools paths from configure to nmake. # Need to make sure they contain \\ and not /. ifneq ($(SPEC),) ifeq ($(USING_CYGWIN), true) diff -r b69312e4eceb -r 9d29e5aa54d2 make/windows/makefiles/vm.make --- a/make/windows/makefiles/vm.make Sat Apr 20 12:22:54 2013 +0200 +++ b/make/windows/makefiles/vm.make Sat Apr 20 12:23:29 2013 +0200 @@ -31,11 +31,7 @@ ALTSRC=$(WorkSpace)\src\closed !ifdef RELEASE -!ifdef DEVELOP -CXX_FLAGS=$(CXX_FLAGS) /D "DEBUG" -!else CXX_FLAGS=$(CXX_FLAGS) /D "PRODUCT" -!endif !else CXX_FLAGS=$(CXX_FLAGS) /D "ASSERT" !endif @@ -191,7 +187,7 @@ # Special case files not using precompiled header files. -c1_RInfo_$(Platform_arch).obj: $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp +c1_RInfo_$(Platform_arch).obj: $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp $(CXX) $(CXX_FLAGS) $(CXX_DONT_USE_PCH) /c $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp os_windows.obj: $(WorkSpace)\src\os\windows\vm\os_windows.cpp diff -r b69312e4eceb -r 9d29e5aa54d2 make/windows/projectfiles/compiler2/ADLCompiler.dsp --- a/make/windows/projectfiles/compiler2/ADLCompiler.dsp Sat Apr 20 12:22:54 2013 +0200 +++ b/make/windows/projectfiles/compiler2/ADLCompiler.dsp Sat Apr 20 12:23:29 2013 +0200 @@ -67,7 +67,7 @@ # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /ML /W3 /WX /Gm /GX /Zi /Od /I "." /I "$(HotSpotWorkSpace)\src\share\vm\opto" /I "$(HotSpotWorkSpace)\src\share\vm\prims" /I "$(HotSpotWorkSpace)\src\share\vm\lookup" /I "$(HotSpotWorkSpace)\src\share\vm\interpreter" /I "$(HotSpotWorkSpace)\src\share\vm\asm" /I "$(HotSpotWorkSpace)\src\share\vm\compiler" /I "$(HotSpotWorkSpace)\src\share\vm\utilities" /I "$(HotSpotWorkSpace)\src\share\vm\code" /I "$(HotSpotWorkSpace)\src\share\vm\oops" /I "$(HotSpotWorkSpace)\src\share\vm\runtime" /I "$(HotSpotWorkSpace)\src\share\vm\memory" /I "$(HotSpotWorkSpace)\src\share\vm\libadt" /I "$(HotSpotWorkSpace)\src\cpu\i486\vm" /I "$(HotSpotWorkSpace)\src\os\win32\vm" /D "WIN32" /D "DEBUG" /D "_WINDOWS" /D "ASSERT" /Fr /FD /c +# ADD CPP /nologo /ML /W3 /WX /Gm /GX /Zi /Od /I "." /I "$(HotSpotWorkSpace)\src\share\vm\opto" /I "$(HotSpotWorkSpace)\src\share\vm\prims" /I "$(HotSpotWorkSpace)\src\share\vm\lookup" /I "$(HotSpotWorkSpace)\src\share\vm\interpreter" /I "$(HotSpotWorkSpace)\src\share\vm\asm" /I "$(HotSpotWorkSpace)\src\share\vm\compiler" /I "$(HotSpotWorkSpace)\src\share\vm\utilities" /I "$(HotSpotWorkSpace)\src\share\vm\code" /I "$(HotSpotWorkSpace)\src\share\vm\oops" /I "$(HotSpotWorkSpace)\src\share\vm\runtime" /I "$(HotSpotWorkSpace)\src\share\vm\memory" /I "$(HotSpotWorkSpace)\src\share\vm\libadt" /I "$(HotSpotWorkSpace)\src\cpu\i486\vm" /I "$(HotSpotWorkSpace)\src\os\win32\vm" /D "WIN32" /D "_WINDOWS" /D "ASSERT" /Fr /FD /c # ADD BASE RSC /l 0x409 # ADD RSC /l 0x409 BSC32=bscmake.exe diff -r b69312e4eceb -r 9d29e5aa54d2 make/windows/projectfiles/tiered/ADLCompiler.dsp --- a/make/windows/projectfiles/tiered/ADLCompiler.dsp Sat Apr 20 12:22:54 2013 +0200 +++ b/make/windows/projectfiles/tiered/ADLCompiler.dsp Sat Apr 20 12:23:29 2013 +0200 @@ -67,7 +67,7 @@ # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /ML /W3 /WX /Gm /GX /Zi /Od /I "." /I "$(HotSpotWorkSpace)\src\share\vm\opto" /I "$(HotSpotWorkSpace)\src\share\vm\prims" /I "$(HotSpotWorkSpace)\src\share\vm\lookup" /I "$(HotSpotWorkSpace)\src\share\vm\interpreter" /I "$(HotSpotWorkSpace)\src\share\vm\asm" /I "$(HotSpotWorkSpace)\src\share\vm\compiler" /I "$(HotSpotWorkSpace)\src\share\vm\utilities" /I "$(HotSpotWorkSpace)\src\share\vm\code" /I "$(HotSpotWorkSpace)\src\share\vm\oops" /I "$(HotSpotWorkSpace)\src\share\vm\runtime" /I "$(HotSpotWorkSpace)\src\share\vm\memory" /I "$(HotSpotWorkSpace)\src\share\vm\libadt" /I "$(HotSpotWorkSpace)\src\cpu\i486\vm" /I "$(HotSpotWorkSpace)\src\os\win32\vm" /D "WIN32" /D "DEBUG" /D "_WINDOWS" /D "ASSERT" /Fr /FD /c +# ADD CPP /nologo /ML /W3 /WX /Gm /GX /Zi /Od /I "." /I "$(HotSpotWorkSpace)\src\share\vm\opto" /I "$(HotSpotWorkSpace)\src\share\vm\prims" /I "$(HotSpotWorkSpace)\src\share\vm\lookup" /I "$(HotSpotWorkSpace)\src\share\vm\interpreter" /I "$(HotSpotWorkSpace)\src\share\vm\asm" /I "$(HotSpotWorkSpace)\src\share\vm\compiler" /I "$(HotSpotWorkSpace)\src\share\vm\utilities" /I "$(HotSpotWorkSpace)\src\share\vm\code" /I "$(HotSpotWorkSpace)\src\share\vm\oops" /I "$(HotSpotWorkSpace)\src\share\vm\runtime" /I "$(HotSpotWorkSpace)\src\share\vm\memory" /I "$(HotSpotWorkSpace)\src\share\vm\libadt" /I "$(HotSpotWorkSpace)\src\cpu\i486\vm" /I "$(HotSpotWorkSpace)\src\os\win32\vm" /D "WIN32" /D "_WINDOWS" /D "ASSERT" /Fr /FD /c # ADD BASE RSC /l 0x409 # ADD RSC /l 0x409 BSC32=bscmake.exe diff -r b69312e4eceb -r 9d29e5aa54d2 mx/commands.py --- a/mx/commands.py Sat Apr 20 12:22:54 2013 +0200 +++ b/mx/commands.py Sat Apr 20 12:23:29 2013 +0200 @@ -31,20 +31,26 @@ from argparse import ArgumentParser, REMAINDER import mx import sanitycheck -import json +import json, textwrap _graal_home = dirname(dirname(__file__)) """ Used to distinguish an exported GraalVM (see 'mx export'). """ _vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src')) -""" The VM that will be run by the 'vm' command: graal(default), client or server. +""" The VMs that can be built and run - default is first in list """ +_vmChoices = ['graal', 'server', 'client', 'server-nograal', 'client-nograal', 'original'] + +""" The VM that will be run by the 'vm' command and built by default by the 'build' command. This can be set via the global '--vm' option. """ -_vm = 'graal' +_vm = _vmChoices[0] -""" The VM build that will be run by the 'vm' command: product(default), fastdebug or debug. - This can be set via the global '--fastdebug' and '--debug' options. """ -_vmbuild = 'product' +""" The VM builds that will be run by the 'vm' command - default is first in list """ +_vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized'] + +""" The VM build that will be run by the 'vm' command. + This can be set via the global '--product', '--fastdebug' and '--debug' options. """ +_vmbuild = _vmbuildChoices[0] _jacoco = 'off' @@ -66,11 +72,16 @@ """clean the GraalVM source tree""" opts = mx.clean(args, parser=ArgumentParser(prog='mx clean')) if opts.native: - os.environ.update(ARCH_DATA_MODEL='64', LANG='C', HOTSPOT_BUILD_JOBS='16') - mx.run([mx.gmake_cmd(), 'clean'], cwd=join(_graal_home, 'make')) - jdks = join(_graal_home, 'jdk' + str(mx.java().version)) - if exists(jdks): - shutil.rmtree(jdks) + def rmIfExists(name): + if os.path.isdir(name): + shutil.rmtree(name) + elif os.path.isfile(name): + os.unlink(name) + + rmIfExists(join(_graal_home, 'build')) + rmIfExists(join(_graal_home, 'build-nograal')) + rmIfExists(_jdksDir()) + rmIfExists(mx.distribution('GRAAL').path) def export(args): """create a GraalVM zip file for distribution""" @@ -116,47 +127,6 @@ mx.log('Created distribution in ' + zfName) -def example(args): - """run some or all Graal examples""" - examples = { - 'safeadd': ['com.oracle.graal.examples.safeadd', 'com.oracle.graal.examples.safeadd.Main'], - 'vectorlib': ['com.oracle.graal.examples.vectorlib', 'com.oracle.graal.examples.vectorlib.Main'], - } - - def run_example(verbose, project, mainClass): - cp = mx.classpath(project) - sharedArgs = ['-Xcomp', '-XX:CompileOnly=Main', mainClass] - - res = [] - mx.log("=== Server VM ===") - printArg = '-XX:+PrintCompilation' if verbose else '-XX:-PrintCompilation' - res.append(vm(['-cp', cp, printArg] + sharedArgs, vm='server')) - mx.log("=== Graal VM ===") - printArg = '-G:+PrintCompilation' if verbose else '-G:-PrintCompilation' - res.append(vm(['-cp', cp, printArg, '-G:-Extend', '-G:-Inline'] + sharedArgs)) - mx.log("=== Graal VM with extensions ===") - res.append(vm(['-cp', cp, printArg, '-G:+Extend', '-G:-Inline'] + sharedArgs)) - - if len([x for x in res if x != 0]) != 0: - return 1 - return 0 - - verbose = False - if '-v' in args: - verbose = True - args = [a for a in args if a != '-v'] - - if len(args) == 0: - args = examples.keys() - for a in args: - config = examples.get(a) - if config is None: - mx.log('unknown example: ' + a + ' {available examples = ' + str(examples.keys()) + '}') - else: - mx.log('--------- ' + a + ' ------------') - project, mainClass = config - run_example(verbose, project, mainClass) - def dacapo(args): """run one or all DaCapo benchmarks @@ -291,11 +261,14 @@ return join(jdk, 'jre', 'lib', _arch(), 'jvm.cfg') return join(_vmLibDirInJdk(jdk), 'jvm.cfg') +def _jdksDir(): + return join(_graal_home, 'jdk' + str(mx.java().version)) + def _jdk(build='product', vmToCheck=None, create=False): """ Get the JDK into which Graal is installed, creating it first if necessary. """ - jdk = join(_graal_home, 'jdk' + str(mx.java().version), build) + jdk = join(_jdksDir(), build) srcJdk = mx.java().jdk jdkContents = ['bin', 'include', 'jre', 'lib'] if exists(join(srcJdk, 'db')): @@ -328,14 +301,15 @@ assert len(parts) == 2, parts assert parts[1] == 'KNOWN', parts[1] defaultVM = parts[0][1:] - jvmCfgLines += ['-' + defaultVM + '0 KNOWN\n'] + jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n'] + jvmCfgLines += ['-original KNOWN\n'] else: jvmCfgLines += [line] assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg if mx.get_os() != 'windows': chmodRecursive(jdk, 0755) - shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), defaultVM + '0')) + shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original')) with open(jvmCfg, 'w') as fp: @@ -349,7 +323,8 @@ pass else: if not exists(jdk): - mx.abort('The ' + build + ' VM has not been created - run "mx build ' + build + '"') + vmOption = ' --vm ' + vmToCheck if vmToCheck else '' + mx.abort('The ' + build + ' VM has not been created - run "mx' + vmOption + ' build ' + build + '"') _installGraalJarInJdks(mx.distribution('GRAAL')) @@ -485,11 +460,31 @@ out.element('target', {'name' : 'main', 'depends' : 'jar'}) + serviceMap = {}; + def addService(service, provider): + if service not in serviceMap: + serviceMap[service] = set(); + serviceMap[service].add(provider) + out.open('target', {'name' : 'compile', 'depends' : 'cleanclasses'}) out.element('mkdir', {'dir' : '${classes.dir}'}) out.open('javac', {'destdir' : '${classes.dir}', 'debug' : 'on', 'includeantruntime' : 'false', }) + for p in mx.sorted_deps(mx.distribution('GRAAL').deps): out.element('src', {'path' : '${src.dir}/' + p.name}) + servicesDir = join(p.output_dir(), 'META-INF', 'services') + if exists(servicesDir): + for service in os.listdir(servicesDir): + with open(join(servicesDir, service), 'r') as serviceFile: + for line in serviceFile: + addService(service, line.strip()) + providersDir = join(p.output_dir(), 'META-INF', 'providers') + if exists(providersDir): + for provider in os.listdir(providersDir): + with open(join(providersDir, provider), 'r') as providerFile: + for line in providerFile: + addService(line.strip(), provider) + out.element('compilerarg', {'value' : '-XDignore.symbol.file'}) out.open('classpath') @@ -503,7 +498,15 @@ out.open('target', {'name' : 'jar', 'depends' : 'compile'}) out.element('mkdir', {'dir' : '${jar.dir}'}) - out.element('jar', {'destfile' : '${jar.file}', 'basedir' : '${classes.dir}'}) + out.open('jar', {'destfile' : '${jar.file}', 'basedir' : '${classes.dir}'}) + + for service in sorted(serviceMap.iterkeys()): + out.open('service', {'type' : service}) + for provider in sorted(serviceMap[service]): + out.element('provider', {'classname' : provider}) + out.close('service') + + out.close('jar'); out.close('target') out.open('target', {'name' : 'cleanclasses'}) @@ -516,8 +519,28 @@ out.close('project') - mx.update_file(args.buildfile, out.xml(indent=' ', newl='\n')) + return mx.update_file(args.buildfile, out.xml(indent=' ', newl='\n')) + +def buildvars(args): + """Describes the variables that can be set by the -D option to the 'mx build' commmand""" + buildVars = { + 'ALT_BOOTDIR' : 'The location of the bootstrap JDK installation (default: ' + mx.java().jdk + ')', + 'ALT_OUTPUTDIR' : 'Build directory', + 'HOTSPOT_BUILD_JOBS' : 'Number of CPUs used by make (default: ' + str(multiprocessing.cpu_count()) + ')', + 'INSTALL' : 'Install the built VM into the JDK? (default: y)', + 'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)', + } + + mx.log('HotSpot build variables that can be set by the -D option to "mx build":') + mx.log('') + for n in sorted(buildVars.iterkeys()): + mx.log(n) + mx.log(textwrap.fill(buildVars[n], initial_indent=' ', subsequent_indent=' ', width=200)) + + mx.log('') + mx.log('Note that these variables can be given persistent values in the file ' + join(_graal_home, 'mx', 'env') + ' (see \'mx about\').') + def build(args, vm=None): """build the VM binary @@ -527,7 +550,9 @@ for the VM binary.""" # Call mx.build to compile the Java sources - opts2 = mx.build(['--source', '1.7'] + args, parser=ArgumentParser(prog='mx build')) + parser=ArgumentParser(prog='mx build') + parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value') + opts2 = mx.build(['--source', '1.7'] + args, parser=parser) if not _vmSourcesAvailable or not opts2.native: return @@ -539,9 +564,11 @@ if vm is None: vm = _vm - if vm == 'server' or vm == 'server0': + if vm == 'original': + pass + elif vm.startswith('server'): buildSuffix = '' - elif vm == 'client': + elif vm.startswith('client'): buildSuffix = '1' else: assert vm == 'graal', vm @@ -556,10 +583,12 @@ mx.log('[skipping build from IDE as IDE_BUILD_TARGET environment variable is ""]') continue - if vm == 'server0': - assert build == 'product', 'can not "build" a non-product server0' + jdk = _jdk(build, create=True) - jdk = _jdk(build, create=True) + if vm == 'original': + if build != 'product': + mx.log('only product build of original VM exists') + continue vmDir = join(_vmLibDirInJdk(jdk), vm) if not exists(vmDir): @@ -574,9 +603,7 @@ # Check if a build really needs to be done timestampFile = join(vmDir, '.build-timestamp') - if vm == 'server0': - mustBuild = False - elif opts2.force or not exists(timestampFile): + if opts2.force or not exists(timestampFile): mustBuild = True else: mustBuild = False @@ -617,17 +644,26 @@ else: cpus = multiprocessing.cpu_count() runCmd = [mx.gmake_cmd()] - if build == 'debug': - build = 'jvmg' runCmd.append(build + buildSuffix) env = os.environ.copy() + + if opts2.D: + for nv in opts2.D: + name, value = nv.split('=', 1) + env[name.strip()] = value + env.setdefault('ARCH_DATA_MODEL', '64') env.setdefault('LANG', 'C') env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus)) - env['ALT_BOOTDIR'] = mx.java().jdk + env.setdefault('ALT_BOOTDIR', mx.java().jdk) + if not mx._opts.verbose: + runCmd.append('MAKE_VERBOSE=') env['JAVA_HOME'] = jdk - if not env.has_key('OMIT_GRAAL'): - env['GRAAL'] = join(_graal_home, 'graal') # needed for TEST_IN_BUILD + if vm.endswith('nograal'): + env['INCLUDE_GRAAL'] = 'false' + env.setdefault('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os())) + else: + env['INCLUDE_GRAAL'] = 'true' env.setdefault('INSTALL', 'y') if mx.get_os() == 'solaris' : # If using sparcWorks, setup flags to avoid make complaining about CC version @@ -644,9 +680,6 @@ # This removes the need to unzip the *.diz files before debugging in gdb env.setdefault('ZIP_DEBUGINFO_FILES', '0') - # We don't need to run the Queens test (i.e. test_gamma) - env.setdefault('TEST_IN_BUILD', 'false') - # Clear these 2 variables as having them set can cause very confusing build problems env.pop('LD_LIBRARY_PATH', None) env.pop('CLASSPATH', None) @@ -657,8 +690,8 @@ if not exists(jvmCfg): mx.abort(jvmCfg + ' does not exist') - prefix = '-' + vm - vmKnown = prefix + ' KNOWN\n' + prefix = '-' + vm + ' ' + vmKnown = prefix + 'KNOWN\n' lines = [] found = False with open(jvmCfg) as f: @@ -668,7 +701,7 @@ lines.append(line) if not found: - mx.log('Appending "' + prefix + ' KNOWN" to ' + jvmCfg) + mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg) if mx.get_os() != 'windows': os.chmod(jvmCfg, 0755) with open(jvmCfg, 'w') as f: @@ -776,12 +809,14 @@ name = 'JUnitWrapper' javaSource = join(mxdir, name + '.java') javaClass = join(mxdir, name + '.class') - (_, testfile) = tempfile.mkstemp(".testclasses", "graal") + testfile = os.environ.get('MX_TESTFILE', None) + if testfile is None: + (_, testfile) = tempfile.mkstemp(".testclasses", "graal") def harness(projectscp, vmArgs): if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource]) - if _vm == 'server0': + if _vm == 'original' or _vm.endswith('nograal'): prefixArgs = ['-esa', '-ea'] else: prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea'] @@ -790,7 +825,8 @@ try: _run_tests(args, harness, annotations, testfile) finally: - os.remove(testfile) + if os.environ.get('MX_TESTFILE') is None: + os.remove(testfile) def unittest(args): """run the JUnit tests (all testcases) @@ -822,9 +858,14 @@ def buildvms(args): """build one or more VMs in various configurations""" + vmsDefault = ','.join(_vmChoices) + vmbuildsDefault = ','.join(_vmbuildChoices) + parser = ArgumentParser(prog='mx buildvms'); - parser.add_argument('--vms', help='a comma separated list of VMs to build (default: server,client,graal)', default='server,client,graal') - parser.add_argument('--builds', help='a comma separated list of build types (default: product,fastdebug,debug)', default='product,fastdebug,debug') + parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='', default=vmsDefault) + parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='', default=vmbuildsDefault) + parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build') + parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file') args = parser.parse_args(args) vms = args.vms.split(',') @@ -833,14 +874,26 @@ allStart = time.time() for v in vms: for vmbuild in builds: - logFile = join(v + '-' + vmbuild + '.log') - log = open(join(_graal_home, logFile), 'wb') - start = time.time() - mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')') - # Run as subprocess so that output can be directed to a file - subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, 'build', vmbuild], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT) - duration = datetime.timedelta(seconds=time.time() - start) - mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']') + if v == 'original' and vmbuild != 'product': + continue + if not args.console: + logFile = join(v + '-' + vmbuild + '.log') + log = open(join(_graal_home, logFile), 'wb') + start = time.time() + mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')') + # Run as subprocess so that output can be directed to a file + subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, 'build', vmbuild], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT) + duration = datetime.timedelta(seconds=time.time() - start) + mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']') + else: + global _vm + _vm = v + build([vmbuild]) + if not args.no_check: + vmargs = ['-version'] + if v == 'graal': + vmargs.insert(0, '-XX:-BootstrapGraal') + vm(vmargs, vm=v, vmbuild=vmbuild) allDuration = datetime.timedelta(seconds=time.time() - allStart) mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') @@ -910,6 +963,12 @@ t = Task('BuildJava') build(['--no-native', '--jdt-warning-as-error']) tasks.append(t.stop()) + + t = Task('Check build-graal.xml') + mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring make/build-graal.xml file is up to date...')) + if initantbuild([]): + t.abort('Rerun "mx build" and check-in the modified make/build-graal.xml file.') + tasks.append(t.stop()) t = Task('Checkstyle') if mx.checkstyle([]) != 0: @@ -965,6 +1024,7 @@ if args.buildNonGraal: t = Task('BuildHotSpotVarieties') buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) + buildvms(['--vms', 'server-nograal', '--builds', 'product']) tasks.append(t.stop()) for vmbuild in ['product', 'fastdebug']: @@ -1096,6 +1156,13 @@ if ('specjbb2013' in args): # or 'all' in args //currently not in default set benchmarks += [sanitycheck.getSPECjbb2013()] + + if ('ctw-full' in args): + benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.Full)) + if ('ctw-noinline' in args): + benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoInline)) + if ('ctw-nocomplex' in args): + benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoComplex)) for test in benchmarks: for (groupName, res) in test.bench(vm, opts=vmArgs).items(): @@ -1257,6 +1324,7 @@ _vmbuild = 'product' commands = { 'build': [build, '[-options]'], + 'buildvars': [buildvars, ''], 'buildvms': [buildvms, '[-options]'], 'clean': [clean, ''], 'hsdis': [hsdis, '[att]'], @@ -1269,7 +1337,6 @@ 'specjvm2008': [specjvm2008, '[VM options|specjvm2008 options (-v, -ikv, -ict, -wt, -it)]'], 'specjbb2013': [specjbb2013, '[VM options]'], 'specjbb2005': [specjbb2005, '[VM options]'], - #'example': [example, '[-v] example names...'], 'gate' : [gate, '[-options]'], 'gv' : [gv, ''], 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], @@ -1288,18 +1355,16 @@ mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) if (_vmSourcesAvailable): - mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=['graal', 'server', 'client', 'server0'], help='the VM to build/run (default: graal)') - mx.add_argument('--product', action='store_const', dest='vmbuild', const='product', help='select the product build of the VM') - mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug build of the VM') - mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug build of the VM') + mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=_vmChoices, help='the VM to build/run (default: ' + _vmChoices[0] + ')') + for c in _vmbuildChoices: + mx.add_argument('--' + c, action='store_const', dest='vmbuild', const=c, help='select the ' + c + ' build of the VM') mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse') mx.add_argument('--native-dbg', action='store', dest='native_dbg', help='Start the vm inside a debugger', metavar='') mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='native_dbg', help='alias for --native-dbg /usr/bin/gdb -- args') - commands.update({ 'export': [export, '[-options] [zipfile]'], - 'build': [build, '[-options] [product|debug|fastdebug]...'] + 'build': [build, '[-options] [' + '|'.join(_vmbuildChoices) + ']...'] }) mx.commands.update(commands) diff -r b69312e4eceb -r 9d29e5aa54d2 mx/eclipse-settings/org.eclipse.core.resources.prefs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mx/eclipse-settings/org.eclipse.core.resources.prefs Sat Apr 20 12:23:29 2013 +0200 @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=US-ASCII \ No newline at end of file diff -r b69312e4eceb -r 9d29e5aa54d2 mx/projects --- a/mx/projects Sat Apr 20 12:22:54 2013 +0200 +++ b/mx/projects Sat Apr 20 12:23:29 2013 +0200 @@ -1,5 +1,7 @@ # The format of this file is described in the documentation for my.py. +suite=graal + library@JDK_TOOLS@path=${JAVA_HOME}/lib/tools.jar library@JDK_TOOLS@optional=true @@ -125,7 +127,7 @@ # graal.hotspot.test project@com.oracle.graal.hotspot.test@subDir=graal project@com.oracle.graal.hotspot.test@sourceDirs=src -project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test,com.oracle.graal.hotspot +project@com.oracle.graal.hotspot.test@dependencies=com.oracle.graal.replacements.test project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot.test@javaCompliance=1.7 @@ -155,6 +157,13 @@ project@com.oracle.graal.debug@checkstyle=com.oracle.graal.graph project@com.oracle.graal.debug@javaCompliance=1.7 +# graal.debug.test +project@com.oracle.graal.debug.test@subDir=graal +project@com.oracle.graal.debug.test@sourceDirs=src +project@com.oracle.graal.debug.test@dependencies=JUNIT,com.oracle.graal.debug +project@com.oracle.graal.debug.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.debug.test@javaCompliance=1.7 + # graal.lir project@com.oracle.graal.lir@subDir=graal project@com.oracle.graal.lir@sourceDirs=src @@ -200,7 +209,7 @@ # graal.replacements project@com.oracle.graal.replacements@subDir=graal project@com.oracle.graal.replacements@sourceDirs=src -project@com.oracle.graal.replacements@dependencies=com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.word,com.oracle.graal.api.runtime +project@com.oracle.graal.replacements@dependencies=com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.word project@com.oracle.graal.replacements@checkstyle=com.oracle.graal.graph project@com.oracle.graal.replacements@javaCompliance=1.7 project@com.oracle.graal.replacements@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor @@ -215,7 +224,7 @@ # graal.replacements.test project@com.oracle.graal.replacements.test@subDir=graal project@com.oracle.graal.replacements.test@sourceDirs=src -project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.replacements,com.oracle.graal.compiler.test +project@com.oracle.graal.replacements.test@dependencies=com.oracle.graal.compiler.test project@com.oracle.graal.replacements.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.replacements.test@javaCompliance=1.7 @@ -264,9 +273,10 @@ # graal.compiler project@com.oracle.graal.compiler@subDir=graal project@com.oracle.graal.compiler@sourceDirs=src -project@com.oracle.graal.compiler@dependencies=com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir +project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler@javaCompliance=1.7 +project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor # graal.compiler.amd64 project@com.oracle.graal.compiler.amd64@subDir=graal @@ -333,7 +343,7 @@ # graal.compiler.test project@com.oracle.graal.compiler.test@subDir=graal project@com.oracle.graal.compiler.test@sourceDirs=src -project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,com.oracle.graal.test +project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.hotspot project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.test@javaCompliance=1.7 diff -r b69312e4eceb -r 9d29e5aa54d2 mx/sanitycheck.py --- a/mx/sanitycheck.py Sat Apr 20 12:22:54 2013 +0200 +++ b/mx/sanitycheck.py Sat Apr 20 12:23:29 2013 +0200 @@ -220,6 +220,34 @@ tests.append(Test("Bootstrap-bigHeap", ['-version'], successREs=[time], scoreMatchers=[scoreMatcherBig], vmOpts=['-Xms2g'], ignoredVMs=['client', 'server'], benchmarkCompilationRate=False)) return tests +class CTWMode: + Full, NoInline, NoComplex = range(3) + +def getCTW(vm,mode): + time = re.compile(r"CompileTheWorld : Done \([0-9]+ classes, [0-9]+ methods, (?P