# HG changeset patch # User Michael Van De Vanter # Date 1401250801 25200 # Node ID 57303ce74a21c7952a38efe2c48499435b8efb88 # Parent eedf6c29363921cf798ae4c359da103682db44b3# Parent 5c73b162eec248fc2d06f59d8f25860871a21be5 Merge with 5c73b162eec248fc2d06f59d8f25860871a21be5 diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Tue May 27 21:20:01 2014 -0700 @@ -63,7 +63,7 @@ assert NULL_OBJECT.isNull(); } - protected Constant(Kind kind) { + protected Constant(PlatformKind kind) { super(kind); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Service.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Service.java Tue May 27 21:20:01 2014 -0700 @@ -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.runtime; + +/** + * Denotes a service that may be efficiently loaded by {@link Services#load(Class)}. + */ +public interface Service { +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 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.runtime; + +import static java.lang.String.*; + +import java.util.*; + +/** + * A mechanism on top of the standard {@link ServiceLoader} that enables a runtime to efficiently + * load services marked by {@link Service}. This may be important for services loaded early in the + * runtime initialization process. + */ +public class Services { + + private static final ClassValue> cache = new ClassValue>() { + @Override + protected List computeValue(Class type) { + Service[] names = getServiceImpls(type); + if (names == null || names.length == 0) { + throw new InternalError(format("No implementations for %s found (ensure %s extends %s)", type.getSimpleName(), type.getSimpleName(), Service.class)); + } + return Arrays.asList(names); + } + }; + + /** + * Gets an {@link Iterable} of the implementations available for a given service. + */ + @SuppressWarnings("unchecked") + public static Iterable load(Class service) { + if (Service.class.isAssignableFrom(service)) { + try { + return (Iterable) cache.get(service); + } catch (UnsatisfiedLinkError e) { + // Fall back to standard SerivceLoader + } + } + return ServiceLoader.loadInstalled(service); + } + + private static native S[] getServiceImpls(Class service); +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java --- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java Tue May 27 21:20:01 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ /** * Closes this buffer. No extra data can be written to this buffer after this call. - * + * * @param trimmedCopy if {@code true}, then a copy of the underlying byte array up to (but not * including) {@code position()} is returned * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true} @@ -68,7 +68,7 @@ /** * Copies the data from this buffer into a given array. - * + * * @param dst the destination array * @param off starting position in {@code dst} * @param len number of bytes to copy @@ -114,7 +114,7 @@ } public int emitByte(int b, int pos) { - assert NumUtil.isUByte(b); + assert NumUtil.isUByte(b) || NumUtil.isByte(b); int newPos = pos + 1; ensureSize(newPos); data[pos] = (byte) (b & 0xFF); @@ -139,7 +139,7 @@ @Override public int emitShort(int b, int pos) { - assert NumUtil.isUShort(b); + assert NumUtil.isUShort(b) || NumUtil.isShort(b); int newPos = pos + 2; ensureSize(pos + 2); data[pos] = (byte) ((b >> 8) & 0xFF); @@ -188,7 +188,7 @@ @Override public int emitShort(int b, int pos) { - assert NumUtil.isUShort(b); + assert NumUtil.isUShort(b) || NumUtil.isShort(b); int newPos = pos + 2; ensureSize(newPos); data[pos] = (byte) (b & 0xFF); diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue May 27 21:20:01 2014 -0700 @@ -131,13 +131,7 @@ @Override public Variable emitMove(Value input) { - PlatformKind kind; - if (input instanceof Constant) { - kind = input.getKind().getStackKind(); - } else { - kind = input.getPlatformKind(); - } - Variable result = newVariable(kind); + Variable result = newVariable(input.getPlatformKind()); emitMove(result, input); return result; } @@ -248,18 +242,10 @@ public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) { boolean mirrored = emitCompare(cmpKind, left, right); Condition finalCondition = mirrored ? cond.mirror() : cond; - switch (left.getKind().getStackKind()) { - case Int: - case Long: - case Object: - append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); - break; - case Float: - case Double: - append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability)); - break; - default: - throw GraalInternalError.shouldNotReachHere("" + left.getKind()); + if (cmpKind == Kind.Float || cmpKind == Kind.Double) { + append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability)); + } else { + append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); } } @@ -267,18 +253,10 @@ double trueLabelProbability) { boolean mirrored = emitCompareMemory(cmpKind, left, right, state); Condition finalCondition = mirrored ? cond.mirror() : cond; - switch (left.getKind().getStackKind()) { - case Int: - case Long: - case Object: - append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); - break; - case Float: - case Double: - append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability)); - break; - default: - throw GraalInternalError.shouldNotReachHere("" + left.getKind()); + if (cmpKind == Kind.Float || cmpKind == Kind.Double) { + append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability)); + } else { + append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); } } @@ -299,18 +277,10 @@ 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("" + left.getKind()); + if (cmpKind == Kind.Float || cmpKind == Kind.Double) { + append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); + } else { + append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); } return result; } @@ -376,13 +346,13 @@ emitCompareRegMemoryOp(cmpKind, left, b, state); mirrored = false; } else { - emitCompareMemoryConOp(cmpKind, b, a, state); + emitCompareMemoryConOp(cmpKind, b, (Constant) a, state); mirrored = true; } return mirrored; } - protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Value value, LIRFrameState state) { + protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Constant value, LIRFrameState state) { assert kind.getStackKind() == value.getKind().getStackKind(); switch (kind) { case Byte: @@ -399,6 +369,10 @@ case Long: append(new CompareMemoryOp(LCMP, kind, address, value, state)); break; + case Object: + assert value.isNull(); + append(new CompareMemoryOp(ACMP, kind, address, value, state)); + break; default: throw GraalInternalError.shouldNotReachHere(); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java Tue May 27 21:20:01 2014 -0700 @@ -53,6 +53,12 @@ } @Override + public Stamp constant(Constant c, MetaAccessProvider meta) { + ResolvedJavaType constType = c.isNull() ? null : meta.lookupJavaType(c); + return copyWith(constType, c.isNonNull(), c.isNonNull(), c.isNull()); + } + + @Override public boolean isLegal() { return !exactType || (type != null && (isConcreteType(type))); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Tue May 27 21:20:01 2014 -0700 @@ -54,6 +54,12 @@ } @Override + public Stamp constant(Constant c, MetaAccessProvider meta) { + assert c.getKind().isNumericFloat() && c.getKind().getBitCount() == getBits(); + return StampFactory.forConstant(c); + } + + @Override public boolean isLegal() { return lowerBound <= upperBound || !nonNaN; } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java Tue May 27 21:20:01 2014 -0700 @@ -55,6 +55,11 @@ } @Override + public Stamp constant(Constant c, MetaAccessProvider meta) { + throw GraalInternalError.shouldNotReachHere("illegal stamp has no value"); + } + + @Override public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { throw GraalInternalError.shouldNotReachHere("illegal stamp has no Java type"); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Tue May 27 21:20:01 2014 -0700 @@ -64,6 +64,12 @@ } @Override + public Stamp constant(Constant c, MetaAccessProvider meta) { + long value = c.asLong(); + return StampFactory.forInteger(getBits(), value, value); + } + + @Override public boolean isLegal() { return lowerBound <= upperBound; } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java Tue May 27 21:20:01 2014 -0700 @@ -88,6 +88,15 @@ public abstract Stamp illegal(); /** + * If it is possible to represent single value stamps of this kind, this method returns the + * stamp representing the single value c. stamp.constant(c).asConstant() should be equal to c. + *

