# HG changeset patch # User Lukas Stadler # Date 1369313041 -7200 # Node ID b49fdcee6cb0e2c7f63c17368b367c9539c174d2 # Parent a8a5d5832deffcb87666f104c6abe10bcdaab7c6# Parent 8e33b4ebfef1e16ba6c3590955239ffa882f2b6c Merge diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Thu May 23 14:44:01 2013 +0200 @@ -161,8 +161,25 @@ /** * Determine the maximum vector length supported for vector operations on values of a given * {@link Kind}. + * + * @param kind the kind of the individual vector elements + * @return the maximum supported vector size */ - public int getMaxVectorLength(@SuppressWarnings("unused") Kind kind) { + public int getMaxVectorLength(Kind kind) { + return 1; + } + + /** + * Get a natively supported vector length for breaking down some vector operation on a constant + * length vector. + * + * @param kind the kind of the individual vector elements + * @param maxLength the maximum length that should be returned + * @param arithmetic whether the vector length needs to support arithmetic operations or just + * load and store + * @return a supported vector size, but at most {@code maxLength} + */ + public int getSupportedVectorLength(Kind kind, int maxLength, boolean arithmetic) { return 1; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Thu May 23 14:44:01 2013 +0200 @@ -213,7 +213,8 @@ public boolean equals(Object obj) { if (obj instanceof Register) { Register other = (Register) obj; - if (number == other.number && name.equals(other.name)) { + if (number == other.number) { + assert name.equals(other.name); assert encoding == other.encoding; assert registerCategory == other.registerCategory; return true; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Thu May 23 14:44:01 2013 +0200 @@ -120,7 +120,7 @@ } public static boolean sameRegister(Value v1, Value v2) { - return isRegister(v1) && isRegister(v2) && asRegister(v1) == asRegister(v2); + return isRegister(v1) && isRegister(v2) && asRegister(v1).equals(asRegister(v2)); } public static boolean sameRegister(Value v1, Value v2, Value v3) { @@ -128,7 +128,7 @@ } public static boolean differentRegisters(Value v1, Value v2) { - return !isRegister(v1) || !isRegister(v2) || asRegister(v1) != asRegister(v2); + return !isRegister(v1) || !isRegister(v2) || !asRegister(v1).equals(asRegister(v2)); } public static boolean differentRegisters(Value v1, Value v2, Value v3) { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java Thu May 23 14:44:01 2013 +0200 @@ -147,7 +147,8 @@ } else { Kind componentKind = type.getComponentType().getKind().getStackKind(); for (int i = 0; i < values.length; i++) { - assert values[i].getKind().getStackKind() == componentKind : values[i].getKind() + " != " + componentKind; + assert values[i].getKind().getStackKind() == componentKind || componentKind.getBitCount() >= values[i].getKind().getStackKind().getBitCount() : values[i].getKind() + " != " + + componentKind; } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractJavaProfile.java Thu May 23 14:44:01 2013 +0200 @@ -0,0 +1,151 @@ +/* + * 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.meta; + +import java.io.*; + +/** + * This profile object represents a certain set of profiling information at a specific BCI. The + * precision of the supplied values may vary, but a runtime that provides this information should be + * aware that it will be used to guide performance-critical decisions like speculative inlining, + * etc. + */ +public abstract class AbstractJavaProfile, U> implements Serializable { + + private static final long serialVersionUID = 5493379044459116749L; + + private final double notRecordedProbability; + private final T[] pitems; + + public AbstractJavaProfile(double notRecordedProbability, T[] pitems) { + this.pitems = pitems; + assert notRecordedProbability != Double.NaN; + this.notRecordedProbability = notRecordedProbability; + assert isSorted(); + } + + /** + * Determines if an array of profiled items are sorted in descending order of their + * probabilities. + */ + private boolean isSorted() { + for (int i = 1; i < pitems.length; i++) { + if (pitems[i - 1].getProbability() < pitems[i].getProbability()) { + return false; + } + } + return true; + } + + /** + * Returns the estimated probability of all types that could not be recorded due to profiling + * limitations. + * + * @return double value >= 0.0 and <= 1.0 + */ + public double getNotRecordedProbability() { + return notRecordedProbability; + } + + protected T[] getItems() { + return pitems; + } + + /** + * Searches for an entry of a given resolved Java type. + * + * @param type the type for which an entry should be searched + * @return the entry or null if no entry for this type can be found + */ + public T findEntry(ResolvedJavaType type) { + if (pitems != null) { + for (T pt : pitems) { + if (pt.getItem() == type) { + return pt; + } + } + } + return null; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getName()); + builder.append("["); + if (pitems != null) { + for (T pt : pitems) { + builder.append(pt.toString()); + builder.append(", "); + } + } + builder.append(this.notRecordedProbability); + builder.append("]"); + return builder.toString(); + } + + public boolean isIncluded(U item) { + if (this.getNotRecordedProbability() > 0.0) { + return true; + } else { + for (int i = 0; i < getItems().length; i++) { + T pitem = getItems()[i]; + U curType = pitem.getItem(); + if (curType == item) { + return true; + } + } + } + return false; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (getClass() == other.getClass()) { + AbstractJavaProfile javaTypeProfile = (AbstractJavaProfile) other; + if (javaTypeProfile.notRecordedProbability != notRecordedProbability) { + return false; + } + if (javaTypeProfile.pitems.length != pitems.length) { + return false; + } + + for (int i = 0; i < pitems.length; ++i) { + if (!pitems[i].equals(javaTypeProfile.pitems[i])) { + return false; + } + } + + return true; + } + return false; + } + + @Override + public int hashCode() { + return (int) Double.doubleToLongBits(notRecordedProbability) + pitems.length * 13; + } +} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractProfiledItem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AbstractProfiledItem.java Thu May 23 14:44:01 2013 +0200 @@ -0,0 +1,99 @@ +/* + * 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.meta; + +import java.io.*; + +/** + * A profiled type that has a probability. Profiled types are naturally sorted in descending order + * of their probabilities. + */ +public abstract class AbstractProfiledItem implements Comparable, Serializable { + + private static final long serialVersionUID = 7838575753661305744L; + + protected final T item; + protected final double probability; + + public AbstractProfiledItem(T item, double probability) { + assert item != null; + assert probability >= 0.0D && probability <= 1.0D; + this.item = item; + this.probability = probability; + } + + protected T getItem() { + return item; + } + + /** + * Returns the estimated probability of {@link #getItem()}. + * + * @return double value >= 0.0 and <= 1.0 + */ + public double getProbability() { + return probability; + } + + @Override + public int compareTo(AbstractProfiledItem o) { + if (getProbability() > o.getProbability()) { + return -1; + } else if (getProbability() < o.getProbability()) { + return 1; + } + return 0; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(probability); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + item.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + AbstractProfiledItem other = (AbstractProfiledItem) obj; + if (Double.doubleToLongBits(probability) != Double.doubleToLongBits(other.probability)) { + return false; + } + return item.equals(other.item); + } + + @Override + public abstract String toString(); +} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java Thu May 23 14:44:01 2013 +0200 @@ -48,6 +48,11 @@ } @Override + public JavaMethodProfile getMethodProfile(int bci) { + return null; + } + + @Override public double getBranchTakenProbability(int bci) { return -1; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ForeignCallDescriptor.java Thu May 23 14:44:01 2013 +0200 @@ -33,6 +33,9 @@ *
  • The callee has different register saving semantics. For example, the callee may save all * registers (apart from some specified temporaries) in which case the register allocator doesn't * not need to spill all live registers around the call site.
  • + *
  • The call does not occur at an INVOKE* bytecode. Such a call could be transformed into a + * standard Java call if the foreign routine is a normal Java method and the runtime supports + * linking Java calls at arbitrary bytecodes.
  • * */ public class ForeignCallDescriptor { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaMethodProfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaMethodProfile.java Thu May 23 14:44:01 2013 +0200 @@ -0,0 +1,64 @@ +/* + * 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.meta; + +import com.oracle.graal.api.meta.JavaMethodProfile.ProfiledMethod; + +/** + * This profile object represents the method profile at a specific BCI. The precision of the + * supplied values may vary, but a runtime that provides this information should be aware that it + * will be used to guide performance-critical decisions like speculative inlining, etc. + */ +public final class JavaMethodProfile extends AbstractJavaProfile { + + private static final long serialVersionUID = -1440572119913692689L; + + public JavaMethodProfile(double notRecordedProbability, ProfiledMethod[] pitems) { + super(notRecordedProbability, pitems); + } + + public ProfiledMethod[] getMethods() { + return super.getItems(); + } + + public static class ProfiledMethod extends AbstractProfiledItem { + + private static final long serialVersionUID = 5418813647187024693L; + + public ProfiledMethod(ResolvedJavaMethod item, double probability) { + super(item, probability); + } + + /** + * Returns the type for this profile entry. + */ + public ResolvedJavaMethod getMethod() { + return getItem(); + } + + @Override + public String toString() { + return "{" + item.getName() + ", " + probability + "}"; + } + } +} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Thu May 23 14:44:01 2013 +0200 @@ -22,134 +22,26 @@ */ package com.oracle.graal.api.meta; -import java.io.*; import java.util.*; -import com.oracle.graal.api.meta.ProfilingInfo.*; +import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; /** * This profile object represents the type profile at a specific BCI. The precision of the supplied * values may vary, but a runtime that provides this information should be aware that it will be * used to guide performance-critical decisions like speculative inlining, etc. */ -public final class JavaTypeProfile implements Serializable { +public final class JavaTypeProfile extends AbstractJavaProfile { private static final long serialVersionUID = -6877016333706838441L; - - /** - * A profiled type that has a probability. Profiled types are naturally sorted in descending - * order of their probabilities. - */ - public static final class ProfiledType implements Comparable, Serializable { - - private static final long serialVersionUID = 7838575753661305744L; - - public static final ProfiledType[] EMPTY_ARRAY = new ProfiledType[0]; - - private final ResolvedJavaType type; - private final double probability; - - public ProfiledType(ResolvedJavaType type, double probability) { - assert type != null; - assert probability >= 0.0D && probability <= 1.0D; - this.type = type; - this.probability = probability; - } - - /** - * Returns the type for this profile entry. - */ - public ResolvedJavaType getType() { - return type; - } - - /** - * Returns the estimated probability of {@link #getType()}. - * - * @return double value >= 0.0 and <= 1.0 - */ - public double getProbability() { - return probability; - } - - @Override - public int compareTo(ProfiledType o) { - if (getProbability() > o.getProbability()) { - return -1; - } else if (getProbability() < o.getProbability()) { - return 1; - } - return 0; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(probability); - result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + type.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ProfiledType other = (ProfiledType) obj; - if (Double.doubleToLongBits(probability) != Double.doubleToLongBits(other.probability)) { - return false; - } - return type.equals(other.type); - } - - @Override - public String toString() { - return "{" + type.getName() + ", " + probability + "}"; - } - } + private static final ProfiledType[] EMPTY_ARRAY = new ProfiledType[0]; private final TriState nullSeen; - private final double notRecordedProbability; - private final ProfiledType[] ptypes; - /** - * Determines if an array of profiled types are sorted in descending order of their - * probabilities. - */ - private static boolean isSorted(ProfiledType[] ptypes) { - for (int i = 1; i < ptypes.length; i++) { - if (ptypes[i - 1].getProbability() < ptypes[i].getProbability()) { - return false; - } - } - return true; - } - - public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType... ptypes) { + public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType[] pitems) { + super(notRecordedProbability, pitems); this.nullSeen = nullSeen; - this.ptypes = ptypes; - assert notRecordedProbability != Double.NaN; - this.notRecordedProbability = notRecordedProbability; - assert isSorted(ptypes); - } - - /** - * Returns the estimated probability of all types that could not be recorded due to profiling - * limitations. - * - * @return double value >= 0.0 and <= 1.0 - */ - public double getNotRecordedProbability() { - return notRecordedProbability; } /** @@ -165,41 +57,7 @@ * type and a negative type is not. */ public ProfiledType[] getTypes() { - return ptypes; - } - - /** - * Searches for an entry of a given resolved Java type. - * - * @param type the type for which an entry should be searched - * @return the entry or null if no entry for this type can be found - */ - public ProfiledType findEntry(ResolvedJavaType type) { - if (ptypes != null) { - for (ProfiledType pt : ptypes) { - if (pt.getType() == type) { - return pt; - } - } - } - return null; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("JavaTypeProfile["); - builder.append(this.nullSeen); - builder.append(", "); - if (ptypes != null) { - for (ProfiledType pt : ptypes) { - builder.append(pt.toString()); - builder.append(", "); - } - } - builder.append(this.notRecordedProbability); - builder.append("]"); - return builder.toString(); + return getItems(); } public JavaTypeProfile restrict(JavaTypeProfile otherProfile) { @@ -214,57 +72,42 @@ } ArrayList result = new ArrayList<>(); - for (int i = 0; i < getTypes().length; i++) { - ProfiledType ptype = getTypes()[i]; - ResolvedJavaType type = ptype.getType(); + for (int i = 0; i < getItems().length; i++) { + ProfiledType ptype = getItems()[i]; + ResolvedJavaType type = ptype.getItem(); if (otherProfile.isIncluded(type)) { result.add(ptype); } } - TriState newNullSeen = (otherProfile.getNullSeen() == TriState.FALSE) ? TriState.FALSE : this.nullSeen; - double newNotRecorded = this.notRecordedProbability; + TriState newNullSeen = (otherProfile.getNullSeen() == TriState.FALSE) ? TriState.FALSE : getNullSeen(); + double newNotRecorded = getNotRecordedProbability(); return createAdjustedProfile(result, newNullSeen, newNotRecorded); } - public boolean isIncluded(ResolvedJavaType type) { - if (this.getNotRecordedProbability() > 0.0) { - return true; - } else { - for (int i = 0; i < getTypes().length; i++) { - ProfiledType ptype = getTypes()[i]; - ResolvedJavaType curType = ptype.getType(); - if (curType == type) { - return true; - } - } - } - return false; - } - public JavaTypeProfile restrict(ResolvedJavaType declaredType, boolean nonNull) { ArrayList result = new ArrayList<>(); - for (int i = 0; i < getTypes().length; i++) { - ProfiledType ptype = getTypes()[i]; - ResolvedJavaType type = ptype.getType(); + for (int i = 0; i < getItems().length; i++) { + ProfiledType ptype = getItems()[i]; + ResolvedJavaType type = ptype.getItem(); if (declaredType.isAssignableFrom(type)) { result.add(ptype); } } - TriState newNullSeen = (nonNull) ? TriState.FALSE : this.nullSeen; + TriState newNullSeen = (nonNull) ? TriState.FALSE : getNullSeen(); double newNotRecorded = this.getNotRecordedProbability(); // Assume for the types not recorded, the incompatibility rate is the same. - if (getTypes().length != 0) { - newNotRecorded *= ((double) result.size() / (double) getTypes().length); + if (getItems().length != 0) { + newNotRecorded *= ((double) result.size() / (double) getItems().length); } return createAdjustedProfile(result, newNullSeen, newNotRecorded); } private JavaTypeProfile createAdjustedProfile(ArrayList result, TriState newNullSeen, double newNotRecorded) { - if (result.size() != this.getTypes().length || newNotRecorded != getNotRecordedProbability() || newNullSeen != this.nullSeen) { + if (result.size() != this.getItems().length || newNotRecorded != getNotRecordedProbability() || newNullSeen != getNullSeen()) { if (result.size() == 0) { - return new JavaTypeProfile(newNullSeen, 1.0, ProfiledType.EMPTY_ARRAY); + return new JavaTypeProfile(newNullSeen, 1.0, EMPTY_ARRAY); } double probabilitySum = 0.0; for (int i = 0; i < result.size(); i++) { @@ -277,7 +120,7 @@ ProfiledType[] newResult = new ProfiledType[result.size()]; for (int i = 0; i < newResult.length; ++i) { ProfiledType curType = result.get(i); - newResult[i] = new ProfiledType(curType.getType(), Math.min(1.0, curType.getProbability() * factor)); + newResult[i] = new ProfiledType(curType.getItem(), Math.min(1.0, curType.getProbability() * factor)); } double newNotRecordedTypeProbability = Math.min(1.0, newNotRecorded * factor); return new JavaTypeProfile(newNullSeen, newNotRecordedTypeProbability, newResult); @@ -287,34 +130,32 @@ @Override public boolean equals(Object other) { - if (other == this) { - return true; - } - if (other instanceof JavaTypeProfile) { - JavaTypeProfile javaTypeProfile = (JavaTypeProfile) other; - if (javaTypeProfile.nullSeen != nullSeen) { - return false; - } - if (javaTypeProfile.notRecordedProbability != notRecordedProbability) { - return false; - } - if (javaTypeProfile.ptypes.length != ptypes.length) { - return false; - } - - for (int i = 0; i < ptypes.length; ++i) { - if (!ptypes[i].equals(javaTypeProfile.ptypes[i])) { - return false; - } - } - - return true; - } - return false; + return super.equals(other) && nullSeen.equals(((JavaTypeProfile) other).nullSeen); } @Override public int hashCode() { - return nullSeen.hashCode() + (int) Double.doubleToLongBits(notRecordedProbability) + ptypes.length * 13; + return nullSeen.hashCode() + super.hashCode(); + } + + public static class ProfiledType extends AbstractProfiledItem { + + private static final long serialVersionUID = 1481773321889860837L; + + public ProfiledType(ResolvedJavaType item, double probability) { + super(item, probability); + } + + /** + * Returns the type for this profile entry. + */ + public ResolvedJavaType getType() { + return getItem(); + } + + @Override + public String toString() { + return "{" + item.getName() + ", " + probability + "}"; + } } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java Thu May 23 14:44:01 2013 +0200 @@ -362,8 +362,12 @@ case Char: case Short: return 16; + case Float: + return 32; case Int: return 32; + case Double: + return 64; case Long: return 64; default: diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LocationIdentity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LocationIdentity.java Thu May 23 14:44:01 2013 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.meta; + +/** + * Marker interface for location identities. Apart from the special values {@link #ANY_LOCATION} and + * {@link #FINAL_LOCATION}, a different location identity of two memory accesses guarantees that the + * two accesses do not interfere. + */ +public interface LocationIdentity { + + /** + * Denotes any location. A write to such a location kills all values in a memory map during an + * analysis of memory accesses. A read from this location cannot be moved or coalesced with + * other reads because its interaction with other reads is not known. + */ + LocationIdentity ANY_LOCATION = new NamedLocationIdentity("ANY_LOCATION"); + + /** + * Denotes the location of a value that is guaranteed to be final. + */ + LocationIdentity FINAL_LOCATION = new NamedLocationIdentity("FINAL_LOCATION"); + +} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Thu May 23 14:44:01 2013 +0200 @@ -96,8 +96,15 @@ Constant readUnsafeConstant(Kind kind, Object base, long displacement); /** - * Determines if a given foreign call has a side-effect. Deoptimization cannot return execution - * to a point before a foreign call that has a side effect. + * Determines if a given foreign call is side-effect free. Deoptimization cannot return + * execution to a point before a foreign call that has a side effect. */ - boolean hasSideEffect(ForeignCallDescriptor descriptor); + boolean isReexecutable(ForeignCallDescriptor descriptor); + + /** + * Gets the set of memory locations killed by a given foreign call. Returning the special value + * {@link LocationIdentity#ANY_LOCATION} denotes that the call kills all memory locations. + * Returning any empty array denotes that the call does not kill any memory locations. + */ + LocationIdentity[] getKilledLocationIdentities(ForeignCallDescriptor descriptor); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Thu May 23 14:44:01 2013 +0200 @@ -28,7 +28,6 @@ import java.lang.reflect.*; import java.util.*; -import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.api.meta.ProfilingInfo.TriState; /** @@ -546,21 +545,10 @@ } JavaTypeProfile typeProfile = info.getTypeProfile(i); - if (typeProfile != null) { - ProfiledType[] ptypes = typeProfile.getTypes(); - if (ptypes != null) { - buf.append(String.format("types@%d:", i)); - for (int j = 0; j < ptypes.length; j++) { - ProfiledType ptype = ptypes[j]; - buf.append(String.format(" %.6f (%s)%s", ptype.getProbability(), ptype.getType(), sep)); - } - if (typeProfile.getNotRecordedProbability() != 0) { - buf.append(String.format(" %.6f %s", typeProfile.getNotRecordedProbability(), sep)); - } else { - buf.append(String.format(" %s", sep)); - } - } - } + appendProfile(buf, typeProfile, i, "types", sep); + + JavaMethodProfile methodProfile = info.getMethodProfile(i); + appendProfile(buf, methodProfile, i, "methods", sep); } boolean firstDeoptReason = true; @@ -582,6 +570,24 @@ return s.substring(0, s.length() - sep.length()); } + private static void appendProfile(StringBuilder buf, AbstractJavaProfile profile, int bci, String type, String sep) { + if (profile != null) { + AbstractProfiledItem[] pitems = profile.getItems(); + if (pitems != null) { + buf.append(String.format("%s@%d:", type, bci)); + for (int j = 0; j < pitems.length; j++) { + AbstractProfiledItem pitem = pitems[j]; + buf.append(String.format(" %.6f (%s)%s", pitem.getProbability(), pitem.getItem(), sep)); + } + if (profile.getNotRecordedProbability() != 0) { + buf.append(String.format(" %.6f %s", profile.getNotRecordedProbability(), type, sep)); + } else { + buf.append(String.format(" %s", type, sep)); + } + } + } + } + /** * Converts a Java source-language class name into the internal form. * diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/NamedLocationIdentity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/NamedLocationIdentity.java Thu May 23 14:44:01 2013 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.meta; + +import java.util.*; + +/** + * A {@link LocationIdentity} with a name. + */ +public class NamedLocationIdentity implements LocationIdentity { + + protected final String name; + + /** + * Creates a named unique location identity for read and write operations. + * + * @param name the name of the new location identity + */ + public NamedLocationIdentity(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + + /** + * Returns the named location identity for an array of the given element kind. Array accesses of + * the same kind must have the same location identity unless an alias analysis guarantees that + * two distinct arrays are accessed. + */ + public static LocationIdentity getArrayLocation(Kind elementKind) { + return ARRAY_LOCATIONS.get(elementKind); + } + + private static final EnumMap ARRAY_LOCATIONS = initArrayLocations(); + + private static EnumMap initArrayLocations() { + EnumMap result = new EnumMap<>(Kind.class); + for (Kind kind : Kind.values()) { + result.put(kind, new NamedLocationIdentity("Array: " + kind.getJavaName())); + } + return result; + } +} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java Thu May 23 14:44:01 2013 +0200 @@ -66,25 +66,31 @@ /** * Returns the TypeProfile for the given BCI. * - * @return Returns an JavaTypeProfile object, or null if not available. + * @return Returns a JavaTypeProfile object, or null if not available. */ JavaTypeProfile getTypeProfile(int bci); /** + * Returns the MethodProfile for the given BCI. + * + * @return Returns a JavaMethodProfile object, or null if not available. + */ + JavaMethodProfile getMethodProfile(int bci); + + /** * Returns information if the given BCI did ever throw an exception. * * @return {@link TriState#TRUE} if the instruction has thrown an exception at least once, - * {@link TriState#FALSE} if it never threw an exception, and - * {@link TriState#UNKNOWN} if this information was not recorded. + * {@link TriState#FALSE} if it never threw an exception, and {@link TriState#UNKNOWN} + * if this information was not recorded. */ TriState getExceptionSeen(int bci); /** * Returns information if null was ever seen for the given BCI. * - * @return {@link TriState#TRUE} if null was seen for the instruction, - * {@link TriState#FALSE} if null was NOT seen, and - * {@link TriState#UNKNOWN} if this information was not recorded. + * @return {@link TriState#TRUE} if null was seen for the instruction, {@link TriState#FALSE} if + * null was NOT seen, and {@link TriState#UNKNOWN} if this information was not recorded. */ TriState getNullSeen(int bci); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java Thu May 23 14:44:01 2013 +0200 @@ -114,11 +114,11 @@ StringBuilder s = new StringBuilder(); s.append("["); String sep = ""; - if (getBase() != Register.None) { + if (!getBase().equals(Register.None)) { s.append(getBase()); sep = " + "; } - if (getIndex() != Register.None) { + if (!getIndex().equals(Register.None)) { s.append(sep).append(getIndex()).append(" * ").append(getScale().value); sep = " + "; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Thu May 23 14:44:01 2013 +0200 @@ -216,7 +216,7 @@ } protected void emitOperandHelper(Register reg, AMD64Address addr) { - assert reg != Register.None; + assert !reg.equals(Register.None); emitOperandHelper(encode(reg), addr); } @@ -230,14 +230,14 @@ AMD64Address.Scale scale = addr.getScale(); int disp = addr.getDisplacement(); - if (base == Register.Frame) { + if (base.equals(Register.Frame)) { assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration"; base = frameRegister; } - if (base == AMD64.rip) { // also matches Placeholder + if (base.equals(AMD64.rip)) { // also matches Placeholder // [00 000 101] disp32 - assert index == Register.None : "cannot use RIP relative addressing with index register"; + assert index.equals(Register.None) : "cannot use RIP relative addressing with index register"; emitByte(0x05 | regenc); emitInt(disp); } else if (base.isValid()) { @@ -245,28 +245,28 @@ if (index.isValid()) { int indexenc = encode(index) << 3; // [base + indexscale + disp] - if (disp == 0 && base != rbp && (base != r13)) { + if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) { // [base + indexscale] // [00 reg 100][ss index base] - assert index != rsp : "illegal addressing mode"; + assert !index.equals(rsp) : "illegal addressing mode"; emitByte(0x04 | regenc); emitByte(scale.log2 << 6 | indexenc | baseenc); } else if (isByte(disp)) { // [base + indexscale + imm8] // [01 reg 100][ss index base] imm8 - assert index != rsp : "illegal addressing mode"; + assert !index.equals(rsp) : "illegal addressing mode"; emitByte(0x44 | regenc); emitByte(scale.log2 << 6 | indexenc | baseenc); emitByte(disp & 0xFF); } else { // [base + indexscale + disp32] // [10 reg 100][ss index base] disp32 - assert index != rsp : "illegal addressing mode"; + assert !index.equals(rsp) : "illegal addressing mode"; emitByte(0x84 | regenc); emitByte(scale.log2 << 6 | indexenc | baseenc); emitInt(disp); } - } else if (base == rsp || (base == r12)) { + } else if (base.equals(rsp) || base.equals(r12)) { // [rsp + disp] if (disp == 0) { // [rsp] @@ -288,8 +288,8 @@ } } else { // [base + disp] - assert base != rsp && (base != r12) : "illegal addressing mode"; - if (disp == 0 && base != rbp && (base != r13)) { + assert !base.equals(rsp) && !base.equals(r12) : "illegal addressing mode"; + if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) { // [base] // [00 reg base] emitByte(0x00 | regenc | baseenc); @@ -310,7 +310,7 @@ int indexenc = encode(index) << 3; // [indexscale + disp] // [00 reg 100][ss index 101] disp32 - assert index != rsp : "illegal addressing mode"; + assert !index.equals(rsp) : "illegal addressing mode"; emitByte(0x04 | regenc); emitByte(scale.log2 << 6 | indexenc | 0x05); emitInt(disp); @@ -531,7 +531,7 @@ // cmpxchg r,[m] is equivalent to X86.rax, = CAS (m, X86.rax, r) cmpl(rax, adr); movl(rax, adr); - if (reg != rax) { + if (reg.equals(rax)) { Label l = new Label(); jccb(ConditionFlag.NotEqual, l); movl(adr, reg); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Thu May 23 14:44:01 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; /** * This class implements commonly used X86 code patterns. @@ -255,7 +256,7 @@ private AMD64Address trigPrologue(Register value) { assert value.getRegisterCategory() == AMD64.XMM; AMD64Address tmp = new AMD64Address(AMD64.rsp); - subq(AMD64.rsp, 8); + subq(AMD64.rsp, target.arch.getSizeInBytes(Kind.Double)); movsd(tmp, value); fld_d(tmp); return tmp; @@ -265,7 +266,7 @@ assert dest.getRegisterCategory() == AMD64.XMM; fstp_d(tmp); movsd(dest, tmp); - addq(AMD64.rsp, 8); + addq(AMD64.rsp, target.arch.getSizeInBytes(Kind.Double)); } /** diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Thu May 23 14:44:01 2013 +0200 @@ -135,7 +135,7 @@ @Override public Variable emitMove(Value input) { - Variable result = newVariable(input.getKind()); + Variable result = newVariable(input.getPlatformKind()); emitMove(result, input); return result; } diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu May 23 14:44:01 2013 +0200 @@ -426,18 +426,29 @@ } long start = System.currentTimeMillis(); PhasePlan phasePlan = new PhasePlan(); - StructuredGraph graphCopy = graph.copy(); + final StructuredGraph graphCopy = graph.copy(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase()); editPhasePlan(method, graph, phasePlan); CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false); - CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, + final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog()); if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } - return addMethod(method, compResult, graphCopy); + return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable() { + + @Override + public InstalledCode call() throws Exception { + InstalledCode code = addMethod(method, compResult, graphCopy); + if (Debug.isDumpEnabled()) { + Debug.dump(new Object[]{compResult, code}, "After code installation"); + } + + return code; + } + }); } }); @@ -448,18 +459,7 @@ } protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) { - return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable() { - - @Override - public InstalledCode call() throws Exception { - InstalledCode installedCode = runtime.addMethod(method, compResult, graph); - if (Debug.isDumpEnabled()) { - Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); - } - - return installedCode; - } - }); + return runtime.addMethod(method, compResult, graph); } /** diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java Thu May 23 14:44:01 2013 +0200 @@ -105,7 +105,7 @@ } @Test - public void testTypeProfileInvokeVirtual() { + public void testProfileInvokeVirtual() { testTypeProfile("invokeVirtualSnippet", 1); } @@ -140,18 +140,18 @@ return obj instanceof Serializable; } - private void testTypeProfile(String methodName, int bci) { + private void testTypeProfile(String testSnippet, int bci) { ResolvedJavaType stringType = runtime.lookupJavaType(String.class); ResolvedJavaType stringBuilderType = runtime.lookupJavaType(StringBuilder.class); - ProfilingInfo info = profile(methodName, "ABC"); + ProfilingInfo info = profile(testSnippet, "ABC"); JavaTypeProfile typeProfile = info.getTypeProfile(bci); Assert.assertEquals(0.0, typeProfile.getNotRecordedProbability(), DELTA); Assert.assertEquals(1, typeProfile.getTypes().length); Assert.assertEquals(stringType, typeProfile.getTypes()[0].getType()); Assert.assertEquals(1.0, typeProfile.getTypes()[0].getProbability(), DELTA); - continueProfiling(methodName, new StringBuilder()); + continueProfiling(testSnippet, new StringBuilder()); typeProfile = info.getTypeProfile(bci); Assert.assertEquals(0.0, typeProfile.getNotRecordedProbability(), DELTA); Assert.assertEquals(2, typeProfile.getTypes().length); @@ -160,7 +160,7 @@ Assert.assertEquals(0.5, typeProfile.getTypes()[0].getProbability(), DELTA); Assert.assertEquals(0.5, typeProfile.getTypes()[1].getProbability(), DELTA); - resetProfile(methodName); + resetProfile(testSnippet); typeProfile = info.getTypeProfile(bci); Assert.assertNull(typeProfile); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Thu May 23 14:44:01 2013 +0200 @@ -25,6 +25,7 @@ import org.junit.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -95,7 +96,7 @@ for (FloatingReadNode node : graph.getNodes(LocalNode.class).first().usages().filter(FloatingReadNode.class)) { // Checking that the parameter a is not directly used for the access to field // x10 (because x10 must be guarded by the checkcast). - Assert.assertTrue(node.location().getLocationIdentity() == LocationNode.FINAL_LOCATION); + Assert.assertTrue(node.location().getLocationIdentity() == LocationIdentity.FINAL_LOCATION); } } }); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java Thu May 23 14:44:01 2013 +0200 @@ -33,7 +33,6 @@ import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.phases.*; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu May 23 14:44:01 2013 +0200 @@ -125,7 +125,8 @@ } else { Debug.dump(graph, "initial state"); } - new VerifyValueUsage(runtime).apply(graph); + new VerifyUsageWithEquals(runtime, Value.class).apply(graph); + new VerifyUsageWithEquals(runtime, Register.class).apply(graph); if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Thu May 23 14:44:01 2013 +0200 @@ -654,12 +654,12 @@ int number = availableReg.number; if (usePos[number] >= intervalTo) { // this register is free for the full interval - if (minFullReg == null || availableReg == hint || (usePos[number] < usePos[minFullReg.number] && minFullReg != hint)) { + if (minFullReg == null || availableReg.equals(hint) || (usePos[number] < usePos[minFullReg.number] && !minFullReg.equals(hint))) { minFullReg = availableReg; } } else if (usePos[number] > regNeededUntil) { // this register is at least free until regNeededUntil - if (maxPartialReg == null || availableReg == hint || (usePos[number] > usePos[maxPartialReg.number] && maxPartialReg != hint)) { + if (maxPartialReg == null || availableReg.equals(hint) || (usePos[number] > usePos[maxPartialReg.number] && !maxPartialReg.equals(hint))) { maxPartialReg = availableReg; } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Thu May 23 14:44:01 2013 +0200 @@ -53,7 +53,7 @@ masm.movq(rbp, (AMD64Address) tasm.asAddress(savedRbp)); } else { Register framePointer = asRegister(savedRbp); - if (framePointer != rbp) { + if (!framePointer.equals(rbp)) { masm.movq(rbp, framePointer); } } diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu May 23 14:44:01 2013 +0200 @@ -231,14 +231,16 @@ } } } - if (!hsLinkage.isLeaf()) { - append(new AMD64HotSpotCRuntimeCallPrologueOp()); - } - Variable result = super.emitForeignCall(linkage, info, args); + Variable result; if (!hsLinkage.isLeaf()) { + assert info != null; + append(new AMD64HotSpotCRuntimeCallPrologueOp()); + result = super.emitForeignCall(linkage, info, args); append(new AMD64HotSpotCRuntimeCallEpilogueOp()); + } else { + result = super.emitForeignCall(linkage, null, args); } if (destroysRegisters) { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Thu May 23 14:44:01 2013 +0200 @@ -24,15 +24,14 @@ import static com.oracle.graal.amd64.AMD64.*; 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.replacements.AESCryptSubstitutions.DecryptBlockStubCall.*; -import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.EncryptBlockStubCall.*; -import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*; -import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*; +import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.*; +import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -62,14 +61,14 @@ RegisterValue exception = rax.asValue(Kind.Object); RegisterValue exceptionPc = rdx.asValue(word); CallingConvention exceptionCc = new CallingConvention(0, ILLEGAL, exception, exceptionPc); - register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc)); - register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc)); + register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); + register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); // The x86 crypto stubs do callee saving - registerForeignCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF); - registerForeignCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF); - registerForeignCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF); - registerForeignCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF); + registerForeignCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + registerForeignCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + registerForeignCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + registerForeignCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); convertSnippets = new AMD64ConvertSnippets.Templates(this, replacements, graalRuntime.getTarget()); super.registerReplacements(replacements); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Thu May 23 14:44:01 2013 +0200 @@ -61,13 +61,13 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { tasm.recordMark(Marks.MARK_INLINE_INVOKE); Register callReg = asRegister(targetAddress); - assert callReg != METHOD; + assert !callReg.equals(METHOD); AMD64Call.indirectCall(tasm, masm, callReg, callTarget, state); } @Override protected void verify() { super.verify(); - assert asRegister(metaspaceMethod) == METHOD; + assert asRegister(metaspaceMethod).equals(METHOD); } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Thu May 23 14:44:01 2013 +0200 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +import java.io.*; +import java.lang.reflect.*; +import java.security.*; + +import javax.crypto.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; + +/** + * Tests the intrinsification of certain crypto methods. + */ +public class HotSpotCryptoSubstitutionTest extends GraalCompilerTest { + + @Override + protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, StructuredGraph graph) { + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; + HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, graph, true); + HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(hsMethod, StructuredGraph.INVOCATION_ENTRY_BCI, compResult); + CodeInstallResult result = graalRuntime().getCompilerToVM().installCode(compiledNmethod, installedCode, null); + Assert.assertEquals("Error installing method " + method + ": " + result, result, CodeInstallResult.OK); + + // HotSpotRuntime hsRuntime = (HotSpotRuntime) runtime; + // TTY.println(hsMethod.toString()); + // TTY.println(hsRuntime.disassemble(installedCode)); + return installedCode; + } + + @Test + public void testAESEncryptSubstitution() throws Exception { + byte[] seed = {0x4, 0x7, 0x1, 0x1}; + SecureRandom random = new SecureRandom(seed); + KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES"); + aesKeyGen.init(128, random); + SecretKey aesKey = aesKeyGen.generateKey(); + byte[] input = readClassfile16(getClass()); + + ByteArrayOutputStream expected = new ByteArrayOutputStream(); + expected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); + expected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); + + if (compiledAndInstall("com.sun.crypto.provider.AESCrypt", "encryptBlock", "decryptBlock")) { + ByteArrayOutputStream actual = new ByteArrayOutputStream(); + actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); + actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); + Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray()); + } + + if (compiledAndInstall("com.sun.crypto.provider.CipherBlockChaining", "encrypt", "decrypt")) { + ByteArrayOutputStream actual = new ByteArrayOutputStream(); + actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); + actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); + Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray()); + } + } + + /** + * Compiles and installs the substitution for some specified methods. Once installed, the next + * execution of the methods will use the newly installed code. + * + * @param className the name of the class for which substitutions are available + * @param methodNames the names of the substituted methods + * @return true if at least one substitution was compiled and installed + */ + private boolean compiledAndInstall(String className, String... methodNames) { + boolean atLeastOneCompiled = false; + for (String methodName : methodNames) { + Method method = lookup(className, methodName); + if (method != null) { + ResolvedJavaMethod installedCodeOwner = runtime.lookupJavaMethod(method); + StructuredGraph graph = replacements.getMethodSubstitution(installedCodeOwner); + if (graph != null) { + Assert.assertNotNull(getCode(installedCodeOwner, graph, true)); + atLeastOneCompiled = true; + } else { + Assert.assertFalse(graalRuntime().getConfig().useAESIntrinsics); + } + } + } + return atLeastOneCompiled; + } + + private static Method lookup(String className, String methodName) { + Class c; + try { + c = Class.forName(className); + for (Method m : c.getDeclaredMethods()) { + if (m.getName().equals(methodName)) { + return m; + } + } + // If the expected security provider exists, the specific method should also exist + throw new NoSuchMethodError(className + "." + methodName); + } catch (ClassNotFoundException e) { + // It's ok to not find the class - a different security provider + // may have been installed + return null; + } + } + + AlgorithmParameters algorithmParameters; + + private byte[] encrypt(byte[] indata, SecretKey key, String algorithm) throws Exception { + + byte[] result = indata; + + Cipher c = Cipher.getInstance(algorithm); + c.init(Cipher.ENCRYPT_MODE, key); + algorithmParameters = c.getParameters(); + + byte[] r1 = c.update(result); + byte[] r2 = c.doFinal(); + + result = new byte[r1.length + r2.length]; + System.arraycopy(r1, 0, result, 0, r1.length); + System.arraycopy(r2, 0, result, r1.length, r2.length); + + return result; + } + + private byte[] decrypt(byte[] indata, SecretKey key, String algorithm) throws Exception { + + byte[] result = indata; + + Cipher c = Cipher.getInstance(algorithm); + c.init(Cipher.DECRYPT_MODE, key, algorithmParameters); + + byte[] r1 = c.update(result); + byte[] r2 = c.doFinal(); + + result = new byte[r1.length + r2.length]; + System.arraycopy(r1, 0, result, 0, r1.length); + System.arraycopy(r2, 0, result, r1.length, r2.length); + return result; + } + + private static byte[] readClassfile16(Class c) throws IOException { + String classFilePath = "/" + c.getName().replace('.', '/') + ".class"; + InputStream stream = c.getResourceAsStream(classFilePath); + int bytesToRead = stream.available(); + bytesToRead -= bytesToRead % 16; + byte[] classFile = new byte[bytesToRead]; + new DataInputStream(stream).readFully(classFile); + return classFile; + } + + public byte[] runEncryptDecrypt(SecretKey key, String algorithm, byte[] input) throws Exception { + byte[] indata = input.clone(); + byte[] cipher = encrypt(indata, key, algorithm); + byte[] plain = decrypt(cipher, key, algorithm); + Assert.assertArrayEquals(indata, plain); + return plain; + } +} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu May 23 14:44:01 2013 +0200 @@ -184,8 +184,10 @@ bailout.printStackTrace(TTY.cachedOut); } } catch (Throwable t) { + if (GraalOptions.PrintStackTraceOnException || GraalOptions.ExitVMOnException) { + t.printStackTrace(TTY.cachedOut); + } if (GraalOptions.ExitVMOnException) { - t.printStackTrace(TTY.cachedOut); System.exit(-1); } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java Thu May 23 14:44:01 2013 +0200 @@ -88,11 +88,18 @@ private final Transition transition; /** - * The locations defined/killed by the call. + * The registers and stack slots defined/killed by the call. */ private Value[] temporaries = AllocatableValue.NONE; /** + * The memory locations killed by the call. + */ + private final LocationIdentity[] killedLocations; + + private final boolean reexecutable; + + /** * Creates a {@link HotSpotForeignCallLinkage}. * * @param descriptor the descriptor of the call @@ -101,10 +108,15 @@ * temporaries which are always destroyed) * @param ccType calling convention type * @param transition specifies if this is a {@linkplain #isLeaf() leaf} call + * @param reexecutable specifies if the call can be re-executed without (meaningful) side + * effects. Deoptimization will not return to a point before a call that cannot be + * re-executed. + * @param killedLocations the memory locations killed by the call */ - public static HotSpotForeignCallLinkage create(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type ccType, Transition transition) { + public static HotSpotForeignCallLinkage create(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type ccType, Transition transition, boolean reexecutable, + LocationIdentity... killedLocations) { CallingConvention targetCc = createCallingConvention(descriptor, ccType); - return new HotSpotForeignCallLinkage(descriptor, address, effect, transition, targetCc); + return new HotSpotForeignCallLinkage(descriptor, address, effect, transition, targetCc, reexecutable, killedLocations); } /** @@ -130,12 +142,15 @@ } } - public HotSpotForeignCallLinkage(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Transition transition, CallingConvention cc) { + public HotSpotForeignCallLinkage(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Transition transition, CallingConvention cc, boolean reexecutable, + LocationIdentity... killedLocations) { this.address = address; this.effect = effect; this.transition = transition; this.descriptor = descriptor; this.cc = cc; + this.reexecutable = reexecutable; + this.killedLocations = killedLocations; } @Override @@ -153,6 +168,14 @@ return sb.toString(); } + public boolean isReexecutable() { + return reexecutable; + } + + public LocationIdentity[] getKilledLocations() { + return killedLocations; + } + public CallingConvention getCallingConvention() { return cc; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu May 23 14:44:01 2013 +0200 @@ -226,6 +226,16 @@ public int constMethodMaxStackOffset; /** + * Offset of _constants in a metaspace ConstMethod object. + */ + public int constMethodConstantsOffset; + + /** + * Offset of _pool_holder in a metaspace ConstantPool object. + */ + public int constantPoolHolderOffset; + + /** * Value of extra_stack_entries() in method.hpp. */ public int extraStackEntries; @@ -365,6 +375,7 @@ public int dataLayoutCellSize; public int bciProfileWidth; public int typeProfileWidth; + public int methodProfileWidth; public long inlineCacheMissStub; public long handleDeoptStub; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Thu May 23 14:44:01 2013 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.graph.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.JavaMethodProfile.ProfiledMethod; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.hotspot.*; @@ -204,6 +205,11 @@ } @Override + public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) { + return null; + } + + @Override public double getBranchTakenProbability(HotSpotMethodData data, int position) { return -1; } @@ -332,14 +338,14 @@ private abstract static class AbstractTypeData extends CounterData { - private static final int RECEIVER_TYPE_DATA_ROW_SIZE = cellsToBytes(2); - private static final int RECEIVER_TYPE_DATA_SIZE = cellIndexToOffset(2) + RECEIVER_TYPE_DATA_ROW_SIZE * config.typeProfileWidth; - protected static final int NONPROFILED_RECEIVER_COUNT_OFFSET = cellIndexToOffset(1); - private static final int RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET = cellIndexToOffset(2); - private static final int RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET = cellIndexToOffset(3); + protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(2); - protected AbstractTypeData(int tag) { - super(tag, RECEIVER_TYPE_DATA_SIZE); + protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(1); + protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(2); + protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(3); + + protected AbstractTypeData(int tag, int staticSize) { + super(tag, staticSize); } @Override @@ -352,10 +358,10 @@ int entries = 0; for (int i = 0; i < typeProfileWidth; i++) { - long receiverKlass = data.readWord(position, getReceiverOffset(i)); + long receiverKlass = data.readWord(position, getTypeOffset(i)); if (receiverKlass != 0) { types[entries] = HotSpotResolvedObjectType.fromMetaspaceKlass(receiverKlass); - long count = data.readUnsignedInt(position, getCountOffset(i)); + long count = data.readUnsignedInt(position, getTypeCountOffset(i)); totalCount += count; counts[entries] = count; @@ -390,21 +396,22 @@ return new JavaTypeProfile(nullSeen, notRecordedTypeProbability, ptypes); } - private static int getReceiverOffset(int row) { - return RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET + row * RECEIVER_TYPE_DATA_ROW_SIZE; + private static int getTypeOffset(int row) { + return TYPE_DATA_FIRST_TYPE_OFFSET + row * TYPE_DATA_ROW_SIZE; } - protected static int getCountOffset(int row) { - return RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET + row * RECEIVER_TYPE_DATA_ROW_SIZE; + protected static int getTypeCountOffset(int row) { + return TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE; } } private static class TypeCheckData extends AbstractTypeData { - private static final int RECEIVER_TYPE_DATA_TAG = 4; + private static final int TYPE_CHECK_DATA_TAG = 4; + private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth; public TypeCheckData() { - super(RECEIVER_TYPE_DATA_TAG); + super(TYPE_CHECK_DATA_TAG, TYPE_CHECK_DATA_SIZE); } @Override @@ -414,16 +421,19 @@ @Override protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) { - return data.readUnsignedIntAsSignedInt(position, NONPROFILED_RECEIVER_COUNT_OFFSET); + return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET); } } private static class VirtualCallData extends AbstractTypeData { private static final int VIRTUAL_CALL_DATA_TAG = 5; + private static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth); + private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth; + private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth; public VirtualCallData() { - super(VIRTUAL_CALL_DATA_TAG); + super(VIRTUAL_CALL_DATA_TAG, VIRTUAL_CALL_DATA_SIZE); } @Override @@ -432,7 +442,7 @@ long total = 0; for (int i = 0; i < typeProfileWidth; i++) { - total += data.readUnsignedInt(position, getCountOffset(i)); + total += data.readUnsignedInt(position, getTypeCountOffset(i)); } total += getCounterValue(data, position); @@ -443,6 +453,64 @@ protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) { return getCounterValue(data, position); } + + private static long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) { + return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET); + } + + @Override + public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) { + int profileWidth = config.methodProfileWidth; + + ResolvedJavaMethod[] methods = new ResolvedJavaMethod[profileWidth]; + long[] counts = new long[profileWidth]; + long totalCount = 0; + int entries = 0; + + for (int i = 0; i < profileWidth; i++) { + long method = data.readWord(position, getMethodOffset(i)); + if (method != 0) { + methods[entries] = HotSpotResolvedJavaMethod.fromMetaspace(method); + long count = data.readUnsignedInt(position, getMethodCountOffset(i)); + totalCount += count; + counts[entries] = count; + + entries++; + } + } + + totalCount += getMethodsNotRecordedExecutionCount(data, position); + return createMethodProfile(methods, counts, totalCount, entries); + } + + private static JavaMethodProfile createMethodProfile(ResolvedJavaMethod[] methods, long[] counts, long totalCount, int entries) { + if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) { + return null; + } + + ProfiledMethod[] pmethods = new ProfiledMethod[entries]; + double totalProbability = 0.0; + for (int i = 0; i < entries; i++) { + double p = counts[i]; + p = p / totalCount; + totalProbability += p; + pmethods[i] = new ProfiledMethod(methods[i], p); + } + + Arrays.sort(pmethods); + + double notRecordedMethodProbability = entries < config.methodProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability)); + assert notRecordedMethodProbability == 0 || entries == config.methodProfileWidth; + return new JavaMethodProfile(notRecordedMethodProbability, pmethods); + } + + private static int getMethodOffset(int row) { + return VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET + row * TYPE_DATA_ROW_SIZE; + } + + private static int getMethodCountOffset(int row) { + return VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE; + } } private static class RetData extends CounterData { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java Thu May 23 14:44:01 2013 +0200 @@ -55,6 +55,8 @@ JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position); + JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position); + double getBranchTakenProbability(HotSpotMethodData data, int position); double[] getSwitchProbabilities(HotSpotMethodData data, int position); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java Thu May 23 14:44:01 2013 +0200 @@ -57,6 +57,12 @@ } @Override + public JavaMethodProfile getMethodProfile(int bci) { + findBCI(bci, false); + return dataAccessor.getMethodProfile(methodData, position); + } + + @Override public double getBranchTakenProbability(int bci) { findBCI(bci, false); return dataAccessor.getBranchTakenProbability(methodData, position); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Thu May 23 14:44:01 2013 +0200 @@ -31,7 +31,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Thu May 23 14:44:01 2013 +0200 @@ -66,6 +66,35 @@ private CompilationTask currentTask; private SpeculationLog speculationLog; + /** + * Gets the holder of a HotSpot metaspace method native object. + * + * @param metaspaceMethod a metaspace Method object + * @return the {@link ResolvedJavaType} corresponding to the holder of the + * {@code metaspaceMethod} + */ + public static HotSpotResolvedObjectType getHolder(long metaspaceMethod) { + HotSpotVMConfig config = graalRuntime().getConfig(); + long constMethod = unsafe.getLong(metaspaceMethod + config.methodConstMethodOffset); + assert constMethod != 0; + long constantPool = unsafe.getLong(constMethod + config.constMethodConstantsOffset); + assert constantPool != 0; + long holder = unsafe.getLong(constantPool + config.constantPoolHolderOffset); + assert holder != 0; + return (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromMetaspaceKlass(holder); + } + + /** + * Gets the {@link ResolvedJavaMethod} for a HotSpot metaspace method native object. + * + * @param metaspaceMethod a metaspace Method object + * @return the {@link ResolvedJavaMethod} corresponding to {@code metaspaceMethod} + */ + public static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceMethod) { + HotSpotResolvedObjectType holder = getHolder(metaspaceMethod); + return holder.createMethod(metaspaceMethod); + } + HotSpotResolvedJavaMethod(HotSpotResolvedObjectType holder, long metaspaceMethod) { this.metaspaceMethod = metaspaceMethod; this.holder = holder; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu May 23 14:44:01 2013 +0200 @@ -26,22 +26,23 @@ import static com.oracle.graal.api.code.DeoptimizationAction.*; import static com.oracle.graal.api.code.MemoryBarriers.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.graph.UnsafeAccess.*; 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.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*; 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.ThreadIsInterruptedStubCall.*; import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; -import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*; import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*; import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*; +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*; import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*; +import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*; import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*; import static com.oracle.graal.hotspot.stubs.NewArrayStub.*; import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; @@ -95,6 +96,7 @@ public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class); public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class); + public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class); public final HotSpotVMConfig config; @@ -190,18 +192,29 @@ /** * Creates and registers the details for linking a foreign call to a {@link Stub}. + * + * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side + * effects. Deoptimization will not return to a point before a stub call that cannot + * be re-executed. + * @param killedLocations the memory locations killed by the stub call */ - protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor) { - return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF)); + protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, LocationIdentity... killedLocations) { + return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations)); } /** * Creates and registers the linkage for a foreign call. + * + * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side + * effects. Deoptimization will not return to a point before a stub call that cannot + * be re-executed. + * @param killedLocations the memory locations killed by the stub call */ - protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type ccType, RegisterEffect effect, Transition transition) { + protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type ccType, RegisterEffect effect, Transition transition, + boolean reexecutable, LocationIdentity... killedLocations) { Class resultType = descriptor.getResultType(); assert resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "foreign calls must return objects in thread local storage: " + descriptor; - return register(HotSpotForeignCallLinkage.create(descriptor, address, effect, ccType, transition)); + return register(HotSpotForeignCallLinkage.create(descriptor, address, effect, ccType, transition, reexecutable, killedLocations)); } private static void link(Stub stub) { @@ -215,9 +228,13 @@ * @param address the address of the code to call * @param prependThread true if the JavaThread value for the current thread is to be prepended * to the arguments for the call to {@code address} + * @param reexecutable specifies if the foreign call can be re-executed without (meaningful) + * side effects. Deoptimization will not return to a point before a foreign call that + * cannot be re-executed. + * @param killedLocations the memory locations killed by the foreign call */ - private void linkForeignCall(ForeignCallDescriptor descriptor, long address, boolean prependThread, Replacements replacements) { - ForeignCallStub stub = new ForeignCallStub(address, descriptor, prependThread, this, replacements); + private void linkForeignCall(Replacements replacements, ForeignCallDescriptor descriptor, long address, boolean prependThread, boolean reexecutable, LocationIdentity... killedLocations) { + ForeignCallStub stub = new ForeignCallStub(this, replacements, address, descriptor, prependThread, reexecutable, killedLocations); HotSpotForeignCallLinkage linkage = stub.getLinkage(); HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); linkage.setCompiledStub(stub); @@ -225,78 +242,86 @@ register(targetLinkage); } - public void registerReplacements(Replacements replacements) { + public static final boolean PREPEND_THREAD = true; + public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD; + + public static final boolean REEXECUTABLE = true; + public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE; + + public static final LocationIdentity[] NO_LOCATIONS = {}; + + public void registerReplacements(Replacements r) { HotSpotVMConfig c = config; TargetDescription target = getTarget(); - registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF); - registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF); - registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF); + registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF); - registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF); - registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF); - registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF); - registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF); + registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF); - registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF); - registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF); - registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF); - registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF); + registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); - link(new NewInstanceStub(this, replacements, target, registerStubCall(NEW_INSTANCE))); - link(new NewArrayStub(this, replacements, target, registerStubCall(NEW_ARRAY))); - link(new ExceptionHandlerStub(this, replacements, target, foreignCalls.get(EXCEPTION_HANDLER))); - link(new UnwindExceptionToCallerStub(this, replacements, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER))); - link(new VerifyOopStub(this, replacements, target, registerStubCall(VERIFY_OOP))); + link(new NewInstanceStub(this, r, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, ANY_LOCATION))); + link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, ANY_LOCATION))); + link(new ExceptionHandlerStub(this, r, target, foreignCalls.get(EXCEPTION_HANDLER))); + link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, ANY_LOCATION))); + link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, NO_LOCATIONS))); - linkForeignCall(IDENTITY_HASHCODE, c.identityHashCodeAddress, true, replacements); - linkForeignCall(REGISTER_FINALIZER, c.registerFinalizerAddress, true, replacements); - linkForeignCall(CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, true, replacements); - linkForeignCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, true, replacements); - linkForeignCall(MONITORENTER, c.monitorenterAddress, true, replacements); - linkForeignCall(MONITOREXIT, c.monitorexitAddress, true, replacements); - linkForeignCall(WRITE_BARRIER_PRE, c.writeBarrierPreAddress, true, replacements); - linkForeignCall(WRITE_BARRIER_POST, c.writeBarrierPostAddress, true, replacements); - linkForeignCall(NEW_MULTI_ARRAY, c.newMultiArrayAddress, true, replacements); - linkForeignCall(LOG_PRINTF, c.logPrintfAddress, true, replacements); - linkForeignCall(LOG_OBJECT, c.logObjectAddress, true, replacements); - linkForeignCall(LOG_PRIMITIVE, c.logPrimitiveAddress, true, replacements); - linkForeignCall(THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, true, replacements); - linkForeignCall(VM_ERROR, c.vmErrorAddress, true, replacements); - linkForeignCall(OSR_MIGRATION_END, c.osrMigrationEndAddress, false, replacements); + linkForeignCall(r, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_REEXECUTABLE, MARK_WORD_LOCATION); + linkForeignCall(r, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, WRITE_BARRIER_PRE, c.writeBarrierPreAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, WRITE_BARRIER_POST, c.writeBarrierPostAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, NOT_REEXECUTABLE, NO_LOCATIONS); if (GraalOptions.IntrinsifyObjectMethods) { - replacements.registerSubstitutions(ObjectSubstitutions.class); + r.registerSubstitutions(ObjectSubstitutions.class); } if (GraalOptions.IntrinsifySystemMethods) { - replacements.registerSubstitutions(SystemSubstitutions.class); + r.registerSubstitutions(SystemSubstitutions.class); } if (GraalOptions.IntrinsifyThreadMethods) { - replacements.registerSubstitutions(ThreadSubstitutions.class); + r.registerSubstitutions(ThreadSubstitutions.class); } if (GraalOptions.IntrinsifyUnsafeMethods) { - replacements.registerSubstitutions(UnsafeSubstitutions.class); + r.registerSubstitutions(UnsafeSubstitutions.class); } if (GraalOptions.IntrinsifyClassMethods) { - replacements.registerSubstitutions(ClassSubstitutions.class); + r.registerSubstitutions(ClassSubstitutions.class); } if (GraalOptions.IntrinsifyAESMethods) { - replacements.registerSubstitutions(AESCryptSubstitutions.class); - replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class); + r.registerSubstitutions(AESCryptSubstitutions.class); + r.registerSubstitutions(CipherBlockChainingSubstitutions.class); } if (GraalOptions.IntrinsifyReflectionMethods) { - replacements.registerSubstitutions(ReflectionSubstitutions.class); + r.registerSubstitutions(ReflectionSubstitutions.class); } - checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget()); - instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget()); - newObjectSnippets = new NewObjectSnippets.Templates(this, replacements, graalRuntime.getTarget()); - monitorSnippets = new MonitorSnippets.Templates(this, replacements, graalRuntime.getTarget(), c.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, replacements, graalRuntime.getTarget()); - boxingSnippets = new BoxingSnippets.Templates(this, replacements, graalRuntime.getTarget()); - exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, replacements, graalRuntime.getTarget()); + checkcastSnippets = new CheckCastSnippets.Templates(this, r, graalRuntime.getTarget()); + instanceofSnippets = new InstanceOfSnippets.Templates(this, r, graalRuntime.getTarget()); + newObjectSnippets = new NewObjectSnippets.Templates(this, r, graalRuntime.getTarget()); + monitorSnippets = new MonitorSnippets.Templates(this, r, graalRuntime.getTarget(), c.useFastLocking); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(this, r, graalRuntime.getTarget()); + boxingSnippets = new BoxingSnippets.Templates(this, r, graalRuntime.getTarget()); + exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(this, r, graalRuntime.getTarget()); } public HotSpotGraalRuntime getGraalRuntime() { @@ -449,7 +474,7 @@ if (n instanceof ArrayLengthNode) { ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; ValueNode array = arrayLengthNode.array(); - ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt())); + ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt())); tool.createNullCheckGuard(arrayLengthRead, array); graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); } else if (n instanceof Invoke) { @@ -476,7 +501,7 @@ // We use LocationNode.ANY_LOCATION for the reads that access the // compiled code entry as HotSpot does not guarantee they are final // values. - ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), + ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), StampFactory.forKind(wordKind()))); loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), @@ -532,7 +557,7 @@ } else if (n instanceof CompareAndSwapNode) { // Separate out GC barrier semantics CompareAndSwapNode cas = (CompareAndSwapNode) n; - LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); + LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); cas.setLocation(location); cas.setWriteBarrierType(getCompareAndSwapBarrier(cas)); } else if (n instanceof LoadIndexedNode) { @@ -562,7 +587,7 @@ } } else { LoadHubNode arrayClass = graph.add(new LoadHubNode(array, wordKind)); - LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); + LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind()))); CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); graph.addBeforeFixed(storeIndexed, checkcast); @@ -579,7 +604,7 @@ } else if (n instanceof UnsafeLoadNode) { UnsafeLoadNode load = (UnsafeLoadNode) n; assert load.kind() != Kind.Illegal; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1); + IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1); ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); // An unsafe read must not floating outside its block as may float above an explicit // null check on its object. @@ -587,7 +612,7 @@ graph.replaceFixedWithFixed(load, memoryRead); } else if (n instanceof UnsafeStoreNode) { UnsafeStoreNode store = (UnsafeStoreNode) n; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1); + IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1); ValueNode object = store.object(); WriteBarrierType barrierType = getUnsafeStoreBarrierType(store); WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType)); @@ -683,8 +708,8 @@ OSRStartNode osrStart = (OSRStartNode) n; StartNode newStart = graph.add(new StartNode()); LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind()))); - ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(OSR_MIGRATION_END, buffer)); - newStart.setStateAfter(osrStart.stateAfter()); + ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(this, OSR_MIGRATION_END, buffer)); + migrationEnd.setStateAfter(osrStart.stateAfter()); newStart.setNext(migrationEnd); FixedNode next = osrStart.next(); @@ -749,12 +774,12 @@ assert vtableEntryOffset > 0; // We use LocationNode.ANY_LOCATION for the reads that access the vtable // entry as HotSpot does not guarantee that this is a final value. - ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()))); + ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()))); return metaspaceMethod; } private ReadNode createReadHub(LoweringTool tool, StructuredGraph graph, Kind wordKind, ValueNode object) { - LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph); + LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph); assert !object.isConstant() || object.asConstant().isNull(); ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()))); tool.createNullCheckGuard(hub, object); @@ -809,7 +834,7 @@ protected IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { int scale = this.graalRuntime.getTarget().arch.getSizeInBytes(elementKind); - return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale); + return IndexedLocationNode.create(NamedLocationIdentity.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale); } private static GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { @@ -967,12 +992,12 @@ } @Override - public boolean hasSideEffect(ForeignCallDescriptor descriptor) { - // Only these two foreign calls are expected to be made with - // a node that implements StateSplit. They need to be a state - // split so that the stack trace they produce is accurate. - assert descriptor == CREATE_NULL_POINTER_EXCEPTION || descriptor == CREATE_OUT_OF_BOUNDS_EXCEPTION : descriptor; - return false; + public boolean isReexecutable(ForeignCallDescriptor descriptor) { + return foreignCalls.get(descriptor).isReexecutable(); + } + + public LocationIdentity[] getKilledLocationIdentities(ForeignCallDescriptor descriptor) { + return foreignCalls.get(descriptor).getKilledLocations(); } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; @@ -29,7 +31,6 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; @@ -55,7 +56,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.word.*; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,11 +22,13 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.api.meta.LocationIdentity.*; + +import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.type.*; /** @@ -46,7 +48,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java Thu May 23 14:44:01 2013 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -49,7 +48,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{LocationIdentity.ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java Fri May 17 16:47:13 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.word.*; - -/** - * Node implementing a call to {@code GraalRuntime::monitorenter}. - */ -public class MonitorEnterStubCall extends DeoptimizingStubCall implements LIRGenLowerable { - - @Input private ValueNode object; - @Input private ValueNode lock; - public static final ForeignCallDescriptor MONITORENTER = new ForeignCallDescriptor("monitorenter", void.class, Object.class, Word.class); - - public MonitorEnterStubCall(ValueNode object, ValueNode lock) { - super(StampFactory.forVoid()); - this.object = object; - this.lock = lock; - } - - @Override - public void generate(LIRGenerator gen) { - ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(MONITORENTER); - gen.emitForeignCall(linkage, this, gen.operand(object), gen.operand(lock)); - } - - @NodeIntrinsic - public static native void call(Object object, Word lock); -} diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Thu May 23 14:44:01 2013 +0200 @@ -43,8 +43,8 @@ public static final ForeignCallDescriptor NEW_MULTI_ARRAY = new ForeignCallDescriptor("new_multi_array", Object.class, Word.class, int.class, Word.class); - public NewMultiArrayStubCall(ValueNode hub, int rank, ValueNode dims) { - super(NEW_MULTI_ARRAY, defaultStamp); + public NewMultiArrayStubCall(MetaAccessProvider runtime, ValueNode hub, int rank, ValueNode dims) { + super(runtime, NEW_MULTI_ARRAY, defaultStamp); this.hub = hub; this.rank = rank; this.dims = dims; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java Fri May 17 16:47:13 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import java.lang.reflect.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; - -/** - * Node implementing a call to {@code GraalRuntime::thread_is_interrupted}. - */ -public class ThreadIsInterruptedStubCall extends DeoptimizingStubCall implements LIRGenLowerable { - - @Input private ValueNode thread; - @Input private ValueNode clearIsInterrupted; - public static final ForeignCallDescriptor THREAD_IS_INTERRUPTED = new ForeignCallDescriptor("thread_is_interrupted", boolean.class, Object.class, boolean.class); - - public ThreadIsInterruptedStubCall(ValueNode thread, ValueNode clearIsInterrupted) { - super(StampFactory.forInteger(Kind.Int, 0, 1)); - this.thread = thread; - this.clearIsInterrupted = clearIsInterrupted; - } - - @Override - public void generate(LIRGenerator gen) { - ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(ThreadIsInterruptedStubCall.THREAD_IS_INTERRUPTED); - Variable result = gen.emitForeignCall(linkage, this, gen.operand(thread), gen.operand(clearIsInterrupted)); - gen.setResult(this, result); - } - - @NodeIntrinsic - public static boolean call(Thread thread, boolean clearIsInterrupted) { - try { - Method isInterrupted = Thread.class.getDeclaredMethod("isInterrupted", boolean.class); - isInterrupted.setAccessible(true); - return (Boolean) isInterrupted.invoke(thread, clearIsInterrupted); - } catch (Exception e) { - throw new GraalInternalError(e); - } - } -} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Fri May 17 16:47:13 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.hotspot.stubs.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; - -/** - * Call to {@link VerifyOopStub}. - */ -public class VerifyOopStubCall extends DeoptimizingStubCall implements LIRGenLowerable { - - @Input private ValueNode object; - public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class); - - public VerifyOopStubCall(ValueNode object) { - super(StampFactory.objectNonNull()); - this.object = object; - } - - @Override - public void generate(LIRGenerator gen) { - ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(VerifyOopStubCall.VERIFY_OOP); - gen.emitForeignCall(linkage, this, gen.operand(object)); - } - - @NodeIntrinsic - public static native Object call(Object object); -} diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Thu May 23 14:44:01 2013 +0200 @@ -22,18 +22,17 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import sun.misc.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.word.*; /** @@ -72,56 +71,18 @@ Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); if (encrypt) { - EncryptBlockStubCall.call(inAddr, outAddr, kAddr); + encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr); } else { - DecryptBlockStubCall.call(inAddr, outAddr, kAddr); + decryptBlockStub(DECRYPT_BLOCK, inAddr, outAddr, kAddr); } } - abstract static class CryptBlockStubCall extends DeoptimizingStubCall implements LIRGenLowerable { - - @Input private ValueNode in; - @Input private ValueNode out; - @Input private ValueNode key; - - private final ForeignCallDescriptor descriptor; - - public CryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key, ForeignCallDescriptor descriptor) { - super(StampFactory.forVoid()); - this.in = in; - this.out = out; - this.key = key; - this.descriptor = descriptor; - } - - @Override - public void generate(LIRGenerator gen) { - ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor); - gen.emitForeignCall(linkage, null, gen.operand(in), gen.operand(out), gen.operand(key)); - } - } + 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); - public static class EncryptBlockStubCall extends CryptBlockStubCall { - - public static final ForeignCallDescriptor ENCRYPT_BLOCK = new ForeignCallDescriptor("encrypt_block", void.class, Word.class, Word.class, Word.class); - - public EncryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key) { - super(in, out, key, ENCRYPT_BLOCK); - } - - @NodeIntrinsic - public static native void call(Word in, Word out, Word key); - } + @NodeIntrinsic(ForeignCallNode.class) + public static native void encryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key); - public static class DecryptBlockStubCall extends CryptBlockStubCall { - - public static final ForeignCallDescriptor DECRYPT_BLOCK = new ForeignCallDescriptor("decrypt_block", void.class, Word.class, Word.class, Word.class); - - public DecryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key) { - super(in, out, key, DECRYPT_BLOCK); - } - - @NodeIntrinsic - public static native void call(Word in, Word out, Word key); - } + @NodeIntrinsic(ForeignCallNode.class) + public static native void decryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Thu May 23 14:44:01 2013 +0200 @@ -273,9 +273,20 @@ ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]); callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType); } + graph().add(callTarget); - graph().add(callTarget); - InvokeNode invoke = graph().add(new InvokeNode(callTarget, getBci())); + // The call target can have a different return type than the invoker, + // e.g. the target returns an Object but the invoker void. In this case + // we need to use the stamp of the invoker. Note: always using the + // invoker's stamp would be wrong because it's a less concrete type + // (usually java.lang.Object). + InvokeNode invoke; + if (callTarget.returnStamp().kind() != stamp().kind()) { + invoke = new InvokeNode(callTarget, getBci(), stamp()); + } else { + invoke = new InvokeNode(callTarget, getBci()); + } + graph().add(invoke); invoke.setStateAfter(stateAfter()); return invoke; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Thu May 23 14:44:01 2013 +0200 @@ -31,6 +31,7 @@ import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.*; @@ -94,7 +95,7 @@ isNull.inc(); } else { Word objectHub = loadHub(object); - if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) { + if (objectHub.readWord(superCheckOffset, LocationIdentity.FINAL_LOCATION).notEqual(hub)) { displayMiss.inc(); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } @@ -187,7 +188,7 @@ args = new Arguments(secondary); args.add("hub", hub); args.add("object", object); - args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints); + args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints); } args.addConst("checkNull", !object.stamp().nonNull()); diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Thu May 23 14:44:01 2013 +0200 @@ -22,18 +22,17 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import sun.misc.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.word.*; @@ -72,19 +71,6 @@ } } - private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) { - Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte)); - Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte)); - Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); - Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); - if (encrypt) { - EncryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength); - } else { - DecryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength); - } - - } - @MethodSubstitution(isStatic = false) static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), ANY_LOCATION); @@ -95,54 +81,24 @@ } } - abstract static class AESCryptStubCall extends DeoptimizingStubCall implements LIRGenLowerable { - - @Input private ValueNode in; - @Input private ValueNode out; - @Input private ValueNode key; - @Input private ValueNode r; - @Input private ValueNode inLength; - - private final ForeignCallDescriptor descriptor; - - public AESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength, ForeignCallDescriptor descriptor) { - super(StampFactory.forVoid()); - this.in = in; - this.out = out; - this.key = key; - this.r = r; - this.inLength = inLength; - this.descriptor = descriptor; - } - - @Override - public void generate(LIRGenerator gen) { - ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor); - gen.emitForeignCall(linkage, null, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength)); + private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) { + Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte)); + Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), ANY_LOCATION).add(arrayBaseOffset(Kind.Byte)); + Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); + Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); + if (encrypt) { + encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength); + } else { + decryptAESCryptStub(DECRYPT, inAddr, outAddr, kAddr, rAddr, inLength); } } - public static class EncryptAESCryptStubCall extends AESCryptStubCall { - - public static final ForeignCallDescriptor ENCRYPT = new ForeignCallDescriptor("encrypt", void.class, Word.class, Word.class, Word.class, Word.class, int.class); - - public EncryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) { - super(in, out, key, r, inLength, ENCRYPT); - } - - @NodeIntrinsic - public static native void call(Word in, Word out, Word key, Word r, int inLength); - } + 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); - public static class DecryptAESCryptStubCall extends AESCryptStubCall { - - 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); - public DecryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) { - super(in, out, key, r, inLength, DECRYPT); - } - - @NodeIntrinsic - public static native void call(Word in, Word out, Word key, Word r, int inLength); - } + @NodeIntrinsic(ForeignCallNode.class) + public static native void decryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key, Word r, int inLength); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Thu May 23 14:44:01 2013 +0200 @@ -27,6 +27,7 @@ import java.lang.reflect.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.word.*; @@ -44,7 +45,7 @@ // Class for primitive type return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; } else { - return klass.readInt(klassModifierFlagsOffset(), FINAL_LOCATION); + return klass.readInt(klassModifierFlagsOffset(), LocationIdentity.FINAL_LOCATION); } } @@ -54,7 +55,7 @@ if (klass.equal(0)) { return false; } else { - int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION); + int accessFlags = klass.readInt(klassAccessFlagsOffset(), LocationIdentity.FINAL_LOCATION); return (accessFlags & Modifier.INTERFACE) != 0; } } @@ -79,16 +80,16 @@ public static Class getSuperclass(final Class thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); if (klass.notEqual(0)) { - int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION); + int accessFlags = klass.readInt(klassAccessFlagsOffset(), LocationIdentity.FINAL_LOCATION); if ((accessFlags & Modifier.INTERFACE) == 0) { if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) { return Object.class; } else { - Word superKlass = klass.readWord(klassSuperKlassOffset(), FINAL_LOCATION); + Word superKlass = klass.readWord(klassSuperKlassOffset(), LocationIdentity.FINAL_LOCATION); if (superKlass.equal(0)) { return null; } else { - return unsafeCast(superKlass.readObject(classMirrorOffset(), FINAL_LOCATION), Class.class, true, true); + return unsafeCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } } } @@ -101,7 +102,7 @@ Word klass = loadWordFromObject(thisObj, klassOffset()); if (klass.notEqual(0)) { if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) { - return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), FINAL_LOCATION), Class.class, true, true); + return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } } return null; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Thu May 23 14:44:01 2013 +0200 @@ -33,9 +33,7 @@ import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.replacements.Snippet.Fold; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -47,9 +45,6 @@ */ public class HotSpotReplacementsUtil { - public static final LocationIdentity ANY_LOCATION = LocationNode.ANY_LOCATION; - public static final LocationIdentity FINAL_LOCATION = LocationNode.FINAL_LOCATION; - public static HotSpotVMConfig config() { return graalRuntime().getConfig(); } @@ -64,7 +59,7 @@ return config().verifyOops; } - public static final LocationIdentity EXCEPTION_OOP_LOCATION = LocationNode.createLocation("ExceptionOop"); + public static final LocationIdentity EXCEPTION_OOP_LOCATION = new NamedLocationIdentity("ExceptionOop"); /** * @see HotSpotVMConfig#threadExceptionOopOffset @@ -74,35 +69,35 @@ return config().threadExceptionOopOffset; } - public static final LocationIdentity EXCEPTION_PC_LOCATION = LocationNode.createLocation("ExceptionPc"); + public static final LocationIdentity EXCEPTION_PC_LOCATION = new NamedLocationIdentity("ExceptionPc"); @Fold public static int threadExceptionPcOffset() { return config().threadExceptionPcOffset; } - public static final LocationIdentity TLAB_TOP_LOCATION = LocationNode.createLocation("TlabTop"); + public static final LocationIdentity TLAB_TOP_LOCATION = new NamedLocationIdentity("TlabTop"); @Fold public static int threadTlabTopOffset() { return config().threadTlabTopOffset; } - public static final LocationIdentity TLAB_END_LOCATION = LocationNode.createLocation("TlabEnd"); + public static final LocationIdentity TLAB_END_LOCATION = new NamedLocationIdentity("TlabEnd"); @Fold private static int threadTlabEndOffset() { return config().threadTlabEndOffset; } - public static final LocationIdentity TLAB_START_LOCATION = LocationNode.createLocation("TlabStart"); + public static final LocationIdentity TLAB_START_LOCATION = new NamedLocationIdentity("TlabStart"); @Fold private static int threadTlabStartOffset() { return config().threadTlabStartOffset; } - public static final LocationIdentity PENDING_EXCEPTION_LOCATION = LocationNode.createLocation("PendingException"); + public static final LocationIdentity PENDING_EXCEPTION_LOCATION = new NamedLocationIdentity("PendingException"); /** * @see HotSpotVMConfig#pendingExceptionOffset @@ -112,7 +107,7 @@ return config().pendingExceptionOffset; } - public static final LocationIdentity OBJECT_RESULT_LOCATION = LocationNode.createLocation("ObjectResult"); + public static final LocationIdentity OBJECT_RESULT_LOCATION = new NamedLocationIdentity("ObjectResult"); @Fold private static int objectResultOffset() { @@ -201,7 +196,7 @@ } @Fold - public static Kind wordKind() { + public static Kind getWordKind() { return graalRuntime().getTarget().wordKind; } @@ -225,7 +220,7 @@ return Unsafe.getUnsafe().pageSize(); } - public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = LocationNode.createLocation("PrototypeMarkWord"); + public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = new NamedLocationIdentity("PrototypeMarkWord"); @Fold public static int prototypeMarkWordOffset() { @@ -248,7 +243,7 @@ } public static int readLayoutHelper(Word hub) { - return hub.readInt(klassLayoutHelperOffset(), FINAL_LOCATION); + return hub.readInt(klassLayoutHelperOffset(), LocationIdentity.FINAL_LOCATION); } @Fold @@ -266,14 +261,14 @@ return config().klassSuperKlassOffset; } - public static final LocationIdentity MARK_WORD_LOCATION = LocationNode.createLocation("MarkWord"); + public static final LocationIdentity MARK_WORD_LOCATION = new NamedLocationIdentity("MarkWord"); @Fold public static int markOffset() { return config().markOffset; } - public static final LocationIdentity HUB_LOCATION = LocationNode.createLocation("Hub"); + public static final LocationIdentity HUB_LOCATION = new NamedLocationIdentity("Hub"); @Fold private static int hubOffset() { @@ -400,21 +395,21 @@ return config().superCheckOffsetOffset; } - public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = LocationNode.createLocation("SecondarySuperCache"); + public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = new NamedLocationIdentity("SecondarySuperCache"); @Fold public static int secondarySuperCacheOffset() { return config().secondarySuperCacheOffset; } - public static final LocationIdentity SECONDARY_SUPERS_LOCATION = LocationNode.createLocation("SecondarySupers"); + public static final LocationIdentity SECONDARY_SUPERS_LOCATION = new NamedLocationIdentity("SecondarySupers"); @Fold public static int secondarySupersOffset() { return config().secondarySupersOffset; } - public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = LocationNode.createLocation("DisplacedMarkWord"); + public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = new NamedLocationIdentity("DisplacedMarkWord"); @Fold public static int lockDisplacedMarkOffset() { @@ -445,16 +440,19 @@ * Loads the hub from a object, null checking it first. */ public static Word loadHub(Object object) { - return loadHubIntrinsic(object, wordKind()); + return loadHubIntrinsic(object, getWordKind()); } public static Object verifyOop(Object object) { if (verifyOops()) { - VerifyOopStubCall.call(object); + verifyOopStub(VERIFY_OOP, object); } return object; } + @NodeIntrinsic(ForeignCallNode.class) + private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object); + /** * Gets the value of the stack pointer register as a Word. */ @@ -470,7 +468,7 @@ } public static Word loadWordFromObject(Object object, int offset) { - return loadWordFromObjectIntrinsic(object, 0, offset, wordKind()); + return loadWordFromObjectIntrinsic(object, 0, offset, getWordKind()); } @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) @@ -493,7 +491,7 @@ return CodeUtil.log2(wordSize()); } - public static final LocationIdentity CLASS_STATE_LOCATION = LocationNode.createLocation("ClassState"); + public static final LocationIdentity CLASS_STATE_LOCATION = new NamedLocationIdentity("ClassState"); @Fold public static int klassStateOffset() { @@ -525,14 +523,14 @@ return config().klassInstanceSizeOffset; } - public static final LocationIdentity HEAP_TOP_LOCATION = LocationNode.createLocation("HeapTop"); + public static final LocationIdentity HEAP_TOP_LOCATION = new NamedLocationIdentity("HeapTop"); @Fold public static long heapTopAddress() { return config().heapTopAddress; } - public static final LocationIdentity HEAP_END_LOCATION = LocationNode.createLocation("HeapEnd"); + public static final LocationIdentity HEAP_END_LOCATION = new NamedLocationIdentity("HeapEnd"); @Fold public static long heapEndAddress() { @@ -554,42 +552,42 @@ return config().tlabAlignmentReserve; } - public static final LocationIdentity TLAB_SIZE_LOCATION = LocationNode.createLocation("TlabSize"); + public static final LocationIdentity TLAB_SIZE_LOCATION = new NamedLocationIdentity("TlabSize"); @Fold public static int threadTlabSizeOffset() { return config().threadTlabSizeOffset; } - public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = LocationNode.createLocation("TlabThreadAllocatedBytes"); + public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = new NamedLocationIdentity("TlabThreadAllocatedBytes"); @Fold public static int threadAllocatedBytesOffset() { return config().threadAllocatedBytesOffset; } - public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = LocationNode.createLocation("RefillWasteLimit"); + public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = new NamedLocationIdentity("RefillWasteLimit"); @Fold public static int tlabRefillWasteLimitOffset() { return config().tlabRefillWasteLimitOffset; } - public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = LocationNode.createLocation("TlabNOfRefills"); + public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = new NamedLocationIdentity("TlabNOfRefills"); @Fold public static int tlabNumberOfRefillsOffset() { return config().tlabNumberOfRefillsOffset; } - public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = LocationNode.createLocation("TlabFastRefillWaste"); + public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = new NamedLocationIdentity("TlabFastRefillWaste"); @Fold public static int tlabFastRefillWasteOffset() { return config().tlabFastRefillWasteOffset; } - public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = LocationNode.createLocation("TlabSlowAllocations"); + public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = new NamedLocationIdentity("TlabSlowAllocations"); @Fold public static int tlabSlowAllocationsOffset() { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Thu May 23 14:44:01 2013 +0200 @@ -81,7 +81,7 @@ return falseValue; } Word objectHub = loadHub(object); - if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub))) { + if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, LocationIdentity.FINAL_LOCATION).notEqual(hub))) { displayMiss.inc(); return falseValue; } @@ -171,7 +171,7 @@ args = new Arguments(instanceofSecondary); args.add("hub", hub); args.add("object", object); - args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs); + args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints.hubs); args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive); } args.add("trueValue", replacer.trueValue); diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Thu May 23 14:44:01 2013 +0200 @@ -35,12 +35,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; @@ -159,7 +159,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); - MonitorEnterStubCall.call(object, lock); + monitorenterStub(MONITORENTER, object, lock); return; } else { // At this point we know the epoch has expired, meaning that the @@ -179,7 +179,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); - MonitorEnterStubCall.call(object, lock); + monitorenterStub(MONITORENTER, object, lock); return; } } else { @@ -236,7 +236,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); - MonitorEnterStubCall.call(object, lock); + monitorenterStub(MONITORENTER, object, lock); return; } else { // Recursively locked => write 0 to the lock slot @@ -262,7 +262,7 @@ // cannot float about the null check above final Word lock = beginLockScope(lockDepth); traceObject(trace, "+lock{stub}", object); - MonitorEnterStubCall.call(object, lock); + monitorenterStub(MONITORENTER, object, lock); } @Snippet @@ -344,7 +344,7 @@ */ private static final boolean ENABLE_BREAKPOINT = false; - private static final LocationIdentity MONITOR_COUNTER_LOCATION = LocationNode.createLocation("MonitorCounter"); + private static final LocationIdentity MONITOR_COUNTER_LOCATION = new NamedLocationIdentity("MonitorCounter"); @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word mark, Word tmp, Word value); @@ -517,4 +517,10 @@ } } } + + public static final ForeignCallDescriptor MONITORENTER = new ForeignCallDescriptor("monitorenter", void.class, Object.class, Word.class); + + @NodeIntrinsic(ForeignCallNode.class) + private static native void monitorenterStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); + } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Thu May 23 14:44:01 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.api.code.UnsignedMath.*; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Thu May 23 14:44:01 2013 +0200 @@ -25,8 +25,8 @@ import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -40,7 +40,7 @@ @MethodSubstitution(isStatic = false) public static Class getClass(final Object thisObj) { Word hub = loadHub(thisObj); - return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationNode.FINAL_LOCATION), Class.class, true, true); + return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } @MethodSubstitution(isStatic = false) diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java Thu May 23 14:44:01 2013 +0200 @@ -22,10 +22,18 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.word.*; /** @@ -36,21 +44,37 @@ @MethodSubstitution public static Thread currentThread() { - return (Thread) CurrentJavaThreadNode.get().readObject(threadObjectOffset(), FINAL_LOCATION); + return (Thread) CurrentJavaThreadNode.get().readObject(threadObjectOffset(), LocationIdentity.FINAL_LOCATION); } @MethodSubstitution(isStatic = false) public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { Word javaThread = CurrentJavaThreadNode.get(); - Object thread = javaThread.readObject(threadObjectOffset(), FINAL_LOCATION); + Object thread = javaThread.readObject(threadObjectOffset(), LocationIdentity.FINAL_LOCATION); if (thisObject == thread) { - Word osThread = javaThread.readWord(osThreadOffset(), FINAL_LOCATION); + Word osThread = javaThread.readWord(osThreadOffset(), LocationIdentity.FINAL_LOCATION); boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), ANY_LOCATION) != 0; if (!interrupted || !clearInterrupted) { return interrupted; } } - return ThreadIsInterruptedStubCall.call(thisObject, clearInterrupted); + return threadIsInterruptedStub(THREAD_IS_INTERRUPTED, thisObject, clearInterrupted); + } + + public static final ForeignCallDescriptor THREAD_IS_INTERRUPTED = new ForeignCallDescriptor("thread_is_interrupted", boolean.class, Object.class, boolean.class); + + /** + * @param descriptor + */ + @NodeIntrinsic(ForeignCallNode.class) + private static boolean threadIsInterruptedStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Thread thread, boolean clearIsInterrupted) { + try { + Method isInterrupted = Thread.class.getDeclaredMethod("isInterrupted", boolean.class); + isInterrupted.setAccessible(true); + return (Boolean) isInterrupted.invoke(thread, clearIsInterrupted); + } catch (Exception e) { + throw new GraalInternalError(e); + } } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Thu May 23 14:44:01 2013 +0200 @@ -32,8 +32,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; import com.oracle.graal.word.*; @@ -45,7 +43,7 @@ */ public class TypeCheckSnippetUtils { - public static final LocationIdentity TYPE_DISPLAY_LOCATION = LocationNode.createLocation("TypeDisplay"); + public static final LocationIdentity TYPE_DISPLAY_LOCATION = new NamedLocationIdentity("TypeDisplay"); static boolean checkSecondarySubType(Word t, Word s) { // if (S.cache == T) return true @@ -59,7 +57,7 @@ static boolean checkUnknownSubType(Word t, Word s) { // int off = T.offset - int superCheckOffset = t.readInt(superCheckOffsetOffset(), FINAL_LOCATION); + int superCheckOffset = t.readInt(superCheckOffsetOffset(), LocationIdentity.FINAL_LOCATION); boolean primary = superCheckOffset != secondarySuperCacheOffset(); // if (T = S[off]) return true @@ -90,7 +88,7 @@ // if (S.scan_s_s_array(T)) { S.cache = T; return true; } Word secondarySupers = s.readWord(secondarySupersOffset(), SECONDARY_SUPERS_LOCATION); - int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), FINAL_LOCATION); + int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), LocationIdentity.FINAL_LOCATION); for (int i = 0; i < length; i++) { if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) { s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION); @@ -144,7 +142,7 @@ } static Word loadSecondarySupersElement(Word metaspaceArray, int index) { - return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), FINAL_LOCATION); + return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), LocationIdentity.FINAL_LOCATION); } private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("TypeCheck") : null; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Thu May 23 14:44:01 2013 +0200 @@ -80,13 +80,18 @@ * @param descriptor the signature of the call to this stub * @param prependThread true if the JavaThread value for the current thread is to be prepended * to the arguments for the call to {@code address} + * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side + * effects. Deoptimization will not return to a point before a stub call that cannot + * be re-executed. + * @param killedLocations the memory locations killed by the stub call */ - public ForeignCallStub(long address, ForeignCallDescriptor descriptor, boolean prependThread, HotSpotRuntime runtime, Replacements replacements) { - super(runtime, replacements, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF)); + public ForeignCallStub(HotSpotRuntime runtime, Replacements replacements, long address, ForeignCallDescriptor descriptor, boolean prependThread, boolean reexecutable, + LocationIdentity... killedLocations) { + super(runtime, replacements, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCallee, NOT_LEAF, reexecutable, killedLocations)); this.prependThread = prependThread; Class[] targetParameterTypes = createTargetParameters(descriptor); ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes); - target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NOT_LEAF); + target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NOT_LEAF, reexecutable, killedLocations); } /** @@ -283,9 +288,9 @@ ValueNode[] targetArguments = new ValueNode[1 + locals.length]; targetArguments[0] = thread; System.arraycopy(locals, 0, targetArguments, 1, locals.length); - return builder.append(new ForeignCallNode(target.getDescriptor(), targetArguments)); + return builder.append(new ForeignCallNode(runtime, target.getDescriptor(), targetArguments)); } else { - return builder.append(new ForeignCallNode(target.getDescriptor(), locals)); + return builder.append(new ForeignCallNode(runtime, target.getDescriptor(), locals)); } } diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Thu May 23 14:44:01 2013 +0200 @@ -89,7 +89,7 @@ */ @Snippet private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub) { - int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); + int layoutHelper = hub.readInt(layoutHelperOffset(), LocationIdentity.FINAL_LOCATION); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask(); diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.stubs; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; @@ -87,7 +88,7 @@ */ @Snippet private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub) { - int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION); + int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), LocationIdentity.FINAL_LOCATION); if (!forceSlowPath() && inlineContiguousAllocationSupported()) { if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) { Word memory = refillAllocate(intArrayHub, sizeInBytes, logging()); diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java Thu May 23 14:44:01 2013 +0200 @@ -27,12 +27,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; /** - * Stub called from {@link VerifyOopStubCall}. + * Stub called via {@link HotSpotRuntime#VERIFY_OOP}. */ public class VerifyOopStub extends SnippetStub { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu May 23 14:44:01 2013 +0200 @@ -925,7 +925,7 @@ ValueNode exception = ConstantNode.forObject(cachedNullPointerException, runtime, currentGraph); trueSucc.setNext(handleException(exception, bci())); } else { - ForeignCallStateSplitNode call = currentGraph.add(new ForeignCallStateSplitNode(runtime, CREATE_NULL_POINTER_EXCEPTION)); + ForeignCallNode call = currentGraph.add(new ForeignCallNode(runtime, CREATE_NULL_POINTER_EXCEPTION)); call.setStateAfter(frameState.create(bci())); trueSucc.setNext(call); call.setNext(handleException(call, bci())); @@ -949,7 +949,7 @@ ValueNode exception = ConstantNode.forObject(cachedArrayIndexOutOfBoundsException, runtime, currentGraph); falseSucc.setNext(handleException(exception, bci())); } else { - ForeignCallStateSplitNode call = currentGraph.add(new ForeignCallStateSplitNode(runtime, CREATE_OUT_OF_BOUNDS_EXCEPTION, index)); + ForeignCallNode call = currentGraph.add(new ForeignCallNode(runtime, CREATE_OUT_OF_BOUNDS_EXCEPTION, index)); call.setStateAfter(frameState.create(bci())); falseSucc.setNext(call); call.setNext(handleException(call, bci())); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Thu May 23 14:44:01 2013 +0200 @@ -273,7 +273,7 @@ protected void verify() { super.verify(); // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx - assert asRegister(x) == AMD64.rax; + assert asRegister(x).equals(AMD64.rax); assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue()); verifyKind(opcode, divResult, x, y); verifyKind(opcode, remResult, x, y); @@ -360,9 +360,9 @@ case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break; case IOR: masm.orl(asIntReg(dst), asIntReg(src)); break; case IXOR: masm.xorl(asIntReg(dst), asIntReg(src)); break; - case ISHL: assert asIntReg(src) == AMD64.rcx; masm.shll(asIntReg(dst)); break; - case ISHR: assert asIntReg(src) == AMD64.rcx; masm.sarl(asIntReg(dst)); break; - case IUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrl(asIntReg(dst)); break; + case ISHL: assert asIntReg(src).equals(AMD64.rcx); masm.shll(asIntReg(dst)); break; + case ISHR: assert asIntReg(src).equals(AMD64.rcx); masm.sarl(asIntReg(dst)); break; + case IUSHR: assert asIntReg(src).equals(AMD64.rcx); masm.shrl(asIntReg(dst)); break; case LADD: masm.addq(asLongReg(dst), asLongReg(src)); break; case LSUB: masm.subq(asLongReg(dst), asLongReg(src)); break; @@ -370,9 +370,9 @@ case LAND: masm.andq(asLongReg(dst), asLongReg(src)); break; case LOR: masm.orq(asLongReg(dst), asLongReg(src)); break; case LXOR: masm.xorq(asLongReg(dst), asLongReg(src)); break; - case LSHL: assert asIntReg(src) == AMD64.rcx; masm.shlq(asLongReg(dst)); break; - case LSHR: assert asIntReg(src) == AMD64.rcx; masm.sarq(asLongReg(dst)); break; - case LUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrq(asLongReg(dst)); break; + case LSHL: assert asIntReg(src).equals(AMD64.rcx); masm.shlq(asLongReg(dst)); break; + case LSHR: assert asIntReg(src).equals(AMD64.rcx); masm.sarq(asLongReg(dst)); break; + case LUSHR: assert asIntReg(src).equals(AMD64.rcx); masm.shrq(asLongReg(dst)); break; case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break; case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break; @@ -556,6 +556,6 @@ || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double) - || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y) == AMD64.rcx)); + || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y).equals(AMD64.rcx))); } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Thu May 23 14:44:01 2013 +0200 @@ -404,7 +404,7 @@ private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, ConditionFlag cond, Value other) { if (isRegister(other)) { - assert asRegister(other) != asRegister(result) : "other already overwritten by previous move"; + assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move"; switch (other.getKind()) { case Int: masm.cmovl(cond, asRegister(result), asRegister(other)); break; case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Thu May 23 14:44:01 2013 +0200 @@ -526,7 +526,7 @@ } protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { - assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax; + assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax); if (tasm.target.isMP) { masm.lock(); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Thu May 23 14:44:01 2013 +0200 @@ -31,7 +31,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.lir.LIRInstruction.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.nodes.cfg.*; public final class LIRVerifier { @@ -230,14 +232,17 @@ return value; } + // @formatter:off private static Value allowed(Object op, Value value, OperandMode mode, EnumSet flags) { - if ((isVariable(value) && flags.contains(OperandFlag.REG)) || (isRegister(value) && flags.contains(OperandFlag.REG)) || (isStackSlot(value) && flags.contains(OperandFlag.STACK)) || - (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) { + if ((isVariable(value) && flags.contains(OperandFlag.REG)) || + (isRegister(value) && flags.contains(OperandFlag.REG)) || + (isStackSlot(value) && flags.contains(OperandFlag.STACK)) || + (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || + (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) { return value; } - TTY.println("instruction %s", op); - TTY.println("mode: %s flags: %s", mode, flags); - TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value); - throw GraalInternalError.shouldNotReachHere(); + throw new GraalInternalError("Invalid LIR%n Instruction: %s%n Mode: %s%n Flags: %s%n Unexpected value: %s %s", + op, mode, flags, value.getClass().getSimpleName(), value); } + // @formatter:on } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Thu May 23 14:44:01 2013 +0200 @@ -83,9 +83,4 @@ public DeoptimizationReason getDeoptimizationReason() { return reason; } - - @Override - public boolean isCallSiteDeoptimization() { - return false; - } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Thu May 23 14:44:01 2013 +0200 @@ -42,9 +42,4 @@ updateUsages(deoptState, f); deoptState = f; } - - @Override - public boolean isCallSiteDeoptimization() { - return false; - } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java Thu May 23 14:44:01 2013 +0200 @@ -25,29 +25,24 @@ import com.oracle.graal.api.meta.*; /** - * Interface that needs to be implemented by nodes which need deoptimization information. - * + * Interface implemented by nodes which need deoptimization information. */ public interface DeoptimizingNode { /** - * Returns true if this particular instance needs deoptimization information. - * - * @return true if this particular instance needs deoptimization information + * Determines if this node needs deoptimization information. */ boolean canDeoptimize(); /** - * Returns the deoptimization information associated with this node if any. - * - * @return the deoptimization information associated with this node if any. + * Gets the deoptimization information associated with this node if any. */ FrameState getDeoptimizationState(); /** - * Set the deoptimization information associated with this node. + * Sets the deoptimization information associated with this node. * - * @param state the FrameState which represents the deoptimization information. + * @param state the FrameState which represents the deoptimization information */ void setDeoptimizationState(FrameState state); @@ -59,13 +54,4 @@ * @return the reason for deoptimization triggered by this node. */ DeoptimizationReason getDeoptimizationReason(); - - /** - * Returns true if this node needs deoptimization information for stack-walking purposes because - * it is a call-site. While most other nodes use deoptimization information representing a state - * that happened before them, these nodes use a state that is valid during the call itself. - * - * @return true if this node needs deoptimization information for stack-walking purposes. - */ - boolean isCallSiteDeoptimization(); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,13 +22,15 @@ */ package com.oracle.graal.nodes; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.Stamp; import com.oracle.graal.nodes.util.*; /** @@ -47,11 +49,22 @@ /** * Constructs a new Invoke instruction. * + * @param callTarget the target method being called * @param bci the bytecode index of the original invoke (used for debug infos) - * @param callTarget the target method being called */ public InvokeNode(CallTargetNode callTarget, int bci) { - super(callTarget.returnStamp()); + this(callTarget, bci, callTarget.returnStamp()); + } + + /** + * Constructs a new Invoke instruction. + * + * @param callTarget the target method being called + * @param bci the bytecode index of the original invoke (used for debug infos) + * @param stamp the stamp to be used for this value + */ + public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) { + super(stamp); this.callTarget = callTarget; this.bci = bci; this.polymorphic = false; @@ -93,7 +106,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override @@ -188,11 +201,6 @@ } @Override - public boolean isCallSiteDeoptimization() { - return true; - } - - @Override public GuardingNode getGuard() { return guard; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.graal.nodes; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -154,7 +155,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } public FrameState stateDuring() { @@ -237,11 +238,6 @@ } @Override - public boolean isCallSiteDeoptimization() { - return true; - } - - @Override public GuardingNode getGuard() { return guard; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Thu May 23 14:44:01 2013 +0200 @@ -61,12 +61,6 @@ @Override public boolean inferStamp() { - if (stamp() instanceof ObjectStamp && object().objectStamp().alwaysNull() && objectStamp().nonNull()) { - // a null value flowing into a nonNull PiNode should be guarded by a type/isNull guard, - // but the - // compiler might see this situation before the branch is deleted - return false; - } return updateStamp(stamp().join(object().stamp())); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,8 +22,10 @@ */ package com.oracle.graal.nodes; +import static com.oracle.graal.api.meta.LocationIdentity.*; + +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; /** * The start node of a graph. @@ -32,6 +34,6 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Thu May 23 14:44:01 2013 +0200 @@ -60,7 +60,7 @@ * @return true if the stamp has changed, false otherwise. */ protected final boolean updateStamp(Stamp newStamp) { - if (newStamp.equals(stamp)) { + if (newStamp == null || newStamp.equals(stamp)) { return false; } else { stamp = newStamp; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Thu May 23 14:44:01 2013 +0200 @@ -91,10 +91,5 @@ deoptState = f; } - @Override - public boolean isCallSiteDeoptimization() { - return false; - } - public abstract Access asFixedNode(); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Thu May 23 14:44:01 2013 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -34,22 +33,31 @@ * Node for a {@linkplain ForeignCallDescriptor foreign} call. */ @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}") -public class ForeignCallNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint { +public class ForeignCallNode extends AbstractStateSplit implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint { @Input private final NodeInputList arguments; + private final MetaAccessProvider runtime; + @Input private FrameState deoptState; private final ForeignCallDescriptor descriptor; - public ForeignCallNode(ForeignCallDescriptor descriptor, ValueNode... arguments) { + public ForeignCallNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, ValueNode... arguments) { super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; + this.runtime = runtime; } - protected ForeignCallNode(ForeignCallDescriptor descriptor, Stamp stamp) { + protected ForeignCallNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, Stamp stamp) { super(stamp); this.arguments = new NodeInputList<>(this); this.descriptor = descriptor; + this.runtime = runtime; + } + + @Override + public boolean hasSideEffect() { + return !runtime.isReexecutable(descriptor); } public ForeignCallDescriptor getDescriptor() { @@ -58,7 +66,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return runtime.getKilledLocationIdentities(descriptor); } protected Value[] operands(LIRGeneratorTool gen) { @@ -80,6 +88,30 @@ } @Override + public FrameState getDeoptimizationState() { + if (deoptState != null) { + return deoptState; + } else if (stateAfter() != null) { + FrameState stateDuring = stateAfter(); + if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) { + stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind()); + } + setDeoptimizationState(stateDuring); + return stateDuring; + } + return null; + } + + @Override + public void setDeoptimizationState(FrameState f) { + updateUsages(deoptState, f); + if (deoptState != null) { + throw new IllegalStateException(toString(Verbosity.Debugger)); + } + deoptState = f; + } + + @Override public String toString(Verbosity verbosity) { if (verbosity == Verbosity.Name) { return super.toString(verbosity) + "#" + descriptor; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallStateSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallStateSplitNode.java Fri May 17 16:47:13 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.extended; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -/** - * A foreign call that is also a state split. - */ -@NodeInfo(nameTemplate = "ForeignCallStateSplit#{p#descriptor/s}") -public class ForeignCallStateSplitNode extends ForeignCallNode implements LIRLowerable, StateSplit, DeoptimizingNode { - - @Input(notDataflow = true) private FrameState stateAfter; - private MetaAccessProvider runtime; - - public ForeignCallStateSplitNode(MetaAccessProvider runtime, ForeignCallDescriptor descriptor, ValueNode... arguments) { - super(descriptor, arguments); - this.runtime = runtime; - } - - public FrameState stateAfter() { - return stateAfter; - } - - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - updateUsages(stateAfter, x); - stateAfter = x; - } - - public boolean hasSideEffect() { - return runtime.hasSideEffect(getDescriptor()); - } - - @Override - public FrameState getDeoptimizationState() { - if (super.getDeoptimizationState() != null) { - return super.getDeoptimizationState(); - } else if (stateAfter() != null) { - FrameState stateDuring = stateAfter(); - if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) { - stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind()); - } - setDeoptimizationState(stateDuring); - return stateDuring; - } - return null; - } - - @Override - public void setDeoptimizationState(FrameState f) { - if (super.getDeoptimizationState() != null) { - throw new IllegalStateException(); - } - super.setDeoptimizationState(f); - } -} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import java.util.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.nodes.calc.*; @@ -38,61 +36,6 @@ public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable { /** - * Marker interface for location identities. Apart from the special values {@link #ANY_LOCATION} - * and {@link #FINAL_LOCATION}, a different location identity of two memory accesses guarantees - * that the two accesses do not interfere. - */ - public interface LocationIdentity { - } - - /** - * Denotes any location. A write to such a location kills all values in a memory map during an - * analysis of memory accesses in a graph. A read from this location cannot be moved or - * coalesced with other reads because its interaction with other reads is not known. - */ - public static final LocationIdentity ANY_LOCATION = createLocation("ANY_LOCATION"); - - /** - * Denotes the location of a value that is guaranteed to be final. - */ - public static final LocationIdentity FINAL_LOCATION = createLocation("FINAL_LOCATION"); - - /** - * Creates a new unique location identity for read and write operations. - * - * @param name the name of the new location identity, for debugging purposes - * @return the new location identity - */ - public static LocationIdentity createLocation(final String name) { - return new LocationIdentity() { - - @Override - public String toString() { - return name; - } - }; - } - - /** - * Returns the location identity for an array of the given element kind. Array accesses of the - * same kind must have the same location identity unless an alias analysis guarantees that two - * distinct arrays are accessed. - */ - public static LocationIdentity getArrayLocation(Kind elementKind) { - return ARRAY_LOCATIONS.get(elementKind); - } - - private static final EnumMap ARRAY_LOCATIONS = initArrayLocations(); - - private static EnumMap initArrayLocations() { - EnumMap result = new EnumMap<>(Kind.class); - for (Kind kind : Kind.values()) { - result.put(kind, createLocation("Array: " + kind.getJavaName())); - } - return result; - } - - /** * Marker interface for locations in snippets. */ public interface Location { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.extended; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.graph.UnsafeAccess.*; import java.lang.reflect.*; @@ -29,9 +30,9 @@ import sun.misc.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -52,7 +53,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Thu May 23 14:44:01 2013 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; /** * This interface marks subclasses of {@link FixedNode} that kill a set of memory locations @@ -34,7 +34,7 @@ /** * This method is used to determine which set of memory locations is killed by this node. - * Returning the special value {@link LocationNode#ANY_LOCATION} will kill all memory locations. + * Returning the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory locations. * * @return the identities of all locations killed by this node. */ diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu May 23 14:44:01 2013 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -77,7 +76,7 @@ return null; } if (runtime != null && object != null && object.isConstant()) { - if (location.getLocationIdentity() == LocationNode.FINAL_LOCATION && location instanceof ConstantLocationNode) { + if (location.getLocationIdentity() == LocationIdentity.FINAL_LOCATION && location instanceof ConstantLocationNode) { long displacement = ((ConstantLocationNode) location).getDisplacement(); Kind kind = location.getValueKind(); if (object.kind() == Kind.Object) { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.extended; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -74,7 +76,7 @@ return (LocationIdentity) locationIdentity.asConstant().asObject(); } // We do not know our actual location identity yet, so be conservative. - return LocationNode.ANY_LOCATION; + return ANY_LOCATION; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Thu May 23 14:44:01 2013 +0200 @@ -52,12 +52,6 @@ if (stamp() == StampFactory.forNodeIntrinsic()) { return false; } - if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) { - // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull - // guard, but the - // compiler might see this situation before the branch is deleted - return false; - } return updateStamp(stamp().join(object().stamp())); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.nodes.extended; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.graph.UnsafeAccess.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -76,7 +76,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,8 +22,10 @@ */ package com.oracle.graal.nodes.extended; +import static com.oracle.graal.api.meta.LocationIdentity.*; + +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -39,7 +41,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Thu May 23 14:44:01 2013 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.LocationNode.Location; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Thu May 23 14:44:01 2013 +0200 @@ -69,9 +69,6 @@ @Override public boolean inferStamp() { - if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) { - return false; - } return updateStamp(stamp().join(object().stamp())); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,13 +22,13 @@ */ package com.oracle.graal.nodes.java; +import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.graph.UnsafeAccess.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -97,7 +97,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,10 +22,11 @@ */ package com.oracle.graal.nodes.java; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -41,7 +42,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,9 +22,11 @@ */ package com.oracle.graal.nodes.java; +import static com.oracle.graal.api.meta.LocationIdentity.*; + +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; /** @@ -46,7 +48,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,10 +22,12 @@ */ package com.oracle.graal.nodes.java; +import static com.oracle.graal.api.meta.LocationIdentity.*; + +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.spi.*; /** @@ -47,7 +49,7 @@ @Override public LocationIdentity[] getLocationIdentities() { - return new LocationIdentity[]{LocationNode.ANY_LOCATION}; + return new LocationIdentity[]{ANY_LOCATION}; } @Override diff -r a8a5d5832def -r b49fdcee6cb0 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 Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Thu May 23 14:44:01 2013 +0200 @@ -106,11 +106,6 @@ return null; } - @Override - public boolean isCallSiteDeoptimization() { - return false; - } - @SuppressWarnings("unused") @NodeIntrinsic public static void register(Object thisObj) { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.type; +import java.lang.reflect.*; + import com.oracle.graal.api.meta.*; public class ObjectStamp extends Stamp { @@ -33,14 +35,29 @@ public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { super(Kind.Object); - assert !exactType || type != null; - assert !(nonNull && alwaysNull); + assert isValid(type, exactType, nonNull, alwaysNull); this.type = type; this.exactType = exactType; this.nonNull = nonNull; this.alwaysNull = alwaysNull; } + public static boolean isValid(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { + if (exactType && type == null) { + return false; + } + + if (exactType && Modifier.isAbstract(type.getModifiers()) && !type.isArray()) { + return false; + } + + if (nonNull && alwaysNull) { + return false; + } + + return true; + } + @Override public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { if (type != null) { @@ -152,12 +169,19 @@ joinType = type; } } + if (joinType == type && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) { return this; } else if (joinType == other.type && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) { return other; } else { - return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull); + if (isValid(joinType, joinExactType, joinNonNull, joinAlwaysNull)) { + return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull); + } else { + // This situation can happen in case the compiler wants to join two contradicting + // stamps. + return null; + } } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Thu May 23 14:44:01 2013 +0200 @@ -22,12 +22,14 @@ */ package com.oracle.graal.phases.common; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import java.util.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.graph.ReentrantNodeIterator.LoopInfo; @@ -45,7 +47,7 @@ public MemoryMap(StartNode start) { this(); - lastMemorySnapshot.put(LocationNode.ANY_LOCATION, start); + lastMemorySnapshot.put(ANY_LOCATION, start); } public MemoryMap() { @@ -54,12 +56,12 @@ private ValueNode getLastLocationAccess(LocationIdentity locationIdentity) { ValueNode lastLocationAccess; - if (locationIdentity == LocationNode.FINAL_LOCATION) { + if (locationIdentity == FINAL_LOCATION) { return null; } else { lastLocationAccess = lastMemorySnapshot.get(locationIdentity); if (lastLocationAccess == null) { - lastLocationAccess = lastMemorySnapshot.get(LocationNode.ANY_LOCATION); + lastLocationAccess = lastMemorySnapshot.get(ANY_LOCATION); assert lastLocationAccess != null; } return lastLocationAccess; @@ -122,7 +124,7 @@ exit.addAll(modifiedLocations); exit.addAll(initialState); } - assert !modifiedLocations.contains(LocationNode.FINAL_LOCATION); + assert !modifiedLocations.contains(FINAL_LOCATION); modifiedInLoops.put(loop, modifiedLocations); return loopInfo.exitStates; } @@ -149,7 +151,7 @@ private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) { for (LocationIdentity identity : checkpoint.getLocationIdentities()) { - if (identity == LocationNode.ANY_LOCATION) { + if (identity == ANY_LOCATION) { state.lastMemorySnapshot.clear(); } state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint); @@ -160,7 +162,7 @@ StructuredGraph graph = accessNode.graph(); assert accessNode.getNullCheck() == false; LocationIdentity locationIdentity = accessNode.location().getLocationIdentity(); - if (locationIdentity != LocationNode.ANY_LOCATION) { + if (locationIdentity != ANY_LOCATION) { ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity); FloatingAccessNode floatingNode = accessNode.asFloatingNode(lastLocationAccess); floatingNode.setNullCheck(accessNode.getNullCheck()); @@ -182,7 +184,7 @@ for (MemoryMap other : states) { keys.addAll(other.lastMemorySnapshot.keySet()); } - assert !keys.contains(LocationNode.FINAL_LOCATION); + assert !keys.contains(FINAL_LOCATION); for (LocationIdentity key : keys) { int mergedStatesCount = 0; @@ -236,7 +238,7 @@ @Override protected Map processLoop(LoopBeginNode loop, MemoryMap initialState) { Set modifiedLocations = modifiedInLoops.get(loop); - if (modifiedLocations.contains(LocationNode.ANY_LOCATION)) { + if (modifiedLocations.contains(ANY_LOCATION)) { // create phis for all locations if ANY is modified in the loop modifiedLocations = new HashSet<>(modifiedLocations); modifiedLocations.addAll(initialState.lastMemorySnapshot.keySet()); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Thu May 23 14:44:01 2013 +0200 @@ -255,7 +255,7 @@ callerHasMoreInformationAboutArguments = true; } else { Stamp joinedStamp = localNode.stamp().join(arg.stamp()); - if (!joinedStamp.equals(localNode.stamp())) { + if (joinedStamp != null && !joinedStamp.equals(localNode.stamp())) { localNode.setStamp(joinedStamp); callerHasMoreInformationAboutArguments = true; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu May 23 14:44:01 2013 +0200 @@ -60,7 +60,7 @@ public static int TrivialInliningSize = 10; public static int MaximumInliningSize = 300; public static int SmallCompiledLowLevelGraphSize = 300; - public static double LimitInlinedInvokes = 10.0; + public static double LimitInlinedInvokes = 5.0; // escape analysis settings public static boolean PartialEscapeAnalysis = true; @@ -152,6 +152,7 @@ public static int TraceBytecodeParserLevel = 0; public static boolean ExitVMOnBailout = ____; public static boolean ExitVMOnException = true; + public static boolean PrintStackTraceOnException = false; // HotSpot command line options public static boolean HotSpotPrintCompilation = ____; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/VerifyPhase.java Thu May 23 14:44:01 2013 +0200 @@ -24,6 +24,12 @@ import com.oracle.graal.nodes.*; +/*** + * This phase serves as a verification, in order to check the graph for certain properties. The + * {@link #verify(StructuredGraph)} method will be used as an assertion, and implements the actual + * check. Instead of returning false, it is also valid to throw an {@link AssertionError} in the + * implemented {@link #verify(StructuredGraph)} method. + */ public abstract class VerifyPhase extends Phase { @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Thu May 23 14:44:01 2013 +0200 @@ -22,8 +22,11 @@ */ package com.oracle.graal.phases.schedule; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import java.util.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; @@ -31,7 +34,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; @@ -98,7 +100,7 @@ for (Iterator iter = currentState.iterator(); iter.hasNext();) { FloatingReadNode read = iter.next(); FixedNode fixed = (FixedNode) node; - if (identity == LocationNode.ANY_LOCATION || read.location().getLocationIdentity() == identity) { + if (identity == ANY_LOCATION || read.location().getLocationIdentity() == identity) { addPhantomReference(read, fixed); iter.remove(); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Thu May 23 14:44:01 2013 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.verify; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.phases.*; + +/** + * For certain types object identity should not be used for object equality check. This phase checks + * the correct usage of the given type. Equality checks with == or != (except null checks) results + * in an {@link AssertionError}. + */ +public class VerifyUsageWithEquals extends VerifyPhase { + + private MetaAccessProvider runtime; + private Class klass; + + public VerifyUsageWithEquals(MetaAccessProvider runtime, Class klass) { + this.runtime = runtime; + this.klass = klass; + } + + private boolean isAssignableType(ValueNode node) { + if (node.stamp() instanceof ObjectStamp) { + ResolvedJavaType valueType = runtime.lookupJavaType(klass); + ResolvedJavaType nodeType = node.objectStamp().type(); + + if (nodeType != null && valueType.isAssignableFrom(nodeType)) { + return true; + } + } + return false; + } + + private static boolean isNullConstant(ValueNode node) { + return node.isConstant() && node.asConstant().isNull(); + } + + private boolean checkUsage(ValueNode x, ValueNode y) { + return isAssignableType(x) && !isNullConstant(y); + } + + private static boolean isEqualsMethod(StructuredGraph graph) { + Signature signature = graph.method().getSignature(); + return graph.method().getName().equals("equals") && signature.getParameterCount(false) == 1 && signature.getParameterKind(0).equals(Kind.Object); + } + + @Override + protected boolean verify(StructuredGraph graph) { + for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) { + if (!isEqualsMethod(graph)) { + // bail out if we compare an object of type klass with == or != (except null checks) + assert !(checkUsage(cn.x(), cn.y()) && checkUsage(cn.y(), cn.x())) : "Verifcation of " + klass.getName() + " usage failed: Comparison " + cn.x() + " and" + cn.y() + " in " + + graph.method() + " must use .equals() for object equality, not '==' or '!='"; + } + } + return true; + } +} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyValueUsage.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyValueUsage.java Fri May 17 16:47:13 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.verify; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; - -public class VerifyValueUsage extends VerifyPhase { - - private MetaAccessProvider runtime; - - public VerifyValueUsage(MetaAccessProvider runtime) { - this.runtime = runtime; - } - - private boolean checkType(ValueNode node) { - if (node.stamp() instanceof ObjectStamp) { - ResolvedJavaType valueType = runtime.lookupJavaType(Value.class); - ResolvedJavaType nodeType = node.objectStamp().type(); - - if (valueType.isAssignableFrom(nodeType)) { - return true; - } - } - return false; - } - - @Override - protected boolean verify(StructuredGraph graph) { - for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) { - Signature signature = graph.method().getSignature(); - if (!(graph.method().getName().equals("equals") && signature.getParameterCount(false) == 1 && signature.getParameterKind(0).equals(Kind.Object))) { - assert !((checkType(cn.x()) && !(cn.y() instanceof ConstantNode)) || (checkType(cn.y()) && !(cn.x() instanceof ConstantNode))) : "VerifyValueUsage: " + cn.x() + " or " + cn.y() + - " in " + graph.method() + " uses object identity. Should use equals() instead."; - } - } - return true; - } -} diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java Thu May 23 14:44:01 2013 +0200 @@ -31,32 +31,33 @@ @Test public void test0() { - test("lockObjectSimple", new Object(), new Object()); - test("lockObjectSimple", new Object(), null); +// test("lockObjectSimple", new Object(), new Object()); +// test("lockObjectSimple", new Object(), null); + test("lockObjectSimple", null, null); } - @Test + // @Test public void test0_1() { test("lockThisSimple", "test1", new Object()); test("lockThisSimple", "test1", null); } - @Test + // @Test public void test0_2() { test("lockObjectSimple", null, "test1"); } - @Test + // @Test public void test1_1() { test("lockObject", new Object(), "test1", new String[1]); } - @Test + // @Test public void test1_2() { test("lockObject", null, "test1_1", new String[1]); } - @Test + // @Test public void test2() { test("lockThis", "test2", new String[1]); } @@ -64,7 +65,7 @@ /** * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}. */ - @Test + // @Test public void test3() { test("lockLocalObject", "test3", new String[1]); } @@ -72,7 +73,7 @@ /** * Tests recursive locking of objects which should be biasable. */ - @Test + // @Test public void test4() { Chars src = new Chars("1234567890".toCharArray()); Chars dst = new Chars(src.data.length); @@ -82,7 +83,7 @@ /** * Tests recursive locking of objects which do not appear to be biasable. */ - @Test + // @Test public void test5() { char[] src = "1234567890".toCharArray(); char[] dst = new char[src.length]; @@ -92,7 +93,7 @@ /** * Extends {@link #test4()} with contention. */ - @Test + // @Test public void test6() { Chars src = new Chars("1234567890".toCharArray()); Chars dst = new Chars(src.data.length); @@ -103,7 +104,7 @@ /** * Extends {@link #test5()} with contention. */ - @Test + // @Test public void test7() { char[] src = "1234567890".toCharArray(); char[] dst = new char[src.length]; diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Thu May 23 14:44:01 2013 +0200 @@ -33,7 +33,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.*; import com.oracle.graal.word.*; @@ -43,7 +42,7 @@ */ public class PointerTest extends GraalCompilerTest implements Snippets { - private static final LocationIdentity ID = LocationNode.createLocation("ID"); + private static final LocationIdentity ID = new NamedLocationIdentity("ID"); private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}; private final TargetDescription target; private final ReplacementsImpl installer; @@ -78,7 +77,7 @@ @Test public void test_read3() { for (Kind kind : KINDS) { - assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION); + assertRead(parse("read" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION); } } @@ -99,7 +98,7 @@ @Test public void test_write3() { for (Kind kind : KINDS) { - assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION); + assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION); } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Thu May 23 14:44:01 2013 +0200 @@ -22,9 +22,11 @@ */ package com.oracle.graal.replacements.nodes; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.WriteNode.*; +import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; @@ -62,7 +64,7 @@ @Override public void lower(LoweringTool tool, LoweringType loweringType) { - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph(), 1); + IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, value.kind(), displacement, offset, graph(), 1); WriteNode write = graph().add(new WriteNode(object, value, location, WriteBarrierType.NONE)); graph().replaceFixedWithFixed(this, write); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.virtual.phases.ea; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import java.util.*; import com.oracle.graal.api.code.*; @@ -33,7 +35,6 @@ import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; @@ -173,7 +174,7 @@ for (LocationIdentity identity : checkpoint.getLocationIdentities()) { if (identity instanceof ResolvedJavaField) { state.killReadCache((ResolvedJavaField) identity); - } else if (identity == LocationNode.ANY_LOCATION) { + } else if (identity == ANY_LOCATION) { state.killReadCache(); } } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Thu May 23 14:44:01 2013 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.word; +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; public interface Pointer extends Unsigned { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Thu May 23 14:44:01 2013 +0200 @@ -27,10 +27,10 @@ import java.lang.annotation.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; public abstract class Word implements Signed, Unsigned, Pointer { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Thu May 23 14:44:01 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.word.phases; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import java.lang.reflect.*; import com.oracle.graal.api.meta.*; @@ -29,7 +31,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.extended.LocationNode.LocationIdentity; import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; @@ -164,7 +165,7 @@ Kind readKind = asKind(callTargetNode.returnType()); LocationNode location; if (arguments.size() == 2) { - location = makeLocation(graph, arguments.get(1), readKind, LocationNode.ANY_LOCATION); + location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION); } else { location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2)); } @@ -176,7 +177,7 @@ Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass())); LocationNode location; if (arguments.size() == 3) { - location = makeLocation(graph, arguments.get(1), writeKind, LocationNode.ANY_LOCATION); + location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION); } else { location = makeLocation(graph, arguments.get(1), writeKind, arguments.get(3)); } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Thu May 23 14:44:01 2013 +0200 @@ -115,7 +115,7 @@ * @return the code as a String object */ public final String getCode() { - return getSource().getCode().substring(charIndex, charLength); + return getSource().getCode().substring(charIndex, charIndex + charLength); } @Override diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Thu May 23 14:44:01 2013 +0200 @@ -149,6 +149,7 @@ // Pass on the source section to the new node. newNode.assignSourceSection(sourceSection); } + onReplace(newNode, reason); return (T) this.getParent().replaceChild(this, newNode); } @@ -170,6 +171,16 @@ } /** + * Intended to be implemented by subclasses of {@link Node} to receive a notification when the + * node is rewritten. This method is invoked before the actual replace has happened. + * + * @param newNode the replacement node + * @param reason the reason the replace supplied + */ + protected void onReplace(Node newNode, String reason) { + } + + /** * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all * child nodes. * diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java Thu May 23 14:44:01 2013 +0200 @@ -37,4 +37,11 @@ * @return the short name */ String shortName() default ""; + + Kind kind() default Kind.SPECIALIZED; + + public enum Kind { + UNINITIALIZED, SPECIALIZED, GENERIC + } + } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Thu May 23 14:44:01 2013 +0200 @@ -26,7 +26,7 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; -import javax.tools.Diagnostic.*; +import javax.tools.Diagnostic.Kind; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; @@ -47,6 +47,8 @@ private final TypeMirror invalidAssumption; private final DeclaredType childAnnotation; private final DeclaredType childrenAnnotation; + private final DeclaredType nodeInfoAnnotation; + private final DeclaredType nodeInfoKind; private final TypeMirror compilerDirectives; private final TypeMirror compilerAsserts; @@ -63,6 +65,12 @@ compilerAsserts = getRequired(context, CompilerAsserts.class); assumption = getRequired(context, Assumption.class); invalidAssumption = getRequired(context, InvalidAssumptionException.class); + nodeInfoAnnotation = getRequired(context, NodeInfo.class); + nodeInfoKind = getRequired(context, NodeInfo.Kind.class); + } + + public DeclaredType getNodeInfoAnnotation() { + return nodeInfoAnnotation; } public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) { @@ -77,6 +85,10 @@ return false; } + public DeclaredType getNodeInfoKind() { + return nodeInfoKind; + } + private DeclaredType getRequired(ProcessorContext context, Class clazz) { TypeMirror type = context.getType(clazz); if (type == null) { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Thu May 23 14:44:01 2013 +0200 @@ -40,6 +40,26 @@ */ public class Utils { + public static ExecutableElement findExecutableElement(DeclaredType type, String name) { + List elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements()); + for (ExecutableElement executableElement : elements) { + if (executableElement.getSimpleName().toString().equals(name)) { + return executableElement; + } + } + return null; + } + + public static VariableElement findVariableElement(DeclaredType type, String name) { + List elements = ElementFilter.fieldsIn(type.asElement().getEnclosedElements()); + for (VariableElement variableElement : elements) { + if (variableElement.getSimpleName().toString().equals(name)) { + return variableElement; + } + } + return null; + } + public static String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { if (method instanceof CodeExecutableElement) { return ((CodeExecutableElement) method).getBody(); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeAnnotationMirror.java Thu May 23 14:44:01 2013 +0200 @@ -26,8 +26,8 @@ import javax.lang.model.element.*; import javax.lang.model.type.*; -import javax.lang.model.util.*; +import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.api.element.*; public class CodeAnnotationMirror implements WritableAnnotationMirror { @@ -60,13 +60,7 @@ } public ExecutableElement findExecutableElement(String name) { - List elements = ElementFilter.methodsIn(annotationType.asElement().getEnclosedElements()); - for (ExecutableElement executableElement : elements) { - if (executableElement.getSimpleName().toString().equals(name)) { - return executableElement; - } - } - return null; + return Utils.findExecutableElement(annotationType, name); } public static CodeAnnotationMirror clone(AnnotationMirror mirror) { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Thu May 23 14:44:01 2013 +0200 @@ -246,23 +246,7 @@ } public CodeTreeBuilder doubleQuote(String s) { - return startGroup().string("\"").string(s).string("\"").end(); - } - - public CodeTreeBuilder startDoubleQuote() { - startGroup().string("\""); - registerCallBack(new EndCallback() { - - @Override - public void beforeEnd() { - } - - @Override - public void afterEnd() { - string("\""); - } - }); - return this; + return startGroup().string("\"" + s + "\"").end(); } public CodeTreeBuilder string(String chunk1) { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeData.java Thu May 23 14:44:01 2013 +0200 @@ -75,23 +75,6 @@ return count; } - public boolean startsWithSignature(TemplateMethod method) { - for (ActualParameter param : getParameters()) { - if (!param.getSpecification().isSignature()) { - continue; - } - ActualParameter foundParam = method.findParameter(param.getLocalName()); - if (foundParam != null) { - TypeData actualType = param.getTypeSystemType(); - TypeData foundType = foundParam.getTypeSystemType(); - if (actualType == null || foundType == null || !actualType.equalsType(foundType)) { - return false; - } - } - } - return true; - } - public boolean hasGenericSignature() { List types = getSignature(); for (TypeData typeData : types) { diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Thu May 23 14:44:01 2013 +0200 @@ -44,8 +44,15 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null); + List requiredSpecs = new ArrayList<>(spec.getRequired()); + spec.getRequired().clear(); + + for (ParameterSpec originalSpec : requiredSpecs) { + spec.addRequired(new ParameterSpec(originalSpec, Arrays.asList(getNode().getTypeSystem().getGenericType()))); + } + spec.setVariableRequiredArguments(true); - ParameterSpec other = new ParameterSpec("other", nodeTypeMirrors(getNode())); + ParameterSpec other = new ParameterSpec("other", Arrays.asList(getNode().getTypeSystem().getGenericType())); other.setCardinality(Cardinality.MANY); other.setSignature(true); other.setIndexed(true); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Thu May 23 14:44:01 2013 +0200 @@ -766,10 +766,55 @@ } builder.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end(); prefix = null; + + builder.startStatement().string("StringBuilder message = new StringBuilder(reason)").end(); + builder.startStatement().startCall("message", "append").doubleQuote(" (").end().end(); + + String sep = null; + for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) { + if (!parameter.getSpecification().isSignature()) { + continue; + } + + builder.startStatement(); + builder.string("message"); + if (sep != null) { + builder.startCall(".append").doubleQuote(sep).end(); + } + builder.startCall(".append").doubleQuote(parameter.getLocalName()).end(); + builder.startCall(".append").doubleQuote(" = ").end(); + builder.startCall(".append").string(parameter.getLocalName()).end(); + builder.end(); + + if (!Utils.isPrimitive(parameter.getType())) { + builder.startIf().string(parameter.getLocalName() + " != null").end(); + builder.startBlock(); + } + builder.startStatement(); + if (Utils.isPrimitive(parameter.getType())) { + builder.startCall("message.append").doubleQuote(" (" + Utils.getSimpleName(parameter.getType()) + ")").end(); + } else { + builder.startCall("message.append").doubleQuote(" (").end(); + builder.startCall(".append").string(parameter.getLocalName() + ".getClass().getSimpleName()").end(); + builder.startCall(".append").doubleQuote(")").end(); + } + builder.end(); + if (!Utils.isPrimitive(parameter.getType())) { + builder.end(); + } + + sep = ", "; + } + + builder.startStatement().startCall("message", "append").doubleQuote(")").end().end(); } addInternalValueParameters(method, node.getGenericSpecialization(), true); + if (specialize) { + method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason")); + } + List specializations = node.getSpecializations(); if (!specialize && !node.getGenericSpecialization().isUseSpecializationsForGeneric()) { specializations = Arrays.asList(node.getGenericSpecialization()); @@ -864,6 +909,7 @@ builder.startStatement().startCall("super", "replace"); builder.startGroup().startNew(nodeSpecializationClassName(current)).string("this").end().end(); + builder.string("message.toString()"); builder.end().end(); if (current.getReturnSignature().isVoid()) { @@ -1336,6 +1382,27 @@ baseType = nodeGen.asType(); } CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); + + String shortName = specialization.getNode().getShortName(); + CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation()); + if (shortName != null) { + nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName)); + } + + DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind(); + VariableElement kind; + if (specialization.isGeneric()) { + kind = Utils.findVariableElement(nodeinfoKind, "GENERIC"); + } else if (specialization.isUninitialized()) { + kind = Utils.findVariableElement(nodeinfoKind, "UNINITIALIZED"); + } else { + kind = Utils.findVariableElement(nodeinfoKind, "SPECIALIZED"); + } + + nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(kind)); + + clazz.getAnnotationMirrors().add(nodeInfoMirror); + return clazz; } @@ -1373,12 +1440,13 @@ CodeTreeBuilder builder = new CodeTreeBuilder(parent); - ExecutableTypeData foundEvaluatedPrimaryType = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); + List primaryExecutes = findFunctionalExecutableType(specialization, execType.getEvaluatedCount()); - if (execType == foundEvaluatedPrimaryType || foundEvaluatedPrimaryType == null) { + if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) { builder.tree(createFunctionalExecute(builder, specialization, execType)); } else if (needsCastingExecuteMethod(execType, primaryType)) { - builder.tree(createCastingExecute(builder, specialization, execType, foundEvaluatedPrimaryType)); + assert !primaryExecutes.isEmpty(); + builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0))); } else { return null; } @@ -1420,7 +1488,7 @@ return false; } - private ExecutableTypeData findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { + private List findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) { TypeData primaryType = specialization.getReturnType().getTypeSystemType(); List otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount); @@ -1432,19 +1500,24 @@ filteredTypes.add(compareType); } - for (ExecutableTypeData compareType : filteredTypes) { - if (compareType.startsWithSignature(specialization)) { - return compareType; + // no direct matches found use generic where the type is Object + if (filteredTypes.isEmpty()) { + for (ExecutableTypeData compareType : otherTypes) { + if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) { + filteredTypes.add(compareType); + } } } - for (ExecutableTypeData compareType : otherTypes) { - if (compareType.startsWithSignature(specialization)) { - return compareType; + if (filteredTypes.isEmpty()) { + for (ExecutableTypeData compareType : otherTypes) { + if (compareType.getType().isGeneric()) { + filteredTypes.add(compareType); + } } } - return null; + return filteredTypes; } private CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) { @@ -1558,7 +1631,7 @@ if (next != null) { CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder); returnBuilder.tree(createDeoptimize(builder)); - returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null)); + returnBuilder.tree(createReturnExecuteAndSpecialize(builder, executable, next, null, "One of guards " + specialization.getGuards() + " failed")); returnSpecialized = returnBuilder.getRoot(); } builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false)); @@ -1592,6 +1665,7 @@ returnBuilder.startCall("super", EXECUTE_SPECIALIZE_NAME); returnBuilder.startGroup().string(nodeSpecializationClassName(specialization)).string(".class").end(); addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); + returnBuilder.doubleQuote("Uninitialized"); returnBuilder.end(); } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { emitEncounteredSynthetic(builder); @@ -1623,13 +1697,13 @@ for (SpecializationThrowsData exception : specialization.getExceptions()) { builder.end().startCatchBlock(exception.getJavaClass(), "ex"); builder.tree(createDeoptimize(builder)); - builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null)); + builder.tree(createReturnExecuteAndSpecialize(parent, executable, exception.getTransitionTo(), null, "Thrown " + Utils.getSimpleName(exception.getJavaClass()))); } builder.end(); } if (!specialization.getAssumptions().isEmpty()) { builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex"); - builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null)); + builder.tree(createReturnExecuteAndSpecialize(parent, executable, specialization.findNextSpecialization(), null, "Assumption failed")); builder.end(); } @@ -1734,7 +1808,8 @@ List genericParameters = generic.getParametersAfter(genericParameter); builder.tree(createDeoptimize(builder)); builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false)); - builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param)); + builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, + "Expected " + param.getLocalName() + " instanceof " + Utils.getSimpleName(param.getType()))); builder.end(); // catch block } @@ -1850,13 +1925,14 @@ return builder.getRoot(); } - private CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam) { + private CodeTree createReturnExecuteAndSpecialize(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData nextSpecialization, ActualParameter exceptionParam, String reason) { SpecializationData generic = nextSpecialization.getNode().getGenericSpecialization(); CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); specializeCall.startCall(EXECUTE_SPECIALIZE_NAME); specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class"); addInternalValueParameterNames(specializeCall, generic, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true, true); + specializeCall.doubleQuote(reason); specializeCall.end().end(); CodeTreeBuilder builder = new CodeTreeBuilder(parent); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Thu May 23 14:44:01 2013 +0200 @@ -51,6 +51,8 @@ private List shortCircuits; private List assumptions; + private String shortName; + public NodeData(TypeElement type, String id) { super(type, null, null); this.nodeId = id; @@ -72,6 +74,14 @@ this.assumptions = splitSource.assumptions; } + void setShortName(String shortName) { + this.shortName = shortName; + } + + public String getShortName() { + return shortName; + } + public boolean isSplitByMethodName() { return splitByMethodName; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Thu May 23 14:44:01 2013 +0200 @@ -32,6 +32,7 @@ import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.api.codegen.NodeClass.InheritNode; +import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality; import com.oracle.truffle.codegen.processor.node.NodeChildData.ExecutionKind; @@ -577,6 +578,11 @@ } } } + AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class); + if (nodeInfoMirror != null) { + nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName")); + } + nodeData.setAssumptions(new ArrayList<>(assumptionsList)); nodeData.setNodeType(nodeType); nodeData.setSplitByMethodName(splitByMethodName); diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Thu May 23 14:44:01 2013 +0200 @@ -55,6 +55,16 @@ this.allowedTypes = allowedTypes; } + public ParameterSpec(ParameterSpec o, List allowedTypes) { + this.name = o.name; + this.cardinality = o.cardinality; + this.signature = o.signature; + this.indexed = o.indexed; + this.local = o.local; + this.typeDefinition = o.typeDefinition; + this.allowedTypes = allowedTypes; + } + void setTypeDefinition(TypeDef typeDefinition) { this.typeDefinition = typeDefinition; } diff -r a8a5d5832def -r b49fdcee6cb0 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java Fri May 17 16:47:13 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java Thu May 23 14:44:01 2013 +0200 @@ -38,4 +38,9 @@ return specialization; } + @Override + public String toString() { + return getMethodName(); + } + } diff -r a8a5d5832def -r b49fdcee6cb0 mx/commands.py --- a/mx/commands.py Fri May 17 16:47:13 2013 +0200 +++ b/mx/commands.py Thu May 23 14:44:01 2013 +0200 @@ -825,7 +825,7 @@ def harness(projectscp, vmArgs): if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource]) - if _vm == 'original' or _vm.endswith('nograal'): + if not isGraalEnabled(_vm): prefixArgs = ['-esa', '-ea'] else: prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea'] @@ -1333,6 +1333,9 @@ 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]) +def isGraalEnabled(vm): + return vm != 'original' and not vm.endswith('nograal') + def site(args): """create a website containing javadoc and the project dependency graph""" diff -r a8a5d5832def -r b49fdcee6cb0 mx/sanitycheck.py --- a/mx/sanitycheck.py Fri May 17 16:47:13 2013 +0200 +++ b/mx/sanitycheck.py Thu May 23 14:44:01 2013 +0200 @@ -235,15 +235,15 @@ args = ['-XX:+CompileTheWorld', '-Xbootclasspath/p:' + rtjar] - if not vm.endswith('-nograal'): + if commands.isGraalEnabled(vm): args += ['-XX:+BootstrapGraal', '-G:-Debug'] if mode >= CTWMode.NoInline: - if vm.endswith('-nograal'): + if not commands.isGraalEnabled(vm): args.append('-XX:-Inline') else: args.append('-G:-Inline') if mode >= CTWMode.NoComplex: - if not vm.endswith('-nograal'): + if commands.isGraalEnabled(vm): args += ['-G:-OptLoopTransform', '-G:-OptTailDuplication', '-G:-FullUnroll', '-G:-MemoryAwareScheduling', '-G:-PartialEscapeAnalysis'] return Test("CompileTheWorld", args, successREs=[time], scoreMatchers=[scoreMatcher], benchmarkCompilationRate=False) diff -r a8a5d5832def -r b49fdcee6cb0 src/cpu/sparc/vm/c2_globals_sparc.hpp --- a/src/cpu/sparc/vm/c2_globals_sparc.hpp Fri May 17 16:47:13 2013 +0200 +++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp Thu May 23 14:44:01 2013 +0200 @@ -38,6 +38,7 @@ define_pd_global(bool, ProfileTraps, true); define_pd_global(bool, UseOnStackReplacement, true); define_pd_global(intx, TypeProfileWidth, 2 ); +define_pd_global(intx, MethodProfileWidth, 0 ); #ifdef CC_INTERP define_pd_global(bool, ProfileInterpreter, false); #else diff -r a8a5d5832def -r b49fdcee6cb0 src/cpu/x86/vm/c1_globals_x86.hpp --- a/src/cpu/x86/vm/c1_globals_x86.hpp Fri May 17 16:47:13 2013 +0200 +++ b/src/cpu/x86/vm/c1_globals_x86.hpp Thu May 23 14:44:01 2013 +0200 @@ -56,6 +56,7 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); define_pd_global(intx, TypeProfileWidth, 0); +define_pd_global(intx, MethodProfileWidth, 0); #endif // !TIERED define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, RoundFPResults, true ); diff -r a8a5d5832def -r b49fdcee6cb0 src/cpu/x86/vm/c2_globals_x86.hpp --- a/src/cpu/x86/vm/c2_globals_x86.hpp Fri May 17 16:47:13 2013 +0200 +++ b/src/cpu/x86/vm/c2_globals_x86.hpp Thu May 23 14:44:01 2013 +0200 @@ -40,6 +40,7 @@ define_pd_global(bool, ProfileTraps, true); define_pd_global(bool, UseOnStackReplacement, true); define_pd_global(intx, TypeProfileWidth, 2 ); +define_pd_global(intx, MethodProfileWidth, 0 ); #ifdef CC_INTERP define_pd_global(bool, ProfileInterpreter, false); #else diff -r a8a5d5832def -r b49fdcee6cb0 src/cpu/x86/vm/graalGlobals_x86.hpp --- a/src/cpu/x86/vm/graalGlobals_x86.hpp Fri May 17 16:47:13 2013 +0200 +++ b/src/cpu/x86/vm/graalGlobals_x86.hpp Thu May 23 14:44:01 2013 +0200 @@ -58,6 +58,7 @@ define_pd_global(intx, CodeCacheExpansionSize, 64*K ); define_pd_global(uintx,CodeCacheMinBlockLength, 4); define_pd_global(intx, TypeProfileWidth, 8); +define_pd_global(intx, MethodProfileWidth, 4); #endif #endif // CPU_X86_VM_GRAALGLOBALS_X86_HPP diff -r a8a5d5832def -r b49fdcee6cb0 src/cpu/x86/vm/interp_masm_x86_64.cpp --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Fri May 17 16:47:13 2013 +0200 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu May 23 14:44:01 2013 +0200 @@ -1082,9 +1082,10 @@ increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_constant(mdp, - in_bytes(VirtualCallData:: + update_mdp_by_constant(mdp, + in_bytes(VirtualCallData:: virtual_call_data_size())); + bind(profile_continue); } } @@ -1116,13 +1117,38 @@ bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. - update_mdp_by_constant(mdp, - in_bytes(VirtualCallData:: - virtual_call_data_size())); +#ifdef GRAAL + if (MethodProfileWidth == 0) { + update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); + } +#else + update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); +#endif bind(profile_continue); } } +#ifdef GRAAL +void InterpreterMacroAssembler::profile_called_method(Register method, Register mdp, Register reg2) { + assert_different_registers(method, mdp, reg2); + if (ProfileInterpreter && MethodProfileWidth > 0) { + Label profile_continue; + + // If no method data exists, go to profile_continue. + test_method_data_pointer(mdp, profile_continue); + + Label done; + record_item_in_profile_helper(method, mdp, reg2, 0, done, MethodProfileWidth, + &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset())); + bind (done); + + update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); + bind(profile_continue); + } +} + +#endif + // This routine creates a state machine for updating the multi-row // type profile at a virtual call site (or other type-sensitive bytecode). // The machine visits each row (of receiver/count) until the receiver type @@ -1136,8 +1162,7 @@ // See below for example code. void InterpreterMacroAssembler::record_klass_in_profile_helper( Register receiver, Register mdp, - Register reg2, int start_row, - Label& done, bool is_virtual_call) { + Register reg2, Label& done, bool is_virtual_call) { if (TypeProfileWidth == 0) { if (is_virtual_call) { increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); @@ -1147,14 +1172,33 @@ increment_mdp_data_at(mdp, in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset())); } #endif - return; - } + } else { + bool use_non_profiled_counter = !is_virtual_call || IS_GRAAL_DEFINED; + int non_profiled_offset = -1; + if (use_non_profiled_counter) { + non_profiled_offset = in_bytes(CounterData::count_offset()); + #ifdef GRAAL + if (!is_virtual_call) { + non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()); + } + #endif + assert(non_profiled_offset >= 0, "must be"); + } - int last_row = VirtualCallData::row_limit() - 1; + record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth, + &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset); + } +} + +void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp, + Register reg2, int start_row, Label& done, int total_rows, + OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn, + int non_profiled_offset) { + int last_row = total_rows - 1; assert(start_row <= last_row, "must be work left to do"); - // Test this row for both the receiver and for null. + // Test this row for both the item and for null. // Take any of three different outcomes: - // 1. found receiver => increment count and goto done + // 1. found item => increment count and goto done // 2. found null => keep looking for case 1, maybe allocate this cell // 3. found something else => keep looking for cases 1 and 2 // Case 3 is handled by a recursive call. @@ -1162,36 +1206,30 @@ Label next_test; bool test_for_null_also = (row == start_row); - // See if the receiver is receiver[n]. - int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); - test_mdp_data_at(mdp, recvr_offset, receiver, + // See if the item is item[n]. + int item_offset = in_bytes(item_offset_fn(row)); + test_mdp_data_at(mdp, item_offset, item, (test_for_null_also ? reg2 : noreg), next_test); - // (Reg2 now contains the receiver from the CallData.) + // (Reg2 now contains the item from the CallData.) - // The receiver is receiver[n]. Increment count[n]. - int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); + // The item is item[n]. Increment count[n]. + int count_offset = in_bytes(item_count_offset_fn(row)); increment_mdp_data_at(mdp, count_offset); jmp(done); bind(next_test); if (test_for_null_also) { Label found_null; - // Failed the equality check on receiver[n]... Test for null. + // Failed the equality check on item[n]... Test for null. testptr(reg2, reg2); if (start_row == last_row) { // The only thing left to do is handle the null case. - if (is_virtual_call GRAAL_ONLY(|| true)) { + if (non_profiled_offset >= 0) { jccb(Assembler::zero, found_null); - // Receiver did not match any saved receiver and there is no empty row for it. + // Item did not match any saved item and there is no empty row for it. // Increment total counter to indicate polymorphic case. - int offset = in_bytes(CounterData::count_offset()); -#ifdef GRAAL - if (!is_virtual_call) { - offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()); - } -#endif - increment_mdp_data_at(mdp, offset); + increment_mdp_data_at(mdp, non_profiled_offset); jmp(done); bind(found_null); } else { @@ -1203,21 +1241,22 @@ jcc(Assembler::zero, found_null); // Put all the "Case 3" tests here. - record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); + record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows, + item_offset_fn, item_count_offset_fn, non_profiled_offset); - // Found a null. Keep searching for a matching receiver, + // Found a null. Keep searching for a matching item, // but remember that this is an empty (unused) slot. bind(found_null); } } - // In the fall-through case, we found no matching receiver, but we - // observed the receiver[start_row] is NULL. + // In the fall-through case, we found no matching item, but we + // observed the item[start_row] is NULL. - // Fill in the receiver field and increment the count. - int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); - set_mdp_data_at(mdp, recvr_offset, receiver); - int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); + // Fill in the item field and increment the count. + int item_offset = in_bytes(item_offset_fn(start_row)); + set_mdp_data_at(mdp, item_offset, item); + int count_offset = in_bytes(item_count_offset_fn(start_row)); movl(reg2, DataLayout::counter_increment); set_mdp_data_at(mdp, count_offset, reg2); if (start_row > 0) { @@ -1255,7 +1294,7 @@ assert(ProfileInterpreter, "must be profiling"); Label done; - record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); + record_klass_in_profile_helper(receiver, mdp, reg2, done, is_virtual_call); bind (done); } @@ -1310,7 +1349,7 @@ // The method data pointer needs to be updated. int mdp_delta = in_bytes(BitData::bit_data_size()); if (TypeProfileCasts) { - mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); + mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size()); } update_mdp_by_constant(mdp, mdp_delta); @@ -1328,7 +1367,7 @@ int count_offset = in_bytes(CounterData::count_offset()); // Back up the address, since we have already bumped the mdp. - count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); + count_offset -= in_bytes(ReceiverTypeData::receiver_type_data_size()); // *Decrement* the counter. We expect to see zero or small negatives. increment_mdp_data_at(mdp, count_offset, true); @@ -1348,7 +1387,7 @@ // The method data pointer needs to be updated. int mdp_delta = in_bytes(BitData::bit_data_size()); if (TypeProfileCasts) { - mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); + mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size()); // Record the object type. record_klass_in_profile(klass, mdp, reg2, false); diff -r a8a5d5832def -r b49fdcee6cb0 src/cpu/x86/vm/interp_masm_x86_64.hpp --- a/src/cpu/x86/vm/interp_masm_x86_64.hpp Fri May 17 16:47:13 2013 +0200 +++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp Thu May 23 14:44:01 2013 +0200 @@ -32,6 +32,7 @@ // This file specializes the assember with interpreter-specific macros +typedef ByteSize (*OffsetFunction)(uint); class InterpreterMacroAssembler: public MacroAssembler { #ifndef CC_INTERP @@ -213,8 +214,11 @@ void record_klass_in_profile(Register receiver, Register mdp, Register reg2, bool is_virtual_call); void record_klass_in_profile_helper(Register receiver, Register mdp, - Register reg2, int start_row, - Label& done, bool is_virtual_call); + Register reg2, Label& done, bool is_virtual_call); + void record_item_in_profile_helper(Register item, Register mdp, + Register reg2, int start_row, Label& done, int total_rows, + OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn, + int non_profiled_offset); void update_mdp_by_offset(Register mdp_in, int offset_of_offset); void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); @@ -228,6 +232,7 @@ void profile_virtual_call(Register receiver, Register mdp, Register scratch2, bool receiver_can_be_null = false); + void profile_called_method(Register method, Register mdp, Register reg2); void profile_ret(Register return_bci, Register mdp); void profile_null_seen(Register mdp); void profile_typecheck(Register mdp, Register klass, Register scratch); diff -r a8a5d5832def -r b49fdcee6cb0 src/cpu/x86/vm/templateTable_x86_64.cpp --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Fri May 17 16:47:13 2013 +0200 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Thu May 23 14:44:01 2013 +0200 @@ -3017,6 +3017,10 @@ // get target Method* & entry point __ lookup_virtual_method(rax, index, method); +#ifdef GRAAL + // r14: MethodDataPointer (r14 is callee saved) + __ profile_called_method(method, r14, r13); +#endif __ jump_from_interpreted(method, rdx); } @@ -3101,7 +3105,7 @@ __ lookup_interface_method(// inputs: rec. class, interface, itable index rdx, rax, rbx, // outputs: method, scan temp. reg - rbx, r13, + rbx, r14, no_such_interface); // rbx: Method* to call @@ -3116,6 +3120,10 @@ // do the call // rcx: receiver // rbx,: Method* +#ifdef GRAAL + // r13: MethodDataPointer (r13 is callee saved) + __ profile_called_method(rbx, r13, r14); +#endif __ jump_from_interpreted(rbx, rdx); __ should_not_reach_here(); diff -r a8a5d5832def -r b49fdcee6cb0 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri May 17 16:47:13 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Thu May 23 14:44:01 2013 +0200 @@ -687,6 +687,8 @@ set_int("methodMaxLocalsOffset", in_bytes(ConstMethod::size_of_locals_offset())); set_int("methodConstMethodOffset", in_bytes(Method::const_offset())); set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset())); + set_int("constMethodConstantsOffset", in_bytes(ConstMethod::constants_offset())); + set_int("constantPoolHolderOffset", ConstantPool::pool_holder_offset_in_bytes()); set_int("extraStackEntries", Method::extra_stack_entries()); set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes()); @@ -730,6 +732,7 @@ set_int("dataLayoutCellSize", DataLayout::cell_size); set_int("bciProfileWidth", BciProfileWidth); set_int("typeProfileWidth", TypeProfileWidth); + set_int("methodProfileWidth", MethodProfileWidth); set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); diff -r a8a5d5832def -r b49fdcee6cb0 src/share/vm/oops/methodData.cpp --- a/src/share/vm/oops/methodData.cpp Fri May 17 16:47:13 2013 +0200 +++ b/src/share/vm/oops/methodData.cpp Thu May 23 14:44:01 2013 +0200 @@ -168,6 +168,18 @@ } } +#ifdef GRAAL +void VirtualCallData::clean_weak_klass_links(BoolObjectClosure* is_alive_cl) { + ReceiverTypeData::clean_weak_klass_links(is_alive_cl); + for (uint row = 0; row < method_row_limit(); row++) { + Method* p = method(row); + if (p != NULL && !p->method_holder()->is_loader_alive(is_alive_cl)) { + clear_method_row(row); + } + } +} +#endif // GRAAL + #ifndef PRODUCT void ReceiverTypeData::print_receiver_data_on(outputStream* st) { uint row; diff -r a8a5d5832def -r b49fdcee6cb0 src/share/vm/oops/methodData.hpp --- a/src/share/vm/oops/methodData.hpp Fri May 17 16:47:13 2013 +0200 +++ b/src/share/vm/oops/methodData.hpp Thu May 23 14:44:01 2013 +0200 @@ -635,9 +635,17 @@ protected: enum { #ifdef GRAAL - // Graal is interested in knowing the percentage of type checks - // involving a type not explicitly in the profile - nonprofiled_receiver_count_off_set = counter_cell_count, + // Description of the different counters + // ReceiverTypeData for instanceof/checkcast/aastore: + // C1/C2: count is incremented on type overflow and decremented for failed type checks + // Graal: count decremented for failed type checks and nonprofiled_count is incremented on type overflow + // TODO (chaeubl): in fact, Graal should also increment the count for failed type checks to mimic the C1/C2 behavior + // VirtualCallData for invokevirtual/invokeinterface: + // C1/C2: count is incremented on type overflow + // Graal: count is incremented on type overflow, nonprofiled_count is increment on method overflow + + // Graal is interested in knowing the percentage of type checks involving a type not explicitly in the profile + nonprofiled_count_off_set = counter_cell_count, receiver0_offset, #else receiver0_offset = counter_cell_count, @@ -717,6 +725,13 @@ set_count(0); set_receiver(row, NULL); set_receiver_count(row, 0); +#ifdef GRAAL + if (!this->is_VirtualCallData()) { + // if this is a ReceiverTypeData for Graal, the nonprofiled_count + // must also be reset (see "Description of the different counters" above) + set_nonprofiled_count(0); + } +#endif } // Code generation support @@ -728,7 +743,10 @@ } #ifdef GRAAL static ByteSize nonprofiled_receiver_count_offset() { - return cell_offset(nonprofiled_receiver_count_off_set); + return cell_offset(nonprofiled_count_off_set); + } + void set_nonprofiled_count(uint count) { + set_uint_at(nonprofiled_count_off_set, count); } #endif static ByteSize receiver_type_data_size() { @@ -759,7 +777,7 @@ static int static_cell_count() { // At this point we could add more profile state, e.g., for arguments. // But for now it's the same size as the base record type. - return ReceiverTypeData::static_cell_count(); + return ReceiverTypeData::static_cell_count() GRAAL_ONLY(+ (uint) MethodProfileWidth * receiver_type_row_cell_count); } virtual int cell_count() { @@ -771,6 +789,53 @@ return cell_offset(static_cell_count()); } +#ifdef GRAAL + static ByteSize method_offset(uint row) { + return cell_offset(method_cell_index(row)); + } + static ByteSize method_count_offset(uint row) { + return cell_offset(method_count_cell_index(row)); + } + static int method_cell_index(uint row) { + return receiver0_offset + (row + TypeProfileWidth) * receiver_type_row_cell_count; + } + static int method_count_cell_index(uint row) { + return count0_offset + (row + TypeProfileWidth) * receiver_type_row_cell_count; + } + static uint method_row_limit() { + return MethodProfileWidth; + } + + Method* method(uint row) { + assert(row < method_row_limit(), "oob"); + + Method* method = (Method*)intptr_at(method_cell_index(row)); + assert(method == NULL || method->is_method(), "must be"); + return method; + } + + void set_method(uint row, Method* m) { + assert((uint)row < method_row_limit(), "oob"); + set_intptr_at(method_cell_index(row), (uintptr_t)m); + } + + void set_method_count(uint row, uint count) { + assert(row < method_row_limit(), "oob"); + set_uint_at(method_count_cell_index(row), count); + } + + void clear_method_row(uint row) { + assert(row < method_row_limit(), "oob"); + // Clear total count - indicator of polymorphic call site (see comment for clear_row() in ReceiverTypeData). + set_nonprofiled_count(0); + set_method(row, NULL); + set_method_count(row, 0); + } + + // GC support + virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure); +#endif + #ifndef PRODUCT void print_data_on(outputStream* st); #endif diff -r a8a5d5832def -r b49fdcee6cb0 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Fri May 17 16:47:13 2013 +0200 +++ b/src/share/vm/runtime/globals.hpp Thu May 23 14:44:01 2013 +0200 @@ -2949,6 +2949,9 @@ product_pd(intx, TypeProfileWidth, \ "number of receiver types to record in call/cast profile") \ \ + product_pd(intx, MethodProfileWidth, \ + "number of methods to record in call profile") \ + \ develop(intx, BciProfileWidth, 2, \ "number of return bci's to record in ret profile") \ \ diff -r a8a5d5832def -r b49fdcee6cb0 src/share/vm/utilities/macros.hpp --- a/src/share/vm/utilities/macros.hpp Fri May 17 16:47:13 2013 +0200 +++ b/src/share/vm/utilities/macros.hpp Thu May 23 14:44:01 2013 +0200 @@ -182,6 +182,7 @@ #ifdef GRAAL #define GRAAL_ONLY(code) code #define NOT_GRAAL(code) +#define IS_GRAAL_DEFINED true #if !defined(COMPILER1) && !defined(COMPILER2) // Graal is the only compiler in the system and so will be used for compilation // requests issued by the compile broker. @@ -197,6 +198,7 @@ #else // !GRAAL #define GRAAL_ONLY(code) #define NOT_GRAAL(code) code +#define IS_GRAAL_DEFINED false #define GRAALVM_ONLY(code) #define NOT_GRAALVM(code) code #endif // GRAAL