Mercurial > hg > truffle
changeset 6998:49f0841607b7
Merge.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 20 Nov 2012 22:50:44 +0100 |
parents | b3a647ae5032 (diff) 17fd2de85bf7 (current diff) |
children | 679e6584c177 |
files | src/share/vm/runtime/arguments.cpp |
diffstat | 13 files changed, 464 insertions(+), 108 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Tue Nov 20 22:50:44 2012 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.api.code; +import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.RuntimeCall.Descriptor; import com.oracle.graal.api.meta.*; @@ -93,4 +94,11 @@ * @return the encoded value as an integer */ int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason); + + /** + * Determines if a {@link DataPatch} should be created for a given {@linkplain Constant#getPrimitiveAnnotation() annotated} + * primitive constant that part of a {@link CompilationResult}. A data patch is always + * created for an object constant. + */ + boolean needsDataPatch(Constant constant); }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Tue Nov 20 22:50:44 2012 +0100 @@ -136,10 +136,16 @@ public final Constant constant; public final int alignment; - DataPatch(int pcOffset, Constant data, int alignment) { + /** + * Determines if the data is encoded inline or is loaded from a separate data area. + */ + public final boolean inlined; + + DataPatch(int pcOffset, Constant data, int alignment, boolean inlined) { super(pcOffset); this.constant = data; this.alignment = alignment; + this.inlined = inlined; } @Override @@ -387,10 +393,11 @@ * @param codePos the position in the code where the data reference occurs * @param data the data that is referenced * @param alignment the alignment requirement of the data or 0 if there is no alignment requirement + * @param inlined specifies if the data is encoded inline or is loaded from a separate data area */ - public void recordDataReference(int codePos, Constant data, int alignment) { + public void recordDataReference(int codePos, Constant data, int alignment, boolean inlined) { assert codePos >= 0 && data != null; - getDataReferences().add(new DataPatch(codePos, data, alignment)); + getDataReferences().add(new DataPatch(codePos, data, alignment, inlined)); } /**
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Tue Nov 20 22:50:44 2012 +0100 @@ -38,7 +38,7 @@ } } - public static final Constant NULL_OBJECT = new Constant(Kind.Object, null); + public static final Constant NULL_OBJECT = new Constant(null); public static final Constant INT_MINUS_1 = new Constant(Kind.Int, -1); public static final Constant INT_0 = forInt(0); public static final Constant INT_1 = forInt(1); @@ -63,7 +63,8 @@ } /** - * The boxed object value. This is ignored iff {@code !kind.isObject()}. + * The boxed object value if {@code !kind.isObject()} otherwise the (possibly null) + * {@link #getPrimitiveAnnotation() annotation} for a primitive value. */ private final Object object; @@ -75,32 +76,48 @@ private final long primitive; /** - * Create a new constant represented by the specified object reference. - * - * @param kind the type of this constant + * Creates a constant represented by the specified object reference. * @param object the value of this constant */ - private Constant(Kind kind, Object object) { - super(kind); + private Constant(Object object) { + super(Kind.Object); this.object = object; this.primitive = 0L; } /** - * Create a new constant represented by the specified primitive. - * + * Creates a constant represented by the specified primitive. + * * @param kind the type of this constant * @param primitive the value of this constant */ public Constant(Kind kind, long primitive) { super(kind); + assert !kind.isObject(); this.object = null; this.primitive = primitive; } /** + * Creates an annotated primitive constant. An annotation enables a {@linkplain MetaAccessProvider provider} to + * associate some extra semantic or debugging information with a primitive. An annotated primitive constant + * is never {@linkplain #equals(Object) equal} to a non-annotated constant. + * + * @param kind the type of this constant + * @param primitive the value of this constant + * @param annotation an arbitrary non-null object + */ + public Constant(Kind kind, long primitive, Object annotation) { + super(kind); + assert !kind.isObject(); + assert annotation != null; + this.object = annotation; + this.primitive = primitive; + } + + /** * Checks whether this constant is non-null. - * + * * @return {@code true} if this constant is a primitive, or an object constant that is not null */ public boolean isNonNull() { @@ -109,7 +126,7 @@ /** * Checks whether this constant is null. - * + * * @return {@code true} if this constant is the null constant */ public boolean isNull() { @@ -127,12 +144,16 @@ @Override public String toString() { - return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]"; + String annotationSuffix = ""; + if (!getKind().isObject() && getPrimitiveAnnotation() != null) { + annotationSuffix = "{" + getPrimitiveAnnotation() + "}"; + } + return getKind().getJavaName() + "[" + getKind().format(asBoxedValue()) + (getKind() != Kind.Object ? "|0x" + Long.toHexString(primitive) : "") + "]" + annotationSuffix; } /** * Returns the value of this constant as a boxed Java value. - * + * * @return the value of this constant */ public Object asBoxedValue() { @@ -142,15 +163,15 @@ case Boolean: return asInt() == 0 ? Boolean.FALSE : Boolean.TRUE; case Short: - return (short) asInt(); + return (short) primitive; case Char: - return (char) asInt(); + return (char) primitive; case Jsr: return (int) primitive; case Int: - return asInt(); + return (int) primitive; case Long: - return asLong(); + return primitive; case Float: return asFloat(); case Double: @@ -169,12 +190,12 @@ if (getKind().isObject()) { return object == other.object; } - return primitive == other.primitive; + return primitive == other.primitive && getPrimitiveAnnotation() == other.getPrimitiveAnnotation(); } /** * Converts this constant to a primitive int. - * + * * @return the int value of this constant */ public int asInt() { @@ -186,7 +207,7 @@ /** * Converts this constant to a primitive boolean. - * + * * @return the boolean value of this constant */ public boolean asBoolean() { @@ -198,7 +219,7 @@ /** * Converts this constant to a primitive long. - * + * * @return the long value of this constant */ public long asLong() { @@ -218,7 +239,7 @@ /** * Converts this constant to a primitive float. - * + * * @return the float value of this constant */ public float asFloat() { @@ -230,7 +251,7 @@ /** * Converts this constant to a primitive double. - * + * * @return the double value of this constant */ public double asDouble() { @@ -245,7 +266,7 @@ /** * Converts this constant to the object reference it represents. - * + * * @return the object which this constant represents */ public Object asObject() { @@ -257,7 +278,7 @@ /** * Converts this constant to the jsr reference it represents. - * + * * @return the object which this constant represents */ public int asJsr() { @@ -278,8 +299,17 @@ } /** + * Gets the annotation (if any) associated with this constant. + * + * @return null if this constant is not primitive or has no annotation + */ + public Object getPrimitiveAnnotation() { + return getKind().isObject() ? null : object; + } + + /** * Computes the hashcode of this constant. - * + * * @return a suitable hashcode for this constant */ @Override @@ -291,9 +321,9 @@ } /** - * Checks whether this constant equals another object. This is only true if the other object is a constant and has - * the same value. - * + * Checks whether this constant equals another object. This is only true if the other object is a constant that has + * the same {@linkplain #getKind() kind}, value and {@link #getPrimitiveAnnotation() annotation}. + * * @param o the object to compare equality * @return {@code true} if this constant is equivalent to the specified object */ @@ -304,7 +334,7 @@ /** * Creates a boxed double constant. - * + * * @param d the double value to box * @return a boxed copy of {@code value} */ @@ -320,7 +350,7 @@ /** * Creates a boxed float constant. - * + * * @param f the float value to box * @return a boxed copy of {@code value} */ @@ -339,7 +369,7 @@ /** * Creates a boxed long constant. - * + * * @param i the long value to box * @return a boxed copy of {@code value} */ @@ -349,7 +379,7 @@ /** * Creates a boxed integer constant. - * + * * @param i the integer value to box * @return a boxed copy of {@code value} */ @@ -365,7 +395,7 @@ /** * Creates a boxed byte constant. - * + * * @param i the byte value to box * @return a boxed copy of {@code value} */ @@ -375,7 +405,7 @@ /** * Creates a boxed boolean constant. - * + * * @param i the boolean value to box * @return a boxed copy of {@code value} */ @@ -385,7 +415,7 @@ /** * Creates a boxed char constant. - * + * * @param i the char value to box * @return a boxed copy of {@code value} */ @@ -395,7 +425,7 @@ /** * Creates a boxed short constant. - * + * * @param i the short value to box * @return a boxed copy of {@code value} */ @@ -405,7 +435,7 @@ /** * Creates a boxed address (jsr/ret address) constant. - * + * * @param i the address value to box * @return a boxed copy of {@code value} */ @@ -415,7 +445,7 @@ /** * Creates a boxed object constant. - * + * * @param o the object value to box * @return a boxed copy of {@code value} */ @@ -423,13 +453,13 @@ if (o == null) { return NULL_OBJECT; } - return new Constant(Kind.Object, o); + return new Constant(o); } /** * Creates a boxed constant for the given kind from an Object. The object needs to be of the Java boxed type * corresponding to the kind. - * + * * @param kind the kind of the constant to create * @param value the Java boxed value: a {@link Byte} instance for {@link Kind#Byte}, etc. * @return the boxed copy of {@code value}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Tue Nov 20 22:50:44 2012 +0100 @@ -403,8 +403,7 @@ @Override public Constant klass() { - Kind wordKind = HotSpotGraalRuntime.getInstance().getTarget().wordKind; - return wordKind.isLong() ? Constant.forLong(metaspaceKlass) : Constant.forInt((int) metaspaceKlass); + return new Constant(HotSpotGraalRuntime.getInstance().getTarget().wordKind, metaspaceKlass, this); } public boolean isPrimaryType() { @@ -419,12 +418,4 @@ public long prototypeMarkWord() { return HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrototypeMarkWord(this); } - - public long address() { - return metaspaceKlass; - } - - public String symbol() { - return javaMirror.getName(); - } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Nov 20 22:50:44 2012 +0100 @@ -733,4 +733,8 @@ default: throw GraalInternalError.shouldNotReachHere(); } } + + public boolean needsDataPatch(Constant constant) { + return constant.getPrimitiveAnnotation() instanceof HotSpotResolvedJavaType; + } }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Nov 20 22:50:44 2012 +0100 @@ -79,7 +79,6 @@ private ProfilingInfo profilingInfo; private BytecodeStream stream; // the bytecode stream - private final LogStream log; private FrameStateBuilder frameState; // the current execution state private Block currentBlock; @@ -113,7 +112,6 @@ this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.runtime = runtime; - this.log = GraalOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; assert runtime != null; } @@ -131,7 +129,12 @@ methodSynchronizedObject = null; this.currentGraph = graph; this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving()); - build(); + TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method); + try { + build(); + } finally { + filter.remove(); + } } @Override @@ -148,11 +151,6 @@ } private void build() { - if (log != null) { - log.println(); - log.println("Compiling " + method); - } - if (GraalOptions.PrintProfilingInformation) { TTY.println("Profiling info for " + method); TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), " ")); @@ -1533,14 +1531,14 @@ private void traceState() { if (GraalOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { - log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method)); + TTY.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method)); for (int i = 0; i < frameState.localsSize(); ++i) { ValueNode value = frameState.localAt(i); - log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); + TTY.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); } for (int i = 0; i < frameState.stackSize(); ++i) { ValueNode value = frameState.stackAt(i); - log.println(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); + TTY.println(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); } } } @@ -1774,7 +1772,7 @@ if (!currentBlock.jsrScope.isEmpty()) { sb.append(' ').append(currentBlock.jsrScope); } - log.println(sb.toString()); + TTY.println(sb.toString()); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6823354.java Tue Nov 20 22:50:44 2012 +0100 @@ -0,0 +1,268 @@ +/* + * 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.jtt.hotspot; + +/** + * @test + * @bug 6823354 + * @summary These methods can be instrinsified by using bit scan, bit test, and population count instructions. + * + * @run main/othervm -Xcomp -XX:CompileOnly=Test6823354.lzcomp,Test6823354.tzcomp,.dolzcomp,.dotzcomp Test6823354 + */ + +import java.net.*; + +// Checkstyle: stop +public class Test6823354 { + // Arrays of corner case values. + static final int[] ia = new int[] { 0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE }; + static final long[] la = new long[] { 0L, 1L, -1L, Long.MIN_VALUE, Long.MAX_VALUE }; + + public static void main(String[] args) throws Exception { + // Load the classes and the methods. + Integer.numberOfLeadingZeros(0); + Integer.numberOfTrailingZeros(0); + Long.numberOfLeadingZeros(0); + Long.numberOfTrailingZeros(0); + + lz(); + tz(); + } + + static void lz() throws Exception { + // int + + // Test corner cases. + for (int i = 0; i < ia.length; i++) { + int x = ia[i]; + check(x, lzcomp(x), lzint(x)); + } + + // Test all possible return values. + for (int i = 0; i < Integer.SIZE; i++) { + int x = 1 << i; + check(x, lzcomp(x), lzint(x)); + } + + String classname = Test6823354.class.getName() + "$lzconI"; + + // Test Ideal optimizations (constant values). + for (int i = 0; i < ia.length; i++) { + testclass(classname, ia[i]); + } + + // Test Ideal optimizations (constant values). + for (int i = 0; i < Integer.SIZE; i++) { + int x = 1 << i; + testclass(classname, x); + } + + + // long + + // Test corner cases. + for (int i = 0; i < ia.length; i++) { + long x = la[i]; + check(x, lzcomp(x), lzint(x)); + } + + // Test all possible return values. + for (int i = 0; i < Long.SIZE; i++) { + long x = 1L << i; + check(x, lzcomp(x), lzint(x)); + } + + classname = Test6823354.class.getName() + "$lzconL"; + + // Test Ideal optimizations (constant values). + for (int i = 0; i < la.length; i++) { + testclass(classname, la[i]); + } + + // Test Ideal optimizations (constant values). + for (int i = 0; i < Long.SIZE; i++) { + long x = 1L << i; + testclass(classname, x); + } + } + + static void tz() throws Exception { + // int + + // Test corner cases. + for (int i = 0; i < ia.length; i++) { + int x = ia[i]; + check(x, tzcomp(x), tzint(x)); + } + + // Test all possible return values. + for (int i = 0; i < Integer.SIZE; i++) { + int x = 1 << i; + check(x, tzcomp(x), tzint(x)); + } + + String classname = Test6823354.class.getName() + "$tzconI"; + + // Test Ideal optimizations (constant values). + for (int i = 0; i < ia.length; i++) { + testclass(classname, ia[i]); + } + + // Test Ideal optimizations (constant values). + for (int i = 0; i < Integer.SIZE; i++) { + int x = 1 << i; + testclass(classname, x); + } + + + // long + + // Test corner cases. + for (int i = 0; i < la.length; i++) { + long x = la[i]; + check(x, tzcomp(x), tzint(x)); + } + + // Test all possible return values. + for (int i = 0; i < Long.SIZE; i++) { + long x = 1L << i; + check(x, tzcomp(x), tzint(x)); + } + + classname = Test6823354.class.getName() + "$tzconL"; + + // Test Ideal optimizations (constant values). + for (int i = 0; i < la.length; i++) { + testclass(classname, la[i]); + } + + // Test Ideal optimizations (constant values). + for (int i = 0; i < Long.SIZE; i++) { + long x = 1L << i; + testclass(classname, x); + } + } + + static void check(int value, int result, int expected) { + //System.out.println(value + ": " + result + ", " + expected); + if (result != expected) + throw new InternalError(value + " failed: " + result + " != " + expected); + } + + static void check(long value, long result, long expected) { + //System.out.println(value + ": " + result + ", " + expected); + if (result != expected) + throw new InternalError(value + " failed: " + result + " != " + expected); + } + + static int lzint( int i) { return Integer.numberOfLeadingZeros(i); } + static int lzcomp(int i) { return Integer.numberOfLeadingZeros(i); } + + static int lzint( long l) { return Long.numberOfLeadingZeros(l); } + static int lzcomp(long l) { return Long.numberOfLeadingZeros(l); } + + static int tzint( int i) { return Integer.numberOfTrailingZeros(i); } + static int tzcomp(int i) { return Integer.numberOfTrailingZeros(i); } + + static int tzint( long l) { return Long.numberOfTrailingZeros(l); } + static int tzcomp(long l) { return Long.numberOfTrailingZeros(l); } + + static void testclass(String classname, int x) throws Exception { + System.setProperty("value", "" + x); + loadandrunclass(classname); + } + + static void testclass(String classname, long x) throws Exception { + System.setProperty("value", "" + x); + loadandrunclass(classname); + } + + static void loadandrunclass(String classname) throws Exception { + Class cl = Class.forName(classname); + URLClassLoader apploader = (URLClassLoader) cl.getClassLoader(); + ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent()); + Class c = loader.loadClass(classname); + Runnable r = (Runnable) c.newInstance(); + r.run(); + } + + public static class lzconI implements Runnable { + static final int VALUE; + + static { + int value = 0; + try { + value = Integer.decode(System.getProperty("value")); + } catch (Throwable e) {} + VALUE = value; + } + + public void run() { check(VALUE, lzint(VALUE), dolzcomp()); } + static int dolzcomp() { return lzcomp(VALUE); } + } + + public static class lzconL implements Runnable { + static final long VALUE; + + static { + long value = 0; + try { + value = Long.decode(System.getProperty("value")); + } catch (Throwable e) {} + VALUE = value; + } + + public void run() { check(VALUE, lzint(VALUE), dolzcomp()); } + static int dolzcomp() { return lzcomp(VALUE); } + } + + public static class tzconI implements Runnable { + static final int VALUE; + + static { + int value = 0; + try { + value = Integer.decode(System.getProperty("value")); + } catch (Throwable e) {} + VALUE = value; + } + + public void run() { check(VALUE, tzint(VALUE), dotzcomp()); } + static int dotzcomp() { return tzcomp(VALUE); } + } + + public static class tzconL implements Runnable { + static final long VALUE; + + static { + long value = 0; + try { + value = Long.decode(System.getProperty("value")); + } catch (Throwable e) {} + VALUE = value; + } + + public void run() { check(VALUE, tzint(VALUE), dotzcomp()); } + static int dotzcomp() { return tzcomp(VALUE); } + } +}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Tue Nov 20 22:50:44 2012 +0100 @@ -155,7 +155,12 @@ if (key.getKind() == Kind.Int) { Register intKey = asIntReg(key); for (int i = 0; i < keyConstants.length; i++) { - masm.cmpl(intKey, tasm.asIntConst(keyConstants[i])); + if (tasm.runtime.needsDataPatch(keyConstants[i])) { + tasm.recordDataReferenceInCode(keyConstants[i], 0, true); + } + long lc = keyConstants[i].asLong(); + assert NumUtil.isInt(lc); + masm.cmpl(intKey, (int) lc); masm.jcc(ConditionFlag.equal, keyTargets[i].label()); } } else if (key.getKind() == Kind.Long) {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Tue Nov 20 22:50:44 2012 +0100 @@ -296,12 +296,19 @@ switch (input.getKind().getStackKind()) { case Jsr: case Int: + if (tasm.runtime.needsDataPatch(input)) { + tasm.recordDataReferenceInCode(input, 0, true); + } // Do not optimize with an XOR as this instruction may be between // a CMP and a Jcc in which case the XOR will modify the condition // flags and interfere with the Jcc. - masm.movl(asRegister(result), tasm.asIntConst(input)); + masm.movl(asRegister(result), input.asInt()); + break; case Long: + if (tasm.runtime.needsDataPatch(input)) { + tasm.recordDataReferenceInCode(input, 0, true); + } // Do not optimize with an XOR as this instruction may be between // a CMP and a Jcc in which case the XOR will modify the condition // flags and interfere with the Jcc. @@ -310,6 +317,7 @@ case Float: // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f if (Float.floatToRawIntBits(input.asFloat()) == Float.floatToRawIntBits(0.0f)) { + assert !tasm.runtime.needsDataPatch(input); masm.xorps(asFloatReg(result), asFloatReg(result)); } else { masm.movflt(asFloatReg(result), tasm.asFloatConstRef(input)); @@ -318,6 +326,7 @@ case Double: // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d if (Double.doubleToRawLongBits(input.asDouble()) == Double.doubleToRawLongBits(0.0d)) { + assert !tasm.runtime.needsDataPatch(input); masm.xorpd(asDoubleReg(result), asDoubleReg(result)); } else { masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(input)); @@ -330,10 +339,10 @@ if (input.isNull()) { masm.movq(asRegister(result), 0x0L); } else if (tasm.target.inlineObjects) { - tasm.recordDataReferenceInCode(input, 0); + tasm.recordDataReferenceInCode(input, 0, true); masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); } else { - masm.movq(asRegister(result), tasm.recordDataReferenceInCode(input, 0)); + masm.movq(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false)); } break; default: @@ -342,6 +351,7 @@ } private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Constant input) { + assert !tasm.runtime.needsDataPatch(input); switch (input.getKind().getStackKind()) { case Jsr: case Int: masm.movl(tasm.asAddress(result), input.asInt()); break;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Tue Nov 20 14:03:57 2012 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Tue Nov 20 22:50:44 2012 +0100 @@ -163,11 +163,11 @@ targetMethod.recordSafepoint(pos, debugInfo); } - public Address recordDataReferenceInCode(Constant data, int alignment) { + public Address recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { assert data != null; int pos = asm.codeBuffer.position(); Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString()); - targetMethod.recordDataReference(pos, data, alignment); + targetMethod.recordDataReference(pos, data, alignment, inlined); return Address.Placeholder; } @@ -175,15 +175,16 @@ return lastSafepointPos; } - /** - * Returns the integer value of any constants that can be represented by a 32-bit integer value, + * Returns the integer value of any constant that can be represented by a 32-bit integer value, * including long constants that fit into the 32-bit range. */ public int asIntConst(Value value) { assert (value.getKind().getStackKind() == Kind.Int || value.getKind() == Kind.Jsr || value.getKind() == Kind.Long) && isConstant(value); - long c = ((Constant) value).asLong(); - if (!(NumUtil.isInt(c))) { + Constant constant = (Constant) value; + assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; + long c = constant.asLong(); + if (!NumUtil.isInt(c)) { throw GraalInternalError.shouldNotReachHere(); } return (int) c; @@ -198,7 +199,7 @@ public Address asFloatConstRef(Value value, int alignment) { assert value.getKind() == Kind.Float && isConstant(value); - return recordDataReferenceInCode((Constant) value, alignment); + return recordDataReferenceInCode((Constant) value, alignment, false); } /** @@ -210,7 +211,7 @@ public Address asDoubleConstRef(Value value, int alignment) { assert value.getKind() == Kind.Double && isConstant(value); - return recordDataReferenceInCode((Constant) value, alignment); + return recordDataReferenceInCode((Constant) value, alignment, false); } /** @@ -218,7 +219,7 @@ */ public Address asLongConstRef(Value value) { assert value.getKind() == Kind.Long && isConstant(value); - return recordDataReferenceInCode((Constant) value, 8); + return recordDataReferenceInCode((Constant) value, 8, false); } public Address asIntAddr(Value value) {
--- a/src/share/vm/graal/graalCodeInstaller.cpp Tue Nov 20 14:03:57 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Tue Nov 20 22:50:44 2012 +0100 @@ -102,7 +102,28 @@ return map; } -static ScopeValue* get_hotspot_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects, ScopeValue* &second) { +// Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedJavaType.klass()). +static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) { + char kind = Kind::typeChar(Constant::kind(constant)); + char wordKind = 'j'; + if (kind == wordKind) { + oop obj = Constant::object(constant); + jlong prim = Constant::primitive(constant); + if (obj != NULL) { + if (obj->is_a(HotSpotResolvedJavaType::klass())) { + Klass* klass = (Klass*) (address) HotSpotResolvedJavaType::metaspaceKlass(obj); + assert((Klass*) prim == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim)); + int index = oop_recorder->find_index(klass); + TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string()); + } else { + assert(java_lang_String::is_instance(obj), + err_msg("unexpected annotation type (%s) for constant %ld (%p) of kind %c", obj->klass()->name()->as_C_string(), prim, prim, kind)); + } + } + } +} + +static ScopeValue* get_hotspot_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, OopRecorder* oop_recorder) { second = NULL; if (value == Value::ILLEGAL()) { return new LocationValue(Location::new_stk_loc(Location::invalid, 0)); @@ -157,7 +178,7 @@ } return value; } else if (value->is_a(Constant::klass())){ - oop obj = Constant::object(value); + record_metadata_in_constant(value, oop_recorder); jlong prim = Constant::primitive(value); if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) { return new ConstantIntValue(*(jint*)&prim); @@ -195,7 +216,7 @@ arrayOop values = (arrayOop) VirtualObject::values(value); for (jint i = 0; i < values->length(); i++) { ScopeValue* cur_second = NULL; - ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second); + ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second, oop_recorder); if (isLongArray && cur_second == NULL) { // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations. @@ -222,14 +243,14 @@ return NULL; } -static MonitorValue* get_monitor_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects) { +static MonitorValue* get_monitor_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects, OopRecorder* oop_recorder) { guarantee(value->is_a(code_MonitorValue::klass()), "Monitors must be of type MonitorValue"); ScopeValue* second = NULL; - ScopeValue* owner_value = get_hotspot_value(code_MonitorValue::owner(value), total_frame_size, objects, second); + ScopeValue* owner_value = get_hotspot_value(code_MonitorValue::owner(value), total_frame_size, objects, second, oop_recorder); assert(second == NULL, "monitor cannot occupy two stack slots"); - ScopeValue* lock_data_value = get_hotspot_value(code_MonitorValue::lockData(value), total_frame_size, objects, second); + ScopeValue* lock_data_value = get_hotspot_value(code_MonitorValue::lockData(value), total_frame_size, objects, second, oop_recorder); assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots"); assert(lock_data_value->is_location(), "invalid monitor location"); Location lock_data_loc = ((LocationValue*)lock_data_value)->location(); @@ -482,19 +503,19 @@ oop value = ((oop*) values->base(T_OBJECT))[i]; if (i < local_count) { - ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second); + ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second, _oop_recorder); if (second != NULL) { locals->append(second); } locals->append(first); } else if (i < local_count + expression_count) { - ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second); + ScopeValue* first = get_hotspot_value(value, _total_frame_size, objects, second, _oop_recorder); if (second != NULL) { expressions->append(second); } expressions->append(first); } else { - monitors->append(get_monitor_value(value, _total_frame_size, objects)); + monitors->append(get_monitor_value(value, _total_frame_size, objects, _oop_recorder)); } if (second != NULL) { i++; @@ -601,7 +622,7 @@ jump->set_jump_destination(VmIds::getStub(global_stub)); _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); } - TRACE_graal_3("relocating (stub) at %016x", inst); + TRACE_graal_3("relocating (stub) at %p", inst); } else { // method != NULL assert(hotspot_method != NULL, "unexpected JavaMethod"); assert(debug_info != NULL, "debug info expected"); @@ -659,6 +680,7 @@ void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) { oop constant = CompilationResult_DataPatch::constant(site); int alignment = CompilationResult_DataPatch::alignment(site); + bool inlined = CompilationResult_DataPatch::inlined(site); oop kind = Constant::kind(constant); address instruction = _instructions->start() + pc_offset; @@ -675,24 +697,30 @@ case 'f': case 'j': case 'd': { - address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); - address next_instruction = Assembler::locate_next_instruction(instruction); - int size = _constants->size(); - if (alignment > 0) { - guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); - size = align_size_up(size, alignment); + record_metadata_in_constant(constant, _oop_recorder); + if (inlined) { + address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); + *((jlong*) operand) = Constant::primitive(constant); + } else { + address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); + address next_instruction = Assembler::locate_next_instruction(instruction); + int size = _constants->size(); + if (alignment > 0) { + guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); + size = align_size_up(size, alignment); + } + // we don't care if this is a long/double/etc., the primitive field contains the right bits + address dest = _constants->start() + size; + _constants->set_end(dest + BytesPerLong); + *(jlong*) dest = Constant::primitive(constant); + + long disp = dest - next_instruction; + assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); + *((jint*) operand) = (jint) disp; + + _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); + TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size); } - // we don't care if this is a long/double/etc., the primitive field contains the right bits - address dest = _constants->start() + size; - _constants->set_end(dest + BytesPerLong); - *(jlong*) dest = Constant::primitive(constant); - - long disp = dest - next_instruction; - assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); - *((jint*) operand) = (jint) disp; - - _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); - TRACE_graal_3("relocating (%c) at %016x/%016x with destination at %016x (%d)", typeChar, instruction, operand, dest, size); break; } case 'a': { @@ -702,11 +730,11 @@ jobject value = JNIHandles::make_local(obj()); *((jobject*) operand) = value; _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - TRACE_graal_3("relocating (oop constant) at %016x/%016x", instruction, operand); + TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand); break; } default: - fatal("unexpected Kind in DataPatch"); + fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar)); break; } }
--- a/src/share/vm/graal/graalJavaAccess.hpp Tue Nov 20 14:03:57 2012 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Tue Nov 20 22:50:44 2012 +0100 @@ -127,6 +127,7 @@ start_class(CompilationResult_DataPatch) \ oop_field(CompilationResult_DataPatch, constant, "Lcom/oracle/graal/api/meta/Constant;") \ int_field(CompilationResult_DataPatch, alignment) \ + boolean_field(CompilationResult_DataPatch, inlined) \ end_class \ start_class(CompilationResult_Safepoint) \ oop_field(CompilationResult_Safepoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \
--- a/src/share/vm/runtime/arguments.cpp Tue Nov 20 14:03:57 2012 +0100 +++ b/src/share/vm/runtime/arguments.cpp Tue Nov 20 22:50:44 2012 +0100 @@ -2035,6 +2035,11 @@ "CompressedOops are not supported in Graal at the moment\n"); status = false; } + if (UseCompressedKlassPointers) { + jio_fprintf(defaultStream::error_stream(), + "UseCompressedKlassPointers are not supported in Graal at the moment\n"); + status = false; + } if (UseG1GC) { jio_fprintf(defaultStream::error_stream(), "G1 is not supported in Graal at the moment\n");