+ * If it is not possible to represent single value stamps, this method returns a stamp that + * includes c, and is otherwise as narrow as possible. + */ + public abstract Stamp constant(Constant c, MetaAccessProvider meta); + + /** * Test whether two stamps have the same base type. */ public abstract boolean isCompatible(Stamp other); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java Tue May 27 21:20:01 2014 -0700 @@ -195,7 +195,6 @@ } public static Stamp forConstant(Constant value, MetaAccessProvider metaAccess) { - assert value.getKind() == Kind.Object; if (value.getKind() == Kind.Object) { ResolvedJavaType type = value.isNull() ? null : metaAccess.lookupJavaType(value); return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull()); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java Tue May 27 21:20:01 2014 -0700 @@ -102,6 +102,11 @@ return true; } + @Override + public Stamp constant(Constant c, MetaAccessProvider meta) { + throw GraalInternalError.shouldNotReachHere("void stamp has no value"); + } + private static VoidStamp instance = new VoidStamp(); static VoidStamp getInstance() { diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java --- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Tue May 27 21:20:01 2014 -0700 @@ -54,7 +54,7 @@ private static synchronized void installSubstitutions() { if (!substitutionsInstalled) { - getHSAILBackend().getProviders().getReplacements().registerSubstitutions(ForceDeoptSubstitutions.class); + getHSAILBackend().getProviders().getReplacements().registerSubstitutions(GraalKernelTester.class, ForceDeoptSubstitutions.class); substitutionsInstalled = true; } } diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue May 27 21:20:01 2014 -0700 @@ -89,7 +89,7 @@ private void installSubstitutions() { if (!substitutionsInstalled) { - this.providers.getReplacements().registerSubstitutions(InjectProfileDataSubstitutions.class); + this.providers.getReplacements().registerSubstitutions(GraalCompilerTest.class, InjectProfileDataSubstitutions.class); substitutionsInstalled = true; } } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Tue May 27 21:20:01 2014 -0700 @@ -69,45 +69,60 @@ */ public Interval any; - public RegisterBindingLists(Interval fixed, Interval any) { + /** + * List of intervals whose binding is currently {@link RegisterBinding#Stack}. + */ + public Interval stack; + + public RegisterBindingLists(Interval fixed, Interval any, Interval stack) { this.fixed = fixed; this.any = any; + this.stack = stack; } /** * Gets the list for a specified binding. - * + * * @param binding specifies the list to be returned * @return the list of intervals whose binding is {@code binding} */ public Interval get(RegisterBinding binding) { - if (binding == RegisterBinding.Any) { - return any; + switch (binding) { + case Any: + return any; + case Fixed: + return fixed; + case Stack: + return stack; } - assert binding == RegisterBinding.Fixed; - return fixed; + throw GraalInternalError.shouldNotReachHere(); } /** * Sets the list for a specified binding. - * + * * @param binding specifies the list to be replaced * @param list a list of intervals whose binding is {@code binding} */ public void set(RegisterBinding binding, Interval list) { assert list != null; - if (binding == RegisterBinding.Any) { - any = list; - } else { - assert binding == RegisterBinding.Fixed; - fixed = list; + switch (binding) { + case Any: + any = list; + break; + case Fixed: + fixed = list; + break; + case Stack: + stack = list; + break; } } /** * Adds an interval to a list sorted by {@linkplain Interval#currentFrom() current from} * positions. - * + * * @param binding specifies the list to be updated * @param interval the interval to add */ @@ -134,7 +149,7 @@ /** * Adds an interval to a list sorted by {@linkplain Interval#from() start} positions and * {@linkplain Interval#firstUsage(RegisterPriority) first usage} positions. - * + * * @param binding specifies the list to be updated * @param interval the interval to add */ @@ -157,7 +172,7 @@ /** * Removes an interval from a list. - * + * * @param binding specifies the list to be updated * @param i the interval to remove */ @@ -234,7 +249,12 @@ /** * Interval has no specific register requirements. */ - Any; + Any, + + /** + * Interval is bound to a stack slot. + */ + Stack; public static final RegisterBinding[] VALUES = values(); } @@ -310,7 +330,7 @@ * List of use positions. Each entry in the list records the use position and register priority * associated with the use position. The entries in the list are in descending order of use * position. - * + * */ public static final class UsePosList { @@ -318,7 +338,7 @@ /** * Creates a use list. - * + * * @param initialCapacity the initial capacity of the list in terms of entries */ public UsePosList(int initialCapacity) { @@ -333,7 +353,7 @@ * Splits this list around a given position. All entries in this list with a use position * greater or equal than {@code splitPos} are removed from this list and added to the * returned list. - * + * * @param splitPos the position for the split * @return a use position list containing all entries removed from this list that have a use * position greater or equal than {@code splitPos} @@ -355,7 +375,7 @@ /** * Gets the use position at a specified index in this list. - * + * * @param index the index of the entry for which the use position is returned * @return the use position of entry {@code index} in this list */ @@ -365,7 +385,7 @@ /** * Gets the register priority for the use position at a specified index in this list. - * + * * @param index the index of the entry for which the register priority is returned * @return the register priority of entry {@code index} in this list */ @@ -863,6 +883,32 @@ return true; } + // returns the interval that covers the given opId or null if there is none + Interval getIntervalCoveringOpId(int opId) { + assert opId >= 0 : "invalid opId"; + assert opId < to() : "can only look into the past"; + + if (opId >= from()) { + return this; + } + + Interval parent = splitParent(); + Interval result = null; + + assert !parent.splitChildren.isEmpty() : "no split children available"; + int len = parent.splitChildren.size(); + + for (int i = len - 1; i >= 0; i--) { + Interval cur = parent.splitChildren.get(i); + if (cur.from() <= opId && opId < cur.to()) { + assert result == null : "covered by multiple split children " + result + " and " + cur; + result = cur; + } + } + + return result; + } + // returns the last split child that ends before the given opId Interval getSplitChildBeforeOpId(int opId) { assert opId >= 0 : "invalid opId"; @@ -1044,7 +1090,7 @@ * When a split child is split again, the new created interval is a direct child of the original * parent. That is, there is no tree of split children stored, just a flat list. All split * children are spilled to the same {@linkplain #spillSlot spill slot}. - * + * * @param splitPos the position at which to split this interval * @param allocator the register allocator context * @return the child interval split off from this interval @@ -1094,7 +1140,7 @@ /** * Splits this interval at a specified position and returns the head as a new interval (this * interval is the tail). - * + * * Currently, only the first range can be split, and the new interval must not have split * positions */ @@ -1196,7 +1242,7 @@ /** * Gets a single line string for logging the details of this interval to a log stream. - * + * * @param allocator the register allocator context */ public String logString(LinearScan allocator) { diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java Tue May 27 21:20:01 2014 -0700 @@ -36,22 +36,17 @@ /** * Sorted list of intervals, not live before the current position. */ - RegisterBindingLists unhandledLists; + protected RegisterBindingLists unhandledLists; /** * Sorted list of intervals, live at the current position. */ - RegisterBindingLists activeLists; + protected RegisterBindingLists activeLists; /** * Sorted list of intervals in a life time hole at the current position. */ - RegisterBindingLists inactiveLists; - - /** - * The current interval (taken from the unhandled list) being processed. - */ - protected Interval currentInterval; + protected RegisterBindingLists inactiveLists; /** * The current position (intercept point through the intervals). @@ -64,14 +59,12 @@ protected RegisterBinding currentBinding; /** - * Processes the {@linkplain #currentInterval} interval in an attempt to allocate a physical - * register to it and thus allow it to be moved to a list of {@linkplain #activeLists active} - * intervals. - * - * @return {@code true} if a register was allocated to the {@linkplain #currentInterval} - * interval + * Processes the {@code currentInterval} interval in an attempt to allocate a physical register + * to it and thus allow it to be moved to a list of {@linkplain #activeLists active} intervals. + * + * @return {@code true} if a register was allocated to the {@code currentInterval} interval */ - boolean activateCurrent() { + protected boolean activateCurrent(@SuppressWarnings({"unused"}) Interval currentInterval) { return true; } @@ -85,7 +78,7 @@ /** * Creates a new interval walker. - * + * * @param allocator the register allocator context * @param unhandledFixed the list of unhandled {@linkplain RegisterBinding#Fixed fixed} * intervals @@ -95,15 +88,13 @@ IntervalWalker(LinearScan allocator, Interval unhandledFixed, Interval unhandledAny) { this.allocator = allocator; - unhandledLists = new RegisterBindingLists(unhandledFixed, unhandledAny); - activeLists = new RegisterBindingLists(Interval.EndMarker, Interval.EndMarker); - inactiveLists = new RegisterBindingLists(Interval.EndMarker, Interval.EndMarker); + unhandledLists = new RegisterBindingLists(unhandledFixed, unhandledAny, Interval.EndMarker); + activeLists = new RegisterBindingLists(Interval.EndMarker, Interval.EndMarker, Interval.EndMarker); + inactiveLists = new RegisterBindingLists(Interval.EndMarker, Interval.EndMarker, Interval.EndMarker); currentPosition = -1; - currentInterval = null; - nextInterval(); } - void removeFromList(Interval interval) { + protected void removeFromList(Interval interval) { if (interval.state == State.Active) { activeLists.remove(RegisterBinding.Any, interval); } else { @@ -112,7 +103,7 @@ } } - void walkTo(State state, int from) { + private void walkTo(State state, int from) { assert state == State.Active || state == State.Inactive : "wrong state"; for (RegisterBinding binding : RegisterBinding.VALUES) { Interval prevprev = null; @@ -176,7 +167,16 @@ } } - void nextInterval() { + /** + * Get the next interval from {@linkplain #unhandledLists} which starts before or at + * {@code toOpId}. The returned interval is removed and {@link #currentBinding} is set. + * + * @postcondition all intervals in {@linkplain #unhandledLists} start after {@code toOpId}. + * + * @return The next interval or null if there is no {@linkplain #unhandledLists unhandled} + * interval at position {@code toOpId}. + */ + private Interval nextInterval(int toOpId) { RegisterBinding binding; Interval any = unhandledLists.any; Interval fixed = unhandledLists.fixed; @@ -191,42 +191,61 @@ } else if (fixed != Interval.EndMarker) { binding = RegisterBinding.Fixed; } else { - currentInterval = null; - return; + return null; } + Interval currentInterval = unhandledLists.get(binding); + + if (toOpId < currentInterval.from()) { + return null; + } + currentBinding = binding; - currentInterval = unhandledLists.get(binding); unhandledLists.set(binding, currentInterval.next); currentInterval.next = Interval.EndMarker; currentInterval.rewindRange(); + return currentInterval; } - void walkTo(int toOpId) { + /** + * Walk up to {@code toOpId}. + * + * @postcondition {@link #currentPosition} is set to {@code toOpId}, {@link #activeLists} and + * {@link #inactiveLists} are populated and {@link Interval#state}s are up to + * date. + */ + protected void walkTo(int toOpId) { assert currentPosition <= toOpId : "can not walk backwards"; - while (currentInterval != null) { - boolean isActive = currentInterval.from() <= toOpId; - int opId = isActive ? currentInterval.from() : toOpId; + for (Interval currentInterval = nextInterval(toOpId); currentInterval != null; currentInterval = nextInterval(toOpId)) { + int opId = currentInterval.from(); // set currentPosition prior to call of walkTo currentPosition = opId; + // update unhandled stack intervals + updateUnhandledStackIntervals(opId); + // call walkTo even if currentPosition == id walkTo(State.Active, opId); walkTo(State.Inactive, opId); - if (isActive) { - try (Indent indent = Debug.logAndIndent("walk to op %d", opId)) { - currentInterval.state = State.Active; - if (activateCurrent()) { - activeLists.addToListSortedByCurrentFromPositions(currentBinding, currentInterval); - intervalMoved(currentInterval, State.Unhandled, State.Active); - } + try (Indent indent = Debug.logAndIndent("walk to op %d", opId)) { + currentInterval.state = State.Active; + if (activateCurrent(currentInterval)) { + activeLists.addToListSortedByCurrentFromPositions(currentBinding, currentInterval); + intervalMoved(currentInterval, State.Unhandled, State.Active); + } + } + } + // set currentPosition prior to call of walkTo + currentPosition = toOpId; - nextInterval(); - } - } else { - return; - } + if (currentPosition <= allocator.maxOpId()) { + // update unhandled stack intervals + updateUnhandledStackIntervals(toOpId); + + // call walkTo if still in range + walkTo(State.Active, toOpId); + walkTo(State.Inactive, toOpId); } } @@ -237,4 +256,29 @@ Debug.log("interval moved from %s to %s: %s", from, to, interval.logString(allocator)); } } + + /** + * Move {@linkplain #unhandledLists unhandled} stack intervals to + * {@linkplain IntervalWalker #activeLists active}. + * + * Note that for {@linkplain RegisterBinding#Fixed fixed} and {@linkplain RegisterBinding#Any + * any} intervals this is done in {@link #nextInterval(int)}. + */ + private void updateUnhandledStackIntervals(int opId) { + Interval currentInterval = unhandledLists.get(RegisterBinding.Stack); + while (currentInterval != Interval.EndMarker && currentInterval.from() <= opId) { + Interval next = currentInterval.next; + if (currentInterval.to() > opId) { + currentInterval.state = State.Active; + activeLists.addToListSortedByCurrentFromPositions(RegisterBinding.Stack, currentInterval); + intervalMoved(currentInterval, State.Unhandled, State.Active); + } else { + currentInterval.state = State.Handled; + intervalMoved(currentInterval, State.Unhandled, State.Handled); + } + currentInterval = next; + } + unhandledLists.set(RegisterBinding.Stack, currentInterval); + } + } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue May 27 21:20:01 2014 -0700 @@ -1396,7 +1396,12 @@ notPrecoloredIntervals = result.second; // allocate cpu registers - LinearScanWalker lsw = new LinearScanWalker(this, precoloredIntervals, notPrecoloredIntervals); + LinearScanWalker lsw; + if (OptimizingLinearScanWalker.Options.LSRAOptimization.getValue()) { + lsw = new OptimizingLinearScanWalker(this, precoloredIntervals, notPrecoloredIntervals); + } else { + lsw = new LinearScanWalker(this, precoloredIntervals, notPrecoloredIntervals); + } lsw.walk(); lsw.finishAllocation(); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Tue May 27 21:20:01 2014 -0700 @@ -42,14 +42,14 @@ /** */ -final class LinearScanWalker extends IntervalWalker { +class LinearScanWalker extends IntervalWalker { - private Register[] availableRegs; + protected Register[] availableRegs; - private final int[] usePos; - private final int[] blockPos; + protected final int[] usePos; + protected final int[] blockPos; - private List[] spillIntervals; + protected List[] spillIntervals; private MoveResolver moveResolver; // for ordering spill moves @@ -430,7 +430,7 @@ splitPart.setInsertMoveWhenActivated(moveNecessary); - assert splitPart.from() >= currentInterval.currentFrom() : "cannot append new interval before current walk position"; + assert splitPart.from() >= currentPosition : "cannot append new interval before current walk position"; unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Any, splitPart); if (Debug.isLogEnabled()) { @@ -466,6 +466,7 @@ assert interval.firstUsage(RegisterPriority.ShouldHaveRegister) > currentPosition : "interval must not have use position before currentPosition"; allocator.assignSpillSlot(interval); + handleSpillSlot(interval); allocator.changeSpillState(interval, minSplitPos); // Also kick parent intervals out of register to memory when they have no use @@ -480,6 +481,7 @@ // parent is never used, so kick it out of its assigned register Debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); allocator.assignSpillSlot(parent); + handleSpillSlot(parent); } else { // do not go further back because the register is actually used by // the interval @@ -508,6 +510,7 @@ Interval spilledPart = interval.split(optimalSplitPos, allocator); allocator.assignSpillSlot(spilledPart); + handleSpillSlot(spilledPart); allocator.changeSpillState(spilledPart, optimalSplitPos); if (!allocator.isBlockBegin(optimalSplitPos)) { @@ -528,6 +531,14 @@ } } + /** + * This is called for every interval that is assigned to a stack slot. + */ + protected void handleSpillSlot(Interval interval) { + assert interval.location() != null && (interval.canMaterialize() || isStackSlot(interval.location())) : "interval not assigned to a stack slot " + interval; + // Do nothing. Stack slots are not processed in this implementation. + } + void splitStackInterval(Interval interval) { int minSplitPos = currentPosition + 1; int maxSplitPos = Math.min(interval.firstUsage(RegisterPriority.ShouldHaveRegister), interval.to()); @@ -836,8 +847,7 @@ // allocate a physical register or memory location to an interval @Override - boolean activateCurrent() { - Interval interval = currentInterval; + protected boolean activateCurrent(Interval interval) { boolean result = true; try (Indent indent = Debug.logAndIndent("activating interval %s, splitParent: %d", interval, interval.splitParent().operandNumber)) { diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/OptimizingLinearScanWalker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/OptimizingLinearScanWalker.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.alloc; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.alloc.Interval.RegisterBinding; +import com.oracle.graal.compiler.alloc.Interval.RegisterBindingLists; +import com.oracle.graal.compiler.alloc.Interval.State; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.options.*; + +public class OptimizingLinearScanWalker extends LinearScanWalker { + + public static class Options { + // @formatter:off + @Option(help = "Enable LSRA optimization") + public static final OptionValue LSRAOptimization = new OptionValue<>(true); + @Option(help = "LSRA optimization: Only split but do not reassign") + public static final OptionValue LSRAOptSplitOnly = new OptionValue<>(false); + // @formatter:on + } + + OptimizingLinearScanWalker(LinearScan allocator, Interval unhandledFixedFirst, Interval unhandledAnyFirst) { + super(allocator, unhandledFixedFirst, unhandledAnyFirst); + } + + @Override + protected void handleSpillSlot(Interval interval) { + assert interval.location() != null : "interval not assigned " + interval; + if (interval.canMaterialize()) { + assert !isStackSlot(interval.location()) : "interval can materialize but assigned to a stack slot " + interval; + return; + } + assert isStackSlot(interval.location()) : "interval not assigned to a stack slot " + interval; + try (Scope s1 = Debug.scope("LSRAOptimization")) { + Debug.log("adding stack to unhandled list %s", interval); + unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Stack, interval); + } + } + + @SuppressWarnings("unused") + private static void printRegisterBindingList(RegisterBindingLists list, RegisterBinding binding) { + for (Interval interval = list.get(binding); interval != Interval.EndMarker; interval = interval.next) { + Debug.log("%s", interval); + } + } + + @Override + void walk() { + try (Scope s = Debug.scope("OptimizingLinearScanWalker")) { + for (AbstractBlock block : allocator.sortedBlocks) { + int nextBlock = allocator.getFirstLirInstructionId(block); + try (Scope s1 = Debug.scope("LSRAOptimization")) { + Debug.log("next block: %s (%d)", block, nextBlock); + } + try (Indent indent0 = Debug.indent()) { + walkTo(nextBlock); + + try (Scope s1 = Debug.scope("LSRAOptimization")) { + boolean changed = true; + // we need to do this because the active lists might change + loop: while (changed) { + changed = false; + try (Indent indent1 = Debug.logAndIndent("Active intervals: (block %s [%d])", block, nextBlock)) { + for (Interval active = activeLists.get(RegisterBinding.Any); active != Interval.EndMarker; active = active.next) { + Debug.log("active (any): %s", active); + if (optimize(nextBlock, block, active, RegisterBinding.Any)) { + changed = true; + break loop; + } + } + for (Interval active = activeLists.get(RegisterBinding.Stack); active != Interval.EndMarker; active = active.next) { + Debug.log("active (stack): %s", active); + if (optimize(nextBlock, block, active, RegisterBinding.Stack)) { + changed = true; + break loop; + } + } + } + } + } + } + } + } + super.walk(); + } + + private boolean optimize(int currentPos, AbstractBlock currentBlock, Interval currentInterval, RegisterBinding binding) { + // BEGIN initialize and sanity checks + assert currentBlock != null : "block must not be null"; + assert currentInterval != null : "interval must not be null"; + + if (currentBlock.getPredecessorCount() != 1) { + // more than one predecessors -> optimization not possible + return false; + } + if (!currentInterval.isSplitChild()) { + // interval is not a split child -> no need for optimization + return false; + } + + if (currentInterval.from() == currentPos) { + // the interval starts at the current position so no need for splitting + return false; + } + + // get current location + AllocatableValue currentLocation = currentInterval.location(); + assert currentLocation != null : "active intervals must have a location assigned!"; + + // get predecessor stuff + AbstractBlock predecessorBlock = currentBlock.getPredecessors().get(0); + int predEndId = allocator.getLastLirInstructionId(predecessorBlock); + Interval predecessorInterval = currentInterval.getIntervalCoveringOpId(predEndId); + assert predecessorInterval != null : "variable not live at the end of the only predecessor! " + predecessorBlock + " -> " + currentBlock + " interval: " + currentInterval; + AllocatableValue predecessorLocation = predecessorInterval.location(); + assert predecessorLocation != null : "handled intervals must have a location assigned!"; + + // END initialize and sanity checks + + if (currentLocation.equals(predecessorLocation)) { + // locations are already equal -> nothing to optimize + return false; + } + + if (!isStackSlot(predecessorLocation) && !isRegister(predecessorLocation)) { + assert predecessorInterval.canMaterialize(); + // value is materialized -> no need for optimization + return false; + } + + assert isStackSlot(currentLocation) || isRegister(currentLocation) : "current location not a register or stack slot " + currentLocation; + + try (Indent indent = Debug.logAndIndent("location differs: %s vs. %s", predecessorLocation, currentLocation)) { + // split current interval at current position + Debug.log("splitting at position %d", currentPos); + + assert allocator.isBlockBegin(currentPos) && ((currentPos & 1) == 0) : "split pos must be even when on block boundary"; + + Interval splitPart = currentInterval.split(currentPos, allocator); + activeLists.remove(binding, currentInterval); + + assert splitPart.from() >= currentPosition : "cannot append new interval before current walk position"; + + // the currentSplitChild is needed later when moves are inserted for reloading + assert splitPart.currentSplitChild() == currentInterval : "overwriting wrong currentSplitChild"; + splitPart.makeCurrentSplitChild(); + + if (Debug.isLogEnabled()) { + Debug.log("left interval : %s", currentInterval.logString(allocator)); + Debug.log("right interval : %s", splitPart.logString(allocator)); + } + + if (Options.LSRAOptSplitOnly.getValue()) { + // just add the split interval to the unhandled list + unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Any, splitPart); + } else { + if (isRegister(predecessorLocation)) { + splitRegisterInterval(splitPart, asRegister(predecessorLocation)); + } else { + assert isStackSlot(predecessorLocation); + Debug.log("assigning interval %s to %s", splitPart, predecessorLocation); + splitPart.assignLocation(predecessorLocation); + // activate interval + activeLists.addToListSortedByCurrentFromPositions(RegisterBinding.Stack, splitPart); + splitPart.state = State.Active; + + splitStackInterval(splitPart); + } + } + } + return true; + } + + private void splitRegisterInterval(Interval interval, Register reg) { + // collect current usage of registers + initVarsForAlloc(interval); + initUseLists(false); + spillExcludeActiveFixed(); + // spillBlockUnhandledFixed(cur); + assert unhandledLists.get(RegisterBinding.Fixed) == Interval.EndMarker : "must not have unhandled fixed intervals because all fixed intervals have a use at position 0"; + spillBlockInactiveFixed(interval); + spillCollectActiveAny(); + spillCollectInactiveAny(interval); + + if (Debug.isLogEnabled()) { + try (Indent indent2 = Debug.logAndIndent("state of registers:")) { + for (Register register : availableRegs) { + int i = register.number; + try (Indent indent3 = Debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, intervals: ", i, usePos[i], blockPos[i])) { + for (int j = 0; j < spillIntervals[i].size(); j++) { + Debug.log("%d ", spillIntervals[i].get(j).operandNumber); + } + } + } + } + } + + // the register must be free at least until this position + boolean needSplit = blockPos[reg.number] <= interval.to(); + + int splitPos = blockPos[reg.number]; + + assert splitPos > 0 : "invalid splitPos"; + assert needSplit || splitPos > interval.from() : "splitting interval at from"; + + Debug.log("assigning interval %s to %s", interval, reg); + interval.assignLocation(reg.asValue(interval.kind())); + if (needSplit) { + // register not available for full interval : so split it + splitWhenPartialRegisterAvailable(interval, splitPos); + } + + // perform splitting and spilling for all affected intervals + splitAndSpillIntersectingIntervals(reg); + + // activate interval + activeLists.addToListSortedByCurrentFromPositions(RegisterBinding.Any, interval); + interval.state = State.Active; + + } +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeMapTest.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.test; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.graph.*; + +public class NodeMapTest { + + private static class TestNode extends Node { + } + + private Graph graph; + private TestNode[] nodes = new TestNode[100]; + private NodeMap map; + + @Before + public void before() { + graph = new Graph(); + for (int i = 0; i < nodes.length; i++) { + nodes[i] = graph.add(new TestNode()); + } + map = new NodeMap<>(graph); + for (int i = 0; i < nodes.length; i += 2) { + map.set(nodes[i], i); + } + } + + @Test + public void testEmpty() { + NodeMap emptyMap = new NodeMap<>(graph); + for (TestNode node : nodes) { + assertEquals(null, emptyMap.get(node)); + } + } + + @Test + public void testSimple() { + for (int i = 0; i < nodes.length; i++) { + if ((i & 1) == 0) { + assertEquals((Integer) i, map.get(nodes[i])); + } else { + assertEquals(null, map.get(nodes[i])); + } + } + } + + @Test + public void testSimpleChanged() { + for (TestNode node : nodes) { + map.set(node, 1); + } + for (TestNode node : nodes) { + map.set(node, null); + } + for (int i = 0; i < nodes.length; i += 2) { + map.set(nodes[i], i); + } + + for (int i = 0; i < nodes.length; i++) { + if ((i & 1) == 0) { + assertEquals((Integer) i, map.get(nodes[i])); + } else { + assertEquals(null, map.get(nodes[i])); + } + } + } + + @Test(expected = AssertionError.class) + public void testNewGet() { + /* + * Failing here is not required, but if this behavior changes, usages of get need to be + * checked for compatibility. + */ + TestNode newNode = graph.add(new TestNode()); + map.get(newNode); + } + + @Test(expected = AssertionError.class) + public void testNewSet() { + /* + * Failing here is not required, but if this behavior changes, usages of set need to be + * checked for compatibility. + */ + TestNode newNode = graph.add(new TestNode()); + map.set(newNode, 1); + } + + @Test + public void testNewGetAndGrow() { + TestNode newNode = graph.add(new TestNode()); + assertEquals(null, map.getAndGrow(newNode)); + } + + @Test + public void testNewSetAndGrow() { + TestNode newNode = graph.add(new TestNode()); + map.setAndGrow(newNode, 1); + assertEquals((Integer) 1, map.get(newNode)); + } + + @Test(expected = AssertionError.class) + public void testNewSetAndGrowMultiple() { + TestNode newNode = graph.add(new TestNode()); + map.setAndGrow(newNode, 1); + assertEquals((Integer) 1, map.get(newNode)); + /* + * Failing here is not required, but if this behavior changes, usages of getAndGrow and + * setAndGrow need to be checked for compatibility. + */ + TestNode newNode2 = graph.add(new TestNode()); + map.get(newNode2); + } +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Tue May 27 21:20:01 2014 -0700 @@ -46,6 +46,19 @@ return (T) values[getNodeId(node)]; } + @SuppressWarnings("unchecked") + public T getAndGrow(Node node) { + checkAndGrow(node); + return (T) values[getNodeId(node)]; + } + + private void checkAndGrow(Node node) { + if (isNew(node)) { + this.values = Arrays.copyOf(values, graph.nodeIdCount()); + } + assert check(node); + } + public boolean isEmpty() { return !entries().iterator().hasNext(); } @@ -78,6 +91,11 @@ values[getNodeId(node)] = value; } + public void setAndGrow(Node node, T value) { + checkAndGrow(node); + values[getNodeId(node)] = value; + } + public int size() { return values.length; } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue May 27 21:20:01 2014 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.amd64; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; + import java.util.*; import com.oracle.graal.amd64.*; @@ -30,6 +32,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; @@ -98,26 +101,65 @@ assert host == null; TargetDescription target = createTarget(runtime.getConfig()); - HotSpotRegistersProvider registers = createRegisters(); - HotSpotMetaAccessProvider metaAccess = createMetaAccess(runtime); - HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target); - HotSpotConstantReflectionProvider constantReflection = createConstantReflection(runtime); - Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); - HotSpotHostForeignCallsProvider foreignCalls = createForeignCalls(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); - HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target); - // Replacements cannot have speculative optimizations since they have - // to be valid for the entire run of the VM. - Assumptions assumptions = new Assumptions(false); - Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); - HotSpotSnippetReflectionProvider snippetReflection = createSnippetReflection(); - Replacements replacements = createReplacements(runtime, assumptions, p, snippetReflection); - HotSpotDisassemblerProvider disassembler = createDisassembler(runtime); - HotSpotSuitesProvider suites = createSuites(runtime); - HotSpotMethodHandleAccessProvider methodHandleAccess = new HotSpotMethodHandleAccessProvider(); - HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection, - methodHandleAccess); - - return createBackend(runtime, providers); + HotSpotProviders providers; + HotSpotRegistersProvider registers; + HotSpotCodeCacheProvider codeCache; + HotSpotConstantReflectionProvider constantReflection; + HotSpotHostForeignCallsProvider foreignCalls; + Value[] nativeABICallerSaveRegisters; + HotSpotMetaAccessProvider metaAccess; + HotSpotLoweringProvider lowerer; + HotSpotSnippetReflectionProvider snippetReflection; + Replacements replacements; + HotSpotDisassemblerProvider disassembler; + HotSpotSuitesProvider suites; + HotSpotMethodHandleAccessProvider methodHandleAccess; + try (InitTimer t = timer("create providers")) { + try (InitTimer rt = timer("create HotSpotRegisters provider")) { + registers = createRegisters(); + } + try (InitTimer rt = timer("create MetaAccess provider")) { + metaAccess = createMetaAccess(runtime); + } + try (InitTimer rt = timer("create CodeCache provider")) { + codeCache = createCodeCache(runtime, target); + } + try (InitTimer rt = timer("create ConstantReflection provider")) { + constantReflection = createConstantReflection(runtime); + } + try (InitTimer rt = timer("create NativeABICallerSaveRegisters")) { + nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); + } + try (InitTimer rt = timer("create ForeignCalls provider")) { + foreignCalls = createForeignCalls(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); + } + try (InitTimer rt = timer("create Lowerer provider")) { + lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target); + } + // Replacements cannot have speculative optimizations since they have + // to be valid for the entire run of the VM. + Assumptions assumptions = new Assumptions(false); + Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); + try (InitTimer rt = timer("create SnippetReflection provider")) { + snippetReflection = createSnippetReflection(); + } + try (InitTimer rt = timer("create Replacements provider")) { + replacements = createReplacements(runtime, assumptions, p, snippetReflection); + } + try (InitTimer rt = timer("create Disassembler provider")) { + disassembler = createDisassembler(runtime); + } + try (InitTimer rt = timer("create Suites provider")) { + suites = createSuites(runtime); + } + try (InitTimer rt = timer("create MethodHandleAccess provider")) { + methodHandleAccess = new HotSpotMethodHandleAccessProvider(); + } + providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection, methodHandleAccess); + } + try (InitTimer rt = timer("instantiate backend")) { + return createBackend(runtime, providers); + } } protected AMD64HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) { diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCompare.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.hotspot.data.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64Move.MemOp; +import com.oracle.graal.lir.asm.*; + +public class AMD64HotSpotCompare { + + @Opcode("NCMP") + public static class HotSpotCompareNarrowOp extends AMD64LIRInstruction { + + @Use({REG}) protected AllocatableValue x; + @Use({REG, STACK}) protected AllocatableValue y; + + public HotSpotCompareNarrowOp(AllocatableValue x, AllocatableValue y) { + this.x = x; + this.y = y; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + if (isRegister(y)) { + masm.cmpl(asRegister(x), asRegister(y)); + } else { + assert isStackSlot(y); + masm.cmpl(asRegister(x), (AMD64Address) crb.asAddress(y)); + } + } + + @Override + protected void verify() { + assert x.getPlatformKind() == NarrowOopStamp.NarrowOop && y.getPlatformKind() == NarrowOopStamp.NarrowOop; + } + } + + @Opcode("CMP") + public static class HotSpotCompareConstantOp extends AMD64LIRInstruction { + + @Use({REG}) protected AllocatableValue x; + protected Constant y; + + public HotSpotCompareConstantOp(AllocatableValue x, Constant y) { + this.x = x; + this.y = y; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + assert isRegister(x); + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(y)) { + // compressed null + masm.testl(asRegister(x), asRegister(x)); + } else if (y instanceof HotSpotObjectConstant) { + if (HotSpotObjectConstant.isCompressed(y)) { + // compressed oop + crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(y), true)); + masm.cmpl(asRegister(x), 0xDEADDEAD); + } else { + // uncompressed oop + AMD64Address patch = (AMD64Address) crb.recordDataReferenceInCode(new OopData(8, HotSpotObjectConstant.asObject(y), false)); + masm.cmpq(asRegister(x), patch); + } + } else if (y instanceof HotSpotMetaspaceConstant) { + if (y.getKind() == Kind.Int) { + // compressed metaspace pointer + crb.recordInlineDataInCode(new MetaspaceData(0, y.asInt(), HotSpotMetaspaceConstant.getMetaspaceObject(y), true)); + masm.cmpl(asRegister(x), y.asInt()); + } else { + // uncompressed metaspace pointer + AMD64Address patch = (AMD64Address) crb.recordDataReferenceInCode(new MetaspaceData(8, y.asLong(), HotSpotObjectConstant.asObject(y), false)); + masm.cmpq(asRegister(x), patch); + } + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + @Opcode("CMP") + public static class HotSpotCompareMemoryConstantOp extends MemOp { + + protected Constant y; + + public HotSpotCompareMemoryConstantOp(Kind kind, AMD64AddressValue x, Constant y, LIRFrameState state) { + super(kind, x, state); + this.y = y; + } + + @Override + protected void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(y)) { + // compressed null + masm.cmpl(address.toAddress(), 0); + } else if (y instanceof HotSpotObjectConstant) { + if (HotSpotObjectConstant.isCompressed(y) && crb.target.inlineObjects) { + // compressed oop + crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(y), true)); + masm.cmpl(address.toAddress(), 0xDEADDEAD); + } else { + // uncompressed oop + throw GraalInternalError.shouldNotReachHere(); + } + } else if (y instanceof HotSpotMetaspaceConstant) { + if (y.getKind() == Kind.Int) { + // compressed metaspace pointer + crb.recordInlineDataInCode(new MetaspaceData(0, y.asInt(), HotSpotMetaspaceConstant.getMetaspaceObject(y), true)); + masm.cmpl(address.toAddress(), y.asInt()); + } else { + // uncompressed metaspace pointer + throw GraalInternalError.shouldNotReachHere(); + } + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + } + +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Tue May 27 21:20:01 2014 -0700 @@ -26,13 +26,12 @@ import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.api.meta.Value.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*; import static com.oracle.graal.hotspot.HotSpotHostBackend.*; -import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.*; import static com.oracle.graal.hotspot.replacements.CRC32Substitutions.*; -import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue May 27 21:20:01 2014 -0700 @@ -24,8 +24,8 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import java.util.*; @@ -39,6 +39,7 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; +import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.HotSpotStoreConstantOp; import com.oracle.graal.hotspot.data.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -55,7 +56,6 @@ import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; -import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.gen.*; @@ -480,7 +480,7 @@ if (isConstant(inputVal)) { Constant c = asConstant(inputVal); if (canStoreConstant(c, false)) { - append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); + append(new HotSpotStoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); return; } } @@ -499,8 +499,7 @@ Variable result = newVariable(Kind.Int); AllocatableValue base = Value.ILLEGAL; if (encoding.base != 0) { - base = newVariable(Kind.Long); - append(new AMD64Move.MoveToRegOp(Kind.Long, base, Constant.forLong(encoding.base))); + base = emitMove(Constant.forLong(encoding.base)); } append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -518,8 +517,7 @@ Variable result = newVariable(Kind.Long); AllocatableValue base = Value.ILLEGAL; if (encoding.base != 0) { - base = newVariable(Kind.Long); - append(new AMD64Move.MoveToRegOp(Kind.Long, base, Constant.forLong(encoding.base))); + base = emitMove(Constant.forLong(encoding.base)); } append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -528,7 +526,9 @@ @Override protected AMD64LIRInstruction createMove(AllocatableValue dst, Value src) { - if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) { + if (src instanceof Constant) { + return new AMD64HotSpotMove.HotSpotLoadConstantOp(dst, (Constant) src); + } else if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) { if (isRegister(src) || isStackSlot(dst)) { return new MoveFromRegOp(Kind.Int, dst, src); } else { @@ -641,4 +641,35 @@ assert address.getKind() == Kind.Object : address + " - " + address.getKind() + " not an object!"; append(new AMD64Move.NullCheckOp(load(address), state)); } + + @Override + protected void emitCompareOp(PlatformKind cmpKind, Variable left, Value right) { + if (right instanceof HotSpotConstant) { + append(new AMD64HotSpotCompare.HotSpotCompareConstantOp(left, (Constant) right)); + } else if (cmpKind == NarrowOopStamp.NarrowOop) { + append(new AMD64HotSpotCompare.HotSpotCompareNarrowOp(left, asAllocatable(right))); + } else { + super.emitCompareOp(cmpKind, left, right); + } + } + + @Override + protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Constant value, LIRFrameState state) { + if (value instanceof HotSpotConstant) { + append(new AMD64HotSpotCompare.HotSpotCompareMemoryConstantOp(kind, address, value, state)); + } else { + super.emitCompareMemoryConOp(kind, address, value, state); + } + } + + @Override + public boolean canInlineConstant(Constant c) { + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { + return true; + } else if (c instanceof HotSpotObjectConstant) { + return HotSpotObjectConstant.isCompressed(c); + } else { + return super.canInlineConstant(c); + } + } } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Tue May 27 21:20:01 2014 -0700 @@ -36,6 +36,7 @@ import com.oracle.graal.hotspot.data.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; @@ -75,6 +76,125 @@ } } + public static class HotSpotLoadConstantOp extends AMD64LIRInstruction implements MoveOp { + + @Def({REG, STACK}) private AllocatableValue result; + private final Constant input; + + public HotSpotLoadConstantOp(AllocatableValue result, Constant input) { + this.result = result; + this.input = input; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(input)) { + if (isRegister(result)) { + masm.movl(asRegister(result), 0); + } else { + assert isStackSlot(result); + masm.movl((AMD64Address) crb.asAddress(result), 0); + } + } else if (input instanceof HotSpotObjectConstant) { + boolean compressed = HotSpotObjectConstant.isCompressed(input); + OopData data = new OopData(compressed ? 4 : 8, HotSpotObjectConstant.asObject(input), compressed); + if (crb.target.inlineObjects) { + crb.recordInlineDataInCode(data); + if (isRegister(result)) { + if (compressed) { + masm.movl(asRegister(result), 0xDEADDEAD); + } else { + masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); + } + } else { + assert isStackSlot(result); + if (compressed) { + masm.movl((AMD64Address) crb.asAddress(result), 0xDEADDEAD); + } else { + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + } + } else { + if (isRegister(result)) { + AMD64Address address = (AMD64Address) crb.recordDataReferenceInCode(data); + if (compressed) { + masm.movl(asRegister(result), address); + } else { + masm.movq(asRegister(result), address); + } + } else { + throw GraalInternalError.shouldNotReachHere("Cannot directly store data patch to memory"); + } + } + } else if (input instanceof HotSpotMetaspaceConstant) { + assert input.getKind() == Kind.Int || input.getKind() == Kind.Long; + boolean compressed = input.getKind() == Kind.Int; + MetaspaceData data = new MetaspaceData(compressed ? 4 : 8, input.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(input), compressed); + crb.recordInlineDataInCode(data); + if (isRegister(result)) { + if (compressed) { + masm.movl(asRegister(result), input.asInt()); + } else { + masm.movq(asRegister(result), input.asLong()); + } + } else { + assert isStackSlot(result); + if (compressed) { + masm.movl((AMD64Address) crb.asAddress(result), input.asInt()); + } else { + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + } + } else { + AMD64Move.move(crb, masm, result, input); + } + } + + public Value getInput() { + return input; + } + + public AllocatableValue getResult() { + return result; + } + } + + public static class HotSpotStoreConstantOp extends StoreConstantOp { + + public HotSpotStoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state) { + super(kind, address, input, state); + } + + @Override + public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + if (input.isNull() && kind == Kind.Int) { + // compressed null + masm.movl(address.toAddress(), 0); + } else if (input instanceof HotSpotObjectConstant) { + if (HotSpotObjectConstant.isCompressed(input) && crb.target.inlineObjects) { + // compressed oop + crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(input), true)); + masm.movl(address.toAddress(), 0xDEADDEAD); + } else { + // uncompressed oop + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + } else if (input instanceof HotSpotMetaspaceConstant) { + if (input.getKind() == Kind.Int) { + // compressed metaspace pointer + crb.recordInlineDataInCode(new MetaspaceData(0, input.asInt(), HotSpotMetaspaceConstant.getMetaspaceObject(input), true)); + masm.movl(address.toAddress(), input.asInt()); + } else { + // uncompressed metaspace pointer + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + } else { + // primitive value + super.emitMemAccess(crb, masm); + } + } + } + public static class CompressPointer extends AMD64LIRInstruction { private final CompressEncoding encoding; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Tue May 27 21:20:01 2014 -0700 @@ -94,7 +94,16 @@ @Override public boolean canStoreConstant(Constant c, boolean isCompressed) { - return true; + return !(c instanceof HotSpotObjectConstant); + } + + @Override + public boolean canInlineConstant(Constant c) { + if (c instanceof HotSpotObjectConstant) { + return c.isNull(); + } else { + return super.canInlineConstant(c); + } } private static Kind getMemoryKind(PlatformKind kind) { @@ -122,6 +131,9 @@ HSAILAddressValue storeAddress = asAddressValue(address); if (isConstant(inputVal)) { Constant c = asConstant(inputVal); + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { + c = Constant.INT_0; + } if (canStoreConstant(c, false)) { append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); return; @@ -224,7 +236,18 @@ @Override protected HSAILLIRInstruction createMove(AllocatableValue dst, Value src) { if (dst.getPlatformKind() == NarrowOopStamp.NarrowOop) { - if (isRegister(src) || isStackSlot(dst)) { + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(src)) { + return new MoveToRegOp(Kind.Int, dst, Constant.INT_0); + } else if (src instanceof HotSpotObjectConstant) { + if (HotSpotObjectConstant.isCompressed((Constant) src)) { + Variable uncompressed = newVariable(Kind.Object); + append(new MoveToRegOp(Kind.Object, uncompressed, src)); + CompressEncoding oopEncoding = config.getOopEncoding(); + return new HSAILMove.CompressPointer(dst, newVariable(Kind.Object), uncompressed, oopEncoding.base, oopEncoding.shift, oopEncoding.alignment, true); + } else { + return new MoveToRegOp(Kind.Object, dst, src); + } + } else if (isRegister(src) || isStackSlot(dst)) { return new MoveFromRegOp(Kind.Int, dst, src); } else { return new MoveToRegOp(Kind.Int, dst, src); @@ -291,5 +314,4 @@ emitMove(obj, address); append(new HSAILMove.NullCheckOp(obj, state)); } - } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java Tue May 27 21:20:01 2014 -0700 @@ -59,16 +59,16 @@ public void completeInitialization() { // Register the substitutions for java.lang.Math routines. - registerSubstitutions(HSAILMathSubstitutions.class); + registerSubstitutions(Math.class, HSAILMathSubstitutions.class); // Register the ignored substitutions addIgnoredResolvedMethod(String.class, "equals", Object.class); } @Override - protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) { + protected ResolvedJavaMethod registerMethodSubstitution(ClassReplacements cr, Member originalMethod, Method substituteMethod) { // TODO: decide if we want to override this in any way - return super.registerMethodSubstitution(originalMethod, substituteMethod); + return super.registerMethodSubstitution(cr, originalMethod, substituteMethod); } @Override diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Tue May 27 21:20:01 2014 -0700 @@ -22,10 +22,13 @@ */ package com.oracle.graal.hotspot.ptx; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; @@ -37,19 +40,50 @@ public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend hostBackend) { HotSpotProviders host = hostBackend.getProviders(); - - HotSpotMetaAccessProvider metaAccess = host.getMetaAccess(); - PTXHotSpotCodeCacheProvider codeCache = new PTXHotSpotCodeCacheProvider(runtime, createTarget()); - ConstantReflectionProvider constantReflection = host.getConstantReflection(); - HotSpotForeignCallsProvider foreignCalls = new PTXHotSpotForeignCallsProvider(); - LoweringProvider lowerer = new PTXHotSpotLoweringProvider(host.getLowerer()); - Replacements replacements = host.getReplacements(); - HotSpotDisassemblerProvider disassembler = host.getDisassembler(); - SuitesProvider suites = new DefaultSuitesProvider(); - HotSpotRegistersProvider registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None); - HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection(), - host.getMethodHandleAccess()); - return new PTXHotSpotBackend(runtime, providers); + HotSpotMetaAccessProvider metaAccess; + PTXHotSpotCodeCacheProvider codeCache; + ConstantReflectionProvider constantReflection; + HotSpotForeignCallsProvider foreignCalls; + LoweringProvider lowerer; + Replacements replacements; + HotSpotDisassemblerProvider disassembler; + SuitesProvider suites; + HotSpotRegistersProvider registers; + HotSpotProviders providers; + try (InitTimer t = timer("create providers")) { + try (InitTimer rt = timer("create MetaAccess provider")) { + metaAccess = host.getMetaAccess(); + } + try (InitTimer rt = timer("create CodeCache provider")) { + codeCache = new PTXHotSpotCodeCacheProvider(runtime, createTarget()); + } + try (InitTimer rt = timer("create ConstantReflection provider")) { + constantReflection = host.getConstantReflection(); + } + try (InitTimer rt = timer("create ForeignCalls provider")) { + foreignCalls = new PTXHotSpotForeignCallsProvider(); + } + try (InitTimer rt = timer("create Lowerer provider")) { + lowerer = new PTXHotSpotLoweringProvider(host.getLowerer()); + } + try (InitTimer rt = timer("create Replacements provider")) { + replacements = host.getReplacements(); + } + try (InitTimer rt = timer("create Disassembler provider")) { + disassembler = host.getDisassembler(); + } + try (InitTimer rt = timer("create Suites provider")) { + suites = new DefaultSuitesProvider(); + } + try (InitTimer rt = timer("create HotSpotRegisters provider")) { + registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None); + } + providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection(), + host.getMethodHandleAccess()); + } + try (InitTimer rt = timer("instantiate backend")) { + return new PTXHotSpotBackend(runtime, providers); + } } protected Architecture createArchitecture() { diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.sourcegen; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.zip.*; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.options.*; + +/** + * Command line utility for generating the source code of {@code GraalRuntime.inline.hpp}. + */ +public class GenGraalRuntimeInlineHpp { + + public static void main(String[] args) { + PrintStream out = System.out; + try { + genGetServiceImpls(out); + genSetOption(out); + } catch (Throwable t) { + t.printStackTrace(out); + } + out.flush(); + } + + /** + * Generates code for {@code GraalRuntime::get_service_impls()}. + */ + private static void genGetServiceImpls(PrintStream out) throws Exception { + String graalJar = null; + String classPath = System.getProperty("java.class.path"); + for (String e : classPath.split(File.pathSeparator)) { + if (e.endsWith("graal.jar")) { + graalJar = e; + break; + } + } + final List> services = new ArrayList<>(); + final ZipFile zipFile = new ZipFile(new File(Objects.requireNonNull(graalJar, "Could not find graal.jar on class path: " + classPath))); + for (final Enumeration e = zipFile.entries(); e.hasMoreElements();) { + final ZipEntry zipEntry = e.nextElement(); + String name = zipEntry.getName(); + if (name.startsWith("META-INF/services/")) { + String serviceName = name.substring("META-INF/services/".length()); + Class c = Class.forName(serviceName); + if (Service.class.isAssignableFrom(c)) { + @SuppressWarnings("unchecked") + Class sc = (Class) c; + + services.add(sc); + } + } + } + + out.println("Handle GraalRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) {"); + for (Class service : services) { + out.printf(" if (serviceKlass->name()->equals(\"%s\")) {%n", toInternalName(service)); + List> impls = new ArrayList<>(); + for (Object impl : ServiceLoader.load(service)) { + impls.add(impl.getClass()); + } + + out.printf(" objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), %d, CHECK_NH);%n", impls.size()); + out.println(" objArrayHandle services(THREAD, servicesOop);"); + for (int i = 0; i < impls.size(); i++) { + String name = toInternalName(impls.get(i)); + out.printf(" %sservice = create_Service(\"%s\", CHECK_NH);%n", (i == 0 ? "Handle " : ""), name); + out.printf(" services->obj_at_put(%d, service());%n", i); + } + out.println(" return services;"); + out.println(" }"); + } + out.println(" return Handle();"); + out.println("}"); + } + + /** + * Generates code for {@code GraalRuntime::set_option()}. + */ + private static void genSetOption(PrintStream out) throws Exception { + SortedMap options = getOptions(); + + Set lengths = new TreeSet<>(); + for (String s : options.keySet()) { + lengths.add(s.length()); + } + lengths.add("PrintFlags".length()); + + out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS) {"); + out.println(" if (value[0] == '+' || value[0] == '-') {"); + out.println(" // boolean options"); + genMatchers(out, lengths, options, true); + out.println(" } else {"); + out.println(" // non-boolean options"); + genMatchers(out, lengths, options, false); + out.println(" }"); + out.println(" return false;"); + out.println("}"); + } + + protected static void genMatchers(PrintStream out, Set lengths, SortedMap options, boolean isBoolean) throws Exception { + out.println(" switch (name_len) {"); + for (int len : lengths) { + boolean printedCase = false; + + // The use of strncmp is required (instead of strcmp) as the option name will not be + // null terminated for = style options. + if (len == "PrintFlags".length() && isBoolean) { + printedCase = true; + out.println(" case " + len + ":"); + out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len); + out.println(" if (value[0] == '+') {"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);"); + out.println(" }"); + out.println(" return true;"); + out.println(" }"); + } + for (Map.Entry e : options.entrySet()) { + OptionDescriptor desc = e.getValue(); + if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) { + if (!printedCase) { + printedCase = true; + out.println(" case " + len + ":"); + } + out.printf(" if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len); + Class declaringClass = desc.getDeclaringClass(); + out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), + toInternalName(getFieldType(desc))); + if (isBoolean) { + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);"); + } else if (desc.getType() == String.class) { + out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);"); + } else { + char spec = getPrimitiveSpecChar(desc); + out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name_handle, value, CHECK_(true));"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);"); + } + out.println(" return true;"); + out.println(" }"); + } + } + } + out.println(" }"); + } + + @SuppressWarnings("unchecked") + static SortedMap getOptions() throws Exception { + Field field = Class.forName("com.oracle.graal.hotspot.HotSpotOptionsLoader").getDeclaredField("options"); + field.setAccessible(true); + return (SortedMap) field.get(null); + } + + private static Class getFieldType(OptionDescriptor desc) throws Exception { + return desc.getDeclaringClass().getDeclaredField(desc.getFieldName()).getType(); + } + + private static String toInternalName(Class c) { + return c.getName().replace('.', '/'); + } + + /** + * @see HotSpotOptions#setOption(String, OptionValue, char, String, long) + */ + @SuppressWarnings("javadoc") + private static char getPrimitiveSpecChar(OptionDescriptor desc) { + if (desc.getType() == Integer.class) { + return 'i'; + } + if (desc.getType() == Float.class) { + return 'f'; + } + if (desc.getType() == Double.class) { + return 'd'; + } + throw GraalInternalError.shouldNotReachHere("Unexpected primitive option type: " + desc.getType().getName()); + } +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Tue May 27 21:20:01 2014 -0700 @@ -23,8 +23,8 @@ package com.oracle.graal.hotspot.sparc; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Tue May 27 21:20:01 2014 -0700 @@ -30,6 +30,8 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.ValueProcedure; @@ -69,6 +71,51 @@ private final HotSpotGraalRuntime runtime; + /** + * @see AESCryptSubstitutions#encryptBlockStub(ForeignCallDescriptor, Word, Word, Word) + */ + public static final ForeignCallDescriptor ENCRYPT_BLOCK = new ForeignCallDescriptor("encrypt_block", void.class, Word.class, Word.class, Word.class); + + /** + * @see AESCryptSubstitutions#decryptBlockStub(ForeignCallDescriptor, Word, Word, Word) + */ + public static final ForeignCallDescriptor DECRYPT_BLOCK = new ForeignCallDescriptor("decrypt_block", void.class, Word.class, Word.class, Word.class); + + /** + * @see CipherBlockChainingSubstitutions#crypt + */ + public static final ForeignCallDescriptor ENCRYPT = new ForeignCallDescriptor("encrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class); + + /** + * @see CipherBlockChainingSubstitutions#crypt + */ + public static final ForeignCallDescriptor DECRYPT = new ForeignCallDescriptor("decrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class); + + /** + * @see VMErrorNode + */ + public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, Object.class, Object.class, long.class); + + /** + * @see NewMultiArrayStubCall + */ + public static final ForeignCallDescriptor NEW_MULTI_ARRAY = new ForeignCallDescriptor("new_multi_array", Object.class, Word.class, int.class, Word.class); + + /** + * @see NewArrayStubCall + */ + public static final ForeignCallDescriptor NEW_ARRAY = new ForeignCallDescriptor("new_array", Object.class, Word.class, int.class); + + /** + * @see NewInstanceStubCall + */ + public static final ForeignCallDescriptor NEW_INSTANCE = new ForeignCallDescriptor("new_instance", Object.class, Word.class); + + /** + * @see UncommonTrapCallNode + */ + public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("uncommonTrap", Word.class, Word.class, int.class); + public HotSpotBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) { super(providers); this.runtime = runtime; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackendFactory.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackendFactory.java Tue May 27 21:20:01 2014 -0700 @@ -22,9 +22,10 @@ */ package com.oracle.graal.hotspot; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.hotspot.HotSpotGraalRuntime.Options; -public interface HotSpotBackendFactory { +public interface HotSpotBackendFactory extends Service { HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue May 27 21:20:01 2014 -0700 @@ -24,6 +24,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.Options.*; import static sun.reflect.Reflection.*; @@ -41,6 +42,7 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.target.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.events.*; @@ -56,6 +58,47 @@ */ public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider, StackIntrospection { + /** + * A facility for timing a step in the initialization sequence for the runtime. This exists + * separate from {@link DebugTimer} as it must be independent from all other Graal code so as to + * not perturb the initialization sequence. + */ + public static class InitTimer implements AutoCloseable { + final String name; + final long start; + + private InitTimer(String name) { + this.name = name; + this.start = System.currentTimeMillis(); + System.out.println("START: " + SPACES.substring(0, timerDepth * 2) + name); + assert Thread.currentThread() == initializingThread; + timerDepth++; + } + + public void close() { + final long end = System.currentTimeMillis(); + timerDepth--; + System.out.println(" DONE: " + SPACES.substring(0, timerDepth * 2) + name + " [" + (end - start) + " ms]"); + } + + public static InitTimer timer(String name) { + return ENABLED ? new InitTimer(name) : null; + } + + public static InitTimer timer(String name, Object suffix) { + return ENABLED ? new InitTimer(name + suffix) : null; + } + + /** + * Specified initialization timing is enabled. This must only be set via a system property + * as the timing facility is used to time initialization of {@link HotSpotOptions}. + */ + private static final boolean ENABLED = Boolean.getBoolean("graal.runtime.TimeInit"); + public static int timerDepth = 0; + public static final String SPACES = " "; + public static final Thread initializingThread = Thread.currentThread(); + } + private static final HotSpotGraalRuntime instance; /** @@ -64,16 +107,24 @@ private static native void init(Class compilerToVMClass); static { - init(CompilerToVMImpl.class); + try (InitTimer t = timer("initialize natives")) { + init(CompilerToVMImpl.class); + } - // The options must be processed before any code using them... - HotSpotOptions.initialize(); + try (InitTimer t = timer("initialize HotSpotOptions")) { + // The options must be processed before any code using them... + HotSpotOptions.initialize(); + } - // ... including code in the constructor - instance = new HotSpotGraalRuntime(); + try (InitTimer t = timer("HotSpotGraalRuntime.")) { + // ... including code in the constructor + instance = new HotSpotGraalRuntime(); + } - // Why deferred initialization? See comment in completeInitialization(). - instance.completeInitialization(); + try (InitTimer t = timer("HotSpotGraalRuntime.completeInitialization")) { + // Why deferred initialization? See comment in completeInitialization(). + instance.completeInitialization(); + } registerFieldsToFilter(HotSpotGraalRuntime.class, "instance"); } @@ -138,7 +189,7 @@ HotSpotBackendFactory nonBasic = null; int nonBasicCount = 0; - for (HotSpotBackendFactory factory : ServiceLoader.loadInstalled(HotSpotBackendFactory.class)) { + for (HotSpotBackendFactory factory : Services.load(HotSpotBackendFactory.class)) { if (factory.getArchitecture().equalsIgnoreCase(architecture)) { if (factory.getGraalRuntimeName().equals(GraalRuntime.getValue())) { assert selected == null || checkFactoryOverriding(selected, factory); @@ -244,7 +295,9 @@ compilerToVm = toVM; vmToCompiler = toCompiler; - config = new HotSpotVMConfig(compilerToVm); + try (InitTimer t = timer("HotSpotVMConfig")) { + config = new HotSpotVMConfig(compilerToVm); + } CompileTheWorld.Options.overrideWithNativeOptions(config); @@ -265,18 +318,31 @@ } String hostArchitecture = config.getHostArchitectureName(); - hostBackend = registerBackend(findFactory(hostArchitecture).createBackend(this, null)); + + HotSpotBackendFactory factory; + try (InitTimer t = timer("find factory:", hostArchitecture)) { + factory = findFactory(hostArchitecture); + } + try (InitTimer t = timer("create backend:", hostArchitecture)) { + hostBackend = registerBackend(factory.createBackend(this, null)); + } String[] gpuArchitectures = getGPUArchitectureNames(compilerToVm); for (String arch : gpuArchitectures) { - HotSpotBackendFactory factory = findFactory(arch); + try (InitTimer t = timer("find factory:", arch)) { + factory = findFactory(arch); + } if (factory == null) { throw new GraalInternalError("No backend available for specified GPU architecture \"%s\"", arch); } - registerBackend(factory.createBackend(this, hostBackend)); + try (InitTimer t = timer("create backend:", arch)) { + registerBackend(factory.createBackend(this, hostBackend)); + } } - eventProvider = createEventProvider(); + try (InitTimer t = timer("createEventProvider")) { + eventProvider = createEventProvider(); + } } private HotSpotBackend registerBackend(HotSpotBackend backend) { @@ -386,7 +452,7 @@ private EventProvider createEventProvider() { if (config.flightRecorder) { - ServiceLoader sl = ServiceLoader.loadInstalled(EventProvider.class); + Iterable sl = Services.load(EventProvider.class); EventProvider singleProvider = null; for (EventProvider ep : sl) { assert singleProvider == null : String.format("multiple %s service implementations found: %s and %s", EventProvider.class.getName(), singleProvider.getClass().getName(), diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Tue May 27 21:20:01 2014 -0700 @@ -23,13 +23,14 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.common.GraalOptions.*; - -import java.util.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.spi.*; @@ -65,16 +66,23 @@ HotSpotVMConfig config = getRuntime().getConfig(); HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); - foreignCalls.initialize(providers, config); - lowerer.initialize(providers, config); + + try (InitTimer st = timer("foreignCalls.initialize")) { + foreignCalls.initialize(providers, config); + } + try (InitTimer st = timer("lowerer.initialize")) { + lowerer.initialize(providers, config); + } HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); // Install intrinsics. if (Intrinsify.getValue()) { try (Scope s = Debug.scope("RegisterReplacements", new DebugDumpScope("RegisterReplacements"))) { - ServiceLoader sl = ServiceLoader.loadInstalled(ReplacementsProvider.class); - for (ReplacementsProvider replacementsProvider : sl) { - replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, providers.getSnippetReflection(), replacements, providers.getCodeCache().getTarget()); + try (InitTimer st = timer("replacementsProviders.registerReplacements")) { + Iterable sl = Services.load(ReplacementsProvider.class); + for (ReplacementsProvider replacementsProvider : sl) { + replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, providers.getSnippetReflection(), replacements, providers.getCodeCache().getTarget()); + } } if (BootstrapReplacements.getValue()) { for (ResolvedJavaMethod method : replacements.getAllReplacements()) { diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java Tue May 27 21:20:01 2014 -0700 @@ -22,10 +22,8 @@ */ package com.oracle.graal.hotspot; -import java.io.*; import java.util.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.options.*; /** @@ -56,103 +54,4 @@ private static boolean isHotSpotOption(OptionDescriptor desc) { return desc.getClass().getName().startsWith("com.oracle.graal"); } - - /** - * Command line utility for generating the source code of GraalRuntime::set_option() which is - * written {@link System#out}. - */ - public static void main(String[] args) { - PrintStream out = System.out; - try { - Set lengths = new TreeSet<>(); - for (String s : options.keySet()) { - lengths.add(s.length()); - } - lengths.add("PrintFlags".length()); - - out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS) {"); - out.println(" if (value[0] == '+' || value[0] == '-') {"); - out.println(" // boolean options"); - genMatchers(out, lengths, true); - out.println(" } else {"); - out.println(" // non-boolean options"); - genMatchers(out, lengths, false); - out.println(" }"); - out.println(" return false;"); - out.println("}"); - } catch (Throwable t) { - t.printStackTrace(out); - } - out.flush(); - } - - protected static void genMatchers(PrintStream out, Set lengths, boolean isBoolean) throws Exception { - out.println(" switch (name_len) {"); - for (int len : lengths) { - boolean printedCase = false; - - // The use of strncmp is required (instead of strcmp) as the option name will not be - // null terminated for = style options. - if (len == "PrintFlags".length() && isBoolean) { - printedCase = true; - out.println(" case " + len + ":"); - out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {\n", len); - out.println(" if (value[0] == '+') {"); - out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);"); - out.println(" }"); - out.println(" return true;"); - out.println(" }"); - } - for (Map.Entry e : options.entrySet()) { - OptionDescriptor desc = e.getValue(); - if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) { - if (!printedCase) { - printedCase = true; - out.println(" case " + len + ":"); - } - out.printf(" if (strncmp(name, \"%s\", %d) == 0) {\n", e.getKey(), len); - Class declaringClass = desc.getDeclaringClass(); - out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));\n", toInternalName(declaringClass), desc.getFieldName(), - toInternalName(getFieldType(desc))); - if (isBoolean) { - out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);"); - } else if (desc.getType() == String.class) { - out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); - out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);"); - } else { - char spec = getPrimitiveSpecChar(desc); - out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name_handle, value, CHECK_(true));"); - out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);"); - } - out.println(" return true;"); - out.println(" }"); - } - } - } - out.println(" }"); - } - - private static Class getFieldType(OptionDescriptor desc) throws Exception { - return desc.getDeclaringClass().getDeclaredField(desc.getFieldName()).getType(); - } - - private static String toInternalName(Class c) { - return c.getName().replace('.', '/'); - } - - /** - * @see HotSpotOptions#setOption(String, OptionValue, char, String, long) - */ - private static char getPrimitiveSpecChar(OptionDescriptor desc) { - if (desc.getType() == Integer.class) { - return 'i'; - } - if (desc.getType() == Float.class) { - return 'f'; - } - if (desc.getType() == Double.class) { - return 'd'; - } - throw GraalInternalError.shouldNotReachHere("Unexpected primitive option type: " + desc.getType().getName()); - } } \ No newline at end of file diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Tue May 27 21:20:01 2014 -0700 @@ -48,7 +48,7 @@ } @Override - protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) { + protected ResolvedJavaMethod registerMethodSubstitution(ClassReplacements cr, Member originalMethod, Method substituteMethod) { final Class substituteClass = substituteMethod.getDeclaringClass(); if (substituteClass.getDeclaringClass() == BoxingSubstitutions.class) { if (config.useHeapProfiler) { @@ -78,7 +78,7 @@ return null; } } - return super.registerMethodSubstitution(originalMethod, substituteMethod); + return super.registerMethodSubstitution(cr, originalMethod, substituteMethod); } @Override diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue May 27 21:20:01 2014 -0700 @@ -24,6 +24,7 @@ import static com.oracle.graal.compiler.GraalDebugConfig.*; import static com.oracle.graal.hotspot.CompileTheWorld.Options.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; import java.io.*; import java.lang.reflect.*; @@ -40,6 +41,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.CompilationTask.Enqueueing; import com.oracle.graal.hotspot.CompileTheWorld.Config; +import com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer; import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; @@ -191,10 +193,14 @@ assert VerifyOptionsPhase.checkOptions(hostProviders.getMetaAccess()); // Complete initialization of backends - hostBackend.completeInitialization(); + try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { + hostBackend.completeInitialization(); + } for (HotSpotBackend backend : runtime.getBackends().values()) { if (backend != hostBackend) { - backend.completeInitialization(); + try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) { + backend.completeInitialization(); + } } } @@ -204,6 +210,12 @@ } public void startCompiler(boolean bootstrapEnabled) throws Throwable { + try (InitTimer timer = timer("startCompiler")) { + startCompiler0(bootstrapEnabled); + } + } + + private void startCompiler0(boolean bootstrapEnabled) throws Throwable { bootstrapRunning = bootstrapEnabled; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompressedNullConstant.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompressedNullConstant.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.nodes.type.*; + +/** + * The compressed representation of the {@link Constant#NULL_OBJECT null constant}. + */ +public final class HotSpotCompressedNullConstant extends Constant implements HotSpotConstant { + + private static final long serialVersionUID = 8906209595800783961L; + + public static final Constant COMPRESSED_NULL = new HotSpotCompressedNullConstant(); + + private HotSpotCompressedNullConstant() { + super(NarrowOopStamp.NarrowOop); + } + + @Override + public boolean isNull() { + return true; + } + + @Override + public boolean isDefaultForKind() { + return true; + } + + @Override + public Object asBoxedPrimitive() { + throw new IllegalArgumentException(); + } + + @Override + public int asInt() { + throw new IllegalArgumentException(); + } + + @Override + public boolean asBoolean() { + throw new IllegalArgumentException(); + } + + @Override + public long asLong() { + throw new IllegalArgumentException(); + } + + @Override + public float asFloat() { + throw new IllegalArgumentException(); + } + + @Override + public double asDouble() { + throw new IllegalArgumentException(); + } + + @Override + public String toValueString() { + return "null"; + } + + @Override + public int hashCode() { + return System.identityHashCode(this); + } + + @Override + public boolean equals(Object o) { + assert o == this || !(o instanceof HotSpotCompressedNullConstant) : "null constant is a singleton"; + return o == this; + } +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstant.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstant.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.meta; + +/** + * Marker interface for hotspot specific constants. + */ +public interface HotSpotConstant { +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Tue May 27 21:20:01 2014 -0700 @@ -223,7 +223,7 @@ @Override public ResolvedJavaType asJavaType(Constant constant) { - if (constant.getKind() == Kind.Object) { + if (constant instanceof HotSpotObjectConstant) { Object obj = HotSpotObjectConstant.asObject(constant); if (obj instanceof Class) { return runtime.getHostProviders().getMetaAccess().lookupJavaType((Class) obj); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Tue May 27 21:20:01 2014 -0700 @@ -27,11 +27,7 @@ import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*; -import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*; -import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; -import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*; -import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; -import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; +import static com.oracle.graal.hotspot.meta.DefaultHotSpotLoweringProvider.RuntimeCalls.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; @@ -44,8 +40,7 @@ import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; import static com.oracle.graal.hotspot.stubs.StubUtil.*; import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*; -import static com.oracle.graal.hotspot.meta.DefaultHotSpotLoweringProvider.RuntimeCalls.*; -import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; +import static com.oracle.graal.nodes.java.ForeignCallDescriptors.*; import static com.oracle.graal.replacements.Log.*; import static com.oracle.graal.replacements.MathSubstitutionsX86.*; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Tue May 27 21:20:01 2014 -0700 @@ -51,7 +51,7 @@ } public ResolvedJavaType lookupJavaType(Constant constant) { - if (constant.getKind() != Kind.Object || constant.isNull()) { + if (constant.isNull() || !(constant instanceof HotSpotObjectConstant)) { return null; } Object o = HotSpotObjectConstant.asObject(constant); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstant.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstant.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstant.java Tue May 27 21:20:01 2014 -0700 @@ -26,7 +26,7 @@ import com.oracle.graal.api.meta.*; -public final class HotSpotMetaspaceConstant extends PrimitiveConstant { +public final class HotSpotMetaspaceConstant extends PrimitiveConstant implements HotSpotConstant { private static final long serialVersionUID = 1003463314013122983L; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java Tue May 27 21:20:01 2014 -0700 @@ -23,12 +23,13 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.nodes.type.*; /** * Represents a constant non-{@code null} object reference, within the compiler and across the * compiler/runtime interface. */ -public final class HotSpotObjectConstant extends Constant { +public final class HotSpotObjectConstant extends Constant implements HotSpotConstant { private static final long serialVersionUID = 3592151693708093496L; @@ -36,7 +37,7 @@ if (object == null) { return Constant.NULL_OBJECT; } else { - return new HotSpotObjectConstant(object); + return new HotSpotObjectConstant(object, false); } } @@ -59,21 +60,41 @@ public static Object asBoxedValue(Constant constant) { if (constant.isNull()) { return null; - } else if (constant.getKind() == Kind.Object) { + } else if (constant instanceof HotSpotObjectConstant) { return ((HotSpotObjectConstant) constant).object; } else { return constant.asBoxedPrimitive(); } } + public static boolean isCompressed(Constant constant) { + if (constant.isNull()) { + return HotSpotCompressedNullConstant.NULL_OBJECT.equals(constant); + } else { + return ((HotSpotObjectConstant) constant).compressed; + } + } + private final Object object; + private final boolean compressed; - private HotSpotObjectConstant(Object object) { - super(Kind.Object); + private HotSpotObjectConstant(Object object, boolean compressed) { + super(compressed ? NarrowOopStamp.NarrowOop : Kind.Object); this.object = object; + this.compressed = compressed; assert object != null; } + public Constant compress() { + assert !compressed; + return new HotSpotObjectConstant(object, true); + } + + public Constant uncompress() { + assert compressed; + return new HotSpotObjectConstant(object, false); + } + @Override public boolean isNull() { return false; @@ -135,6 +156,6 @@ @Override public String toString() { - return getKind().getJavaName() + "[" + Kind.Object.format(object) + "]"; + return (compressed ? "NarrowOop" : getKind().getJavaName()) + "[" + Kind.Object.format(object) + "]"; } } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Tue May 27 21:20:01 2014 -0700 @@ -58,7 +58,7 @@ if (ImmutableCode.getValue()) { // lowering introduces class constants, therefore it must be after lowering - ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(runtime.getConfig().classMirrorOffset)); + ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(runtime.getConfig().classMirrorOffset, runtime.getConfig().getOopEncoding())); if (VerifyPhases.getValue()) { ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Tue May 27 21:20:01 2014 -0700 @@ -29,6 +29,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -39,7 +40,7 @@ * Compress or uncompress an oop or metaspace pointer. */ @NodeInfo(nameTemplate = "{p#op/s}") -public final class CompressionNode extends FloatingNode implements LIRLowerable, Canonicalizable { +public final class CompressionNode extends ConvertNode implements LIRLowerable, Canonicalizable { private enum CompressionOp { Compress, @@ -49,13 +50,10 @@ private final CompressionOp op; private final CompressEncoding encoding; - @Input private ValueNode input; - private CompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) { - super(mkStamp(op, input.stamp(), encoding)); + super(mkStamp(op, input.stamp(), encoding), input); this.op = op; this.encoding = encoding; - this.input = input; } public static CompressionNode compress(ValueNode input, CompressEncoding encoding) { @@ -66,6 +64,61 @@ return input.graph().unique(new CompressionNode(CompressionOp.Uncompress, input, encoding)); } + private static Constant compress(Constant c, CompressEncoding encoding) { + if (Constant.NULL_OBJECT.equals(c)) { + return HotSpotCompressedNullConstant.COMPRESSED_NULL; + } else if (c instanceof HotSpotObjectConstant) { + return ((HotSpotObjectConstant) c).compress(); + } else if (c instanceof HotSpotMetaspaceConstant) { + assert c.getKind() == Kind.Long; + return HotSpotMetaspaceConstant.forMetaspaceObject(Kind.Int, encoding.compress(c.asLong()), HotSpotMetaspaceConstant.getMetaspaceObject(c)); + } else { + throw GraalInternalError.shouldNotReachHere("invalid constant input for compress op: " + c); + } + } + + private static Constant uncompress(Constant c, CompressEncoding encoding) { + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { + return Constant.NULL_OBJECT; + } else if (c instanceof HotSpotObjectConstant) { + return ((HotSpotObjectConstant) c).uncompress(); + } else if (c instanceof HotSpotMetaspaceConstant) { + assert c.getKind() == Kind.Int; + return HotSpotMetaspaceConstant.forMetaspaceObject(Kind.Long, encoding.uncompress(c.asInt()), HotSpotMetaspaceConstant.getMetaspaceObject(c)); + } else { + throw GraalInternalError.shouldNotReachHere("invalid constant input for uncompress op: " + c); + } + } + + @Override + public Constant convert(Constant c) { + switch (op) { + case Compress: + return compress(c, encoding); + case Uncompress: + return uncompress(c, encoding); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Constant reverse(Constant c) { + switch (op) { + case Compress: + return uncompress(c, encoding); + case Uncompress: + return compress(c, encoding); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public boolean isLossless() { + return true; + } + private static Stamp mkStamp(CompressionOp op, Stamp input, CompressEncoding encoding) { switch (op) { case Compress: @@ -93,20 +146,18 @@ throw GraalInternalError.shouldNotReachHere(String.format("Unexpected input stamp %s", input)); } - public ValueNode getInput() { - return input; - } - public CompressEncoding getEncoding() { return encoding; } @Override public Node canonical(CanonicalizerTool tool) { - if (input instanceof CompressionNode) { - CompressionNode other = (CompressionNode) input; + if (getInput().isConstant()) { + return ConstantNode.forConstant(stamp(), evalConst(getInput().asConstant()), tool.getMetaAccess(), graph()); + } else if (getInput() instanceof CompressionNode) { + CompressionNode other = (CompressionNode) getInput(); if (op != other.op && encoding.equals(other.encoding)) { - return other.input; + return other.getInput(); } } return this; @@ -116,8 +167,8 @@ public void generate(NodeLIRBuilderTool gen) { HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); boolean nonNull; - if (input.stamp() instanceof ObjectStamp) { - nonNull = StampTool.isObjectNonNull(input.stamp()); + if (getInput().stamp() instanceof ObjectStamp) { + nonNull = StampTool.isObjectNonNull(getInput().stamp()); } else { // metaspace pointers are never null nonNull = true; @@ -126,10 +177,10 @@ Value result; switch (op) { case Compress: - result = hsGen.emitCompress(gen.operand(input), encoding, nonNull); + result = hsGen.emitCompress(gen.operand(getInput()), encoding, nonNull); break; case Uncompress: - result = hsGen.emitUncompress(gen.operand(input), encoding, nonNull); + result = hsGen.emitUncompress(gen.operand(getInput()), encoding, nonNull); break; default: throw GraalInternalError.shouldNotReachHere(); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Tue May 27 21:20:01 2014 -0700 @@ -22,8 +22,9 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.hotspot.HotSpotBackend.*; + import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; @@ -42,8 +43,6 @@ @Input private ValueNode hub; @Input private ValueNode length; - public static final ForeignCallDescriptor NEW_ARRAY = new ForeignCallDescriptor("new_array", Object.class, Word.class, int.class); - public NewArrayStubCall(ValueNode hub, ValueNode length) { super(defaultStamp); this.hub = hub; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Tue May 27 21:20:01 2014 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.hotspot.HotSpotBackend.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; @@ -40,8 +42,6 @@ @Input private ValueNode hub; - public static final ForeignCallDescriptor NEW_INSTANCE = new ForeignCallDescriptor("new_instance", Object.class, Word.class); - public NewInstanceStubCall(ValueNode hub) { super(defaultStamp); this.hub = hub; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Tue May 27 21:20:01 2014 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.hotspot.HotSpotBackend.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; @@ -42,8 +44,6 @@ @Input private ValueNode dims; private final int rank; - public static final ForeignCallDescriptor NEW_MULTI_ARRAY = new ForeignCallDescriptor("new_multi_array", Object.class, Word.class, int.class, Word.class); - public NewMultiArrayStubCall(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode hub, int rank, ValueNode dims) { super(foreignCalls, NEW_MULTI_ARRAY, defaultStamp); this.hub = hub; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Tue May 27 21:20:01 2014 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.hotspot.HotSpotBackend.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; @@ -42,7 +44,6 @@ @Input private ValueNode trapRequest; @Input private SaveAllRegistersNode registerSaver; private final ForeignCallsProvider foreignCalls; - public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("uncommonTrap", Word.class, Word.class, int.class); public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) { super(StampFactory.forKind(Kind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Tue May 27 21:20:01 2014 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.nodes; import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.nodes.CStringNode.*; import com.oracle.graal.api.code.*; @@ -40,7 +41,6 @@ private final String format; @Input private ValueNode value; - public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, Object.class, Object.class, long.class); public VMErrorNode(String format, ValueNode value) { super(StampFactory.forVoid()); @@ -67,7 +67,7 @@ Value whereArg = emitCString(gen, whereString); Value formatArg = emitCString(gen, format); - ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(VMErrorNode.VM_ERROR); + ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(VM_ERROR); gen.getLIRGeneratorTool().emitForeignCall(linkage, null, whereArg, formatArg, gen.operand(value)); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Tue May 27 21:20:01 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.HotSpotVMConfig.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.*; @@ -39,22 +41,24 @@ * directly. Instead the {@link Class} reference should be obtained from the {@code Klass} object. * The reason for this is, that in Class Data Sharing (CDS) a {@code Klass} object is mapped to a * fixed address in memory, but the {@code javaMirror} is not (which lives in the Java heap). - * + * * Lowering can introduce new {@link ConstantNode}s containing a {@link Class} reference, thus this * phase must be applied after {@link LoweringPhase}. - * + * * @see AheadOfTimeVerificationPhase */ public class LoadJavaMirrorWithKlassPhase extends BasePhase { private final int classMirrorOffset; + private final CompressEncoding oopEncoding; - public LoadJavaMirrorWithKlassPhase(int classMirrorOffset) { + public LoadJavaMirrorWithKlassPhase(int classMirrorOffset, CompressEncoding oopEncoding) { this.classMirrorOffset = classMirrorOffset; + this.oopEncoding = oopEncoding; } - private FloatingReadNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, Constant constant) { - if (constant.getKind() == Kind.Object && HotSpotObjectConstant.asObject(constant) instanceof Class) { + private ValueNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, Constant constant) { + if (constant instanceof HotSpotObjectConstant && HotSpotObjectConstant.asObject(constant) instanceof Class) { MetaAccessProvider metaAccess = context.getMetaAccess(); ResolvedJavaType type = metaAccess.lookupJavaType((Class) HotSpotObjectConstant.asObject(constant)); assert type instanceof HotSpotResolvedObjectType; @@ -65,7 +69,12 @@ Stamp stamp = StampFactory.exactNonNull(metaAccess.lookupJavaType(Class.class)); LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Object, classMirrorOffset, graph); FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp)); - return freadNode; + + if (HotSpotObjectConstant.isCompressed(constant)) { + return CompressionNode.compress(freadNode, oopEncoding); + } else { + return freadNode; + } } return null; } @@ -74,7 +83,7 @@ protected void run(StructuredGraph graph, PhaseContext context) { for (ConstantNode node : getConstantNodes(graph)) { Constant constant = node.asConstant(); - FloatingReadNode freadNode = getClassConstantReplacement(graph, context, constant); + ValueNode freadNode = getClassConstantReplacement(graph, context, constant); if (freadNode != null) { node.replace(graph, freadNode); } diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Tue May 27 21:20:01 2014 -0700 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import sun.misc.*; @@ -93,9 +94,6 @@ } } - public static final ForeignCallDescriptor ENCRYPT_BLOCK = new ForeignCallDescriptor("encrypt_block", void.class, Word.class, Word.class, Word.class); - public static final ForeignCallDescriptor DECRYPT_BLOCK = new ForeignCallDescriptor("decrypt_block", void.class, Word.class, Word.class, Word.class); - @NodeIntrinsic(ForeignCallNode.class) public static native void encryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Tue May 27 21:20:01 2014 -0700 @@ -35,9 +35,9 @@ @Override public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { - replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class); - replacements.registerSubstitutions(MutableCallSiteSubstitutions.class); - replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class); + replacements.registerSubstitutions(ConstantCallSite.class, ConstantCallSiteSubstitutions.class); + replacements.registerSubstitutions(MutableCallSite.class, MutableCallSiteSubstitutions.class); + replacements.registerSubstitutions(VolatileCallSite.class, VolatileCallSiteSubstitutions.class); } @ClassSubstitution(ConstantCallSite.class) diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Tue May 27 21:20:01 2014 -0700 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import sun.misc.*; @@ -108,9 +109,6 @@ } } - public static final ForeignCallDescriptor ENCRYPT = new ForeignCallDescriptor("encrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class); - public static final ForeignCallDescriptor DECRYPT = new ForeignCallDescriptor("decrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class); - @NodeIntrinsic(ForeignCallNode.class) public static native void encryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key, Word r, int inLength); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Tue May 27 21:20:01 2014 -0700 @@ -22,29 +22,50 @@ */ package com.oracle.graal.hotspot.replacements; +import java.lang.reflect.*; +import java.util.zip.*; + +import sun.misc.*; +import sun.reflect.*; + 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.graph.*; +import com.oracle.graal.lir.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @ServiceProvider(ReplacementsProvider.class) public class HotSpotSubstitutions implements ReplacementsProvider { + static class NamedType implements Type { + private final String name; + + public NamedType(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + } + @Override public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { - replacements.registerSubstitutions(ObjectSubstitutions.class); - replacements.registerSubstitutions(SystemSubstitutions.class); - replacements.registerSubstitutions(ThreadSubstitutions.class); - replacements.registerSubstitutions(UnsafeSubstitutions.class); - replacements.registerSubstitutions(ClassSubstitutions.class); - replacements.registerSubstitutions(AESCryptSubstitutions.class); - replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class); - replacements.registerSubstitutions(CRC32Substitutions.class); - replacements.registerSubstitutions(ReflectionSubstitutions.class); - replacements.registerSubstitutions(HotSpotNodeClassSubstitutions.class); - replacements.registerSubstitutions(HotSpotNodeSubstitutions.class); - replacements.registerSubstitutions(CompositeValueClassSubstitutions.class); + replacements.registerSubstitutions(Object.class, ObjectSubstitutions.class); + replacements.registerSubstitutions(System.class, SystemSubstitutions.class); + replacements.registerSubstitutions(Thread.class, ThreadSubstitutions.class); + replacements.registerSubstitutions(Unsafe.class, UnsafeSubstitutions.class); + replacements.registerSubstitutions(Class.class, ClassSubstitutions.class); + replacements.registerSubstitutions(CRC32.class, CRC32Substitutions.class); + replacements.registerSubstitutions(Reflection.class, ReflectionSubstitutions.class); + replacements.registerSubstitutions(NodeClass.class, HotSpotNodeClassSubstitutions.class); + replacements.registerSubstitutions(Node.class, HotSpotNodeSubstitutions.class); + replacements.registerSubstitutions(CompositeValueClass.class, CompositeValueClassSubstitutions.class); + replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.AESCrypt"), AESCryptSubstitutions.class); + replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.CipherBlockChaining"), CipherBlockChainingSubstitutions.class); } } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue May 27 21:20:01 2014 -0700 @@ -180,7 +180,7 @@ // owns the bias and we need to revoke that bias. The revocation will occur // in the interpreter runtime. traceObject(trace, "+lock{stub:revoke}", object, true); - monitorenterStub(MONITORENTER, object, lock); + monitorenterStubC(MONITORENTER, object, lock); return; } else { // At this point we know the epoch has expired, meaning that the @@ -200,7 +200,7 @@ // succeeded in biasing it toward itself and we need to revoke that // bias. The revocation will occur in the runtime in the slow case. traceObject(trace, "+lock{stub:epoch-expired}", object, true); - monitorenterStub(MONITORENTER, object, lock); + monitorenterStubC(MONITORENTER, object, lock); return; } } else { @@ -257,7 +257,7 @@ if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) { // Most likely not a recursive lock, go into a slow runtime call traceObject(trace, "+lock{stub:failed-cas}", object, true); - monitorenterStub(MONITORENTER, object, lock); + monitorenterStubC(MONITORENTER, object, lock); return; } else { // Recursively locked => write 0 to the lock slot @@ -283,7 +283,7 @@ // cannot float about the null check above final Word lock = beginLockScope(lockDepth); traceObject(trace, "+lock{stub}", object, true); - monitorenterStub(MONITORENTER, object, lock); + monitorenterStubC(MONITORENTER, object, lock); } @Snippet @@ -324,7 +324,7 @@ // The object's mark word was not pointing to the displaced header, // we do unlocking via runtime call. traceObject(trace, "-lock{stub}", object, false); - monitorexitStub(MONITOREXIT, object, lock); + monitorexitStubC(MONITOREXIT, object, lock); } else { traceObject(trace, "-lock{cas}", object, false); } @@ -341,7 +341,7 @@ verifyOop(object); traceObject(trace, "-lock{stub}", object, false); final Word lock = CurrentLockNode.currentLock(lockDepth); - monitorexitStub(MONITOREXIT, object, lock); + monitorexitStubC(MONITOREXIT, object, lock); endLockScope(); decCounter(); } @@ -531,9 +531,9 @@ public static final ForeignCallDescriptor MONITOREXIT = new ForeignCallDescriptor("monitorexit", void.class, Object.class, Word.class); @NodeIntrinsic(ForeignCallNode.class) - private static native void monitorenterStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); + private static native void monitorenterStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); @NodeIntrinsic(ForeignCallNode.class) - private static native void monitorexitStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); + private static native void monitorexitStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Tue May 27 21:20:01 2014 -0700 @@ -35,7 +35,8 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.word.*; /** @@ -80,7 +81,7 @@ private final TargetDescription target; public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); + super(DeoptimizationStub.class, "deoptimizationHandler", providers, target, linkage); this.target = target; } @@ -270,8 +271,8 @@ return config().deoptimizationUnpackUncommonTrap; } - public static final ForeignCallDescriptor FETCH_UNROLL_INFO = descriptorFor(DeoptimizationStub.class, "fetchUnrollInfo"); - public static final ForeignCallDescriptor UNPACK_FRAMES = descriptorFor(DeoptimizationStub.class, "unpackFrames"); + public static final ForeignCallDescriptor FETCH_UNROLL_INFO = newDescriptor(DeoptimizationStub.class, "fetchUnrollInfo", Word.class, Word.class); + public static final ForeignCallDescriptor UNPACK_FRAMES = newDescriptor(DeoptimizationStub.class, "unpackFrames", int.class, Word.class, int.class); @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) public static native Word fetchUnrollInfo(@ConstantNodeParameter ForeignCallDescriptor fetchUnrollInfo, Word thread); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Tue May 27 21:20:01 2014 -0700 @@ -50,7 +50,7 @@ public class ExceptionHandlerStub extends SnippetStub { public ExceptionHandlerStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); + super("exceptionHandler", providers, target, linkage); } /** @@ -142,7 +142,7 @@ return enabled || cAssertionsEnabled(); } - public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = descriptorFor(ExceptionHandlerStub.class, "exceptionHandlerForPc"); + public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = newDescriptor(ExceptionHandlerStub.class, "exceptionHandlerForPc", Word.class, Word.class); @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) public static native Word exceptionHandlerForPc(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForPc, Word thread); diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Tue May 27 21:20:01 2014 -0700 @@ -53,7 +53,7 @@ public class NewArrayStub extends SnippetStub { public NewArrayStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); + super("newArray", providers, target, linkage); } @Override @@ -115,7 +115,7 @@ return verifyObject(getAndClearObjectResult(thread)); } - public static final ForeignCallDescriptor NEW_ARRAY_C = descriptorFor(NewArrayStub.class, "newArrayC"); + public static final ForeignCallDescriptor NEW_ARRAY_C = newDescriptor(NewArrayStub.class, "newArrayC", void.class, Word.class, Word.class, int.class); @NodeIntrinsic(StubForeignCallNode.class) public static native void newArrayC(@ConstantNodeParameter ForeignCallDescriptor newArrayC, Word thread, Word hub, int length); diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Tue May 27 21:20:01 2014 -0700 @@ -53,7 +53,7 @@ public class NewInstanceStub extends SnippetStub { public NewInstanceStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); + super("newInstance", providers, target, linkage); } @Override @@ -251,7 +251,7 @@ return Boolean.getBoolean("graal.newInstanceStub.forceSlowPath"); } - public static final ForeignCallDescriptor NEW_INSTANCE_C = descriptorFor(NewInstanceStub.class, "newInstanceC"); + public static final ForeignCallDescriptor NEW_INSTANCE_C = newDescriptor(NewInstanceStub.class, "newInstanceC", void.class, Word.class, Word.class); @NodeIntrinsic(StubForeignCallNode.class) public static native void newInstanceC(@ConstantNodeParameter ForeignCallDescriptor newInstanceC, Word thread, Word hub); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Tue May 27 21:20:01 2014 -0700 @@ -44,9 +44,9 @@ static class Template extends AbstractTemplates { - Template(HotSpotProviders providers, TargetDescription target, Class declaringClass) { + Template(HotSpotProviders providers, TargetDescription target, Class declaringClass, String snippetMethodName) { super(providers, providers.getSnippetReflection(), target); - this.info = snippet(declaringClass, null); + this.info = snippet(declaringClass, snippetMethodName); } /** @@ -65,11 +65,26 @@ /** * Creates a new snippet stub. * + * @param snippetMethodName name of the single {@link Snippet} annotated method in the class of + * this object * @param linkage linkage details for a call to the stub */ - public SnippetStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + public SnippetStub(String snippetMethodName, HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + this(null, snippetMethodName, providers, target, linkage); + } + + /** + * Creates a new snippet stub. + * + * @param snippetDeclaringClass this class in which the {@link Snippet} annotated method is + * declared. If {@code null}, this the class of this object is used. + * @param snippetMethodName name of the single {@link Snippet} annotated method in + * {@code snippetDeclaringClass} + * @param linkage linkage details for a call to the stub + */ + public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { super(providers, linkage); - this.snippet = new Template(providers, target, getClass()); + this.snippet = new Template(providers, target, snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName); } @Override diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Tue May 27 21:20:01 2014 -0700 @@ -47,14 +47,20 @@ */ public class StubUtil { - public static final ForeignCallDescriptor VM_MESSAGE_C = descriptorFor(StubUtil.class, "vmMessageC"); + public static final ForeignCallDescriptor VM_MESSAGE_C = newDescriptor(StubUtil.class, "vmMessageC", void.class, boolean.class, Word.class, long.class, long.class, long.class); + + public static ForeignCallDescriptor newDescriptor(Class stubClass, String name, Class resultType, Class... argumentTypes) { + ForeignCallDescriptor d = new ForeignCallDescriptor(name, resultType, argumentTypes); + assert descriptorFor(stubClass, name).equals(d) : descriptorFor(stubClass, name) + " != " + d; + return d; + } /** * Looks for a {@link StubForeignCallNode} node intrinsic named {@code name} in * {@code stubClass} and returns a {@link ForeignCallDescriptor} based on its signature and the * value of {@code hasSideEffect}. */ - public static ForeignCallDescriptor descriptorFor(Class stubClass, String name) { + private static ForeignCallDescriptor descriptorFor(Class stubClass, String name) { Method found = null; for (Method method : stubClass.getDeclaredMethods()) { if (Modifier.isStatic(method.getModifiers()) && method.getAnnotation(NodeIntrinsic.class) != null && method.getName().equals(name)) { diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Tue May 27 21:20:01 2014 -0700 @@ -80,7 +80,7 @@ private final TargetDescription target; public UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); + super(UncommonTrapStub.class, "uncommonTrapHandler", providers, target, linkage); this.target = target; } @@ -281,7 +281,7 @@ return config().deoptimizationUnpackUncommonTrap; } - public static final ForeignCallDescriptor UNPACK_FRAMES = descriptorFor(UncommonTrapStub.class, "unpackFrames"); + public static final ForeignCallDescriptor UNPACK_FRAMES = newDescriptor(UncommonTrapStub.class, "unpackFrames", int.class, Word.class, int.class); @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Tue May 27 21:20:01 2014 -0700 @@ -47,7 +47,7 @@ public class UnwindExceptionToCallerStub extends SnippetStub { public UnwindExceptionToCallerStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); + super("unwindExceptionToCaller", providers, target, linkage); } /** @@ -110,7 +110,8 @@ return enabled || cAssertionsEnabled(); } - public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = descriptorFor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress"); + public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class, + Word.class); @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java Tue May 27 21:20:01 2014 -0700 @@ -35,7 +35,7 @@ public class VerifyOopStub extends SnippetStub { public VerifyOopStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); + super("verifyOop", providers, target, linkage); } @Snippet diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Tue May 27 21:20:01 2014 -0700 @@ -280,9 +280,10 @@ this.method = method; exceptionHandlers = method.getExceptionHandlers(); stream = new BytecodeStream(method.getCode()); - this.blockMap = new BciBlock[method.getCodeSize()]; + int codeSize = method.getCodeSize(); + this.blockMap = new BciBlock[codeSize]; this.blocks = new ArrayList<>(); - this.loopHeaders = new BciBlock[64]; + this.loopHeaders = new BciBlock[codeSize < 64 ? codeSize : 64]; } /** @@ -780,7 +781,7 @@ for (BciBlock successor : block.getSuccessors()) { // Recursively process successors. loops |= computeBlockOrder(successor); - if (block.visited && successor.active) { + if (successor.active) { // Reached block via backward branch. block.isLoopEnd = true; } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Tue May 27 21:20:01 2014 -0700 @@ -84,7 +84,7 @@ } @Override - public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + protected void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { if (isRegister(y)) { switch (opcode) { case BCMP: @@ -129,6 +129,13 @@ throw GraalInternalError.shouldNotReachHere(); } break; + case ACMP: + if (asConstant(y).isNull()) { + masm.cmpq(address.toAddress(), 0); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + break; default: throw GraalInternalError.shouldNotReachHere(); } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Tue May 27 21:20:01 2014 -0700 @@ -153,13 +153,7 @@ } public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) { - if (stamp instanceof PrimitiveStamp) { - return forPrimitive(stamp, constant, graph); - } else { - ConstantNode ret = forConstant(constant, metaAccess, graph); - assert ret.stamp().isCompatible(stamp); - return ret; - } + return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess))); } /** diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Tue May 27 21:20:01 2014 -0700 @@ -126,14 +126,14 @@ } } else if (x() instanceof ConvertNode && y().isConstant()) { ConvertNode convertX = (ConvertNode) x(); - ConstantNode newY = canonicalConvertConstant(convertX, y().asConstant()); + ConstantNode newY = canonicalConvertConstant(tool, convertX, y().asConstant()); if (newY != null) { setX(convertX.getInput()); setY(newY); } } else if (y() instanceof ConvertNode && x().isConstant()) { ConvertNode convertY = (ConvertNode) y(); - ConstantNode newX = canonicalConvertConstant(convertY, x().asConstant()); + ConstantNode newX = canonicalConvertConstant(tool, convertY, x().asConstant()); if (newX != null) { setX(newX); setY(convertY.getInput()); @@ -142,11 +142,11 @@ return this; } - private ConstantNode canonicalConvertConstant(ConvertNode convert, Constant constant) { + private ConstantNode canonicalConvertConstant(CanonicalizerTool tool, ConvertNode convert, Constant constant) { if (convert.preservesOrder(condition())) { Constant reverseConverted = convert.reverse(constant); if (convert.convert(reverseConverted).equals(constant)) { - return ConstantNode.forPrimitive(convert.getInput().stamp(), reverseConverted, convert.graph()); + return ConstantNode.forConstant(convert.getInput().stamp(), reverseConverted, tool.getMetaAccess(), convert.graph()); } } return null; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Tue May 27 21:20:01 2014 -0700 @@ -41,7 +41,8 @@ } public static long narrow(long value, int resultBits) { - return value & IntegerStamp.defaultMask(resultBits); + long ret = value & IntegerStamp.defaultMask(resultBits); + return SignExtendNode.signExtend(ret, resultBits); } @Override diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ForeignCallDescriptors.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ForeignCallDescriptors.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.java; + +import com.oracle.graal.api.meta.*; + +/** + * The foreign call descriptors used by nodes in this package. + *

+ * Using a separate class for such descriptors prevents an access from triggering unwanted class + * initialization during runtime initialization. + */ +public class ForeignCallDescriptors { + + /** + * @see RegisterFinalizerNode + */ + public static final ForeignCallDescriptor REGISTER_FINALIZER = new ForeignCallDescriptor("registerFinalizer", void.class, Object.class); + +} \ No newline at end of file diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Tue May 27 21:20:01 2014 -0700 @@ -22,8 +22,9 @@ */ package com.oracle.graal.nodes.java; +import static com.oracle.graal.nodes.java.ForeignCallDescriptors.*; + import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -36,8 +37,6 @@ */ public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter { - public static final ForeignCallDescriptor REGISTER_FINALIZER = new ForeignCallDescriptor("registerFinalizer", void.class, Object.class); - @Input(InputType.State) private FrameState deoptState; @Input private ValueNode object; diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Tue May 27 21:20:01 2014 -0700 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.spi; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -36,14 +37,14 @@ /** * Gets the snippet graph derived from a given method. - * + * * @return the snippet graph, if any, that is derived from {@code method} */ StructuredGraph getSnippet(ResolvedJavaMethod method); /** * Gets the snippet graph derived from a given method. - * + * * @param recursiveEntry if the snippet contains a call to this method, it's considered as * recursive call and won't be processed for {@linkplain MethodSubstitution * substitutions} or {@linkplain MacroSubstitution macro nodes}. @@ -59,7 +60,7 @@ /** * Notifies this object during snippet specialization once the specialized snippet's constant * parameters have been replaced with constant values. - * + * * @param specializedSnippet the snippet in the process of being specialized. This is a copy of * the unspecialized snippet graph created during snippet preparation. */ @@ -67,14 +68,14 @@ /** * Gets the graph that is a substitution for a given method. - * + * * @return the graph, if any, that is a substitution for {@code method} */ StructuredGraph getMethodSubstitution(ResolvedJavaMethod method); /** * Gets the node class with which a method invocation should be replaced. - * + * * @param method target of an invocation * @return the {@linkplain MacroSubstitution#macro() macro node class} associated with * {@code method} or null if there is no such association @@ -89,8 +90,15 @@ /** * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution * macro} substitutions defined by a given class. + * + * @param original the original class for which substitutions are being registered. This must be + * the same type denoted by the {@link ClassSubstitution} annotation on + * {@code substitutions}. It is required here so that an implementation is not forced + * to read annotations during registration. + * @param substitutions the class defining substitutions for {@code original}. This class must + * be annotated with {@link ClassSubstitution}. */ - void registerSubstitutions(Class substitutions); + void registerSubstitutions(Type original, Class substitutions); /** * Returns all methods that are currently registered as method/macro substitution or as a diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java Tue May 27 21:20:01 2014 -0700 @@ -22,9 +22,10 @@ */ package com.oracle.graal.phases.tiers; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.phases.*; -public interface CompilerConfiguration { +public interface CompilerConfiguration extends Service { PhaseSuite createHighTier(); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Tue May 27 21:20:01 2014 -0700 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -65,7 +66,7 @@ CompilerConfiguration nonBasic = null; int nonBasicCount = 0; - for (CompilerConfiguration config : ServiceLoader.loadInstalled(CompilerConfiguration.class)) { + for (CompilerConfiguration config : Services.load(CompilerConfiguration.class)) { String name = config.getClass().getSimpleName(); if (name.endsWith("CompilerConfiguration")) { name = name.substring(0, name.length() - "CompilerConfiguration".length()); diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java Tue May 27 21:20:01 2014 -0700 @@ -25,6 +25,8 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -40,8 +42,8 @@ public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { if (Intrinsify.getValue()) { - replacements.registerSubstitutions(ArraysSubstitutions.class); - replacements.registerSubstitutions(StringSubstitutions.class); + replacements.registerSubstitutions(Arrays.class, ArraysSubstitutions.class); + replacements.registerSubstitutions(String.class, StringSubstitutions.class); } } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java Tue May 27 21:20:01 2014 -0700 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; public class BoxingSubstitutions { @@ -140,8 +141,14 @@ } } - public static Class[] getClasses() { - return new Class[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class, - LongSubstitutions.class, ShortSubstitutions.class}; + public static void registerReplacements(Replacements replacements) { + replacements.registerSubstitutions(Boolean.class, BooleanSubstitutions.class); + replacements.registerSubstitutions(Character.class, CharacterSubstitutions.class); + replacements.registerSubstitutions(Double.class, DoubleSubstitutions.class); + replacements.registerSubstitutions(Byte.class, ByteSubstitutions.class); + replacements.registerSubstitutions(Float.class, FloatSubstitutions.class); + replacements.registerSubstitutions(Integer.class, IntegerSubstitutions.class); + replacements.registerSubstitutions(Short.class, ShortSubstitutions.class); + replacements.registerSubstitutions(Long.class, LongSubstitutions.class); } } diff -r eedf6c293639 -r 57303ce74a21 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 Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Tue May 27 21:20:01 2014 -0700 @@ -24,6 +24,8 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; +import java.lang.reflect.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -37,20 +39,17 @@ public class GraalMethodSubstitutions implements ReplacementsProvider { public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { - for (Class clazz : BoxingSubstitutions.getClasses()) { - replacements.registerSubstitutions(clazz); - } - + BoxingSubstitutions.registerReplacements(replacements); if (Intrinsify.getValue()) { - replacements.registerSubstitutions(ArraySubstitutions.class); - replacements.registerSubstitutions(MathSubstitutionsX86.class); - replacements.registerSubstitutions(DoubleSubstitutions.class); - replacements.registerSubstitutions(FloatSubstitutions.class); - replacements.registerSubstitutions(LongSubstitutions.class); - replacements.registerSubstitutions(IntegerSubstitutions.class); - replacements.registerSubstitutions(CharacterSubstitutions.class); - replacements.registerSubstitutions(ShortSubstitutions.class); - replacements.registerSubstitutions(UnsignedMathSubstitutions.class); + replacements.registerSubstitutions(Array.class, ArraySubstitutions.class); + replacements.registerSubstitutions(Math.class, MathSubstitutionsX86.class); + replacements.registerSubstitutions(Double.class, DoubleSubstitutions.class); + replacements.registerSubstitutions(Float.class, FloatSubstitutions.class); + replacements.registerSubstitutions(Long.class, LongSubstitutions.class); + replacements.registerSubstitutions(Integer.class, IntegerSubstitutions.class); + replacements.registerSubstitutions(Character.class, CharacterSubstitutions.class); + replacements.registerSubstitutions(Short.class, ShortSubstitutions.class); + replacements.registerSubstitutions(UnsignedMath.class, UnsignedMathSubstitutions.class); } } } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue May 27 21:20:01 2014 -0700 @@ -29,6 +29,7 @@ import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.atomic.*; import sun.misc.*; @@ -68,28 +69,165 @@ */ protected final ConcurrentMap graphs; - // These data structures are all fully initialized during single-threaded - // compiler startup and so do not need to be concurrent. - protected final Map registeredMethodSubstitutions; - private final Map> registeredMacroSubstitutions; - private final Set forcedSubstitutions; + /** + * Encapsulates method and macro substitutions for a single class. + */ + protected class ClassReplacements { + protected final Map methodSubstitutions = new HashMap<>(); + private final Map> macroSubstitutions = new HashMap<>(); + private final Set forcedSubstitutions = new HashSet<>(); + + public ClassReplacements(Class[] substitutionClasses, AtomicReference ref) { + for (Class substitutionClass : substitutionClasses) { + ClassSubstitution classSubstitution = substitutionClass.getAnnotation(ClassSubstitution.class); + assert !Snippets.class.isAssignableFrom(substitutionClass); + SubstitutionGuard defaultGuard = getGuard(classSubstitution.defaultGuard()); + for (Method substituteMethod : substitutionClass.getDeclaredMethods()) { + if (ref.get() != null) { + // Bail if another thread beat us creating the substitutions + return; + } + MethodSubstitution methodSubstitution = substituteMethod.getAnnotation(MethodSubstitution.class); + MacroSubstitution macroSubstitution = substituteMethod.getAnnotation(MacroSubstitution.class); + if (methodSubstitution == null && macroSubstitution == null) { + continue; + } + + int modifiers = substituteMethod.getModifiers(); + if (!Modifier.isStatic(modifiers)) { + throw new GraalInternalError("Substitution methods must be static: " + substituteMethod); + } + + if (methodSubstitution != null) { + SubstitutionGuard guard = getGuard(methodSubstitution.guard()); + if (guard == null) { + guard = defaultGuard; + } + + if (macroSubstitution != null && macroSubstitution.isStatic() != methodSubstitution.isStatic()) { + throw new GraalInternalError("Macro and method substitution must agree on isStatic attribute: " + substituteMethod); + } + if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + throw new GraalInternalError("Substitution method must not be abstract or native: " + substituteMethod); + } + String originalName = originalName(substituteMethod, methodSubstitution.value()); + JavaSignature originalSignature = originalSignature(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic()); + Member originalMethod = originalMethod(classSubstitution, methodSubstitution.optional(), originalName, originalSignature); + if (originalMethod != null && (guard == null || guard.execute())) { + ResolvedJavaMethod original = registerMethodSubstitution(this, originalMethod, substituteMethod); + if (original != null && methodSubstitution.forced() && shouldIntrinsify(original)) { + forcedSubstitutions.add(original); + } + } + } + // We don't have per method guards for macro substitutions but at + // least respect the defaultGuard if there is one. + if (macroSubstitution != null && (defaultGuard == null || defaultGuard.execute())) { + String originalName = originalName(substituteMethod, macroSubstitution.value()); + JavaSignature originalSignature = originalSignature(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic()); + Member originalMethod = originalMethod(classSubstitution, macroSubstitution.optional(), originalName, originalSignature); + if (originalMethod != null) { + ResolvedJavaMethod original = registerMacroSubstitution(this, originalMethod, macroSubstitution.macro()); + if (original != null && macroSubstitution.forced() && shouldIntrinsify(original)) { + forcedSubstitutions.add(original); + } + } + } + } + } + } + + private JavaSignature originalSignature(Method substituteMethod, String methodSubstitution, boolean isStatic) { + Class[] parameters; + Class returnType; + if (methodSubstitution.isEmpty()) { + parameters = substituteMethod.getParameterTypes(); + if (!isStatic) { + assert parameters.length > 0 : "must be a static method with the 'this' object as its first parameter"; + parameters = Arrays.copyOfRange(parameters, 1, parameters.length); + } + returnType = substituteMethod.getReturnType(); + } else { + Signature signature = providers.getMetaAccess().parseMethodDescriptor(methodSubstitution); + parameters = new Class[signature.getParameterCount(false)]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = resolveClass(signature.getParameterType(i, null)); + } + returnType = resolveClass(signature.getReturnType(null)); + } + return new JavaSignature(returnType, parameters); + } + + private Member originalMethod(ClassSubstitution classSubstitution, boolean optional, String name, JavaSignature signature) { + Class originalClass = classSubstitution.value(); + if (originalClass == ClassSubstitution.class) { + originalClass = resolveClass(classSubstitution.className(), classSubstitution.optional()); + if (originalClass == null) { + // optional class was not found + return null; + } + } + try { + if (name.equals("")) { + assert signature.returnType.equals(void.class) : signature; + Constructor original = originalClass.getDeclaredConstructor(signature.parameters); + return original; + } else { + Method original = originalClass.getDeclaredMethod(name, signature.parameters); + if (!original.getReturnType().equals(signature.returnType)) { + throw new NoSuchMethodException(originalClass.getName() + "." + name + signature); + } + return original; + } + } catch (NoSuchMethodException | SecurityException e) { + if (optional) { + return null; + } + throw new GraalInternalError(e); + } + } + } + + /** + * Per-class replacements. The entries in these maps are all fully initialized during + * single-threaded compiler startup and so do not need to be concurrent. + */ + private final Map> classReplacements; + private final Map[]> internalNameToSubstitutionClasses; + private final Map, SnippetTemplateCache> snippetTemplateCache; public ReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, Assumptions assumptions, TargetDescription target) { this.providers = providers.copyWith(this); + this.classReplacements = new HashMap<>(); + this.internalNameToSubstitutionClasses = new HashMap<>(); this.snippetReflection = snippetReflection; this.target = target; this.assumptions = assumptions; this.graphs = new ConcurrentHashMap<>(); - this.registeredMethodSubstitutions = new HashMap<>(); - this.registeredMacroSubstitutions = new HashMap<>(); - this.forcedSubstitutions = new HashSet<>(); this.snippetTemplateCache = new HashMap<>(); } private static final boolean UseSnippetGraphCache = Boolean.parseBoolean(System.getProperty("graal.useSnippetGraphCache", "true")); private static final DebugTimer SnippetPreparationTime = Debug.timer("SnippetPreparationTime"); + /** + * Gets the method and macro replacements for a given class. This method will parse the + * replacements in the substitution classes associated with {@code internalName} the first time + * this method is called for {@code internalName}. + */ + protected ClassReplacements getClassReplacements(String internalName) { + Class[] substitutionClasses = internalNameToSubstitutionClasses.get(internalName); + if (substitutionClasses != null) { + AtomicReference crRef = classReplacements.get(internalName); + if (crRef.get() == null) { + crRef.compareAndSet(null, new ClassReplacements(substitutionClasses, crRef)); + } + return crRef.get(); + } + return null; + } + public StructuredGraph getSnippet(ResolvedJavaMethod method) { return getSnippet(method, null); } @@ -133,7 +271,8 @@ @Override public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) { - ResolvedJavaMethod substitute = registeredMethodSubstitutions.get(original); + ClassReplacements cr = getClassReplacements(original.getDeclaringClass().getName()); + ResolvedJavaMethod substitute = cr == null ? null : cr.methodSubstitutions.get(original); if (substitute == null) { return null; } @@ -150,7 +289,8 @@ } public Class getMacroSubstitution(ResolvedJavaMethod method) { - return registeredMacroSubstitutions.get(method); + ClassReplacements cr = getClassReplacements(method.getDeclaringClass().getName()); + return cr == null ? null : cr.macroSubstitutions.get(method); } public Assumptions getAssumptions() { @@ -168,59 +308,29 @@ return null; } - public void registerSubstitutions(Class substitutions) { - ClassSubstitution classSubstitution = substitutions.getAnnotation(ClassSubstitution.class); - assert classSubstitution != null; - assert !Snippets.class.isAssignableFrom(substitutions); - SubstitutionGuard defaultGuard = getGuard(classSubstitution.defaultGuard()); - for (Method substituteMethod : substitutions.getDeclaredMethods()) { - MethodSubstitution methodSubstitution = substituteMethod.getAnnotation(MethodSubstitution.class); - MacroSubstitution macroSubstitution = substituteMethod.getAnnotation(MacroSubstitution.class); - if (methodSubstitution == null && macroSubstitution == null) { - continue; - } - - int modifiers = substituteMethod.getModifiers(); - if (!Modifier.isStatic(modifiers)) { - throw new GraalInternalError("Substitution methods must be static: " + substituteMethod); - } - - if (methodSubstitution != null) { - SubstitutionGuard guard = getGuard(methodSubstitution.guard()); - if (guard == null) { - guard = defaultGuard; - } + private static String getOriginalInternalName(Class substitutions) { + ClassSubstitution cs = substitutions.getAnnotation(ClassSubstitution.class); + assert cs != null : substitutions + " must be annotated by " + ClassSubstitution.class.getSimpleName(); + if (cs.value() == ClassSubstitution.class) { + return toInternalName(cs.className()); + } + return toInternalName(cs.value().getName()); + } - if (macroSubstitution != null && macroSubstitution.isStatic() != methodSubstitution.isStatic()) { - throw new GraalInternalError("Macro and method substitution must agree on isStatic attribute: " + substituteMethod); - } - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new GraalInternalError("Substitution method must not be abstract or native: " + substituteMethod); - } - String originalName = originalName(substituteMethod, methodSubstitution.value()); - JavaSignature originalSignature = originalSignature(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic()); - Member originalMethod = originalMethod(classSubstitution, methodSubstitution.optional(), originalName, originalSignature); - if (originalMethod != null && (guard == null || guard.execute())) { - ResolvedJavaMethod original = registerMethodSubstitution(originalMethod, substituteMethod); - if (original != null && methodSubstitution.forced() && shouldIntrinsify(original)) { - forcedSubstitutions.add(original); - } - } - } - // We don't have per method guards for macro substitutions but at - // least respect the defaultGuard if there is one. - if (macroSubstitution != null && (defaultGuard == null || defaultGuard.execute())) { - String originalName = originalName(substituteMethod, macroSubstitution.value()); - JavaSignature originalSignature = originalSignature(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic()); - Member originalMethod = originalMethod(classSubstitution, macroSubstitution.optional(), originalName, originalSignature); - if (originalMethod != null) { - ResolvedJavaMethod original = registerMacroSubstitution(originalMethod, macroSubstitution.macro()); - if (original != null && macroSubstitution.forced() && shouldIntrinsify(original)) { - forcedSubstitutions.add(original); - } - } - } + public void registerSubstitutions(Type original, Class substitutionClass) { + String internalName = toInternalName(original.getTypeName()); + assert getOriginalInternalName(substitutionClass).equals(internalName) : getOriginalInternalName(substitutionClass) + " != " + (internalName); + Class[] classes = internalNameToSubstitutionClasses.get(internalName); + if (classes == null) { + classes = new Class[]{substitutionClass}; + } else { + assert !Arrays.asList(classes).contains(substitutionClass); + classes = Arrays.copyOf(classes, classes.length + 1); + classes[classes.length - 1] = substitutionClass; } + internalNameToSubstitutionClasses.put(internalName, classes); + AtomicReference existing = classReplacements.put(internalName, new AtomicReference<>()); + assert existing == null || existing.get() == null; } /** @@ -230,7 +340,7 @@ * @param substituteMethod the substitute method * @return the original method */ - protected ResolvedJavaMethod registerMethodSubstitution(Member originalMember, Method substituteMethod) { + protected ResolvedJavaMethod registerMethodSubstitution(ClassReplacements cr, Member originalMember, Method substituteMethod) { MetaAccessProvider metaAccess = providers.getMetaAccess(); ResolvedJavaMethod substitute = metaAccess.lookupJavaMethod(substituteMethod); ResolvedJavaMethod original; @@ -243,7 +353,7 @@ Debug.log("substitution: %s --> %s", MetaUtil.format("%H.%n(%p) %r", original), MetaUtil.format("%H.%n(%p) %r", substitute)); } - registeredMethodSubstitutions.put(original, substitute); + cr.methodSubstitutions.put(original, substitute); return original; } @@ -254,7 +364,7 @@ * @param macro the substitute macro node class * @return the original method */ - protected ResolvedJavaMethod registerMacroSubstitution(Member originalMethod, Class macro) { + protected ResolvedJavaMethod registerMacroSubstitution(ClassReplacements cr, Member originalMethod, Class macro) { ResolvedJavaMethod originalJavaMethod; MetaAccessProvider metaAccess = providers.getMetaAccess(); if (originalMethod instanceof Method) { @@ -262,7 +372,7 @@ } else { originalJavaMethod = metaAccess.lookupJavaConstructor((Constructor) originalMethod); } - registeredMacroSubstitutions.put(originalJavaMethod, macro); + cr.macroSubstitutions.put(originalJavaMethod, macro); return originalJavaMethod; } @@ -551,7 +661,7 @@ * @param optional if true, resolution failure returns null * @return the resolved class or null if resolution fails and {@code optional} is true */ - static Class resolveType(String className, boolean optional) { + static Class resolveClass(String className, boolean optional) { try { // Need to use launcher class path to handle classes // that are not on the boot class path @@ -565,7 +675,7 @@ } } - private static Class resolveType(JavaType type) { + private static Class resolveClass(JavaType type) { JavaType base = type; int dimensions = 0; while (base.getComponentType() != null) { @@ -573,7 +683,7 @@ dimensions++; } - Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base), false); + Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveClass(toJavaName(base), false); return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass(); } @@ -599,67 +709,21 @@ } } - private JavaSignature originalSignature(Method substituteMethod, String methodSubstitution, boolean isStatic) { - Class[] parameters; - Class returnType; - if (methodSubstitution.isEmpty()) { - parameters = substituteMethod.getParameterTypes(); - if (!isStatic) { - assert parameters.length > 0 : "must be a static method with the 'this' object as its first parameter"; - parameters = Arrays.copyOfRange(parameters, 1, parameters.length); - } - returnType = substituteMethod.getReturnType(); - } else { - Signature signature = providers.getMetaAccess().parseMethodDescriptor(methodSubstitution); - parameters = new Class[signature.getParameterCount(false)]; - for (int i = 0; i < parameters.length; i++) { - parameters[i] = resolveType(signature.getParameterType(i, null)); - } - returnType = resolveType(signature.getReturnType(null)); - } - return new JavaSignature(returnType, parameters); - } - - private static Member originalMethod(ClassSubstitution classSubstitution, boolean optional, String name, JavaSignature signature) { - Class originalClass = classSubstitution.value(); - if (originalClass == ClassSubstitution.class) { - originalClass = resolveType(classSubstitution.className(), classSubstitution.optional()); - if (originalClass == null) { - // optional class was not found - return null; - } - } - try { - if (name.equals("")) { - assert signature.returnType.equals(void.class) : signature; - Constructor original = originalClass.getDeclaredConstructor(signature.parameters); - return original; - } else { - Method original = originalClass.getDeclaredMethod(name, signature.parameters); - if (!original.getReturnType().equals(signature.returnType)) { - throw new NoSuchMethodException(originalClass.getName() + "." + name + signature); - } - return original; - } - } catch (NoSuchMethodException | SecurityException e) { - if (optional) { - return null; - } - throw new GraalInternalError(e); - } - } - @Override public Collection getAllReplacements() { HashSet result = new HashSet<>(); - result.addAll(registeredMethodSubstitutions.keySet()); - result.addAll(registeredMacroSubstitutions.keySet()); + for (String internalName : classReplacements.keySet()) { + ClassReplacements cr = getClassReplacements(internalName); + result.addAll(cr.methodSubstitutions.keySet()); + result.addAll(cr.macroSubstitutions.keySet()); + } return result; } @Override public boolean isForcedSubstitution(ResolvedJavaMethod method) { - return forcedSubstitutions.contains(method); + ClassReplacements cr = getClassReplacements(method.getDeclaringClass().getName()); + return cr != null && cr.forcedSubstitutions.contains(method); } @Override diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue May 27 21:20:01 2014 -0700 @@ -33,6 +33,7 @@ import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.atomic.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -78,8 +79,51 @@ public static class SnippetInfo { protected final ResolvedJavaMethod method; - protected final boolean[] constantParameters; - protected final boolean[] varargsParameters; + + /** + * Lazily constructed parts of {@link SnippetInfo}. + */ + static class Lazy { + public Lazy(ResolvedJavaMethod 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 !constantParameters[i] || !varargsParameters[i] : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" + + VarargsParameter.class.getSimpleName(); + } + + // Retrieve the names only when assertions are turned on. + assert initNames(method, count); + } + + final boolean[] constantParameters; + final boolean[] varargsParameters; + + /** + * The parameter names, taken from the local variables table. Only used for assertion + * checking, so use only within an assert statement. + */ + String[] names; + + private boolean initNames(ResolvedJavaMethod method, int parameterCount) { + names = new String[parameterCount]; + 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; + } + + } + + protected final AtomicReference lazy = new AtomicReference<>(null); /** * Times instantiations of all templates derived form this snippet. @@ -95,31 +139,18 @@ */ private final DebugMetric instantiationCounter; - /** - * 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; + private Lazy lazy() { + if (lazy.get() == null) { + lazy.compareAndSet(null, new Lazy(method)); + } + return lazy.get(); + } protected SnippetInfo(ResolvedJavaMethod method) { this.method = method; instantiationCounter = Debug.metric("SnippetInstantiationCount[%s]", method); instantiationTimer = Debug.timer("SnippetInstantiationTime[%s]", method); assert method.isStatic() : "snippet method must be static: " + MetaUtil.format("%H.%n", method); - int count = method.getSignature().getParameterCount(false); - constantParameters = new boolean[count]; - varargsParameters = new boolean[count]; - 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(); - } - - names = new String[count]; - // Retrieve the names only when assertions are turned on. - assert initNames(); } private int templateCount; @@ -133,35 +164,28 @@ } } - 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 ResolvedJavaMethod getMethod() { return method; } public int getParameterCount() { - return constantParameters.length; + return lazy().constantParameters.length; } public boolean isConstantParameter(int paramIdx) { - return constantParameters[paramIdx]; + return lazy().constantParameters[paramIdx]; } public boolean isVarargsParameter(int paramIdx) { - return varargsParameters[paramIdx]; + return lazy().varargsParameters[paramIdx]; } public String getParameterName(int paramIdx) { - return names[paramIdx]; + String[] names = lazy().names; + if (names != null) { + return names[paramIdx]; + } + return null; } } @@ -223,7 +247,7 @@ private boolean check(String name, boolean constParam, boolean varargsParam) { assert nextParamIdx < info.getParameterCount() : "too many parameters: " + name + " " + this; - assert info.names[nextParamIdx] == null || info.names[nextParamIdx].equals(name) : "wrong parameter name: " + name + " " + this; + assert info.getParameterName(nextParamIdx) == null || info.getParameterName(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 + @@ -243,7 +267,7 @@ } else if (info.isVarargsParameter(i)) { result.append("varargs "); } - result.append(info.names[i]).append(" = ").append(values[i]); + result.append(info.getParameterName(i)).append(" = ").append(values[i]); sep = ", "; } result.append(">"); @@ -260,8 +284,8 @@ for (int i = 0; i < info.getParameterCount(); i++) { if (info.isConstantParameter(i)) { sb.append(sep); - if (info.names[i] != null) { - sb.append(info.names[i]); + if (info.getParameterName(i) != null) { + sb.append(info.getParameterName(i)); } else { sb.append(i); } @@ -418,25 +442,27 @@ } } + private static Method findMethod(Class declaringClass, String methodName, Method except) { + for (Method m : declaringClass.getDeclaredMethods()) { + if (m.getName().equals(methodName) && !m.equals(except)) { + return m; + } + } + return null; + } + /** - * Finds the method in {@code declaringClass} annotated with {@link Snippet} named - * {@code methodName}. If {@code methodName} is null, then there must be exactly one snippet - * method in {@code declaringClass}. + * Finds the unique method in {@code declaringClass} named {@code methodName} annotated by + * {@link Snippet} and returns a {@link SnippetInfo} value describing it. There must be + * exactly one snippet method in {@code declaringClass}. */ protected SnippetInfo snippet(Class declaringClass, String methodName) { - Method found = null; - Class clazz = declaringClass; - while (clazz != Object.class) { - for (Method method : clazz.getDeclaredMethods()) { - if (method.getAnnotation(Snippet.class) != null && (methodName == null || method.getName().equals(methodName))) { - assert found == null : "found more than one @" + Snippet.class.getSimpleName() + " method in " + declaringClass + (methodName == null ? "" : " named " + methodName); - found = method; - } - } - clazz = clazz.getSuperclass(); - } - assert found != null : "did not find @" + Snippet.class.getSimpleName() + " method in " + declaringClass + (methodName == null ? "" : " named " + methodName); - ResolvedJavaMethod javaMethod = providers.getMetaAccess().lookupJavaMethod(found); + assert methodName != null; + Method method = findMethod(declaringClass, methodName, null); + assert method != null : "did not find @" + Snippet.class.getSimpleName() + " method in " + declaringClass + " named " + methodName; + assert method.getAnnotation(Snippet.class) != null : method + " must be annotated with @" + Snippet.class.getSimpleName(); + assert findMethod(declaringClass, methodName, method) == null : "found more than one method named " + methodName + " in " + declaringClass; + ResolvedJavaMethod javaMethod = providers.getMetaAccess().lookupJavaMethod(method); providers.getReplacements().registerSnippet(javaMethod); return new SnippetInfo(javaMethod); } @@ -797,14 +823,14 @@ 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]; + assert parameter != null : this + " has no parameter named " + args.info.getParameterName(i); Object argument = args.values[i]; if (parameter instanceof ParameterNode) { if (argument instanceof ValueNode) { replacements.put((ParameterNode) parameter, (ValueNode) argument); } else { Kind kind = ((ParameterNode) parameter).getKind(); - assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.names[i]; + assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.getParameterName(i); Constant constant = forBoxed(argument, kind); replacements.put((ParameterNode) parameter, ConstantNode.forConstant(constant, metaAccess, replaceeGraph)); } @@ -836,7 +862,7 @@ } } } else { - assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.names[i] + " -> " + parameter; + assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.getParameterName(i) + " -> " + parameter; } } return replacements; @@ -1253,12 +1279,12 @@ for (int i = 0; i < args.info.getParameterCount(); i++) { if (args.info.isConstantParameter(i)) { Kind kind = signature.getParameterKind(i); - assert checkConstantArgument(metaAccess, method, signature, i, args.info.names[i], args.values[i], kind); + assert checkConstantArgument(metaAccess, method, signature, i, args.info.getParameterName(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(metaAccess, method, signature, i, args.info.names[i], varargs); + assert checkVarargs(metaAccess, method, signature, i, args.info.getParameterName(i), varargs); } } return true; diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.test/src/com/oracle/graal/test/GCAfterTestDecorator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GCAfterTestDecorator.java Tue May 27 21:20:01 2014 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.test; + +import org.junit.runner.*; + +public class GCAfterTestDecorator extends GraalJUnitRunListenerDecorator { + + public GCAfterTestDecorator(GraalJUnitRunListener l) { + super(l); + } + + @Override + public void testFinished(Description description) { + System.gc(); + super.testFinished(description); + } +} diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalJUnitCore.java --- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalJUnitCore.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalJUnitCore.java Tue May 27 21:20:01 2014 -0700 @@ -51,6 +51,7 @@ boolean enableTiming = false; boolean color = false; boolean eagerStackTrace = false; + boolean gcAfterTest = false; for (String each : args) { if (each.charAt(0) == '-') { // command line arguments @@ -62,6 +63,8 @@ color = true; } else if (each.contentEquals("-JUnitEagerStackTrace")) { eagerStackTrace = true; + } else if (each.contentEquals("-JUnitGCAfterTest")) { + gcAfterTest = true; } else { system.out().println("Unknown command line argument: " + each); } @@ -92,6 +95,9 @@ if (eagerStackTrace) { graalListener = new EagerStackTraceDecorator(graalListener); } + if (gcAfterTest) { + graalListener = new GCAfterTestDecorator(graalListener); + } junitCore.addListener(GraalTextListener.createRunListener(graalListener)); Result result = junitCore.run(classes.toArray(new Class[0])); for (Failure each : missingClasses) { diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Tue May 27 21:20:01 2014 -0700 @@ -38,7 +38,7 @@ public ExactMathTest() { if (!substitutionsInstalled) { Replacements replacements = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getReplacements(); - replacements.registerSubstitutions(ExactMathSubstitutions.class); + replacements.registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class); substitutionsInstalled = true; } } diff -r eedf6c293639 -r 57303ce74a21 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Tue May 27 21:18:45 2014 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Tue May 27 21:20:01 2014 -0700 @@ -32,6 +32,7 @@ import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; import com.oracle.graal.truffle.substitutions.*; +import com.oracle.truffle.api.*; /** * Custom {@link Replacements} for Truffle compilation. @@ -48,11 +49,11 @@ } protected void registerTruffleSubstitutions() { - registerSubstitutions(CompilerAssertsSubstitutions.class); - registerSubstitutions(CompilerDirectivesSubstitutions.class); - registerSubstitutions(ExactMathSubstitutions.class); - registerSubstitutions(OptimizedAssumptionSubstitutions.class); - registerSubstitutions(OptimizedCallTargetSubstitutions.class); + registerSubstitutions(CompilerAsserts.class, CompilerAssertsSubstitutions.class); + registerSubstitutions(CompilerDirectives.class, CompilerDirectivesSubstitutions.class); + registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class); + registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class); + registerSubstitutions(OptimizedCallTarget.class, OptimizedCallTargetSubstitutions.class); } @Override diff -r eedf6c293639 -r 57303ce74a21 hotspot/.cproject --- a/hotspot/.cproject Tue May 27 21:18:45 2014 -0700 +++ b/hotspot/.cproject Tue May 27 21:20:01 2014 -0700 @@ -1,7 +1,5 @@ - - - + @@ -27,7 +25,9 @@ - - - - - - diff -r eedf6c293639 -r 57303ce74a21 hotspot/.project --- a/hotspot/.project Tue May 27 21:18:45 2014 -0700 +++ b/hotspot/.project Tue May 27 21:20:01 2014 -0700 @@ -96,7 +96,17 @@ PARENT-1-PROJECT_LOC/src/os_cpu/bsd_x86/vm - generated + generated_compiler1 + 2 + PARENT-1-PROJECT_LOC/build/linux/linux_amd64_compiler1/generated + + + generated_compiler2 + 2 + PARENT-1-PROJECT_LOC/build/linux/linux_amd64_compiler2/generated + + + generated_graal 2 PARENT-1-PROJECT_LOC/build/linux/linux_amd64_graal/generated diff -r eedf6c293639 -r 57303ce74a21 mx/mx_graal.py --- a/mx/mx_graal.py Tue May 27 21:18:45 2014 -0700 +++ b/mx/mx_graal.py Tue May 27 21:20:01 2014 -0700 @@ -484,27 +484,21 @@ if exists(toDelete): os.unlink(toDelete) -def _update_HotSpotOptions_inline_hpp(graalJar): - p = mx.project('com.oracle.graal.hotspot') - mainClass = 'com.oracle.graal.hotspot.HotSpotOptionsLoader' - assert exists(join(p.source_dirs()[0], mainClass.replace('.', os.sep) + '.java')) - hsSrcGenDir = join(p.source_gen_dir(), 'hotspot') - if not exists(hsSrcGenDir): - os.makedirs(hsSrcGenDir) - tmp = StringIO.StringIO() - retcode = mx.run_java(['-cp', graalJar, mainClass], out=tmp.write, nonZeroIsFatal=False) - if retcode != 0: - # Suppress the error if it's because the utility class isn't compiled yet - with zipfile.ZipFile(graalJar, 'r') as zf: - mainClassFile = mainClass.replace('.', '/') + '.class' - if mainClassFile not in zf.namelist(): - return - mx.abort(retcode) - mx.update_file(join(hsSrcGenDir, 'HotSpotOptions.inline.hpp'), tmp.getvalue()) +def _update_graalRuntime_inline_hpp(graalJar): + p = mx.project('com.oracle.graal.hotspot.sourcegen') + mainClass = 'com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp' + if exists(join(p.output_dir(), mainClass.replace('.', os.sep) + '.class')): + hsSrcGenDir = join(mx.project('com.oracle.graal.hotspot').source_gen_dir(), 'hotspot') + if not exists(hsSrcGenDir): + os.makedirs(hsSrcGenDir) + + tmp = StringIO.StringIO() + mx.run_java(['-cp', '{}{}{}'.format(graalJar, os.pathsep, p.output_dir()), mainClass], out=tmp.write) + mx.update_file(join(hsSrcGenDir, 'graalRuntime.inline.hpp'), tmp.getvalue()) def _installGraalJarInJdks(graalDist): graalJar = graalDist.path - _update_HotSpotOptions_inline_hpp(graalJar) + _update_graalRuntime_inline_hpp(graalJar) jdks = _jdksDir() if exists(jdks): @@ -976,7 +970,7 @@ f_testfile.close() harness(projectscp, vmArgs) -def _unittest(args, annotations, prefixcp="", whitelist=None, verbose=False, enable_timing=False, regex=None, color=False, eager_stacktrace=False): +def _unittest(args, annotations, prefixcp="", whitelist=None, verbose=False, enable_timing=False, regex=None, color=False, eager_stacktrace=False, gc_after_test=False): mxdir = dirname(__file__) name = 'JUnitWrapper' javaSource = join(mxdir, name + '.java') @@ -999,6 +993,8 @@ coreArgs.append('-JUnitColor') if eager_stacktrace: coreArgs.append('-JUnitEagerStackTrace') + if gc_after_test: + coreArgs.append('-JUnitGCAfterTest') def harness(projectscp, vmArgs): @@ -1031,6 +1027,7 @@ --regex run only testcases matching a regular expression --color enable colors output --eager-stacktrace print stacktrace eagerly + --gc-after-test force a GC after each test To avoid conflicts with VM options '--' can be used as delimiter. @@ -1073,6 +1070,7 @@ parser.add_argument('--regex', help='run only testcases matching a regular expression', metavar='') parser.add_argument('--color', help='enable color output', action='store_true') parser.add_argument('--eager-stacktrace', help='print stacktrace eagerly', action='store_true') + parser.add_argument('--gc-after-test', help='force a GC after each test', action='store_true') ut_args = [] delimiter = False @@ -1830,7 +1828,7 @@ out = args[0] elif len(args) > 1: mx.abort('jacocoreport takes only one argument : an output directory') - mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out]) + mx.run_java(['-jar', jacocoreport.get_path(True), '--in', 'jacoco.exec', '--out', out] + [p.dir for p in mx.projects()]) def sl(args): """run an SL program""" diff -r eedf6c293639 -r 57303ce74a21 mx/projects --- a/mx/projects Tue May 27 21:18:45 2014 -0700 +++ b/mx/projects Tue May 27 21:20:01 2014 -0700 @@ -36,8 +36,8 @@ library@JACOCOAGENT@sha1=2f73a645b02e39290e577ce555f00b02004650b0 library@JACOCOREPORT@path=lib/jacocoreport.jar -library@JACOCOREPORT@urls=http://lafo.ssw.uni-linz.ac.at/jacoco/jacocoreport-0.7.1-1.jar -library@JACOCOREPORT@sha1=0c5db714804416dd1df4d8110762136ce3d5c7dc +library@JACOCOREPORT@urls=http://lafo.ssw.uni-linz.ac.at/jacoco/jacocoreport-0.7.1-2.jar +library@JACOCOREPORT@sha1=a630436391832d697a12c8f7daef8655d7a1efd2 library@DACAPO_SCALA@path=lib/dacapo-scala-0.1.0-20120216.jar library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar @@ -66,6 +66,7 @@ library@VECMATH@sha1=a0ae4f51da409fa0c20fa0ca59e6bbc9413ae71d distribution@GRAAL@path=graal.jar +distribution@GRAAL@subDir=graal distribution@GRAAL@sourcesPath=graal.src.zip distribution@GRAAL@dependencies=\ com.oracle.graal.hotspot.amd64,\ @@ -79,11 +80,13 @@ distribution@GRAAL@exclude=FINDBUGS distribution@TRUFFLE@path=truffle.jar +distribution@TRUFFLE@subDir=graal distribution@TRUFFLE@sourcesPath=truffle-sources.jar distribution@TRUFFLE@dependencies=\ com.oracle.truffle.api.dsl distribution@TRUFFLE-DSL-PROCESSOR@path=truffle-dsl-processor.jar +distribution@TRUFFLE-DSL-PROCESSOR@subDir=graal distribution@TRUFFLE-DSL-PROCESSOR@sourcesPath=truffle-dsl-processor-sources.jar distribution@TRUFFLE-DSL-PROCESSOR@dependencies=\ com.oracle.truffle.dsl.processor @@ -201,6 +204,14 @@ project@com.oracle.graal.hotspot@javaCompliance=1.8 project@com.oracle.graal.hotspot@workingSets=Graal,HotSpot +# graal.hotspot.sourcegen +project@com.oracle.graal.hotspot.sourcegen@subDir=graal +project@com.oracle.graal.hotspot.sourcegen@sourceDirs=src +project@com.oracle.graal.hotspot.sourcegen@dependencies=com.oracle.graal.hotspot +project@com.oracle.graal.hotspot.sourcegen@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.hotspot.sourcegen@javaCompliance=1.8 +project@com.oracle.graal.hotspot.sourcegen@workingSets=Graal,HotSpot + # graal.hotspot.jfr project@com.oracle.graal.hotspot.jfr@subDir=graal project@com.oracle.graal.hotspot.jfr@sourceDirs=src diff -r eedf6c293639 -r 57303ce74a21 mxtool/URLConnectionDownload.java --- a/mxtool/URLConnectionDownload.java Tue May 27 21:18:45 2014 -0700 +++ b/mxtool/URLConnectionDownload.java Tue May 27 21:20:01 2014 -0700 @@ -42,9 +42,11 @@ * successful one */ public static void main(String[] args) { - File path = new File(args[0]); - String[] urls = new String[args.length - 1]; - System.arraycopy(args, 1, urls, 0, urls.length); + File path = new File(args[0]); + boolean verbose = args[1].equals("-v"); + int offset = verbose ? 2 : 1; + String[] urls = new String[args.length - offset]; + System.arraycopy(args, offset, urls, 0, urls.length); File parent = path.getParentFile(); makeDirectory(parent); @@ -92,8 +94,10 @@ int n = 0; while ((read = in.read(buf)) != -1) { n += read; - long percent = ((long) n * 100 / size); - System.err.print("\r " + n + " bytes " + (size == -1 ? "" : " (" + percent + "%)")); + if (verbose) { + long percent = ((long) n * 100 / size); + System.err.print("\r " + n + " bytes " + (size == -1 ? "" : " (" + percent + "%)")); + } out.write(buf, 0, read); } System.err.println(); diff -r eedf6c293639 -r 57303ce74a21 mxtool/mx.py --- a/mxtool/mx.py Tue May 27 21:18:45 2014 -0700 +++ b/mxtool/mx.py Tue May 27 21:20:01 2014 -0700 @@ -33,7 +33,7 @@ Full documentation can be found at https://wiki.openjdk.java.net/display/Graal/The+mx+Tool """ -import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch +import sys, os, errno, time, subprocess, shlex, types, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch import multiprocessing import textwrap import socket @@ -1525,8 +1525,11 @@ # Don't make the reader thread a daemon otherwise output can be droppped t.start() joiners.append(t) - for t in joiners: - t.join() + while any([t.is_alive() for t in joiners]): + # Need to use timeout otherwise all signals (including CTRL-C) are blocked + # see: http://bugs.python.org/issue1167930 + for t in joiners: + t.join(10) if timeout is None or timeout == 0: retcode = waitOn(p) else: @@ -1883,60 +1886,18 @@ if d != '' and not exists(d): os.makedirs(d) - - if not path.endswith(os.sep): - # Try it with the Java tool first since it can show a progress counter - myDir = dirname(__file__) - javaSource = join(myDir, 'URLConnectionDownload.java') - javaClass = join(myDir, 'URLConnectionDownload.class') - if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): - subprocess.check_call([java().javac, '-d', myDir, javaSource]) - if run([java().java, '-cp', myDir, 'URLConnectionDownload', path] + urls, nonZeroIsFatal=False) == 0: - return - - def url_open(url): - userAgent = 'Mozilla/5.0 (compatible)' - headers = {'User-Agent' : userAgent} - req = urllib2.Request(url, headers=headers) - return urllib2.urlopen(req) - - for url in urls: - try: - if verbose: - log('Downloading ' + url + ' to ' + path) - if url.startswith('zip:') or url.startswith('jar:'): - i = url.find('!/') - if i == -1: - abort('Zip or jar URL does not contain "!/": ' + url) - url, _, entry = url[len('zip:'):].partition('!/') - with contextlib.closing(url_open(url)) as f: - data = f.read() - zipdata = StringIO.StringIO(f.read()) - - zf = zipfile.ZipFile(zipdata, 'r') - data = zf.read(entry) - with open(path, 'wb') as f: - f.write(data) - else: - with contextlib.closing(url_open(url)) as f: - data = f.read() - if path.endswith(os.sep): - # Scrape directory listing for relative URLs - hrefs = re.findall(r' href="([^"]*)"', data) - if len(hrefs) != 0: - for href in hrefs: - if not '/' in href: - download(join(path, href), [url + href], verbose) - else: - log('no locals hrefs scraped from ' + url) - else: - with open(path, 'wb') as f: - f.write(data) - return - except IOError as e: - log('Error reading from ' + url + ': ' + str(e)) - except zipfile.BadZipfile as e: - log('Error in zip file downloaded from ' + url + ': ' + str(e)) + assert not path.endswith(os.sep) + + myDir = dirname(__file__) + javaSource = join(myDir, 'URLConnectionDownload.java') + javaClass = join(myDir, 'URLConnectionDownload.class') + if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): + subprocess.check_call([java().javac, '-d', myDir, javaSource]) + verbose = [] + if sys.stderr.isatty(): + verbose.append("-v") + if run([java().java, '-cp', myDir, 'URLConnectionDownload', path] + verbose + urls, nonZeroIsFatal=False) == 0: + return abort('Could not download to ' + path + ' from any of the following URLs:\n\n ' + '\n '.join(urls) + '\n\nPlease use a web browser to do the download manually') @@ -3340,10 +3301,6 @@ refreshFile = os.path.relpath(join(p.dir, p.name + '.jar'), logicalWorkspaceRoot) _genEclipseBuilder(out, p, 'Jar', 'archive ' + p.name, refresh=True, refreshFile=refreshFile, relevantResources=[binFolder], async=True, xmlIndent='', xmlStandalone='no') - if projToDist.has_key(p.name): - dist, distDeps = projToDist[p.name] - _genEclipseBuilder(out, p, 'Create' + dist.name + 'Dist', 'archive @' + dist.name, relevantResources=[binFolder], logToFile=True, refresh=False, async=True) - out.close('buildSpec') out.open('natures') out.element('nature', data='org.eclipse.jdt.core.javanature') @@ -3422,6 +3379,43 @@ _zip_files(files, suite.dir, configZip.path) _zip_files(libFiles, suite.dir, configLibsZip) + # Create an Eclipse project for each distribution that will create/update the archive + # for the distribution whenever any project of the distribution is updated. + for dist in suite.dists: + name = dist.name + if hasattr(dist, 'subDir'): + projectDir = join(suite.dir, dist.subDir, dist.name + '.dist') + else: + projectDir = join(suite.dir, dist.name + '.dist') + if not exists(projectDir): + os.makedirs(projectDir) + distProjects = [d for d in dist.sorted_deps() if d.isProject()] + relevantResources = [] + for p in distProjects: + for srcDir in p.source_dirs(): + relevantResources.append(join(p.name, os.path.relpath(srcDir, p.dir))) + relevantResources.append(join(p.name, os.path.relpath(p.output_dir(), p.dir))) + out = XMLDoc() + out.open('projectDescription') + out.element('name', data=dist.name) + out.element('comment', data='Updates ' + dist.path + ' if a project dependency of ' + dist.name + ' is updated') + out.open('projects') + for p in distProjects: + out.element('project', data=p.name) + out.close('projects') + out.open('buildSpec') + dist.dir = projectDir + dist.javaCompliance = max([p.javaCompliance for p in distProjects]) + _genEclipseBuilder(out, dist, 'Create' + dist.name + 'Dist', 'archive @' + dist.name, relevantResources=relevantResources, logToFile=True, refresh=False, async=True) + out.close('buildSpec') + out.open('natures') + out.element('nature', data='org.eclipse.jdt.core.javanature') + out.close('natures') + out.close('projectDescription') + projectFile = join(projectDir, '.project') + update_file(projectFile, out.xml(indent='\t', newl='\n')) + files.append(projectFile) + def _zip_files(files, baseDir, zipPath): fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(zipPath), dir=baseDir) try: diff -r eedf6c293639 -r 57303ce74a21 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Tue May 27 21:18:45 2014 -0700 +++ b/src/share/vm/graal/graalRuntime.cpp Tue May 27 21:20:01 2014 -0700 @@ -641,6 +641,13 @@ return VMToCompiler::get_HotSpotGraalRuntime_jobject(); JVM_END +// private static String[] Graal.getServiceImpls(Class service) +JVM_ENTRY(jobject, JVM_GetGraalServiceImpls(JNIEnv *env, jclass c, jclass serviceClass)) + HandleMark hm; + KlassHandle serviceKlass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(serviceClass))); + return JNIHandles::make_local(THREAD, GraalRuntime::get_service_impls(serviceKlass, THREAD)()); +JVM_END + // private static TruffleRuntime Truffle.createRuntime() JVM_ENTRY(jobject, JVM_CreateTruffleRuntime(JNIEnv *env, jclass c)) return JNIHandles::make_local(VMToCompiler::create_HotSpotTruffleRuntime()()); @@ -683,7 +690,7 @@ name = arg + 1; name_len = strlen(name); name_handle = java_lang_String::create_from_str(name, CHECK); - valid = set_option(hotSpotOptionsClass, name, name_len, name_handle, arg, CHECK); + valid = set_option(hotSpotOptionsClass, name, (int)name_len, name_handle, arg, CHECK); } else { char* sep = strchr(arg, '='); if (sep != NULL) { @@ -696,7 +703,7 @@ if (HAS_PENDING_EXCEPTION) { return; } - valid = set_option(hotSpotOptionsClass, name, name_len, name_handle, sep + 1, CHECK); + valid = set_option(hotSpotOptionsClass, name, (int)name_len, name_handle, sep + 1, CHECK); } else { char buf[200]; jio_snprintf(buf, sizeof(buf), "Value for option %s must use '-G:%s=' format", arg, arg); @@ -714,7 +721,7 @@ void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) { const char* home = Arguments::get_java_home(); - int path_len = strlen(home) + strlen("/lib/graal.options") + 1; + int path_len = (int)strlen(home) + (int)strlen("/lib/graal.options") + 1; char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); char sep = os::file_separator()[0]; sprintf(path, "%s%clib%cgraal.options", home, sep, sep); @@ -813,4 +820,16 @@ return ret; } -#include "HotSpotOptions.inline.hpp" +Handle GraalRuntime::create_Service(const char* name, TRAPS) { + TempNewSymbol kname = SymbolTable::new_symbol(name, THREAD); + Klass* k = SystemDictionary::resolve_or_fail(kname, true, CHECK_NH); + instanceKlassHandle klass(THREAD, k); + klass->initialize(CHECK_NH); + klass->check_valid_for_instantiation(true, CHECK_NH); + JavaValue result(T_VOID); + instanceHandle service = klass->allocate_instance_handle(CHECK_NH); + JavaCalls::call_special(&result, service, klass, vmSymbols::object_initializer_name(), vmSymbols::void_method_signature(), THREAD); + return service; +} + +#include "graalRuntime.inline.hpp" diff -r eedf6c293639 -r 57303ce74a21 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Tue May 27 21:18:45 2014 -0700 +++ b/src/share/vm/graal/graalRuntime.hpp Tue May 27 21:20:01 2014 -0700 @@ -68,14 +68,35 @@ /** * Searches for a Graal option denoted by a given name and sets it value. * + * The definition of this method is in graalRuntime.inline.hpp + * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. + * * @returns true if the option was found * @throws InternalError if there was a problem setting the option's value */ static bool set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS); + /** + * Instantiates a service object, calls its default constructor and returns it. + * + * @param name the name of a class implementing com.oracle.graal.api.runtime.Service + */ + static Handle create_Service(const char* name, TRAPS); + public: static void initialize_natives(JNIEnv *env, jclass c2vmClass); + + /** + * Given an interface representing a Graal service (i.e. sub-interface of + * com.oracle.graal.api.runtime.Service), gets an array of objects, one per + * known implementation of the service. + * + * The definition of this method is in graalRuntime.inline.hpp + * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. + */ + static Handle get_service_impls(KlassHandle serviceKlass, TRAPS); + static BufferBlob* initialize_buffer_blob(); static bool parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS); diff -r eedf6c293639 -r 57303ce74a21 src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Tue May 27 21:18:45 2014 -0700 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Tue May 27 21:20:01 2014 -0700 @@ -44,6 +44,9 @@ static Handle VMToCompiler_instance(); public: + + static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_instance != NULL; } + // Gets the singleton HotSpotGraalRuntime instance, initializing it if necessary static Handle get_HotSpotGraalRuntime(); diff -r eedf6c293639 -r 57303ce74a21 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Tue May 27 21:18:45 2014 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Tue May 27 21:20:01 2014 -0700 @@ -59,6 +59,10 @@ #include "services/threadService.hpp" #include "utilities/dtrace.hpp" #include "utilities/macros.hpp" +#ifdef GRAAL +#include "classfile/javaAssertions.hpp" +#include "graal/graalVMToCompiler.hpp" +#endif #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" @@ -1205,6 +1209,15 @@ #ifdef GRAAL if (this_oop->is_subtype_of(SystemDictionary::Node_klass())) { if (this_oop() != SystemDictionary::Node_klass()) { + if (!VMToCompiler::is_HotSpotGraalRuntime_initialized() && JavaAssertions::systemClassDefault() == false) { + // We want to ensure that the process of initializing HotSpotGraalRuntime + // is fast since it executes at VM startup. We must avoid triggering + // class initialization of any Node classes during this process. + ResourceMark rm; + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Node subclass %s must not be initialized before HotSpotGraalRuntime is initialized", this_oop->name()->as_C_string()); + THROW_MSG(vmSymbols::java_lang_InternalError(), buf); + } // Create the NodeClass for a Node subclass. TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/Class;)Lcom/oracle/graal/graph/NodeClass;", CHECK); JavaValue result(T_OBJECT); diff -r eedf6c293639 -r 57303ce74a21 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Tue May 27 21:18:45 2014 -0700 +++ b/src/share/vm/prims/nativeLookup.cpp Tue May 27 21:20:01 2014 -0700 @@ -126,6 +126,7 @@ #ifdef GRAAL void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass); jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); + jobject JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c); jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass); #endif @@ -141,6 +142,7 @@ { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, #ifdef GRAAL { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, + { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls", NULL, FN_PTR(JVM_GetGraalServiceImpls) }, { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, diff -r eedf6c293639 -r 57303ce74a21 src/share/vm/runtime/vmStructs.hpp --- a/src/share/vm/runtime/vmStructs.hpp Tue May 27 21:18:45 2014 -0700 +++ b/src/share/vm/runtime/vmStructs.hpp Tue May 27 21:20:01 2014 -0700 @@ -127,7 +127,9 @@ #endif #ifdef GRAAL - static void initHotSpotVMConfig(oop config); + // The definition of this method is generated by + // com.oracle.graal.hotspotvmconfig.HotSpotVMConfigProcessor. +static void initHotSpotVMConfig(oop config); #endif private: