# HG changeset patch # User Josef Eisl # Date 1395319821 -3600 # Node ID 17a735726670aadc22de25171512e96d86d6f6f0 # Parent 5ddfdc13027a057c3787f125041ee0378b289e0e# Parent da2431cc150667e0d93fcd8596b3a58c4b7b732c Merge. diff -r 5ddfdc13027a -r 17a735726670 CHANGELOG.md --- a/CHANGELOG.md Wed Mar 19 19:02:29 2014 +0100 +++ b/CHANGELOG.md Thu Mar 20 13:50:21 2014 +0100 @@ -7,7 +7,22 @@ * Made graph caching compilation-local. ### Truffle -* ... +* New API TruffleRuntime#createCallNode to create call nodes and to give the runtime system control over its implementation. +* New API RootNode#getCachedCallNodes to get a weak set of CallNodes that have registered to call the RootNode. +* New API to split the AST of a call-site context sensitively. CallNode#split, CallNode#isSplittable, CallNode#getSplitCallTarget, CallNode#getCurrentCallTarget, RootNode#isSplittable, RootNode#split. +* New API to inline a call-site into the call-graph. CallNode#isInlinable, CallNode#inline, CallNode#isInlined. +* New API for the runtime environment to register CallTargets as caller to the RootNode. CallNode#registerCallTarget. +* Improved API for counting nodes in Truffle ASTS. NodeUtil#countNodes can be used with a NodeFilter filter Nodes. +* New API to declare the cost of a Node for use in runtime environment specific heuristics. See NodeCost, Node#getCost() and NodeInfo#cost(). +* Removed old API for NodeInfo#Kind and NodeInfo#kind(). As a replacement the new Node cost API can be used. +* Changed Node#replace reason parameter type to CharSequence (to allow for lazy string building) +* Deprecated Node#adoptChild and Node#adoptChild, no longer needed in node constructor +* New Node#insert method for inserting new nodes into the tree (formerly adoptChild) +* New Node#adoptChildren() helper method that adopts all (direct and indirect) children of a node +* New API Node#atomic for atomic tree operations +* Made Node#replace thread-safe + + ## Version 0.1 5-Feb-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/b124e22eb772) diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java --- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Thu Mar 20 13:50:21 2014 +0100 @@ -146,7 +146,6 @@ case Short: case Int: case Long: - case NarrowOop: case Object: return true; } diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Thu Mar 20 13:50:21 2014 +0100 @@ -198,8 +198,6 @@ return 8; case Object: return wordSize; - case NarrowOop: - return wordSize / 2; default: return 0; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java Thu Mar 20 13:50:21 2014 +0100 @@ -71,7 +71,7 @@ * CSA * @param registers the registers that can be saved in the CSA */ - public CalleeSaveLayout(Architecture architecture, int frameOffsetToCSA, int size, int slotSize, Register... registers) { + public CalleeSaveLayout(TargetDescription target, int frameOffsetToCSA, int size, int slotSize, Register... registers) { this.frameOffsetToCSA = frameOffsetToCSA; assert slotSize == 0 || CodeUtil.isPowerOf2(slotSize); this.slotSize = slotSize; @@ -88,8 +88,8 @@ if (offset > maxOffset) { maxOffset = offset; } - PlatformKind kind = architecture.getLargestStorableKind(reg.getRegisterCategory()); - offset += architecture.getSizeInBytes(kind); + PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory()); + offset += target.getSizeInBytes(kind); } if (size == -1) { this.size = offset; @@ -106,8 +106,8 @@ int index = offset / slotSize; regNumToIndex[reg.number] = index; indexToReg[index] = reg; - PlatformKind kind = architecture.getLargestStorableKind(reg.getRegisterCategory()); - offset += architecture.getSizeInBytes(kind); + PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory()); + offset += target.getSizeInBytes(kind); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Thu Mar 20 13:50:21 2014 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.api.code; +import com.oracle.graal.api.code.CompilationResult.Data; import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.meta.*; @@ -85,6 +86,11 @@ boolean needsDataPatch(Constant constant); /** + * Create a {@link Data} item for a {@link Constant}, that can be used in a {@link DataPatch}. + */ + Data createDataItem(Constant constant, int alignment); + + /** * Gets a description of the target architecture. */ TargetDescription getTarget(); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Thu Mar 20 13:50:21 2014 +0100 @@ -281,6 +281,17 @@ } } + public static class NumberedRefMapFormatter implements RefMapFormatter { + + public String formatStackSlot(int frameRefMapIndex) { + return "s" + frameRefMapIndex; + } + + public String formatRegister(int regRefMapIndex) { + return "r" + regRefMapIndex; + } + } + /** * Appends a formatted debug info to a {@link StringBuilder}. * @@ -288,7 +299,11 @@ * @param info the debug info to format and append to {@code sb} * @return the value of {@code sb} */ - public static StringBuilder append(StringBuilder sb, DebugInfo info, RefMapFormatter formatter) { + public static StringBuilder append(StringBuilder sb, DebugInfo info, RefMapFormatter formatterArg) { + RefMapFormatter formatter = formatterArg; + if (formatter == null) { + formatter = new NumberedRefMapFormatter(); + } String nl = NEW_LINE; ReferenceMap refMap = info.getReferenceMap(); if (refMap != null && refMap.hasRegisterRefMap()) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Thu Mar 20 13:50:21 2014 +0100 @@ -28,6 +28,7 @@ import java.nio.*; import java.util.*; +import com.oracle.graal.api.code.CodeUtil.*; import com.oracle.graal.api.meta.*; /** @@ -152,66 +153,64 @@ return alignment; } - public abstract int getSize(Architecture arch); + public abstract int getSize(TargetDescription target); - public abstract void emit(Architecture arch, ByteBuffer buffer); + public abstract Kind getKind(); + + public abstract void emit(TargetDescription target, ByteBuffer buffer); } - public static final class ConstantData extends Data { + /** + * Represents a Java primitive value used in a {@link DataPatch}. This implementation uses + * {@link Kind#getByteCount()} bytes to encode each value. + */ + public static final class PrimitiveData extends Data { public final Constant constant; - public ConstantData(Constant constant, int alignment) { + public PrimitiveData(Constant constant, int alignment) { super(alignment); + assert constant.getKind().isPrimitive(); this.constant = constant; } @Override - public int getSize(Architecture arch) { - return arch.getSizeInBytes(constant.getPlatformKind()); + public int getSize(TargetDescription target) { + return constant.getKind().getByteCount(); + } + + @Override + public Kind getKind() { + return constant.getKind(); } @Override - public void emit(Architecture arch, ByteBuffer buffer) { + public void emit(TargetDescription target, ByteBuffer buffer) { switch (constant.getKind()) { case Boolean: - assert getSize(arch) == 1; buffer.put(constant.asBoolean() ? (byte) 1 : (byte) 0); break; case Byte: - assert getSize(arch) == 1; buffer.put((byte) constant.asInt()); break; case Char: - assert getSize(arch) == 2; buffer.putChar((char) constant.asInt()); break; case Short: - assert getSize(arch) == 2; buffer.putShort((short) constant.asInt()); break; case Int: - assert getSize(arch) == 4; buffer.putInt(constant.asInt()); break; case Long: - assert getSize(arch) == 8; buffer.putLong(constant.asLong()); break; case Float: - assert getSize(arch) == 4; buffer.putFloat(constant.asFloat()); break; case Double: - assert getSize(arch) == 8; buffer.putDouble(constant.asDouble()); break; - case Object: - // placeholder for oop value - for (int i = 0; i < getSize(arch); i++) { - buffer.put((byte) 0); - } - break; } } @@ -219,6 +218,24 @@ public String toString() { return constant.toString(); } + + @Override + public int hashCode() { + return constant.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof PrimitiveData) { + PrimitiveData other = (PrimitiveData) obj; + return constant.equals(other.constant); + } else { + return false; + } + } } public static final class RawData extends Data { @@ -231,12 +248,17 @@ } @Override - public int getSize(Architecture arch) { + public int getSize(TargetDescription target) { return data.length; } @Override - public void emit(Architecture arch, ByteBuffer buffer) { + public Kind getKind() { + return Kind.Illegal; + } + + @Override + public void emit(TargetDescription target, ByteBuffer buffer) { buffer.put(data); } @@ -250,6 +272,24 @@ } return ret.toString(); } + + @Override + public int hashCode() { + return Arrays.hashCode(data); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof RawData) { + RawData other = (RawData) obj; + return Arrays.equals(data, other.data); + } else { + return false; + } + } } /** @@ -260,53 +300,18 @@ public static final class DataPatch extends Site { private static final long serialVersionUID = 5771730331604867476L; - public Data externalData; - public Constant inlineData; - - DataPatch(int pcOffset, Data externalData) { - this(pcOffset, externalData, null); - } - - DataPatch(int pcOffset, Constant inlineData) { - this(pcOffset, null, inlineData); - } - - private DataPatch(int pcOffset, Data externalData, Constant inlineData) { - super(pcOffset); - assert (externalData == null) != (inlineData == null) : "data patch can not be both external and inlined"; - this.externalData = externalData; - this.inlineData = inlineData; - } + public Data data; + public boolean inline; - public Constant getConstant() { - if (inlineData != null) { - return inlineData; - } else if (externalData instanceof ConstantData) { - return ((ConstantData) externalData).constant; - } else { - return null; - } - } - - public int getAlignment() { - if (externalData instanceof ConstantData) { - return ((ConstantData) externalData).getAlignment(); - } else { - return 0; - } - } - - public String getDataString() { - if (inlineData != null) { - return inlineData.toString(); - } else { - return externalData.toString(); - } + public DataPatch(int pcOffset, Data data, boolean inline) { + super(pcOffset); + this.data = data; + this.inline = inline; } @Override public String toString() { - return String.format("%d[]", pcOffset, getDataString()); + return String.format("%d[]", pcOffset, inline ? "inline" : "external", data.toString()); } } @@ -538,18 +543,18 @@ */ public void recordDataReference(int codePos, Data data) { assert codePos >= 0 && data != null; - dataReferences.add(new DataPatch(codePos, data)); + dataReferences.add(new DataPatch(codePos, data, false)); } /** * Records a reference to an inlined constant in the code section (e.g. to load a constant oop). * * @param codePos the position in the code where the inlined constant occurs - * @param constant the constant that is referenced + * @param data the data that is referenced */ - public void recordInlineData(int codePos, Constant constant) { - assert codePos >= 0 && constant != null; - dataReferences.add(new DataPatch(codePos, constant)); + public void recordInlineData(int codePos, Data data) { + assert codePos >= 0 && data != null; + dataReferences.add(new DataPatch(codePos, data, true)); } /** @@ -691,14 +696,15 @@ if (info != null) { ReferenceMap refMap = info.getReferenceMap(); if (refMap != null) { + RefMapFormatter formatter = new CodeUtil.NumberedRefMapFormatter(); if (refMap.hasFrameRefMap()) { sb.append(" stackMap["); - refMap.appendFrameMap(sb, null); + refMap.appendFrameMap(sb, formatter); sb.append(']'); } if (refMap.hasRegisterRefMap()) { sb.append(" registerMap["); - refMap.appendRegisterMap(sb, null); + refMap.appendRegisterMap(sb, formatter); sb.append(']'); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Thu Mar 20 13:50:21 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,123 +22,20 @@ */ package com.oracle.graal.api.code; -import java.io.*; -import java.util.*; - import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; - -public class ReferenceMap implements Serializable { - - private static final long serialVersionUID = -1052183095979496819L; - - /** - * Contains 2 bits per register. - *
    - *
  • bit0 = 0: contains no references
  • - *
  • bit0 = 1, bit1 = 0: contains a wide oop
  • - *
  • bit0 = 1, bit1 = 1: contains a narrow oop
  • - *
- */ - private final BitSet registerRefMap; - - /** - * Contains 3 bits per stack slot. - *
    - *
  • bit0 = 0: contains no references
  • - *
  • bit0 = 1, bit1+2 = 0: contains a wide oop
  • - *
  • bit0 = 1, bit1 = 1: contains a narrow oop in the lower half
  • - *
  • bit0 = 1, bit2 = 1: contains a narrow oop in the upper half
  • - *
- */ - private final BitSet frameRefMap; +import com.oracle.graal.api.meta.*; - public ReferenceMap(int registerCount, int frameSlotCount) { - if (registerCount > 0) { - this.registerRefMap = new BitSet(registerCount * 2); - } else { - this.registerRefMap = null; - } - this.frameRefMap = new BitSet(frameSlotCount * 3); - } +public interface ReferenceMap { - public void setRegister(int idx, boolean narrow) { - registerRefMap.set(2 * idx); - if (narrow) { - registerRefMap.set(2 * idx + 1); - } - } + void setRegister(int idx, PlatformKind kind); - public void setStackSlot(int idx, boolean narrow1, boolean narrow2) { - frameRefMap.set(3 * idx); - if (narrow1) { - frameRefMap.set(3 * idx + 1); - } - if (narrow2) { - frameRefMap.set(3 * idx + 2); - } - } - - public boolean hasRegisterRefMap() { - return registerRefMap != null && registerRefMap.size() > 0; - } + void setStackSlot(int offset, PlatformKind kind); - public boolean hasFrameRefMap() { - return frameRefMap != null && frameRefMap.size() > 0; - } - - public interface Iterator { - void register(int idx, boolean narrow); - - void stackSlot(int idx, boolean narrow1, boolean narrow2); - } + boolean hasRegisterRefMap(); - public void iterate(Iterator iterator) { - if (hasRegisterRefMap()) { - for (int i = 0; i < registerRefMap.size() / 2; i++) { - if (registerRefMap.get(2 * i)) { - iterator.register(i, registerRefMap.get(2 * i + 1)); - } - } - } - if (hasFrameRefMap()) { - for (int i = 0; i < frameRefMap.size() / 3; i++) { - if (frameRefMap.get(3 * i)) { - iterator.stackSlot(i, frameRefMap.get(3 * i + 1), frameRefMap.get(3 * i + 2)); - } - } - } - } - - private static class NumberedRefMapFormatter implements RefMapFormatter { + boolean hasFrameRefMap(); - public String formatStackSlot(int frameRefMapIndex) { - return "s" + frameRefMapIndex; - } - - public String formatRegister(int regRefMapIndex) { - return "r" + regRefMapIndex; - } - } - - public void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg) { - RefMapFormatter formatter = formatterArg; - if (formatter == null) { - formatter = new NumberedRefMapFormatter(); - } + void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg); - for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 2)) { - sb.append(' ').append(formatter.formatRegister(reg / 2)); - } - } - - public void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg) { - RefMapFormatter formatter = formatterArg; - if (formatter == null) { - formatter = new NumberedRefMapFormatter(); - } - - for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + 3)) { - sb.append(' ').append(formatter.formatStackSlot(slot / 3)); - } - } + void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Thu Mar 20 13:50:21 2014 +0100 @@ -102,4 +102,10 @@ * @return the register playing the role specified by {@code id} */ Register getRegisterForRole(int id); + + /** + * Determines if all {@link #getAllocatableRegisters() allocatable} registers are + * {@link #getCallerSaveRegisters() caller saved}. + */ + boolean areAllAllocatableRegistersCallerSaved(); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Thu Mar 20 13:50:21 2014 +0100 @@ -28,7 +28,7 @@ * Represents the target machine for a compiler, including the CPU architecture, the size of * pointers and references, alignment of stacks, caches, etc. */ -public class TargetDescription { +public abstract class TargetDescription { public final Architecture arch; @@ -81,4 +81,10 @@ this.implicitNullCheckLimit = implicitNullCheckLimit; this.inlineObjects = inlineObjects; } + + public int getSizeInBytes(PlatformKind kind) { + return arch.getSizeInBytes(kind); + } + + public abstract ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Thu Mar 20 13:50:21 2014 +0100 @@ -77,22 +77,6 @@ } } - /** - * @see ResolvedJavaMethod#getCompiledCodeSize() - */ - @Test - public void getCompiledCodeSizeTest() { - for (Map.Entry e : methods.entrySet()) { - ResolvedJavaMethod m = e.getValue(); - int size = m.getCompiledCodeSize(); - if (isAbstract(m.getModifiers())) { - assertTrue(size == 0); - } else { - assertTrue(size >= 0); - } - } - } - @Test public void getModifiersTest() { for (Map.Entry e : methods.entrySet()) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Thu Mar 20 13:50:21 2014 +0100 @@ -159,7 +159,6 @@ case Double: return asDouble(); case Object: - case NarrowOop: return object; case Illegal: return this; @@ -172,7 +171,7 @@ if (!ignoreKind && getKind() != other.getKind()) { return false; } - if (getKind() == Kind.Object || getKind() == Kind.NarrowOop) { + if (getKind() == Kind.Object) { return object == other.object; } return primitive == other.primitive && getPrimitiveAnnotation() == other.getPrimitiveAnnotation(); @@ -235,12 +234,12 @@ /** * Returns the object reference this constant represents. The constant must have kind - * {@link Kind#Object} or {@link Kind#NarrowOop}. + * {@link Kind#Object}. * * @return the constant value */ public Object asObject() { - assert getKind() == Kind.Object || getKind() == Kind.NarrowOop; + assert getKind() == Kind.Object; return object; } @@ -250,7 +249,7 @@ * @return null if this constant is not primitive or has no annotation */ public Object getPrimitiveAnnotation() { - return getKind() == Kind.Object || getKind() == Kind.NarrowOop ? null : object; + return getKind() == Kind.Object ? null : object; } /** @@ -260,7 +259,7 @@ */ @Override public int hashCode() { - if (getKind() == Kind.Object || getKind() == Kind.NarrowOop) { + if (getKind() == Kind.Object) { return System.identityHashCode(object); } return (int) primitive * getKind().ordinal(); @@ -394,16 +393,6 @@ } /** - * Creates a boxed narrow oop constant. - * - * @param o the object value to box - * @return a boxed copy of {@code value} - */ - public static Constant forNarrowOop(Object o) { - return new Constant(Kind.NarrowOop, o, 0L); - } - - /** * Creates an annotated int or long constant. An annotation enables a client 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. @@ -463,8 +452,6 @@ return forDouble((Double) value); case Object: return forObject(value); - case NarrowOop: - return forNarrowOop(value); default: throw new RuntimeException("cannot create Constant for boxed " + kind + " value"); } @@ -497,8 +484,6 @@ return LONG_0; case Object: return NULL_OBJECT; - case NarrowOop: - return forNarrowOop(null); default: throw new IllegalArgumentException(kind.toString()); } diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DefaultProfilingInfo.java Thu Mar 20 13:50:21 2014 +0100 @@ -99,4 +99,12 @@ public void setMature() { // Do nothing } + + public boolean setCompilerIRSize(Class irType, int nodeCount) { + return false; + } + + public int getCompilerIRSize(Class irType) { + return -1; + } } diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java Thu Mar 20 13:50:21 2014 +0100 @@ -57,9 +57,6 @@ /** The Object kind, also used for arrays. */ Object('a', "Object", false, null, null), - /** The narrow oop kind. */ - NarrowOop('n', "NarrowOop", false, null, null), - /** The void float kind. */ Void('v', "void", false, java.lang.Void.TYPE, java.lang.Void.class), @@ -149,10 +146,10 @@ /** * Checks whether this represent an Object of some sort. * - * @return {@code true} if this is {@link #Object} or {@link #NarrowOop}. + * @return {@code true} if this is {@link #Object}. */ public boolean isObject() { - return this == Kind.Object || this == Kind.NarrowOop; + return this == Kind.Object; } /** diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ObjectLocationIdentity.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ObjectLocationIdentity.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ObjectLocationIdentity.java Thu Mar 20 13:50:21 2014 +0100 @@ -25,7 +25,7 @@ import java.util.*; /** - * A {@link LocationIdentity} warpping an object. + * A {@link LocationIdentity} wrapping an object. */ public final class ObjectLocationIdentity implements LocationIdentity { diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java Thu Mar 20 13:50:21 2014 +0100 @@ -114,6 +114,25 @@ int getDeoptimizationCount(DeoptimizationReason reason); /** + * Records the size of the compiler intermediate representation (IR) associated with this + * method. + * + * @param irType the IR type for which the size is being recorded + * @param irSize the IR size to be recorded. The unit depends on the IR. + * @return whether recording this information for {@code irType} is supported + */ + boolean setCompilerIRSize(Class irType, int irSize); + + /** + * Gets the size of the compiler intermediate representation (IR) associated with this method + * last recorded by {@link #setCompilerIRSize(Class, int)}. + * + * @param irType the IR type for which the size is being requested + * @return the requested IR size or -1 if it is unavailable for {@code irType} + */ + int getCompilerIRSize(Class irType); + + /** * Returns true if the profiling information can be assumed as sufficiently accurate. * * @return true if the profiling information was recorded often enough mature enough, false @@ -124,6 +143,5 @@ /** * Force data to be treated as mature if possible. */ - void setMature(); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Thu Mar 20 13:50:21 2014 +0100 @@ -24,7 +24,6 @@ import java.lang.annotation.*; import java.lang.reflect.*; -import java.util.*; /** * Represents a resolved Java method. Methods, like fields and types, are resolved through @@ -54,13 +53,6 @@ int getCodeSize(); /** - * Returns the size of the compiled machine code of this method. - * - * @return the size of the compiled machine code in bytes, or 0 if no compiled code exists. - */ - int getCompiledCodeSize(); - - /** * Returns the {@link ResolvedJavaType} object representing the class or interface that declares * this method. */ @@ -144,12 +136,6 @@ void reprofile(); /** - * Returns a map that the compiler can use to store objects that should survive the current - * compilation. - */ - Map getCompilerStorage(); - - /** * Returns the constant pool of this method. */ ConstantPool getConstantPool(); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java --- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -27,7 +27,7 @@ import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.ConstantData; +import com.oracle.graal.api.code.CompilationResult.PrimitiveData; import com.oracle.graal.api.code.CompilationResult.RawData; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; @@ -59,7 +59,7 @@ public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig); Register ret = registerConfig.getReturnRegister(Kind.Double); - compResult.recordDataReference(asm.position(), new ConstantData(Constant.forDouble(84.72), 8)); + compResult.recordDataReference(asm.position(), new PrimitiveData(Constant.forDouble(84.72), 8)); asm.movdbl(ret, asm.getPlaceholder()); asm.ret(0); return asm.close(true); diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Thu Mar 20 13:50:21 2014 +0100 @@ -261,7 +261,7 @@ private AMD64Address trigPrologue(Register value) { assert value.getRegisterCategory() == AMD64.XMM; AMD64Address tmp = new AMD64Address(AMD64.rsp); - subq(AMD64.rsp, target.arch.getSizeInBytes(Kind.Double)); + subq(AMD64.rsp, target.getSizeInBytes(Kind.Double)); movdbl(tmp, value); fldd(tmp); return tmp; @@ -271,7 +271,7 @@ assert dest.getRegisterCategory() == AMD64.XMM; fstpd(tmp); movdbl(dest, tmp); - addq(AMD64.rsp, target.arch.getSizeInBytes(Kind.Double)); + addq(AMD64.rsp, target.getSizeInBytes(Kind.Double)); } /** diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java --- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Thu Mar 20 13:50:21 2014 +0100 @@ -264,9 +264,6 @@ case Byte: prefix = "s8"; break; - case NarrowOop: - prefix = "u32"; - break; default: throw GraalInternalError.shouldNotReachHere(); } diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Thu Mar 20 13:50:21 2014 +0100 @@ -360,9 +360,9 @@ } @Override - public void emitNullCheck(ValueNode v, DeoptimizingNode deoping) { - assert v.stamp() instanceof ObjectStamp; - append(new AMD64Move.NullCheckOp(load(operand(v)), state(deoping))); + public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) { + assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt; + append(new AMD64Move.NullCheckOp(load(operand(v)), state(deopt))); } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/AllocSpy.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import static java.lang.Boolean.*; +import static java.lang.Integer.*; +import static java.lang.System.*; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +import com.google.monitoring.runtime.instrumentation.*; + +/** + * Tool for analyzing allocations within a scope using the Java Allocation Instrumenter. + * Allocation records are aggregated per stack trace at an allocation site. The size of the stack + * trace is governed by the value of the "AllocSpy.ContextSize" system property (default is 5). + *

+ * Using this facility requires using -javaagent on the command line. For example: + * + *

+ * mx --vm server unittest -javaagent:lib/java-allocation-instrumenter.jar -dsa -DAllocSpy.ContextSize=6 BC_iadd2
+ * 
+ * + * @see #SampleBytes + * @see #SampleInstances + * @see #HistogramLimit + * @see #NameSize + * @see #BarSize + * @see #NumberSize + */ +final class AllocSpy implements AutoCloseable { + + static ThreadLocal current = new ThreadLocal<>(); + + private static final boolean ENABLED; + static { + boolean enabled = false; + try { + Field field = AllocationRecorder.class.getDeclaredField("instrumentation"); + field.setAccessible(true); + enabled = field.get(null) != null; + } catch (Exception e) { + } + ENABLED = enabled; + if (ENABLED) { + AllocationRecorder.addSampler(new GraalContextSampler()); + } + } + + static String prop(String sfx) { + return AllocSpy.class.getSimpleName() + "." + sfx; + } + + /** + * Determines if bytes per allocation site are recorded. + */ + private static final boolean SampleBytes = parseBoolean(getProperty(prop("SampleBytes"), "true")); + + /** + * Determines if allocations per allocation site are recorded. + */ + private static final boolean SampleInstances = parseBoolean(getProperty(prop("SampleInstances"), "true")); + + /** + * The size of context to record for each allocation site in terms of Graal frames. + */ + private static final int ContextSize = getInteger(prop("ContextSize"), 5); + + /** + * Only the {@code HistogramLimit} most frequent values are printed. + */ + private static final int HistogramLimit = getInteger(prop("HistogramLimit"), 40); + + /** + * The width of the allocation context column. + */ + private static final int NameSize = getInteger(prop("NameSize"), 50); + + /** + * The width of the histogram bar column. + */ + private static final int BarSize = getInteger(prop("BarSize"), 100); + + /** + * The width of the frequency column. + */ + private static final int NumberSize = getInteger(prop("NumberSize"), 10); + + final Object name; + final AllocSpy parent; + final Map bytesPerGraalContext = new HashMap<>(); + final Map instancesPerGraalContext = new HashMap<>(); + + public static AllocSpy open(Object name) { + if (ENABLED) { + return new AllocSpy(name); + } + return null; + } + + private AllocSpy(Object name) { + this.name = name; + parent = current.get(); + current.set(this); + } + + public void close() { + current.set(parent); + PrintStream ps = System.out; + ps.println("\n\nAllocation histograms for " + name); + if (SampleBytes) { + print(ps, bytesPerGraalContext, "BytesPerGraalContext", HistogramLimit, NameSize + 60, BarSize); + } + if (SampleInstances) { + print(ps, instancesPerGraalContext, "InstancesPerGraalContext", HistogramLimit, NameSize + 60, BarSize); + } + } + + private static void printLine(PrintStream printStream, char c, int lineSize) { + char[] charArr = new char[lineSize]; + Arrays.fill(charArr, c); + printStream.printf("%s%n", new String(charArr)); + } + + private static void print(PrintStream ps, Map map, String name, int limit, int nameSize, int barSize) { + if (map.isEmpty()) { + return; + } + + List list = new ArrayList<>(map.values()); + Collections.sort(list); + + // Sum up the total number of elements. + int total = 0; + for (CountedValue cv : list) { + total += cv.getCount(); + } + + // Print header. + ps.printf("%s has %d unique elements and %d total elements:%n", name, list.size(), total); + + int max = list.get(0).getCount(); + final int lineSize = nameSize + NumberSize + barSize + 10; + printLine(ps, '-', lineSize); + String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n"; + for (int i = 0; i < list.size() && i < limit; ++i) { + CountedValue cv = list.get(i); + int value = cv.getCount(); + char[] bar = new char[(int) (((double) value / (double) max) * barSize)]; + Arrays.fill(bar, '='); + String[] lines = String.valueOf(cv.getValue()).split("\\n"); + + String objectString = lines[0]; + if (objectString.length() > nameSize) { + objectString = objectString.substring(0, nameSize - 3) + "..."; + } + ps.printf(formatString, objectString, value, new String(bar)); + for (int j = 1; j < lines.length; j++) { + String line = lines[j]; + if (line.length() > nameSize) { + line = line.substring(0, nameSize - 3) + "..."; + } + ps.printf("| %-" + (nameSize - 2) + "s | %-" + NumberSize + "s | %-" + barSize + "s |%n", line, " ", " "); + + } + } + printLine(ps, '-', lineSize); + } + + CountedValue bytesPerGraalContext(String context) { + return getCounter(context, bytesPerGraalContext); + } + + CountedValue instancesPerGraalContext(String context) { + return getCounter(context, instancesPerGraalContext); + } + + protected static CountedValue getCounter(String desc, Map map) { + CountedValue count = map.get(desc); + if (count == null) { + count = new CountedValue(0, desc); + map.put(desc, count); + } + return count; + } + + private static final String[] Excluded = {AllocSpy.class.getName(), AllocationRecorder.class.getName()}; + + private static boolean excludeFrame(String className) { + for (String e : Excluded) { + if (className.startsWith(e)) { + return true; + } + } + return false; + } + + static class GraalContextSampler implements Sampler { + + public void sampleAllocation(int count, String desc, Object newObj, long size) { + AllocSpy scope = current.get(); + if (scope != null) { + StringBuilder sb = new StringBuilder(200); + Throwable t = new Throwable(); + int remainingGraalFrames = ContextSize; + for (StackTraceElement e : t.getStackTrace()) { + if (remainingGraalFrames < 0) { + break; + } + String className = e.getClassName(); + boolean isGraalFrame = className.contains(".graal."); + if (sb.length() != 0) { + append(sb.append('\n'), e); + } else { + if (!excludeFrame(className)) { + sb.append("type=").append(desc); + if (count != 1) { + sb.append("[]"); + } + append(sb.append('\n'), e); + } + } + if (isGraalFrame) { + remainingGraalFrames--; + } + } + String context = sb.toString(); + if (SampleBytes) { + scope.bytesPerGraalContext(context).add((int) size); + } + if (SampleInstances) { + scope.instancesPerGraalContext(context).inc(); + } + } + } + + protected StringBuilder append(StringBuilder sb, StackTraceElement e) { + String className = e.getClassName(); + int period = className.lastIndexOf('.'); + if (period != -1) { + sb.append(className, period + 1, className.length()); + } else { + sb.append(className); + } + sb.append('.').append(e.getMethodName()); + if (e.isNativeMethod()) { + sb.append("(Native Method)"); + } else if (e.getFileName() != null && e.getLineNumber() >= 0) { + sb.append('(').append(e.getFileName()).append(':').append(e.getLineNumber()).append(")"); + } else { + sb.append("(Unknown Source)"); + } + return sb; + } + } + + /** + * A value and a frequency. The ordering imposed by {@link #compareTo(CountedValue)} places + * values with higher frequencies first. + */ + static class CountedValue implements Comparable { + + private int count; + private final Object value; + + public CountedValue(int count, Object value) { + this.count = count; + this.value = value; + } + + public int compareTo(CountedValue o) { + if (count < o.count) { + return 1; + } else if (count > o.count) { + return -1; + } + return 0; + } + + @Override + public String toString() { + return count + " -> " + value; + } + + public void inc() { + count++; + } + + public void add(int n) { + count += n; + } + + public int getCount() { + return count; + } + + public Object getValue() { + return value; + } + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Thu Mar 20 13:50:21 2014 +0100 @@ -120,6 +120,9 @@ errors.add(e.getMessage()); } catch (LinkageError e) { // suppress linkages errors resulting from eager resolution + } catch (BailoutException e) { + // Graal bail outs on certain patterns in Java bytecode (e.g., + // unbalanced monitors introduced by jacoco). } catch (Throwable e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -130,7 +130,7 @@ @Before public void beforeTest() { assert debugScope == null; - debugScope = Debug.scope(getClass().getSimpleName()); + debugScope = Debug.scope(getClass()); } @After @@ -498,7 +498,7 @@ } private CompilationResult compileBaseline(ResolvedJavaMethod javaMethod) { - try (Scope bds = Debug.scope("compileBaseline", javaMethod, providers.getCodeCache())) { + try (Scope bds = Debug.scope("CompileBaseline", javaMethod, providers.getCodeCache())) { BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess()); return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default); } catch (Throwable e) { @@ -629,7 +629,7 @@ final int id = compilationId.incrementAndGet(); InstalledCode installedCode = null; - try (Scope ds = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) { + try (AllocSpy spy = AllocSpy.open(method); Scope ds = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) { final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s ...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature())); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Thu Mar 20 13:50:21 2014 +0100 @@ -149,7 +149,7 @@ protected void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) { ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(snippet)); graph = new StructuredGraph(method); - try (Scope s = Debug.scope(getClass().getSimpleName(), graph, method, getCodeCache())) { + try (Scope s = Debug.scope(getClass(), graph, method, getCodeCache())) { new GraphBuilderPhase.Instance(getMetaAccess(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); Assumptions assumptions = new Assumptions(false); context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test.ea; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +/** + * Tests {@link AbstractNewObjectNode#simplify(com.oracle.graal.graph.spi.SimplifierTool)}. + * + */ +public class PoorMansEATest extends GraalCompilerTest { + public static class A { + public A obj; + } + + public static A test1Snippet() { + A a = new A(); + a.obj = a; + return null; + } + + @Test + public void test1() { + test("test1Snippet"); + } + + private void test(final String snippet) { + try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { + StructuredGraph graph = parse(snippet); + Assumptions assumptions = new Assumptions(false); + HighTierContext highTierContext = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); + PhaseContext context = new PhaseContext(getProviders(), assumptions); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + + // remove framestates in order to trigger the simplification. + cleanup: for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) { + for (Node input : fs.inputs()) { + if (input instanceof NewInstanceNode) { + fs.replaceAtUsages(null); + fs.safeDelete(); + continue cleanup; + } + } + } + new CanonicalizerPhase(true).apply(graph, context); + } catch (Throwable e) { + throw Debug.handle(e); + } + } +} diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Mar 20 13:50:21 2014 +0100 @@ -198,14 +198,9 @@ suites.getLowTier().apply(graph, lowTierContext); graph.maybeCompress(); - // we do not want to store statistics about OSR compilations because it may prevent inlining - if (!graph.isOSR()) { - InliningPhase.storeStatisticsAfterLowTier(graph); - } - SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph); - Debug.dump(schedule, "final schedule"); + Debug.dump(schedule, "Final HIR schedule"); return schedule; } @@ -298,18 +293,14 @@ if (Debug.isMeterEnabled()) { List ldp = compilationResult.getDataReferences(); - DebugMetric[] dms = new DebugMetric[Kind.values().length]; + Kind[] kindValues = Kind.values(); + DebugMetric[] dms = new DebugMetric[kindValues.length]; for (int i = 0; i < dms.length; i++) { - dms[i] = Debug.metric("DataPatches-" + Kind.values()[i].toString()); + dms[i] = Debug.metric("DataPatches-%s", kindValues[i]); } - DebugMetric dmRaw = Debug.metric("DataPatches-raw"); for (DataPatch dp : ldp) { - if (dp.getConstant() != null) { - dms[dp.getConstant().getKind().ordinal()].add(1); - } else { - dmRaw.add(1); - } + dms[dp.data.getKind().ordinal()].add(1); } Debug.metric("CompilationResults").increment(); diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Thu Mar 20 13:50:21 2014 +0100 @@ -70,11 +70,8 @@ super(allocator, unhandledFixedFirst, unhandledAnyFirst); // If all allocatable registers are caller saved, then no registers are live across a call - // site. - // The register allocator can save time not trying to find a register at a call site. - HashSet registers = new HashSet<>(Arrays.asList(allocator.frameMap.registerConfig.getAllocatableRegisters())); - registers.removeAll(Arrays.asList(allocator.frameMap.registerConfig.getCallerSaveRegisters())); - allocator.callKillsRegisters = registers.size() == 0; + // site. The register allocator can save time not trying to find a register at a call site. + allocator.callKillsRegisters = allocator.frameMap.registerConfig.areAllAllocatableRegistersCallerSaved(); moveResolver = new MoveResolver(allocator); spillIntervals = Util.uncheckedCast(new List[allocator.registers.length]); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Thu Mar 20 13:50:21 2014 +0100 @@ -25,15 +25,12 @@ import static com.oracle.graal.compiler.phases.HighTier.Options.*; import static com.oracle.graal.phases.GraalOptions.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.phases.verify.*; import com.oracle.graal.virtual.phases.ea.*; public class HighTier extends PhaseSuite { @@ -41,8 +38,6 @@ public static class Options { // @formatter:off - @Option(help = "") - public static final OptionValue VerifyUsageWithEquals = new OptionValue<>(true); @Option(help = "Enable inlining") public static final OptionValue Inline = new OptionValue<>(true); // @formatter:on @@ -51,11 +46,6 @@ public HighTier() { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue()); - if (VerifyUsageWithEquals.getValue()) { - appendPhase(new VerifyUsageWithEquals(Value.class)); - appendPhase(new VerifyUsageWithEquals(Register.class)); - } - if (OptCanonicalizer.getValue()) { appendPhase(canonicalizer); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Thu Mar 20 13:50:21 2014 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.debug; import static com.oracle.graal.debug.Debug.Initialization.*; +import static java.util.FormattableFlags.*; import java.io.*; import java.util.*; @@ -129,7 +130,7 @@ /** * Gets a string composed of the names in the current nesting of debug - * {@linkplain #scope(String, Object...) scopes} separated by {@code '.'}. + * {@linkplain #scope(Object) scopes} separated by {@code '.'}. */ public static String currentScope() { if (ENABLED) { @@ -140,7 +141,7 @@ } /** - * Represents a debug scope entered by {@link Debug#scope(String, Object...)} or + * Represents a debug scope entered by {@link Debug#scope(Object)} or * {@link Debug#sandbox(String, DebugConfig, Object...)}. Leaving the scope is achieved via * {@link #close()}. */ @@ -162,14 +163,67 @@ * } * * + * The {@code name} argument is subject to the following type based conversion before having + * {@link Object#toString()} called on it: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * * @param name the name of the new scope - * @param context objects to be appended to the {@linkplain #context() current} debug context * @return the scope entered by this method which will be exited when its {@link Scope#close()} * method is called */ - public static Scope scope(String name, Object... context) { + public static Scope scope(Object name) { + if (ENABLED) { + return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null); + } else { + return null; + } + } + + /** + * @see #scope(Object) + * @param context an object to be appended to the {@linkplain #context() current} debug context + */ + public static Scope scope(Object name, Object context) { if (ENABLED) { - return DebugScope.getInstance().scope(name, null, context); + return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context); + } else { + return null; + } + } + + /** + * @see #scope(Object) + * @param context1 first object to be appended to the {@linkplain #context() current} debug + * context + * @param context2 second object to be appended to the {@linkplain #context() current} debug + * context + */ + public static Scope scope(Object name, Object context1, Object context2) { + if (ENABLED) { + return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2); + } else { + return null; + } + } + + /** + * @see #scope(Object) + * @param context1 first object to be appended to the {@linkplain #context() current} debug + * context + * @param context2 second object to be appended to the {@linkplain #context() current} debug + * context + * @param context3 third object to be appended to the {@linkplain #context() current} debug + * context + */ + public static Scope scope(Object name, Object context1, Object context2, Object context3) { + if (ENABLED) { + return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2, context3); } else { return null; } @@ -195,7 +249,7 @@ * @return the scope entered by this method which will be exited when its {@link Scope#close()} * method is called */ - public static Scope sandbox(String name, DebugConfig config, Object... context) { + public static Scope sandbox(CharSequence name, DebugConfig config, Object... context) { if (ENABLED) { DebugConfig sandboxConfig = config == null ? silentConfig() : config; return DebugScope.getInstance().scope(name, sandboxConfig, context); @@ -221,10 +275,10 @@ /** * Handles an exception in the context of the debug scope just exited. The just exited scope * must have the current scope as its parent which will be the case if the try-with-resource - * pattern recommended by {@link #scope(String, Object...)} and + * pattern recommended by {@link #scope(Object)} and * {@link #sandbox(String, DebugConfig, Object...)} is used * - * @see #scope(String, Object...) + * @see #scope(Object) * @see #sandbox(String, DebugConfig, Object...) */ public static RuntimeException handle(Throwable exception) { @@ -242,20 +296,79 @@ } /** - * Prints an indented message to the current debug scopes's logging stream if logging is enabled - * in the scope. + * Prints a message to the current debug scope's logging stream if logging is enabled. + * + * @param msg the message to log + */ + public static void log(String msg) { + if (ENABLED) { + DebugScope.getInstance().log(msg); + } + } + + /** + * Prints a message to the current debug scope's logging stream if logging is enabled. * - * @param msg The format string of the log message - * @param args The arguments referenced by the log message string - * @see Indent#log + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + */ + public static void log(String format, Object arg) { + if (ENABLED) { + DebugScope.getInstance().log(format, arg); + } + } + + /** + * @see #log(String, Object) + */ + public static void log(String format, Object arg1, Object arg2) { + if (ENABLED) { + DebugScope.getInstance().log(format, arg1, arg2); + } + } + + /** + * @see #log(String, Object) */ - public static void log(String msg, Object... args) { + public static void log(String format, Object arg1, Object arg2, Object arg3) { + if (ENABLED) { + DebugScope.getInstance().log(format, arg1, arg2, arg3); + } + } + + /** + * @see #log(String, Object) + */ + public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) { if (ENABLED) { - DebugScope.getInstance().log(msg, args); + DebugScope.getInstance().log(format, arg1, arg2, arg3, arg4); + } + } + + /** + * @see #log(String, Object) + */ + public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + if (ENABLED) { + DebugScope.getInstance().log(format, arg1, arg2, arg3, arg4, arg5); } } /** + * Prints a message to the current debug scope's logging stream. This method must only be called + * if debugging is {@linkplain Debug#isEnabled() enabled}. + * + * @param format a format string + * @param args the arguments referenced by the format specifiers in {@code format} + */ + public static void logv(String format, Object... args) { + if (!ENABLED) { + throw new InternalError("Use of Debug.logv() must be guarded by a test of Debug.isEnabled()"); + } + DebugScope.getInstance().log(format, args); + } + + /** * The same as {@link #log}, but without line termination and without indentation. */ public static void printf(String msg, Object... args) { @@ -379,14 +492,87 @@ *

* A disabled metric has virtually no overhead. */ - public static DebugMetric metric(String name) { - if (Boolean.getBoolean(ENABLE_METRIC_PROPERTY_NAME_PREFIX + name)) { - return new MetricImpl(name, false); - } else if (ENABLED) { - return new MetricImpl(name, true); - } else { + public static DebugMetric metric(CharSequence name) { + if (enabledMetrics == null && !ENABLED) { return VOID_METRIC; } + return createMetric("%s", name, null); + } + + public static String applyFormattingFlagsAndWidth(String s, int flags, int width) { + if (flags == 0 && width < 0) { + return s; + } + StringBuilder sb = new StringBuilder(s); + + // apply width and justification + int len = sb.length(); + if (len < width) { + for (int i = 0; i < width - len; i++) { + if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) { + sb.append(' '); + } else { + sb.insert(0, ' '); + } + } + } + + String res = sb.toString(); + if ((flags & UPPERCASE) == UPPERCASE) { + res = res.toUpperCase(); + } + return res; + } + + /** + * Creates a debug metric. Invoking this method is equivalent to: + * + *

+     * Debug.metric(format, arg, null)
+     * 
+ * + * except that the string formatting only happens if metering is enabled. + * + * @see #metric(String, Object, Object) + */ + public static DebugMetric metric(String format, Object arg) { + if (enabledMetrics == null && !ENABLED) { + return VOID_METRIC; + } + return createMetric(format, arg, null); + } + + /** + * Creates a debug metric. Invoking this method is equivalent to: + * + *
+     * Debug.metric(String.format(format, arg1, arg2))
+     * 
+ * + * except that the string formatting only happens if metering is enabled. In addition, each + * argument is subject to the following type based conversion before being passed as an argument + * to {@link String#format(String, Object...)}: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * + * @see #metric(CharSequence) + */ + public static DebugMetric metric(String format, Object arg1, Object arg2) { + if (enabledMetrics == null && !ENABLED) { + return VOID_METRIC; + } + return createMetric(format, arg1, arg2); + } + + private static DebugMetric createMetric(String format, Object arg1, Object arg2) { + String name = formatDebugName(format, arg1, arg2); + boolean conditional = enabledMetrics != null && enabledMetrics.contains(name); + return new MetricImpl(name, conditional); } /** @@ -495,15 +681,33 @@ }; /** - * @see #timer(String) + * @see #timer(CharSequence) */ public static final String ENABLE_TIMER_PROPERTY_NAME_PREFIX = "graal.debug.timer."; /** - * @see #metric(String) + * @see #metric(CharSequence) */ public static final String ENABLE_METRIC_PROPERTY_NAME_PREFIX = "graal.debug.metric."; + private static final Set enabledMetrics; + private static final Set enabledTimers; + static { + Set metrics = new HashSet<>(); + Set timers = new HashSet<>(); + for (Map.Entry e : System.getProperties().entrySet()) { + String name = e.getKey().toString(); + if (name.startsWith(ENABLE_METRIC_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) { + metrics.add(name.substring(ENABLE_METRIC_PROPERTY_NAME_PREFIX.length())); + } + if (name.startsWith(ENABLE_TIMER_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) { + timers.add(name.substring(ENABLE_TIMER_PROPERTY_NAME_PREFIX.length())); + } + } + enabledMetrics = metrics.isEmpty() ? null : metrics; + enabledTimers = timers.isEmpty() ? null : timers; + } + /** * Creates a {@linkplain DebugTimer timer} that is enabled iff debugging is * {@linkplain #isEnabled() enabled} or the system property whose name is formed by adding to @@ -514,14 +718,73 @@ *

* A disabled timer has virtually no overhead. */ - public static DebugTimer timer(String name) { - if (Boolean.getBoolean(ENABLE_TIMER_PROPERTY_NAME_PREFIX + name)) { - return new TimerImpl(name, false); - } else if (ENABLED) { - return new TimerImpl(name, true); - } else { + public static DebugTimer timer(CharSequence name) { + if (enabledTimers == null && !ENABLED) { + return VOID_TIMER; + } + return createTimer("%s", name, null); + } + + /** + * Creates a debug timer. Invoking this method is equivalent to: + * + *

+     * Debug.timer(format, arg, null)
+     * 
+ * + * except that the string formatting only happens if timing is enabled. + * + * @see #timer(String, Object, Object) + */ + public static DebugTimer timer(String format, Object arg) { + if (enabledTimers == null && !ENABLED) { return VOID_TIMER; } + return createTimer(format, arg, null); + } + + /** + * Creates a debug timer. Invoking this method is equivalent to: + * + *
+     * Debug.timer(String.format(format, arg1, arg2))
+     * 
+ * + * except that the string formatting only happens if timing is enabled. In addition, each + * argument is subject to the following type based conversion before being passed as an argument + * to {@link String#format(String, Object...)}: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * + * @see #timer(CharSequence) + */ + public static DebugTimer timer(String format, Object arg1, Object arg2) { + if (enabledTimers == null && !ENABLED) { + return VOID_TIMER; + } + return createTimer(format, arg1, arg2); + } + + public static Object convertFormatArg(Object arg) { + if (arg instanceof Class) { + return ((Class) arg).getSimpleName(); + } + return arg; + } + + private static String formatDebugName(String format, Object arg1, Object arg2) { + return String.format(format, convertFormatArg(arg1), convertFormatArg(arg2)); + } + + private static DebugTimer createTimer(String format, Object arg1, Object arg2) { + String name = formatDebugName(format, arg1, arg2); + boolean conditional = enabledTimers != null && enabledTimers.contains(name); + return new TimerImpl(name, conditional); } private static final DebugTimer VOID_TIMER = new DebugTimer() { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Thu Mar 20 13:50:21 2014 +0100 @@ -28,10 +28,7 @@ public interface DebugConfig { /** - * Determines if logging is enabled in the {@linkplain Debug#currentScope() current debug scope} - * . - * - * @see Debug#log(String, Object...) + * Determines if logging is on in the {@linkplain Debug#currentScope() current debug scope} . */ boolean isLogEnabled(); @@ -45,7 +42,7 @@ * Determines if metering is enabled in the {@linkplain Debug#currentScope() current debug * scope}. * - * @see Debug#metric(String) + * @see Debug#metric(CharSequence) */ boolean isMeterEnabled(); @@ -76,7 +73,7 @@ void removeFromContext(Object o); /** - * @see Debug#timer(String) + * @see Debug#timer(CharSequence) */ boolean isTimeEnabled(); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java Thu Mar 20 13:50:21 2014 +0100 @@ -72,6 +72,10 @@ count++; } + public void add(int n) { + count += n; + } + public int getCount() { return count; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Thu Mar 20 13:50:21 2014 +0100 @@ -231,13 +231,13 @@ * @param newContextObjects objects to be appended to the debug context * @return the new scope which will be exited when its {@link #close()} method is called */ - public DebugScope scope(String name, DebugConfig sandboxConfig, Object... newContextObjects) { + public DebugScope scope(CharSequence name, DebugConfig sandboxConfig, Object... newContextObjects) { DebugScope newScope = null; if (sandboxConfig != null) { - newScope = new DebugScope(name, name, this, true, newContextObjects); + newScope = new DebugScope(name.toString(), name.toString(), this, true, newContextObjects); configTL.set(sandboxConfig); } else { - newScope = this.createChild(name, newContextObjects); + newScope = this.createChild(name.toString(), newContextObjects); } instanceTL.set(newScope); newScope.updateFlags(); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Mar 20 13:50:21 2014 +0100 @@ -458,6 +458,7 @@ * newInput: removes this node from oldInput's usages and adds this node to newInput's usages. */ protected void updateUsages(Node oldInput, Node newInput) { + assert isAlive() && (newInput == null || newInput.isAlive()) : "adding " + newInput + " to " + this + " instead of " + oldInput; if (oldInput != newInput) { if (oldInput != null) { if (oldInput.recordsUsages()) { @@ -482,6 +483,7 @@ * this node to newSuccessor's predecessors. */ protected void updatePredecessor(Node oldSuccessor, Node newSuccessor) { + assert isAlive() && (newSuccessor == null || newSuccessor.isAlive()) : "adding " + newSuccessor + " to " + this + " instead of " + oldSuccessor; assert graph == null || !graph.isFrozen(); if (oldSuccessor != newSuccessor) { if (oldSuccessor != null) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Thu Mar 20 13:50:21 2014 +0100 @@ -234,7 +234,7 @@ } isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0); - nodeIterableCount = Debug.metric("NodeIterable_" + shortName); + nodeIterableCount = Debug.metric("NodeIterable_%s", shortName); } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Thu Mar 20 13:50:21 2014 +0100 @@ -41,8 +41,8 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.nfi.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; @@ -254,7 +254,7 @@ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedEntry) { HotSpotProviders providers = getProviders(); if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) { - crb.recordMark(Marks.MARK_UNVERIFIED_ENTRY); + MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY); CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false); Register inlineCacheKlass = rax; // see definition of IC_Klass in // c1_LIRAssembler_x86.cpp @@ -276,9 +276,9 @@ } asm.align(config.codeEntryAlignment); - crb.recordMark(Marks.MARK_OSR_ENTRY); + MarkId.recordMark(crb, MarkId.OSR_ENTRY); asm.bind(verifiedEntry); - crb.recordMark(Marks.MARK_VERIFIED_ENTRY); + MarkId.recordMark(crb, MarkId.VERIFIED_ENTRY); } /** @@ -298,9 +298,9 @@ HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; if (!frameContext.isStub) { HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls(); - crb.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY); + MarkId.recordMark(crb, MarkId.EXCEPTION_HANDLER_ENTRY); AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null); - crb.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY); + MarkId.recordMark(crb, MarkId.DEOPT_HANDLER_ENTRY); AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_HANDLER), null, false, null); } else { // No need to emit the stubs for entries back into the method since diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Thu Mar 20 13:50:21 2014 +0100 @@ -89,7 +89,7 @@ final int stackFrameAlignment = 16; final int implicitNullCheckLimit = 4096; final boolean inlineObjects = true; - return new TargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + return new HotSpotTargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int); } @Override diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Mar 20 13:50:21 2014 +0100 @@ -488,8 +488,6 @@ protected static Constant compress(Constant c, CompressEncoding encoding) { if (c.getKind() == Kind.Long) { return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation()); - } else if (c.getKind() == Kind.Object) { - return Constant.forNarrowOop(c.asObject()); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -538,8 +536,7 @@ if (canStoreConstant(c, isCompressed)) { if (isCompressed) { if (c.getKind() == Kind.Object) { - Constant value = c.isNull() ? c : compress(c, config.getOopEncoding()); - append(new StoreCompressedConstantOp(kind, storeAddress, value, state)); + append(new StoreCompressedConstantOp(kind, storeAddress, c, state)); } else if (c.getKind() == Kind.Long) { // It's always a good idea to directly store compressed constants since they // have to be materialized as 64 bits encoded otherwise. diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Thu Mar 20 13:50:21 2014 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; +import com.oracle.graal.hotspot.data.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; @@ -51,6 +52,9 @@ public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { if (kind == Kind.Long) { if (NumUtil.isInt(input.asLong())) { + if (input.getPrimitiveAnnotation() != null) { + crb.recordInlineDataInCode(new MetaspaceData(0, input.asLong(), input.getPrimitiveAnnotation(), true)); + } masm.movl(address.toAddress(), (int) input.asLong()); } else { throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); @@ -59,7 +63,7 @@ if (input.isNull()) { masm.movl(address.toAddress(), 0); } else if (crb.target.inlineObjects) { - crb.recordInlineDataInCode(input); + crb.recordInlineDataInCode(new OopData(0, input.asObject(), true)); masm.movl(address.toAddress(), 0xDEADDEAD); } else { throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Thu Mar 20 13:50:21 2014 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.nodes.type.*; public class AMD64HotSpotRegisterConfig implements RegisterConfig { @@ -47,6 +48,8 @@ */ private final Register[] callerSaved; + private final boolean allAllocatableAreCallerSaved; + private final HashMap categorized = new HashMap<>(); private final RegisterAttributes[] attributesMap; @@ -61,9 +64,16 @@ return categorized.get(kind); } + PlatformKind primitiveKind; + if (kind == NarrowOopStamp.NarrowOop) { + primitiveKind = Kind.Int; + } else { + primitiveKind = kind; + } + ArrayList list = new ArrayList<>(); for (Register reg : getAllocatableRegisters()) { - if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { + if (architecture.canStoreValue(reg.getRegisterCategory(), primitiveKind)) { list.add(reg); } } @@ -144,6 +154,7 @@ callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]); assert callerSaved.length == allocatable.length || RegisterPressure.getValue() != null; + allAllocatableAreCallerSaved = true; attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters); } @@ -153,6 +164,11 @@ } @Override + public boolean areAllAllocatableRegistersCallerSaved() { + return allAllocatableAreCallerSaved; + } + + @Override public Register getRegisterForRole(int index) { throw new UnsupportedOperationException(); } @@ -211,7 +227,7 @@ if (locations[i] == null) { locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize); + currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Thu Mar 20 13:50:21 2014 +0100 @@ -24,13 +24,13 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.asm.NumUtil.*; -import static com.oracle.graal.hotspot.bridge.Marks.*; import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -82,21 +82,21 @@ // co-located with the immutable code. asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment)); final int pos = asm.position(); - crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); + MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_FAR : MarkId.POLL_FAR); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); } asm.testl(rax, new AMD64Address(scratch)); } else if (isPollingPageFar(config)) { asm.movq(scratch, config.safepointPollingAddress); - crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); + MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_FAR : MarkId.POLL_FAR); final int pos = asm.position(); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); } asm.testl(rax, new AMD64Address(scratch)); } else { - crb.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR); + MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_NEAR : MarkId.POLL_NEAR); final int pos = asm.position(); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Thu Mar 20 13:50:21 2014 +0100 @@ -26,7 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; @@ -55,7 +55,7 @@ // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. AMD64Move.move(crb, masm, AMD64.rbx.asValue(Kind.Long), metaspaceMethod); - crb.recordMark(invokeKind == InvokeKind.Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL); + MarkId.recordMark(crb, invokeKind == InvokeKind.Static ? MarkId.INVOKESTATIC : MarkId.INVOKESPECIAL); // This must be emitted exactly like this to ensure it's patchable masm.movq(AMD64.rax, HotSpotGraalRuntime.runtime().getConfig().nonOopBits); super.emitCode(crb, masm); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Thu Mar 20 13:50:21 2014 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; import com.oracle.graal.lir.asm.*; @@ -53,7 +53,7 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. - crb.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE); + MarkId.recordMark(crb, invokeKind == Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE); // This must be emitted exactly like this to ensure it's patchable masm.movq(AMD64.rax, HotSpotGraalRuntime.runtime().getConfig().nonOopBits); super.emitCode(crb, masm); diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Thu Mar 20 13:50:21 2014 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp; @@ -58,7 +58,7 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - crb.recordMark(Marks.MARK_INLINE_INVOKE); + MarkId.recordMark(crb, MarkId.INLINE_INVOKE); Register callReg = asRegister(targetAddress); assert !callReg.equals(METHOD); AMD64Call.indirectCall(crb, masm, callReg, callTarget, state); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Thu Mar 20 13:50:21 2014 +0100 @@ -62,7 +62,7 @@ final int stackFrameAlignment = 8; final int implicitNullCheckLimit = 0; final boolean inlineObjects = true; - return new TargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + return new HotSpotTargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int); } public String getArchitecture() { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Thu Mar 20 13:50:21 2014 +0100 @@ -165,7 +165,7 @@ if (canStoreConstant(c, isCompressed)) { if (isCompressed) { if ((c.getKind() == Kind.Object) && c.isNull()) { - append(new StoreConstantOp(Kind.NarrowOop, storeAddress, c, state)); + append(new StoreConstantOp(Kind.Int, storeAddress, Constant.forInt(0), state)); } else { throw GraalInternalError.shouldNotReachHere("can't handle: " + access); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Thu Mar 20 13:50:21 2014 +0100 @@ -59,7 +59,7 @@ final int stackFrameAlignment = 1; final int implicitNullCheckLimit = 0; final boolean inlineObjects = true; - return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + return new HotSpotTargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int); } public String getArchitecture() { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Thu Mar 20 13:50:21 2014 +0100 @@ -74,6 +74,11 @@ } @Override + public boolean areAllAllocatableRegistersCallerSaved() { + throw GraalInternalError.unimplemented(); + } + + @Override public Register getRegisterForRole(int index) { throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getRegisterForRole()"); } @@ -133,7 +138,7 @@ if (locations[i] == null) { locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize); + currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Thu Mar 20 13:50:21 2014 +0100 @@ -48,8 +48,8 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; @@ -201,7 +201,7 @@ // Emit the prefix if (unverifiedStub != null) { - crb.recordMark(Marks.MARK_UNVERIFIED_ENTRY); + MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY); // We need to use JavaCall here because we haven't entered the frame yet. CallingConvention cc = regConfig.getCallingConvention(JavaCall, null, new JavaType[]{getProviders().getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false); Register inlineCacheKlass = g5; // see MacroAssembler::ic_call @@ -216,8 +216,8 @@ } masm.align(config.codeEntryAlignment); - crb.recordMark(Marks.MARK_OSR_ENTRY); - crb.recordMark(Marks.MARK_VERIFIED_ENTRY); + MarkId.recordMark(crb, MarkId.OSR_ENTRY); + MarkId.recordMark(crb, MarkId.VERIFIED_ENTRY); // Emit code for the LIR crb.emit(lir); @@ -225,9 +225,9 @@ HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; HotSpotForeignCallsProvider foreignCalls = getProviders().getForeignCalls(); if (!frameContext.isStub) { - crb.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY); + MarkId.recordMark(crb, MarkId.EXCEPTION_HANDLER_ENTRY); SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null); - crb.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY); + MarkId.recordMark(crb, MarkId.DEOPT_HANDLER_ENTRY); SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(DEOPT_HANDLER), null, false, null); } else { // No need to emit the stubs for entries back into the method since @@ -245,5 +245,4 @@ public NativeFunctionInterface getNativeFunctionInterface() { throw GraalInternalError.unimplemented("No NativeFunctionInterface of SPARC"); } - } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Thu Mar 20 13:50:21 2014 +0100 @@ -42,7 +42,7 @@ final int stackFrameAlignment = 16; final int implicitNullCheckLimit = 4096; final boolean inlineObjects = true; - return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + return new HotSpotTargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects, Kind.Int); } public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCodeCacheProvider.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCodeCacheProvider.java Thu Mar 20 13:50:21 2014 +0100 @@ -34,6 +34,6 @@ @Override protected RegisterConfig createRegisterConfig() { - return new SPARCHotSpotRegisterConfig(getTarget().arch, runtime.getConfig()); + return new SPARCHotSpotRegisterConfig(getTarget(), runtime.getConfig()); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Thu Mar 20 13:50:21 2014 +0100 @@ -130,10 +130,10 @@ return registers; } - public SPARCHotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) { - this.architecture = architecture; + public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) { + this.architecture = target.arch; - csl = new CalleeSaveLayout(architecture, -1, -1, architecture.getWordSize(), calleeSaveRegisters); + csl = new CalleeSaveLayout(target, -1, -1, target.arch.getWordSize(), calleeSaveRegisters); allocatable = initAllocatable(config.useCompressedOops); attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters); } @@ -144,6 +144,11 @@ } @Override + public boolean areAllAllocatableRegistersCallerSaved() { + return false; + } + + @Override public Register getRegisterForRole(int index) { throw new UnsupportedOperationException(); } @@ -203,7 +208,7 @@ if (locations[i] == null) { locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize); + currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Thu Mar 20 13:50:21 2014 +0100 @@ -23,13 +23,13 @@ package com.oracle.graal.hotspot.sparc; import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; -import static com.oracle.graal.hotspot.bridge.Marks.*; import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.asm.*; @@ -61,7 +61,7 @@ public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { final int pos = masm.position(); new Setx(config.safepointPollingAddress, scratch).emit(masm); - crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); + MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_FAR : MarkId.POLL_FAR); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java Thu Mar 20 13:50:21 2014 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp; @@ -42,7 +42,6 @@ @Opcode("CALL_DIRECT") final class SPARCHotspotDirectStaticCallOp extends DirectCallOp { - private static final long nonOopBits = HotSpotGraalRuntime.runtime().getConfig().nonOopBits; private final Constant metaspaceMethod; private final InvokeKind invokeKind; @@ -58,9 +57,9 @@ // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. SPARCMove.move(crb, masm, g5.asValue(Kind.Long), metaspaceMethod); - crb.recordMark(invokeKind == InvokeKind.Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL); + MarkId.recordMark(crb, invokeKind == InvokeKind.Static ? MarkId.INVOKESTATIC : MarkId.INVOKESPECIAL); // SPARCMove.move(crb, masm, g3.asValue(Kind.Long), Constant.LONG_0); - new Setx(nonOopBits, g3, true).emit(masm); + new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, g3, true).emit(masm); super.emitCode(crb, masm); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Thu Mar 20 13:50:21 2014 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.asm.sparc.*; import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp; import com.oracle.graal.lir.asm.*; @@ -54,7 +54,7 @@ public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. - crb.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE); + MarkId.recordMark(crb, invokeKind == Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE); new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, g3, true).emit(masm); super.emitCode(crb, masm); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java Thu Mar 20 13:50:21 2014 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.sparc.SPARCCall.IndirectCallOp; @@ -58,7 +58,7 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - crb.recordMark(Marks.MARK_INLINE_INVOKE); + MarkId.recordMark(crb, MarkId.INLINE_INVOKE); Register callReg = asRegister(targetAddress); assert !callReg.equals(METHOD); SPARCCall.indirectCall(crb, masm, callReg, callTarget, state); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -49,7 +49,7 @@ protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; HotSpotNmethod installedCode = new HotSpotNmethod(hsMethod, compResult.getName(), true); - HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(runtime().getTarget().arch, hsMethod, compResult); + HotSpotCompiledNmethod compiledNmethod = new HotSpotCompiledNmethod(runtime().getTarget(), hsMethod, compResult); CodeInstallResult result = runtime().getCompilerToVM().installCode(compiledNmethod, installedCode, null); Assert.assertEquals("Error installing method " + method + ": " + result, result, CodeInstallResult.OK); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java Thu Mar 20 13:50:21 2014 +0100 @@ -102,10 +102,10 @@ } } - public void finish(HotSpotResolvedJavaMethod method) { + public void finish(HotSpotResolvedJavaMethod method, HotSpotInstalledCode code) { if (ENABLED) { duration = System.nanoTime() - startTime; - codeSize = method.getCompiledCodeSize(); + codeSize = (int) code.getCodeSize(); memoryUsed = getThreadAllocatedBytes() - threadAllocatedBytesStart; if (current.get().getLast() != this) { throw new RuntimeException("mismatch in finish()"); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu Mar 20 13:50:21 2014 +0100 @@ -54,6 +54,8 @@ public class CompilationTask implements Runnable, Comparable { + private static final long TIMESTAMP_START = System.currentTimeMillis(); + // Keep static finals in a group with withinEnqueue as the last one. CompilationTask can be // called from within it's own clinit so it needs to be careful about accessing state. Once // withinEnqueue is non-null we assume that CompilationTask is fully initialized. @@ -279,8 +281,12 @@ try (TimerCloseable b = CodeInstallationTime.start()) { installedCode = installMethod(result); + if (!isOSR) { + ProfilingInfo profile = method.getProfilingInfo(); + profile.setCompilerIRSize(StructuredGraph.class, graph.getNodeCount()); + } } - stats.finish(method); + stats.finish(method, installedCode); } catch (BailoutException bailout) { BAILOUTS.increment(); if (ExitVMOnBailout.getValue()) { @@ -326,7 +332,24 @@ private void printCompilation() { final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; final int mod = method.getModifiers(); - TTY.println(String.format("%7d %4d %c%c%c%c%c %s %s(%d bytes)", 0, id, isOSR ? '%' : ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ', + String compilerName = ""; + if (HotSpotCIPrintCompilerName.getValue()) { + compilerName = "Graal:"; + } + HotSpotVMConfig config = backend.getRuntime().getConfig(); + int compLevel = config.compilationLevelFullOptimization; + char compLevelChar; + if (config.tieredCompilation) { + compLevelChar = '-'; + if (compLevel != -1) { + compLevelChar = (char) ('0' + compLevel); + } + } else { + compLevelChar = ' '; + } + boolean hasExceptionHandlers = method.getExceptionHandlers().length > 0; + TTY.println(String.format("%s%7d %4d %c%c%c%c%c%c %s %s(%d bytes)", compilerName, (System.currentTimeMillis() - TIMESTAMP_START), id, isOSR ? '%' : ' ', + Modifier.isSynchronized(mod) ? 's' : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', Modifier.isNative(mod) ? 'n' : ' ', compLevelChar, MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize())); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Thu Mar 20 13:50:21 2014 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.target.*; -import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; @@ -51,7 +50,8 @@ /** * Descriptor for {@link ExceptionHandlerStub}. This stub is called by the - * {@linkplain Marks#MARK_EXCEPTION_HANDLER_ENTRY exception handler} in a compiled method. + * {@linkplain HotSpotVMConfig#codeInstallerMarkIdExceptionHandlerEntry exception handler} in a + * compiled method. */ public static final ForeignCallDescriptor EXCEPTION_HANDLER = new ForeignCallDescriptor("exceptionHandler", void.class, Object.class, Word.class); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java Thu Mar 20 13:50:21 2014 +0100 @@ -22,21 +22,17 @@ */ package com.oracle.graal.hotspot; -import java.nio.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CompilationResult.CodeAnnotation; import com.oracle.graal.api.code.CompilationResult.CodeComment; -import com.oracle.graal.api.code.CompilationResult.Data; -import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.CompilationResult.ExceptionHandler; import com.oracle.graal.api.code.CompilationResult.Infopoint; import com.oracle.graal.api.code.CompilationResult.JumpTable; import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.code.CompilationResult.Site; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; +import com.oracle.graal.hotspot.data.*; /** * A {@link CompilationResult} with additional HotSpot-specific information required for installing @@ -53,111 +49,6 @@ public final DataSection dataSection; - /** - * Represents a reference to the data section. Before the code is installed, all {@link Data} - * items referenced by a {@link DataPatch} are put into the data section of the method, and - * replaced by {@link HotSpotData}. - */ - public static final class HotSpotData extends Data { - - /** - * The offset of the data item in the data section. - */ - public int offset; - - /** - * If the data item is an oop that needs to be patched by the runtime, this field contains - * the reference to the object. - */ - public Constant constant; - - public HotSpotData(int offset) { - super(0); - this.offset = offset; - } - - @Override - public int getSize(Architecture arch) { - return 0; - } - - @Override - public void emit(Architecture arch, ByteBuffer buffer) { - } - } - - /** - * Represents the data section of a method. - */ - public static final class DataSection { - - /** - * The minimum alignment required for this data section. - */ - public final int sectionAlignment; - - /** - * The raw data contained in the data section. - */ - public final byte[] data; - - /** - * A list of locations where oop pointers need to be patched by the runtime. - */ - public final HotSpotData[] patches; - - public DataSection(Architecture arch, Site[] sites) { - int size = 0; - int patchCount = 0; - List externalDataList = new ArrayList<>(); - - // find all external data items and determine total size of data section - for (Site site : sites) { - if (site instanceof DataPatch) { - DataPatch dataPatch = (DataPatch) site; - if (dataPatch.externalData != null) { - Data d = dataPatch.externalData; - size = NumUtil.roundUp(size, d.getAlignment()); - size += d.getSize(arch); - externalDataList.add(dataPatch); - if (dataPatch.getConstant() != null && dataPatch.getConstant().getKind() == Kind.Object) { - patchCount++; - } - } - } - } - - data = new byte[size]; - patches = new HotSpotData[patchCount]; - ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder()); - int index = 0; - int patchIndex = 0; - int alignment = 0; - - // build data section - for (DataPatch dataPatch : externalDataList) { - Data d = dataPatch.externalData; - - alignment = Math.max(alignment, d.getAlignment()); - index = NumUtil.roundUp(index, d.getAlignment()); - buffer.position(index); - - HotSpotData hsData = new HotSpotData(index); - if (dataPatch.getConstant() != null && dataPatch.getConstant().getKind() == Kind.Object) { - // record patch location for oop pointers - hsData.constant = dataPatch.getConstant(); - patches[patchIndex++] = hsData; - } - dataPatch.externalData = hsData; - - index += d.getSize(arch); - d.emit(arch, buffer); - } - - this.sectionAlignment = alignment; - } - } - public static class Comment { public final String text; @@ -169,10 +60,10 @@ } } - public HotSpotCompiledCode(Architecture arch, CompilationResult compResult) { + public HotSpotCompiledCode(TargetDescription target, CompilationResult compResult) { this.comp = compResult; sites = getSortedSites(compResult); - dataSection = new DataSection(arch, sites); + dataSection = new DataSection(target, sites); if (compResult.getExceptionHandlers().isEmpty()) { exceptionHandlers = null; } else { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java Thu Mar 20 13:50:21 2014 +0100 @@ -35,8 +35,8 @@ public final int entryBCI; public final int id; - public HotSpotCompiledNmethod(Architecture arch, HotSpotResolvedJavaMethod method, CompilationResult compResult) { - super(arch, compResult); + public HotSpotCompiledNmethod(TargetDescription target, HotSpotResolvedJavaMethod method, CompilationResult compResult) { + super(target, compResult); this.method = method; this.entryBCI = compResult.getEntryBCI(); this.id = compResult.getId(); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Thu Mar 20 13:50:21 2014 +0100 @@ -26,7 +26,7 @@ import com.oracle.graal.api.code.CompilationResult.Call; import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.CompilationResult.Infopoint; -import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.data.*; import com.oracle.graal.hotspot.stubs.*; /** @@ -38,8 +38,8 @@ public final String stubName; - public HotSpotCompiledRuntimeStub(Architecture arch, Stub stub, CompilationResult compResult) { - super(arch, compResult); + public HotSpotCompiledRuntimeStub(TargetDescription target, Stub stub, CompilationResult compResult) { + super(target, compResult); assert checkStubInvariants(compResult); this.stubName = stub.toString(); } @@ -50,11 +50,7 @@ private boolean checkStubInvariants(CompilationResult compResult) { assert compResult.getExceptionHandlers().isEmpty(); for (DataPatch data : compResult.getDataReferences()) { - Constant constant = data.getConstant(); - if (constant != null) { - assert constant.getKind() != Kind.Object : this + " cannot have embedded object constant: " + constant; - assert constant.getPrimitiveAnnotation() == null : this + " cannot have embedded metadata: " + constant; - } + assert !(data.data instanceof PatchedData) : this + " cannot have embedded object or metadata constant: " + data.data; } for (Infopoint infopoint : compResult.getInfopoints()) { assert infopoint instanceof Call : this + " cannot have non-call infopoint: " + infopoint; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu Mar 20 13:50:21 2014 +0100 @@ -235,6 +235,9 @@ if (HotSpotPrintInlining.getValue() == false) { HotSpotPrintInlining.setValue(config.printInlining); } + if (HotSpotCIPrintCompilerName.getValue() == false) { + HotSpotCIPrintCompilerName.setValue(config.printCompilerName); + } if (Boolean.valueOf(System.getProperty("graal.printconfig"))) { printConfig(config); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.nodes.type.*; + +public class HotSpotReferenceMap implements ReferenceMap, Serializable { + + private static final long serialVersionUID = -1052183095979496819L; + + /** + * Contains 2 bits per register. + *
    + *
  • bit0 = 0: contains no references
  • + *
  • bit0 = 1, bit1 = 0: contains a wide oop
  • + *
  • bit0 = 1, bit1 = 1: contains a narrow oop
  • + *
+ */ + private final BitSet registerRefMap; + + /** + * Contains 3 bits per stack slot. + *
    + *
  • bit0 = 0: contains no references
  • + *
  • bit0 = 1, bit1+2 = 0: contains a wide oop
  • + *
  • bit0 = 1, bit1 = 1: contains a narrow oop in the lower half
  • + *
  • bit0 = 1, bit2 = 1: contains a narrow oop in the upper half
  • + *
+ */ + private final BitSet frameRefMap; + + private final int frameSlotSize; + + public HotSpotReferenceMap(int registerCount, int frameSlotCount, int frameSlotSize) { + if (registerCount > 0) { + this.registerRefMap = new BitSet(registerCount * 2); + } else { + this.registerRefMap = null; + } + this.frameRefMap = new BitSet(frameSlotCount * 3); + this.frameSlotSize = frameSlotSize; + } + + public void setRegister(int idx, PlatformKind kind) { + if (kind == Kind.Object) { + registerRefMap.set(2 * idx); + } else if (kind == NarrowOopStamp.NarrowOop) { + registerRefMap.set(2 * idx); + registerRefMap.set(2 * idx + 1); + } + } + + public void setStackSlot(int offset, PlatformKind kind) { + int idx = offset / frameSlotSize; + if (kind == Kind.Object) { + assert offset % frameSlotSize == 0; + frameRefMap.set(3 * idx); + } else if (kind == NarrowOopStamp.NarrowOop) { + frameRefMap.set(3 * idx); + if (offset % frameSlotSize == 0) { + frameRefMap.set(3 * idx + 1); + } else { + assert offset % frameSlotSize == frameSlotSize / 2; + frameRefMap.set(3 * idx + 2); + } + } + } + + public boolean hasRegisterRefMap() { + return registerRefMap != null && registerRefMap.size() > 0; + } + + public boolean hasFrameRefMap() { + return frameRefMap != null && frameRefMap.size() > 0; + } + + public void appendRegisterMap(StringBuilder sb, RefMapFormatter formatter) { + for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 2)) { + sb.append(' ').append(formatter.formatRegister(reg / 2)); + } + } + + public void appendFrameMap(StringBuilder sb, RefMapFormatter formatter) { + for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + 3)) { + sb.append(' ').append(formatter.formatStackSlot(slot / 3)); + } + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.nodes.type.*; + +public class HotSpotTargetDescription extends TargetDescription { + + private final PlatformKind rawNarrowOopKind; + + public HotSpotTargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects, PlatformKind rawNarrowOopKind) { + super(arch, isMP, stackAlignment, implicitNullCheckLimit, inlineObjects); + this.rawNarrowOopKind = rawNarrowOopKind; + } + + @Override + public int getSizeInBytes(PlatformKind kind) { + if (kind == NarrowOopStamp.NarrowOop) { + return super.getSizeInBytes(rawNarrowOopKind); + } else { + return super.getSizeInBytes(kind); + } + } + + @Override + public ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount) { + return new HotSpotReferenceMap(hasRegisters ? arch.getRegisterReferenceMapBitCount() : 0, stackSlotCount, wordSize); + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Mar 20 13:50:21 2014 +0100 @@ -709,10 +709,12 @@ @HotSpotVMFlag(name = "DontCompileHugeMethods") @Stable public boolean dontCompileHugeMethods; @HotSpotVMFlag(name = "HugeMethodLimit") @Stable public int hugeMethodLimit; @HotSpotVMFlag(name = "PrintCompilation") @Stable public boolean printCompilation; + @HotSpotVMFlag(name = "CIPrintCompilerName") @Stable public boolean printCompilerName; @HotSpotVMFlag(name = "PrintInlining") @Stable public boolean printInlining; @HotSpotVMFlag(name = "GraalUseFastLocking") @Stable public boolean useFastLocking; @HotSpotVMFlag(name = "ForceUnreachable") @Stable public boolean forceUnreachable; @HotSpotVMFlag(name = "GPUOffload") @Stable public boolean gpuOffload; + @HotSpotVMFlag(name = "TieredCompilation") @Stable public boolean tieredCompilation; @HotSpotVMFlag(name = "UseTLAB") @Stable public boolean useTLAB; @HotSpotVMFlag(name = "UseBiasedLocking") @Stable public boolean useBiasedLocking; @@ -1189,6 +1191,7 @@ @HotSpotVMField(name = "MethodData::_data_size", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataDataSize; @HotSpotVMField(name = "MethodData::_data[0]", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopDataOffset; @HotSpotVMField(name = "MethodData::_trap_hist._array[0]", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataOopTrapHistoryOffset; + @HotSpotVMField(name = "MethodData::_graal_node_count", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodDataGraalNodeCountOffset; @HotSpotVMField(name = "nmethod::_verified_entry_point", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodEntryOffset; @HotSpotVMField(name = "nmethod::_comp_level", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodCompLevelOffset; @@ -1419,6 +1422,22 @@ @HotSpotVMConstant(name = "CompilerToVM::KLASS_TAG") @Stable public int compilerToVMKlassTag; @HotSpotVMConstant(name = "CompilerToVM::SYMBOL_TAG") @Stable public int compilerToVMSymbolTag; + @HotSpotVMConstant(name = "CodeInstaller::VERIFIED_ENTRY") @Stable public int codeInstallerMarkIdVerifiedEntry; + @HotSpotVMConstant(name = "CodeInstaller::UNVERIFIED_ENTRY") @Stable public int codeInstallerMarkIdUnverifiedEntry; + @HotSpotVMConstant(name = "CodeInstaller::OSR_ENTRY") @Stable public int codeInstallerMarkIdOsrEntry; + @HotSpotVMConstant(name = "CodeInstaller::EXCEPTION_HANDLER_ENTRY") @Stable public int codeInstallerMarkIdExceptionHandlerEntry; + @HotSpotVMConstant(name = "CodeInstaller::DEOPT_HANDLER_ENTRY") @Stable public int codeInstallerMarkIdDeoptHandlerEntry; + @HotSpotVMConstant(name = "CodeInstaller::INVOKEINTERFACE") @Stable public int codeInstallerMarkIdInvokeinterface; + @HotSpotVMConstant(name = "CodeInstaller::INVOKEVIRTUAL") @Stable public int codeInstallerMarkIdInvokevirtual; + @HotSpotVMConstant(name = "CodeInstaller::INVOKESTATIC") @Stable public int codeInstallerMarkIdInvokestatic; + @HotSpotVMConstant(name = "CodeInstaller::INVOKESPECIAL") @Stable public int codeInstallerMarkIdInvokespecial; + @HotSpotVMConstant(name = "CodeInstaller::INLINE_INVOKE") @Stable public int codeInstallerMarkIdInlineInvoke; + @HotSpotVMConstant(name = "CodeInstaller::POLL_NEAR") @Stable public int codeInstallerMarkIdPollNear; + @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_NEAR") @Stable public int codeInstallerMarkIdPollReturnNear; + @HotSpotVMConstant(name = "CodeInstaller::POLL_FAR") @Stable public int codeInstallerMarkIdPollFar; + @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_FAR") @Stable public int codeInstallerMarkIdPollReturnFar; + @HotSpotVMConstant(name = "CodeInstaller::INVOKE_INVALID") @Stable public int codeInstallerMarkIdInvokeInvalid; + public boolean check() { for (Field f : getClass().getDeclaredFields()) { int modifiers = f.getModifiers(); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Thu Mar 20 13:50:21 2014 +0100 @@ -252,14 +252,6 @@ boolean hasFinalizableSubclass(long metaspaceKlass); /** - * Gets the compiled code size for a method. - * - * @param metaspaceMethod the metaspace Method object to query - * @return the compiled code size the method - */ - int getCompiledCodeSize(long metaspaceMethod); - - /** * Gets the metaspace Method object corresponding to a given {@link Class} object and slot * number. * diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Thu Mar 20 13:50:21 2014 +0100 @@ -111,9 +111,6 @@ public native long getClassInitializer(long metaspaceKlass); @Override - public native int getCompiledCodeSize(long metaspaceMethod); - - @Override public native long getMaxCallTargetOffset(long address); // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/Marks.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/Marks.java Wed Mar 19 19:02:29 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +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.bridge; - -/** - * Constants used to mark special positions in code being installed into the code cache by Graal C++ - * code. These constants need to be kept in sync with those of the same name defined in - * graalCodeInstaller.hpp. - */ -public interface Marks { - - int MARK_VERIFIED_ENTRY = 1; - int MARK_UNVERIFIED_ENTRY = 2; - int MARK_OSR_ENTRY = 3; - int MARK_EXCEPTION_HANDLER_ENTRY = 4; - int MARK_DEOPT_HANDLER_ENTRY = 5; - int MARK_INVOKEINTERFACE = 6; - int MARK_INVOKEVIRTUAL = 7; - int MARK_INVOKESTATIC = 8; - int MARK_INVOKESPECIAL = 9; - int MARK_INLINE_INVOKE = 10; - int MARK_POLL_NEAR = 11; - int MARK_POLL_RETURN_NEAR = 12; - int MARK_POLL_FAR = 13; - int MARK_POLL_RETURN_FAR = 14; -} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/DataSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/DataSection.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.data; + +import java.nio.*; +import java.util.*; + +import com.oracle.graal.api.code.CompilationResult.Data; +import com.oracle.graal.api.code.CompilationResult.DataPatch; +import com.oracle.graal.api.code.CompilationResult.Site; +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.*; + +/** + * Represents the data section of a method. + */ +public final class DataSection { + + /** + * The minimum alignment required for this data section. + */ + public final int sectionAlignment; + + /** + * The raw data contained in the data section. + */ + public final byte[] data; + + /** + * A list of locations where oop pointers need to be patched by the runtime. + */ + public final DataPatch[] patches; + + public DataSection(TargetDescription target, Site[] sites) { + int size = 0; + int patchCount = 0; + List externalDataList = new ArrayList<>(); + + // find all external data items and determine total size of data section + for (Site site : sites) { + if (site instanceof DataPatch) { + DataPatch dataPatch = (DataPatch) site; + Data d = dataPatch.data; + if (dataPatch.inline) { + assert d instanceof PatchedData : "unnecessary data patch"; + } else { + size = NumUtil.roundUp(size, d.getAlignment()); + size += d.getSize(target); + externalDataList.add(dataPatch); + if (d instanceof PatchedData) { + patchCount++; + } + } + } + } + + data = new byte[size]; + patches = new DataPatch[patchCount]; + ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder()); + int index = 0; + int patchIndex = 0; + int alignment = 0; + + // build data section + for (DataPatch dataPatch : externalDataList) { + assert !dataPatch.inline; + Data d = dataPatch.data; + + alignment = Math.max(alignment, d.getAlignment()); + index = NumUtil.roundUp(index, d.getAlignment()); + buffer.position(index); + + DataSectionReference reference = new DataSectionReference(index); + if (d instanceof PatchedData) { + // record patch location + patches[patchIndex++] = new DataPatch(index, d, true); + } + dataPatch.data = reference; + + index += d.getSize(target); + d.emit(target, buffer); + } + + this.sectionAlignment = alignment; + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/DataSectionReference.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/DataSectionReference.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.data; + +import java.nio.*; + +import com.oracle.graal.api.code.CompilationResult.Data; +import com.oracle.graal.api.code.CompilationResult.DataPatch; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +/** + * Represents a reference to the data section. Before the code is installed, all {@link Data} items + * referenced by a {@link DataPatch} are put into the data section of the method, and replaced by + * {@link DataSectionReference}. + */ +public class DataSectionReference extends Data { + + public final int offset; + + protected DataSectionReference(int offset) { + super(0); + this.offset = offset; + } + + @Override + public int getSize(TargetDescription target) { + return 0; + } + + @Override + public Kind getKind() { + return Kind.Illegal; + } + + @Override + public void emit(TargetDescription target, ByteBuffer buffer) { + } + +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.data; + +import java.nio.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; + +/** + * A data item that represents a metaspace pointer. + */ +public class MetaspaceData extends PatchedData { + + public final long value; + public final Object annotation; + public final boolean compressed; + + public MetaspaceData(int alignment, long value, Object annotation, boolean compressed) { + super(alignment); + assert annotation != null; + this.value = value; + this.annotation = annotation; + this.compressed = compressed; + } + + @Override + public int getSize(TargetDescription target) { + if (compressed) { + return target.getSizeInBytes(Kind.Int); + } else { + return target.getSizeInBytes(target.wordKind); + } + } + + @Override + public Kind getKind() { + return Kind.Long; + } + + @Override + public void emit(TargetDescription target, ByteBuffer buffer) { + switch (getSize(target)) { + case 4: + buffer.putInt((int) value); + break; + case 8: + buffer.putLong(value); + break; + default: + throw GraalInternalError.shouldNotReachHere("unexpected metaspace pointer size"); + } + } + + @Override + public String toString() { + return (compressed ? "NarrowPointer[0x" + Integer.toHexString((int) value) : "Pointer[0x" + Long.toHexString(value)) + "]{" + annotation + "}"; + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.data; + +import java.nio.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.nodes.type.*; + +/** + * A data item that represents an oop value. + */ +public class OopData extends PatchedData { + + public final Object object; + public final boolean compressed; + + public OopData(int alignment, Object object, boolean compressed) { + super(alignment); + this.object = object; + this.compressed = compressed; + } + + @Override + public int getSize(TargetDescription target) { + if (compressed) { + return target.getSizeInBytes(NarrowOopStamp.NarrowOop); + } else { + return target.getSizeInBytes(Kind.Object); + } + } + + @Override + public Kind getKind() { + return Kind.Object; + } + + @Override + public void emit(TargetDescription target, ByteBuffer buffer) { + switch (getSize(target)) { + case 4: + buffer.putInt(0xDEADDEAD); + break; + case 8: + buffer.putLong(0xDEADDEADDEADDEADL); + break; + default: + throw GraalInternalError.shouldNotReachHere("unexpected oop size"); + } + } + + @Override + public String toString() { + return (compressed ? "NarrowOop[" : "Oop[") + Kind.Object.format(object) + "]"; + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/PatchedData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/PatchedData.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.data; + +import com.oracle.graal.api.code.CompilationResult.Data; + +/** + * Represents a data item that needs to be patched. + */ +public abstract class PatchedData extends Data { + + protected PatchedData(int alignment) { + super(alignment); + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Thu Mar 20 13:50:21 2014 +0100 @@ -50,10 +50,10 @@ * infrastructure is enabled by specifying either the GenericDynamicCounters or * BenchmarkDynamicCounters option.
* - * The counters are kept in a special area in the native JavaThread object, and the number of - * counters is configured in {@code thread.hpp (GRAAL_COUNTERS_SIZE)}. This file also contains an - * option to exclude compiler threads ({@code GRAAL_COUNTERS_EXCLUDE_COMPILER_THREADS}, which - * defaults to true). + * The counters are kept in a special area allocated for each native JavaThread object, and the + * number of counters is configured using {@code -XX:GraalCounterSize=value}. + * {@code -XX:+/-GraalCountersExcludeCompiler} configures whether to exclude compiler threads + * (defaults to true). * * The subsystems that use the logging need to have their own options to turn on the counters, and * insert DynamicCounterNodes when they're enabled. @@ -64,12 +64,10 @@ *

Example

In order to create statistics about allocations within the DaCapo pmd benchmark * the following steps are necessary: *
    - *
  • Modify {@code thread.hpp}: increase GRAAL_COUNTER_SIZE. The actual required value depends on - * the granularity of the profiling, 10000 should be enough for most cases. This will increase the - * JavaThread structure by 80kb.
  • - *
  • Also in {@code thread.hpp}: GRAAL_COUNTERS_EXCLUDE_COMPILER_THREADS specifies whether the - * numbers generated by compiler threads should be excluded (default: true).
  • - *
  • Build the Graal VM.
  • + *
  • Set {@code -XX:GraalCounterSize=value}. The actual required value depends on the granularity + * of the profiling, 10000 should be enough for most cases.
  • + *
  • Also: {@code -XX:+/-GraalCountersExcludeCompiler} specifies whether the numbers generated by + * compiler threads should be excluded (default: true).
  • *
  • Start the DaCapo pmd benchmark with * {@code "-G:BenchmarkDynamicCounters=err, starting ====, PASSED in "} and * {@code -G:+ProfileAllocations}.
  • @@ -330,7 +328,7 @@ int index = BenchmarkCounters.getIndex(counter); if (index >= config.graalCountersSize) { - throw new GraalInternalError("too many counters, reduce number of counters or increase GRAAL_COUNTERS_SIZE (current value: " + config.graalCountersSize + ")"); + throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")"); } ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, config.graalCountersThreadOffset, graph); ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false)); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java Thu Mar 20 13:50:21 2014 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.logging; +import java.io.*; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; @@ -94,16 +95,15 @@ } } - // CheckStyle: stop system..print check protected void print() { long sum = 0; + PrintStream out = System.out; for (Map.Entry entry : calls.entrySet()) { Method method = entry.getKey(); long count = entry.getValue().get(); sum += count; - System.out.println(delegate.getClass().getSimpleName() + "." + method.getName() + ": " + count); + out.println(delegate.getClass().getSimpleName() + "." + method.getName() + ": " + count); } - System.out.println(delegate.getClass().getSimpleName() + " calls: " + sum); + out.println(delegate.getClass().getSimpleName() + " calls: " + sum); } - // CheckStyle: resume system..print check } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Thu Mar 20 13:50:21 2014 +0100 @@ -29,15 +29,20 @@ import com.oracle.graal.api.code.CodeUtil.DefaultRefMapFormatter; import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; import com.oracle.graal.api.code.CompilationResult.Call; +import com.oracle.graal.api.code.CompilationResult.Data; import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.CompilationResult.Infopoint; import com.oracle.graal.api.code.CompilationResult.Mark; +import com.oracle.graal.api.code.CompilationResult.PrimitiveData; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult; +import com.oracle.graal.hotspot.data.*; import com.oracle.graal.java.*; +import com.oracle.graal.lir.asm.*; import com.oracle.graal.printer.*; /** @@ -57,6 +62,54 @@ protected abstract RegisterConfig createRegisterConfig(); + /** + * Constants used to mark special positions in code being installed into the code cache by Graal + * C++ code. + */ + public enum MarkId { + VERIFIED_ENTRY(config().codeInstallerMarkIdVerifiedEntry), + UNVERIFIED_ENTRY(config().codeInstallerMarkIdUnverifiedEntry), + OSR_ENTRY(config().codeInstallerMarkIdOsrEntry), + EXCEPTION_HANDLER_ENTRY(config().codeInstallerMarkIdExceptionHandlerEntry), + DEOPT_HANDLER_ENTRY(config().codeInstallerMarkIdDeoptHandlerEntry), + INVOKEINTERFACE(config().codeInstallerMarkIdInvokeinterface), + INVOKEVIRTUAL(config().codeInstallerMarkIdInvokevirtual), + INVOKESTATIC(config().codeInstallerMarkIdInvokestatic), + INVOKESPECIAL(config().codeInstallerMarkIdInvokespecial), + INLINE_INVOKE(config().codeInstallerMarkIdInlineInvoke), + POLL_NEAR(config().codeInstallerMarkIdPollNear), + POLL_RETURN_NEAR(config().codeInstallerMarkIdPollReturnNear), + POLL_FAR(config().codeInstallerMarkIdPollFar), + POLL_RETURN_FAR(config().codeInstallerMarkIdPollReturnFar); + + private final int value; + + private MarkId(int value) { + this.value = value; + } + + private static HotSpotVMConfig config() { + return HotSpotGraalRuntime.runtime().getConfig(); + } + + public static MarkId getEnum(int value) { + for (MarkId e : values()) { + if (e.value == value) { + return e; + } + } + throw GraalInternalError.shouldNotReachHere("unknown enum value " + value); + } + + /** + * Helper method to {@link CompilationResultBuilder#recordMark(Object) record a mark} with a + * {@link CompilationResultBuilder}. + */ + public static void recordMark(CompilationResultBuilder crb, MarkId mark) { + crb.recordMark(mark.value); + } + } + @Override public String disassemble(CompilationResult compResult, InstalledCode installedCode) { byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode(); @@ -82,10 +135,10 @@ } } for (DataPatch site : compResult.getDataReferences()) { - hcf.addOperandComment(site.pcOffset, "{" + site.getDataString() + "}"); + hcf.addOperandComment(site.pcOffset, "{" + site.data.toString() + "}"); } for (Mark mark : compResult.getMarks()) { - hcf.addComment(mark.pcOffset, getMarkName(mark)); + hcf.addComment(mark.pcOffset, MarkId.getEnum((int) mark.id).toString()); } } return hcf.toEmbeddedString(); @@ -111,25 +164,6 @@ return String.valueOf(call.target); } - /** - * Decodes a mark to a mnemonic if possible. - */ - private static String getMarkName(Mark mark) { - Field[] fields = Marks.class.getDeclaredFields(); - for (Field f : fields) { - if (Modifier.isStatic(f.getModifiers()) && f.getName().startsWith("MARK_")) { - f.setAccessible(true); - try { - if (f.get(null).equals(mark.id)) { - return f.getName(); - } - } catch (Exception e) { - } - } - } - return "MARK:" + mark.id; - } - private static void addExceptionHandlersComment(CompilationResult compResult, HexCodeFile hcf) { if (!compResult.getExceptionHandlers().isEmpty()) { String nl = HexCodeFile.NEW_LINE; @@ -173,7 +207,7 @@ compResult.setId(method.allocateCompileId(compResult.getEntryBCI())); } HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), true); - runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target.arch, method, compResult), installedCode, method.getSpeculationLog()); + runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, method, compResult), installedCode, method.getSpeculationLog()); return logOrDump(installedCode, compResult); } @@ -184,7 +218,7 @@ compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI())); } HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false); - CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target.arch, hotspotMethod, compResult), code, log); + CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, hotspotMethod, compResult), code, log); if (result != CodeInstallResult.OK) { return null; } @@ -203,7 +237,7 @@ compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI())); } HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true); - HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(target.arch, javaMethod, compResult); + HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(target, javaMethod, compResult); CompilerToVM vm = runtime.getCompilerToVM(); CodeInstallResult result = vm.installCode(compiled, code, null); if (result != CodeInstallResult.OK) { @@ -216,6 +250,16 @@ return constant.getPrimitiveAnnotation() != null; } + public Data createDataItem(Constant constant, int alignment) { + if (constant.getPrimitiveAnnotation() != null) { + return new MetaspaceData(alignment, constant.asLong(), constant.getPrimitiveAnnotation(), false); + } else if (constant.getKind().isObject()) { + return new OopData(alignment, constant.asObject(), false); + } else { + return new PrimitiveData(constant, alignment); + } + } + @Override public TargetDescription getTarget() { return target; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Thu Mar 20 13:50:21 2014 +0100 @@ -700,9 +700,9 @@ public int getScalingFactor(Kind kind) { if (useCompressedOops() && kind == Kind.Object) { - return this.runtime.getTarget().arch.getSizeInBytes(Kind.Int); + return this.runtime.getTarget().getSizeInBytes(Kind.Int); } else { - return this.runtime.getTarget().arch.getSizeInBytes(kind); + return this.runtime.getTarget().getSizeInBytes(kind); } } @@ -757,7 +757,7 @@ ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection()); if (arrayLength == null) { Stamp stamp = StampFactory.positiveInt(); - ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false)); + ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false)); g.addBeforeFixed(n, readArrayLength); readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool)); arrayLength = readArrayLength; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Thu Mar 20 13:50:21 2014 +0100 @@ -299,7 +299,7 @@ ResolvedJavaType elementType = lookupJavaType.getComponentType(); Kind elementKind = elementType.getKind(); final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind); - int sizeOfElement = HotSpotGraalRuntime.runtime().getTarget().arch.getSizeInBytes(elementKind); + int sizeOfElement = HotSpotGraalRuntime.runtime().getTarget().getSizeInBytes(elementKind); int alignment = HotSpotGraalRuntime.runtime().getTarget().wordSize; int log2ElementSize = CodeUtil.log2(sizeOfElement); return NewObjectSnippets.computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java Thu Mar 20 13:50:21 2014 +0100 @@ -23,11 +23,15 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.debug.Debug.*; +import static java.util.FormattableFlags.*; + +import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; -public abstract class HotSpotMethod extends CompilerObject implements JavaMethod { +public abstract class HotSpotMethod extends CompilerObject implements JavaMethod, Formattable { private static final long serialVersionUID = 7167491397941960839L; protected String name; @@ -54,4 +58,9 @@ String fmt = String.format("HotSpotMethod<%%%c.%%n(%%p)%s>", h, suffix); return format(fmt, this); } + + public void formatTo(Formatter formatter, int flags, int width, int precision) { + String base = (flags & ALTERNATE) == ALTERNATE ? getName() : toString(); + formatter.format(applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width)); + } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Thu Mar 20 13:50:21 2014 +0100 @@ -825,4 +825,12 @@ super(runtime().getConfig().dataLayoutArgInfoDataTag, ARG_INFO_DATA_SIZE); } } + + public void setCompiledGraphSize(int nodeCount) { + unsafe.putInt(metaspaceMethodData + config.methodDataGraalNodeCountOffset, nodeCount); + } + + public int getCompiledGraphSize() { + return unsafe.getInt(metaspaceMethodData + config.methodDataGraalNodeCountOffset); + } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Thu Mar 20 13:50:21 2014 +0100 @@ -43,7 +43,12 @@ private static final long serialVersionUID = -1784683588947054103L; + /** + * This (indirect) Method* reference is safe since class redefinition preserves all methods + * associated with nmethods in the code cache. + */ private final HotSpotResolvedJavaMethod method; + private final boolean isDefault; private final boolean isExternal; private final String name; diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java Thu Mar 20 13:50:21 2014 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodes.*; public final class HotSpotProfilingInfo extends CompilerObject implements ProfilingInfo { @@ -205,4 +206,21 @@ public void setMature() { isMature = true; } + + @Override + public boolean setCompilerIRSize(Class irType, int size) { + if (irType == StructuredGraph.class) { + methodData.setCompiledGraphSize(size); + return true; + } + return false; + } + + @Override + public int getCompilerIRSize(Class irType) { + if (irType == StructuredGraph.class) { + return methodData.getCompiledGraphSize(); + } + return -1; + } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Thu Mar 20 13:50:21 2014 +0100 @@ -28,8 +28,6 @@ import java.lang.annotation.*; import java.lang.reflect.*; -import java.util.*; -import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -59,7 +57,6 @@ private boolean forceInline; private boolean dontInline; private boolean ignoredBySecurityStackWalk; - private Map compilerStorage; private HotSpotMethodData methodData; private byte[] code; private SpeculationLog speculationLog; @@ -356,10 +353,6 @@ return signature; } - public int getCompiledCodeSize() { - return runtime().getCompilerToVM().getCompiledCodeSize(metaspaceMethod); - } - /** * Gets the value of {@code Method::_code}. * @@ -380,9 +373,8 @@ } /** - * Gets the compilation level of the currently installed code for this method. - * - * @return compilation level + * @param level + * @return true if the currently installed code was generated at {@code level}. */ public boolean hasCompiledCodeAtLevel(int level) { long compiledCode = getCompiledCode(); @@ -433,14 +425,6 @@ } @Override - public Map getCompilerStorage() { - if (compilerStorage == null) { - compilerStorage = new ConcurrentHashMap<>(); - } - return compilerStorage; - } - - @Override public ConstantPool getConstantPool() { return constantPool; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Thu Mar 20 13:50:21 2014 +0100 @@ -363,6 +363,10 @@ @Override public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { assert method instanceof HotSpotMethod; + if (!isAbstract(method.getModifiers()) && method.getDeclaringClass().equals(this)) { + return method; + } + final long resolvedMetaspaceMethod = runtime().getCompilerToVM().resolveMethod(metaspaceKlass(), method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor()); if (resolvedMetaspaceMethod == 0) { return null; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class NarrowOopStamp extends ObjectStamp { + + public static final PlatformKind NarrowOop = new PlatformKind() { + + public String name() { + return "NarrowOop"; + } + + @Override + public String toString() { + return name(); + } + }; + + private final CompressEncoding encoding; + + public NarrowOopStamp(ObjectStamp stamp, CompressEncoding encoding) { + this(stamp.type(), stamp.isExactType(), stamp.nonNull(), stamp.alwaysNull(), encoding); + } + + public NarrowOopStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull, CompressEncoding encoding) { + super(type, exactType, nonNull, alwaysNull); + this.encoding = encoding; + } + + public Stamp uncompressed() { + return new ObjectStamp(type(), isExactType(), nonNull(), alwaysNull()); + } + + public CompressEncoding getEncoding() { + return encoding; + } + + @Override + public Stamp unrestricted() { + return new NarrowOopStamp((ObjectStamp) super.unrestricted(), encoding); + } + + @Override + public Kind getStackKind() { + return Kind.Object; + } + + @Override + public PlatformKind getPlatformKind(LIRTypeTool tool) { + return NarrowOop; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append('n'); + str.append(super.toString()); + return str.toString(); + } + + @Override + public Stamp meet(Stamp otherStamp) { + if (this == otherStamp) { + return this; + } + if (otherStamp instanceof IllegalStamp) { + return otherStamp.meet(this); + } + if (!isCompatible(otherStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + return new NarrowOopStamp((ObjectStamp) super.meet(otherStamp), encoding); + } + + @Override + public Stamp join(Stamp otherStamp) { + if (this == otherStamp) { + return this; + } + if (otherStamp instanceof IllegalStamp) { + return otherStamp.join(this); + } + if (!isCompatible(otherStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + return new NarrowOopStamp((ObjectStamp) super.join(otherStamp), encoding); + } + + @Override + public boolean isCompatible(Stamp other) { + if (this == other) { + return true; + } + if (other instanceof NarrowOopStamp) { + NarrowOopStamp narrow = (NarrowOopStamp) other; + return encoding.equals(narrow.encoding); + } + return false; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + encoding.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + NarrowOopStamp other = (NarrowOopStamp) obj; + if (!encoding.equals(other.encoding)) { + return false; + } + return super.equals(other); + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -73,11 +73,11 @@ Node currentNode = iterator.next(); assert !isSafepoint(currentNode) : "Write barrier must be present " + write; if (useG1GC()) { - if (!(currentNode instanceof G1PostWriteBarrier) || ((currentNode instanceof G1PostWriteBarrier) && !validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode))) { + if (!(currentNode instanceof G1PostWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode))) { expandFrontier(frontier, currentNode); } } else { - if (!(currentNode instanceof SerialWriteBarrier) || ((currentNode instanceof SerialWriteBarrier) && !validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode)) || + if (!(currentNode instanceof SerialWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode)) || ((currentNode instanceof SerialWriteBarrier) && !validateBarrier((FixedAccessNode) write, (WriteBarrier) currentNode))) { expandFrontier(frontier, currentNode); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Thu Mar 20 13:50:21 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,16 +31,16 @@ import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.*; import com.oracle.graal.word.*; /** - * Stub called by the {@linkplain Marks#MARK_EXCEPTION_HANDLER_ENTRY exception handler entry point} - * in a compiled method. This entry point is used when returning to a method to handle an exception + * Stub called by the {@linkplain MarkId#EXCEPTION_HANDLER_ENTRY exception handler entry point} in a + * compiled method. This entry point is used when returning to a method to handle an exception * thrown by a callee. It is not used for routing implicit exceptions. Therefore, it does not need * to save any registers as HotSpot uses a caller save convention. *

    diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Thu Mar 20 13:50:21 2014 +0100 @@ -153,7 +153,7 @@ try (Scope s = Debug.scope("CodeInstall")) { Stub stub = Stub.this; HotSpotRuntimeStub installedCode = new HotSpotRuntimeStub(stub); - HotSpotCompiledCode hsCompResult = new HotSpotCompiledRuntimeStub(backend.getTarget().arch, stub, compResult); + HotSpotCompiledCode hsCompResult = new HotSpotCompiledRuntimeStub(backend.getTarget(), stub, compResult); CodeInstallResult result = runtime().getCompilerToVM().installCode(hsCompResult, installedCode, null); if (result != CodeInstallResult.OK) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java --- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Thu Mar 20 13:50:21 2014 +0100 @@ -168,7 +168,7 @@ Kind kind = arg.getKind(); if (kind == Kind.Double || kind == Kind.Long) { regPrefix = "$d"; - } else if (kind == Kind.Int || kind == Kind.Float || kind == Kind.NarrowOop) { + } else if (kind == Kind.Int || kind == Kind.Float) { regPrefix = "$s"; } else { regPrefix = "$d"; @@ -193,7 +193,6 @@ case Int: case Long: case Object: - case NarrowOop: return true; } } else if (category == FPU) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java --- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java Thu Mar 20 13:50:21 2014 +0100 @@ -24,7 +24,6 @@ package com.oracle.graal.hsail; import com.oracle.graal.api.code.*; - import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; @@ -123,7 +122,7 @@ if (locations[i] == null) { locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize); + currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); } } @@ -150,7 +149,6 @@ case Short: case Byte: case Float: - case NarrowOop: return regBitness32.clone(); case Long: case Double: @@ -169,6 +167,11 @@ } @Override + public boolean areAllAllocatableRegistersCallerSaved() { + return false; + } + + @Override public CalleeSaveLayout getCalleeSaveLayout() { return null; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/DecompilerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/DecompilerTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.java.decompiler.test; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.java.decompiler.test.example.*; +import com.oracle.graal.printer.*; +import com.oracle.graal.runtime.*; + +@Ignore +public class DecompilerTest { + + public static void doTest(String name) { + try { + DebugEnvironment.initialize(System.out); + MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess(); + Method method = Example.class.getDeclaredMethod(name, new Class[]{int.class, int.class}); + final ResolvedJavaMethod javaMethod = metaAccess.lookupJavaMethod(method); + TestUtil.compileMethod(javaMethod); + } catch (NoSuchMethodException e) { + Assert.fail(); + } catch (SecurityException e) { + Assert.fail(); + } + } + + @Test + public void test01() { + doTest("loop7"); + } + + @Test + public void test02() { + doTest("loop6"); + } + + @Test + public void test03() { + doTest("loop5"); + } + + @Test + public void test04() { + doTest("loop4"); + } + + @Test + public void test05() { + doTest("loop3"); + } + + @Test + public void test06() { + doTest("loop2"); + } + + @Test + public void test07() { + doTest("loop"); + } + + @Test + public void test08() { + doTest("if0"); + } + + @Test + public void test09() { + doTest("if1"); + } + + @Test + public void test10() { + doTest("if2"); + } + + @Test + public void test11() { + doTest("if3"); + } + + @Test + public void test12() { + doTest("if4"); + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java --- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java Wed Mar 19 19:02:29 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.java.decompiler.test; - -import java.lang.reflect.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.java.decompiler.test.example.*; -import com.oracle.graal.printer.*; -import com.oracle.graal.runtime.*; - -public class Test { - - /** - * @param args - * @throws SecurityException - * @throws NoSuchMethodException - */ - public static void main(String[] args) throws NoSuchMethodException, SecurityException { - DebugEnvironment.initialize(System.out); - MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess(); - Method method = Example.class.getDeclaredMethod("loop7", new Class[]{int.class, int.class}); - final ResolvedJavaMethod javaMethod = metaAccess.lookupJavaMethod(method); - TestUtil.compileMethod(javaMethod); - } -} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java --- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java Thu Mar 20 13:50:21 2014 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerIfSimplify.java --- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerIfSimplify.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerIfSimplify.java Thu Mar 20 13:50:21 2014 +0100 @@ -68,7 +68,7 @@ // TODO(mg) // thenBlocks and elseBlocks can be both empty --> causes an AssertionError DecompilerIfBlock ifBlock = new DecompilerIfBlock(block.getBlock(), decompiler, thenBlocks, elseBlocks, infoStream); - if (thenBlocks.contains(block.getBlock()) || elseBlocks.contains(block.getBlock())) { + if (thenBlocks.contains(block) || elseBlocks.contains(block)) { throw new AssertionError(); } blocks.add(ifBlock); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerIfBlock.java --- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerIfBlock.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerIfBlock.java Thu Mar 20 13:50:21 2014 +0100 @@ -158,7 +158,20 @@ @Override public boolean contains(Block b) { - return b == block || thenBranch.contains(b) || elseBranch.contains(b); + if (b == block) { + return true; + } + for (DecompilerBlock i : thenBranch) { + if (i.block == b) { + return true; + } + } + for (DecompilerBlock i : elseBranch) { + if (i.block == b) { + return true; + } + } + return false; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Thu Mar 20 13:50:21 2014 +0100 @@ -748,7 +748,7 @@ int blockID = block.blockID; // log statements in IFs because debugLiveX creates a new String if (Debug.isLogEnabled()) { - Debug.log(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), + Debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), debugLiveKill(blockID)); } @@ -767,7 +767,7 @@ if (blockChanged) { updateLiveness(blockID); if (Debug.isLogEnabled()) { - Debug.log(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), + Debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), debugLiveKill(blockID)); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -70,7 +70,7 @@ public static final class RuntimeCalls { public static final ForeignCallDescriptor CREATE_NULL_POINTER_EXCEPTION = new ForeignCallDescriptor("createNullPointerException", NullPointerException.class); - public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", IndexOutOfBoundsException.class, int.class); + public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class); } /** diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Thu Mar 20 13:50:21 2014 +0100 @@ -204,7 +204,7 @@ return null; } - PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.getKind(), block)); + PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.stamp().unrestricted(), block)); for (int i = 0; i < block.phiPredecessorCount(); i++) { phi.addInput(currentValue); } @@ -302,7 +302,7 @@ } assert !block.isPhiAtMerge(value) : "phi function for this block already created"; - PhiNode phi = graph.addWithoutUnique(new PhiNode(value.getKind(), block)); + PhiNode phi = graph.addWithoutUnique(new PhiNode(value.stamp().unrestricted(), block)); phi.addInput(value); return phi; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java Thu Mar 20 13:50:21 2014 +0100 @@ -46,19 +46,18 @@ return sum; } - // CheckStyle: stop system..print check private static void doPrint(int n) { + PrintStream out = System.out; for (int i = 0; i < n; i++) { - System.out.print('x'); + out.print('x'); } } public static void main(String[] args) throws Exception { - System.out.println(test(10000)); + PrintStream out = System.out; + out.println(test(10000)); } - // CheckStyle: resume system..print check - @LongTest public void run0() throws Throwable { runTest("test", 10000); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java Thu Mar 20 13:50:21 2014 +0100 @@ -27,6 +27,25 @@ public class LoopParseLong extends JTTTest { + @SuppressWarnings("unused") + public static long testShortened(String s, int radix) throws NumberFormatException { + long result = 0; + boolean negative = false; + int len = s.length(); + char firstChar = s.charAt(0); + if (firstChar < '0') { + if (firstChar == '-') { + negative = true; + } else if (firstChar != '+') { + throw new NumberFormatException(); + } + if (len == 1) { + throw new NumberFormatException(); + } + } + return result; + } + public static long test(String s, int radix) throws NumberFormatException { if (s == null) { throw new NumberFormatException("null"); @@ -81,6 +100,8 @@ @LongTest public void run0() throws Throwable { + runTest("testShortened", "7", 10); + runTest("testShortened", "-100", 10); runTest("test", "7", 10); runTest("test", "-100", 10); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Thu Mar 20 13:50:21 2014 +0100 @@ -237,13 +237,6 @@ throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to object ref"); } break; - case NarrowOop: - if (input.isNull()) { - masm.emitStoreImmediate(kind, 0L, address.toAddress()); - } else { - throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to object ref"); - } - break; default: throw GraalInternalError.shouldNotReachHere(); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Thu Mar 20 13:50:21 2014 +0100 @@ -170,7 +170,7 @@ // Without this, frameNeedsAllocating() would never return true. int total = 0; for (StackSlot s : freedSlots) { - total += target.arch.getSizeInBytes(s.getKind()); + total += target.getSizeInBytes(s.getKind()); } if (total == spillSize - initialSpillSize) { // reset spill area size @@ -256,7 +256,7 @@ * @return the size in bytes */ protected int spillSlotSize(PlatformKind kind) { - return target.arch.getSizeInBytes(kind); + return target.getSizeInBytes(kind); } /** @@ -347,8 +347,8 @@ } } - public ReferenceMap initReferenceMap(boolean canHaveRegisters) { - ReferenceMap refMap = new ReferenceMap(canHaveRegisters ? target.arch.getRegisterReferenceMapBitCount() : 0, frameSize() / target.wordSize); + public ReferenceMap initReferenceMap(boolean hasRegisters) { + ReferenceMap refMap = target.createReferenceMap(hasRegisters, frameSize() / target.wordSize); for (StackSlot slot : objectStackSlots) { setReference(slot, refMap); } @@ -364,22 +364,14 @@ * @param refMap A reference map, as created by {@link #initReferenceMap(boolean)}. */ public void setReference(Value location, ReferenceMap refMap) { - Kind kind = location.getKind(); - if (kind == Kind.Object || kind == Kind.NarrowOop) { - if (isRegister(location)) { - refMap.setRegister(asRegister(location).number, kind == Kind.NarrowOop); - } else if (isStackSlot(location)) { - if (kind == Kind.NarrowOop) { - int offset = offsetForStackSlot(asStackSlot(location)); - assert offset % target.wordSize == 0 || offset % target.wordSize == target.wordSize / 2; - refMap.setStackSlot(offset / target.wordSize, offset % target.wordSize == 0, offset % target.wordSize != 0); - } else { - int index = indexForStackSlot(asStackSlot(location)); - refMap.setStackSlot(index, false, false); - } - } else { - assert isConstant(location); - } + PlatformKind kind = location.getPlatformKind(); + if (isRegister(location)) { + refMap.setRegister(asRegister(location).number, kind); + } else if (isStackSlot(location)) { + int offset = offsetForStackSlot(asStackSlot(location)); + refMap.setStackSlot(offset, kind); + } else { + assert isConstant(location); } } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Thu Mar 20 13:50:21 2014 +0100 @@ -27,7 +27,6 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.ConstantData; import com.oracle.graal.api.code.CompilationResult.Data; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; @@ -157,6 +156,10 @@ } public void recordInlineDataInCode(Constant data) { + recordInlineDataInCode(codeCache.createDataItem(data, 0)); + } + + public void recordInlineDataInCode(Data data) { assert data != null; int pos = asm.position(); Debug.log("Inline data in code: pos = %d, data = %s", pos, data); @@ -165,7 +168,7 @@ public AbstractAddress recordDataReferenceInCode(Constant data, int alignment) { assert data != null; - return recordDataReferenceInCode(new ConstantData(data, alignment)); + return recordDataReferenceInCode(codeCache.createDataItem(data, alignment)); } public AbstractAddress recordDataReferenceInCode(Data data) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Thu Mar 20 13:50:21 2014 +0100 @@ -332,7 +332,7 @@ PhiNode phi; switch (vpn.type()) { case Value: - phi = graph.addWithoutUnique(new PhiNode(vpn.getKind(), merge)); + phi = graph.addWithoutUnique(new PhiNode(vpn.stamp(), merge)); break; case Guard: phi = graph.addWithoutUnique(new PhiNode(vpn.type(), merge)); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Thu Mar 20 13:50:21 2014 +0100 @@ -170,7 +170,7 @@ PhiNode ret; switch (phi.type()) { case Value: - ret = new PhiNode(phi.getKind(), merge); + ret = new PhiNode(phi.stamp(), merge); break; case Guard: ret = new PhiNode(PhiType.Guard, merge); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.calc.*; @@ -53,15 +52,11 @@ private final PhiType type; /** - * Create a value phi ({@link PhiType#Value}) with the specified kind. + * Create a value phi ({@link PhiType#Value}) with the specified stamp. * - * @param kind the kind of the value + * @param stamp the stamp of the value * @param merge the merge that the new phi belongs to */ - public PhiNode(Kind kind, MergeNode merge) { - this(StampFactory.forKind(kind), merge); - } - public PhiNode(Stamp stamp, MergeNode merge) { super(stamp); assert stamp != StampFactory.forVoid(); @@ -186,7 +181,7 @@ public void addInput(ValueNode x) { assert !(x instanceof PhiNode) || ((PhiNode) x).merge() instanceof LoopBeginNode || ((PhiNode) x).merge() != this.merge(); - assert x.getKind() == getKind() || type != PhiType.Value; + assert x.stamp().isCompatible(stamp()) || type != PhiType.Value; values.add(x); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -66,6 +66,14 @@ if ((rawY & mask) == 0) { return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } + if (x().stamp() instanceof IntegerStamp) { + IntegerStamp xStamp = (IntegerStamp) x().stamp(); + if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) { + // No bits are set which are outside the mask, so the mask will have no effect. + return x(); + } + } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -93,6 +93,10 @@ if (stamp().isCompatible(value.stamp())) { return value; } + if (value instanceof ReinterpretNode) { + ReinterpretNode reinterpret = (ReinterpretNode) value; + return value.graph().unique(new ReinterpretNode(stamp(), reinterpret.value())); + } return this; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -73,7 +73,7 @@ return; } } - for (Node usage : usages().snapshot()) { + for (Node usage : usages().distinct().snapshot()) { List snapshot = usage.inputs().snapshot(); graph().removeFixed((FixedWithNextNode) usage); for (Node input : snapshot) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java Thu Mar 20 13:50:21 2014 +0100 @@ -85,8 +85,9 @@ if (stamp instanceof IllegalStamp) { IllegalStamp other = (IllegalStamp) stamp; return kind == other.kind; + } else { + return stamp.isCompatible(this); } - return false; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Thu Mar 20 13:50:21 2014 +0100 @@ -172,7 +172,7 @@ String declaringClass = option.declaringClass; Name fieldName = option.field.getSimpleName(); String comma = i == info.options.size() - 1 ? "" : ","; - out.printf(" new %s(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s%n", desc, name, type, help, declaringClass, fieldName, optionValue, comma); + out.printf(" new %s(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s\n", desc, name, type, help, declaringClass, fieldName, optionValue, comma); i++; } out.println(" );"); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -55,8 +56,8 @@ if (target instanceof AbstractDeoptimizeNode) { merge = graph.add(new MergeNode()); EndNode firstEnd = graph.add(new EndNode()); - reasonActionPhi = graph.addWithoutUnique(new PhiNode(Kind.Int, merge)); - speculationPhi = graph.addWithoutUnique(new PhiNode(Kind.Object, merge)); + reasonActionPhi = graph.addWithoutUnique(new PhiNode(StampFactory.forKind(Kind.Int), merge)); + speculationPhi = graph.addWithoutUnique(new PhiNode(StampFactory.forKind(Kind.Object), merge)); merge.addForwardEnd(firstEnd); reasonActionPhi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess())); speculationPhi.addInput(((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess())); diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -91,14 +91,6 @@ return inliningCount; } - public static void storeStatisticsAfterLowTier(StructuredGraph graph) { - ResolvedJavaMethod method = graph.method(); - if (method != null) { - CompiledMethodInfo info = compiledMethodInfo(graph.method()); - info.setLowLevelNodeCount(graph.getNodeCount()); - } - } - @Override protected void run(final StructuredGraph graph, final HighTierContext context) { final InliningData data = new InliningData(graph, context.getAssumptions()); @@ -310,15 +302,6 @@ return newGraph; } - private static synchronized CompiledMethodInfo compiledMethodInfo(ResolvedJavaMethod m) { - CompiledMethodInfo info = (CompiledMethodInfo) m.getCompilerStorage().get(CompiledMethodInfo.class); - if (info == null) { - info = new CompiledMethodInfo(); - m.getCompilerStorage().put(CompiledMethodInfo.class, info); - } - return info; - } - private abstract static class AbstractInliningPolicy implements InliningPolicy { protected final Map hints; @@ -371,7 +354,12 @@ protected static int previousLowLevelGraphSize(InlineInfo info) { int size = 0; for (int i = 0; i < info.numberOfMethods(); i++) { - size += compiledMethodInfo(info.methodAt(i)).lowLevelNodeCount(); + ResolvedJavaMethod m = info.methodAt(i); + ProfilingInfo profile = m.getProfilingInfo(); + int compiledGraphSize = profile.getCompilerIRSize(StructuredGraph.class); + if (compiledGraphSize > 0) { + size += compiledGraphSize; + } } return size; } @@ -864,21 +852,4 @@ return (graph != null ? MetaUtil.format("%H.%n(%p)", method()) : "") + remainingInvokes; } } - - private static class CompiledMethodInfo { - - private int lowLevelNodes; - - public CompiledMethodInfo() { - } - - public int lowLevelNodeCount() { - return lowLevelNodes; - } - - public void setLowLevelNodeCount(int lowLevelNodes) { - this.lowLevelNodes = lowLevelNodes; - } - - } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Thu Mar 20 13:50:21 2014 +0100 @@ -625,7 +625,7 @@ PhiNode returnValuePhi = null; if (invoke.asNode().getKind() != Kind.Void) { - returnValuePhi = graph.addWithoutUnique(new PhiNode(invoke.asNode().getKind(), returnMerge)); + returnValuePhi = graph.addWithoutUnique(new PhiNode(invoke.asNode().stamp().unrestricted(), returnMerge)); } MergeNode exceptionMerge = null; @@ -638,7 +638,7 @@ FixedNode exceptionSux = exceptionEdge.next(); graph.addBeforeFixed(exceptionSux, exceptionMerge); - exceptionObjectPhi = graph.addWithoutUnique(new PhiNode(Kind.Object, exceptionMerge)); + exceptionObjectPhi = graph.addWithoutUnique(new PhiNode(StampFactory.forKind(Kind.Object), exceptionMerge)); exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, Kind.Object, exceptionObjectPhi)); } @@ -1486,7 +1486,7 @@ if (returnNode.result() != null) { if (returnValuePhi == null) { - returnValuePhi = merge.graph().addWithoutUnique(new PhiNode(returnNode.result().getKind(), merge)); + returnValuePhi = merge.graph().addWithoutUnique(new PhiNode(returnNode.result().stamp().unrestricted(), merge)); } returnValuePhi.addInput(returnNode.result()); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -312,6 +312,8 @@ Mark preLoweringMark = node.graph().getMark(); ((Lowerable) node).lower(loweringTool); if (loweringTool.guardAnchor.asNode().isDeleted()) { + // TODO nextNode could be deleted but this is not currently supported + assert nextNode.isAlive(); loweringTool.guardAnchor = BeginNode.prevBegin(nextNode); } assert checkPostNodeLowering(node, loweringTool, preLoweringMark, unscheduledUsages); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -87,7 +87,7 @@ } if (lastLocationAccess instanceof PhiNode) { PhiNode phi = (PhiNode) lastLocationAccess; - PhiNode newPhi = phi.graph().addWithoutUnique(new PhiNode(n.getKind(), phi.merge())); + PhiNode newPhi = phi.graph().addWithoutUnique(new PhiNode(n.stamp().unrestricted(), phi.merge())); nodeMap.set(phi, newPhi); for (ValueNode value : phi.values()) { newPhi.addInput(getValue(n, (MemoryNode) value, nodeMap)); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -486,7 +486,7 @@ // introduce a new phi PhiNode newPhi = bottomPhis.get(node); if (newPhi == null) { - newPhi = graph.addWithoutUnique(new PhiNode(node.getKind(), newBottomMerge)); + newPhi = graph.addWithoutUnique(new PhiNode(node.stamp().unrestricted(), newBottomMerge)); bottomPhis.put(node, newPhi); newPhi.addInput(node); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -36,7 +36,7 @@ */ public abstract class BasePhase { - private final String name; + private CharSequence name; private final DebugTimer phaseTimer; private final DebugMetric phaseMetric; @@ -49,25 +49,18 @@ } protected BasePhase() { - String nm = this.getClass().getSimpleName(); - if (nm.endsWith("Phase")) { - name = nm.substring(0, nm.length() - "Phase".length()); - } else { - name = nm; - } - assert checkName(name); - phaseTimer = Debug.timer("PhaseTime_" + name); - phaseMetric = Debug.metric("PhaseCount_" + name); + phaseTimer = Debug.timer("PhaseTime_%s", getClass()); + phaseMetric = Debug.metric("PhaseCount_%s", getClass()); } protected BasePhase(String name) { assert checkName(name); this.name = name; - phaseTimer = Debug.timer("PhaseTime_" + name); - phaseMetric = Debug.metric("PhaseCount_" + name); + phaseTimer = Debug.timer("PhaseTime_%s", getClass()); + phaseMetric = Debug.metric("PhaseCount_%s", getClass()); } - protected String getDetailedName() { + protected CharSequence getDetailedName() { return getName(); } @@ -76,7 +69,7 @@ } public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { - try (TimerCloseable a = phaseTimer.start(); Scope s = Debug.scope(name, this)) { + try (TimerCloseable a = phaseTimer.start(); Scope s = Debug.scope(getClass(), this)) { BasePhase.this.run(graph, context); phaseMetric.increment(); if (dumpGraph) { @@ -88,7 +81,14 @@ } } - public final String getName() { + public final CharSequence getName() { + if (name == null) { + String s = BasePhase.this.getClass().getSimpleName(); + if (s.endsWith("Phase")) { + s = s.substring(0, s.length() - "Phase".length()); + } + name = s; + } return name; } diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Mar 20 13:50:21 2014 +0100 @@ -177,6 +177,8 @@ @Option(help = "") public static final OptionValue HotSpotPrintCompilation = new OptionValue<>(false); @Option(help = "") + public static final OptionValue HotSpotCIPrintCompilerName = new OptionValue<>(false); + @Option(help = "") public static final OptionValue HotSpotPrintInlining = new OptionValue<>(false); // Register allocator debugging diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/LazyName.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/LazyName.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases; + +import com.oracle.graal.debug.*; + +/** + * A name whose {@link String} value is computed only when it is needed. This is useful in + * combination with debugging facilities such as {@link Debug#scope(Object)} where the + * {@link String} value of a name is only needed if debugging is enabled. + */ +public abstract class LazyName implements CharSequence { + + private String value; + + public int length() { + return toString().length(); + } + + public char charAt(int index) { + return toString().charAt(index); + } + + public CharSequence subSequence(int start, int end) { + return toString().subSequence(start, end); + } + + @Override + public final String toString() { + if (value == null) { + value = createString(); + } + return value; + } + + /** + * Creates the {@link String} value of this name. + */ + protected abstract String createString(); +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Thu Mar 20 13:50:21 2014 +0100 @@ -85,7 +85,7 @@ private static void visitForward(ArrayList nodes, NodeBitMap visited, Node node, boolean floatingOnly) { try { - assert node.isAlive() : node + " not alive"; + assert node == null || node.isAlive() : node + " not alive"; if (node != null && !visited.isMarked(node)) { if (floatingOnly && node instanceof FixedNode) { throw new GraalInternalError("unexpected reference to fixed node: %s (this indicates an unexpected cycle)", node); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/MethodDebugValueName.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/MethodDebugValueName.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.util; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.phases.*; + +/** + * Lazily computed debug value name composed of a prefix and a {@linkplain JavaMethod#getName() + * method name}. + */ +public class MethodDebugValueName extends LazyName { + final String prefix; + final JavaMethod method; + + public MethodDebugValueName(String prefix, JavaMethod method) { + this.prefix = prefix; + this.method = method; + } + + @Override + public String createString() { + return prefix + "[" + method.getName() + "]"; + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Thu Mar 20 13:50:21 2014 +0100 @@ -41,6 +41,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.schedule.*; /** * Utility for printing Graal IR at various compilation phases. @@ -51,6 +52,7 @@ protected LIR lir; protected LIRGenerator lirGenerator; protected ControlFlowGraph cfg; + protected SchedulePhase schedule; /** * Creates a control flow graph printer. @@ -118,7 +120,7 @@ private NodeBitMap printedNodes; private boolean inFixedSchedule(Node node) { - return lir != null || node.isDeleted() || cfg.getNodeToBlock().get(node) != null; + return lir != null || schedule != null || node.isDeleted() || cfg.getNodeToBlock().get(node) != null; } /** @@ -185,6 +187,20 @@ } private void printBlock(AbstractBlock block, boolean printNodes) { + printBlockProlog(block); + if (printNodes) { + assert block instanceof Block; + printNodes((Block) block); + } + printBlockEpilog(block); + } + + private void printBlockEpilog(AbstractBlock block) { + printLIR(block); + end("block"); + } + + private void printBlockProlog(AbstractBlock block) { begin("block"); out.print("name \"").print(blockToString(block)).println('"'); @@ -229,18 +245,10 @@ out.print("loop_index ").println(block.getLoop().index); out.print("loop_depth ").println(block.getLoop().depth); } - - if (printNodes) { - printedNodes = new NodeBitMap(cfg.graph); - assert block instanceof Block; - printNodes((Block) block); - printedNodes = null; - } - printLIR(block); - end("block"); } private void printNodes(Block block) { + printedNodes = new NodeBitMap(cfg.graph); begin("IR"); out.println("HIR"); out.disableIndentation(); @@ -274,6 +282,7 @@ out.enableIndentation(); end("IR"); + printedNodes = null; } private void printNode(Node node, boolean unscheduled) { @@ -289,7 +298,7 @@ } if (unscheduled) { - assert lir == null : "unscheduled nodes can only be present before LIR generation"; + assert lir == null && schedule == null : "unscheduled nodes can only be present before LIR generation"; out.print("f ").print(HOVER_START).print("u").print(HOVER_SEP).print("unscheduled").print(HOVER_END).println(COLUMN_END); } else if (node instanceof FixedWithNextNode) { out.print("f ").print(HOVER_START).print("#").print(HOVER_SEP).print("fixed with next").print(HOVER_END).println(COLUMN_END); @@ -466,7 +475,7 @@ return "-"; } String prefix; - if (node instanceof AbstractBeginNode && lir == null) { + if (node instanceof AbstractBeginNode && (lir == null && schedule == null)) { prefix = "B"; } else if (node instanceof ValueNode) { ValueNode value = (ValueNode) node; @@ -482,7 +491,7 @@ } private String blockToString(AbstractBlock block) { - if (lir == null && block instanceof Block) { + if (lir == null && schedule == null && block instanceof Block) { // During all the front-end phases, the block schedule is built only for the debug // output. // Therefore, the block numbers would be different for every CFG printed -> use the id @@ -541,4 +550,46 @@ out.printf(" \"%s\"", interval.spillState()); out.println(); } + + public void printSchedule(String message, SchedulePhase theSchedule) { + schedule = theSchedule; + cfg = schedule.getCFG(); + printedNodes = new NodeBitMap(cfg.graph); + + begin("cfg"); + out.print("name \"").print(message).println('"'); + for (Block b : schedule.getCFG().getBlocks()) { + if (schedule.nodesFor(b) != null) { + printScheduledBlock(b, schedule.nodesFor(b)); + } + } + end("cfg"); + + schedule = null; + cfg = null; + printedNodes = null; + } + + private void printScheduledBlock(Block block, List nodesFor) { + printBlockProlog(block); + begin("IR"); + out.println("HIR"); + out.disableIndentation(); + + if (block.getBeginNode() instanceof MergeNode) { + // Currently phi functions are not in the schedule, so print them separately here. + for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) { + printNode(phi, false); + } + } + + for (Node n : nodesFor) { + printNode(n, false); + } + + out.enableIndentation(); + end("IR"); + + printBlockEpilog(block); + } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Mar 20 13:50:21 2014 +0100 @@ -36,6 +36,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.schedule.*; /** * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the @@ -162,6 +163,8 @@ boolean printNodes = previousObject != object && cfgPrinter.cfg != null; cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder(), printNodes); + } else if (object instanceof SchedulePhase) { + cfgPrinter.printSchedule(message, (SchedulePhase) object); } else if (object instanceof StructuredGraph) { if (cfgPrinter.cfg == null) { StructuredGraph graph = (StructuredGraph) object; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java Thu Mar 20 13:50:21 2014 +0100 @@ -134,16 +134,17 @@ */ protected String debugInfoToString(BytecodePosition codePos, ReferenceMap refMap, RegisterSaveLayout calleeSaveInfo, Architecture arch) { StringBuilder sb = new StringBuilder(); + RefMapFormatter formatter = new CodeUtil.NumberedRefMapFormatter(); if (refMap != null && refMap.hasRegisterRefMap()) { sb.append("reg-ref-map:"); - refMap.appendRegisterMap(sb, arch != null ? new ArchitectureRegFormatter(arch) : null); + refMap.appendRegisterMap(sb, arch != null ? new ArchitectureRegFormatter(arch) : formatter); sb.append("\n"); } if (refMap != null && refMap.hasFrameRefMap()) { sb.append("frame-ref-map:"); - refMap.appendFrameMap(sb, null); + refMap.appendFrameMap(sb, formatter); sb.append("\n"); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java Thu Mar 20 13:50:21 2014 +0100 @@ -35,6 +35,7 @@ public class DecompilerDebugDumpHandler implements DebugDumpHandler { + public static boolean printToNowhere; private final PrintStream infoPrintStream = System.out; private File file; private FileOutputStream fos; @@ -55,6 +56,15 @@ filter = filter.substring(0, filter.indexOf("Phase")); } + if (printToNowhere) { + printStream = new PrintStream(new OutputStream() { + @Override + public void write(int b) throws IOException { + // DO NOTHING + } + }); + } + if (printStream == null) { fileName = "decompilerDump_" + uniqueId.incrementAndGet() + "_" + System.currentTimeMillis() + ".txt"; file = new File(fileName); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Thu Mar 20 13:50:21 2014 +0100 @@ -202,7 +202,7 @@ for (Object o : Debug.context()) { JavaMethod method = asJavaMethod(o); if (method != null) { - if (lastMethodOrGraph == null || !asJavaMethod(lastMethodOrGraph).equals(method)) { + if (lastMethodOrGraph == null || asJavaMethod(lastMethodOrGraph) == null || !asJavaMethod(lastMethodOrGraph).equals(method)) { result.add(MetaUtil.format("%H::%n(%p)", method)); } else { // This prevents multiple adjacent method context objects for the same method diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Thu Mar 20 13:50:21 2014 +0100 @@ -293,9 +293,8 @@ } void warning(int offset, String message) { - // CheckStyle: stop system..print check - System.err.println("Warning: " + errorMessage(offset, message)); - // CheckStyle: resume system..print check + PrintStream err = System.err; + err.println("Warning: " + errorMessage(offset, message)); } String errorMessage(int offset, String message) { @@ -323,10 +322,9 @@ int lineStart = input.lastIndexOf(HexCodeFile.NEW_LINE, index) + 1; String l = input.substring(lineStart, lineStart + 10); - // CheckStyle: stop system..print check - System.out.println("YYY" + input.substring(index, index + 10) + "..."); - System.out.println("XXX" + l + "..."); - // CheckStyle: resume system..print check + PrintStream out = System.out; + out.println("YYY" + input.substring(index, index + 10) + "..."); + out.println("XXX" + l + "..."); int pos = input.indexOf(HexCodeFile.NEW_LINE, 0); int line = 1; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -29,8 +29,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.virtual.phases.ea.*; /** * Tests {@link ArraysSubstitutions}. @@ -329,4 +333,111 @@ return Arrays.equals(a, b); } + @Test + public void testEqualsNodeGVN() { + test("testEqualsNodeGVNSnippet", true); + } + + public static int[] intArrayCompare = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; + public static int[] intArray; + + public static boolean testEqualsNodeGVNSnippet(boolean b) { + int[] newIntArray = new int[]{0, 2, 3, 4, 5, 6, 7, 8, 9}; + intArray = newIntArray; + + if (b) { + newIntArray[0] = 1; + return Arrays.equals(newIntArray, intArrayCompare); + } else { + newIntArray[0] = 1; + return Arrays.equals(newIntArray, intArrayCompare); + } + } + + @Test + public void testConstants() { + test("testConstantsSnippet"); + } + + public static final int[] constantArray1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; + public static final int[] constantArray2 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; + + public static boolean testConstantsSnippet() { + constantArray2[0] = 10; + try { + return Arrays.equals(constantArray1, constantArray2); + } finally { + constantArray2[0] = 1; + } + } + + @Test + public void testCanonicalLength() { + StructuredGraph graph = parse("testCanonicalLengthSnippet"); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + + Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 0); + } + + public static final int[] constantArray3 = new int[]{1, 2, 3}; + + public static boolean testCanonicalLengthSnippet() { + return Arrays.equals(constantArray1, constantArray3); + } + + @Test + public void testCanonicalEqual() { + StructuredGraph graph = parse("testCanonicalEqualSnippet"); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + + Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 1); + } + + public static boolean testCanonicalEqualSnippet() { + return Arrays.equals(constantArray1, constantArray1); + } + + @Test + public void testVirtualEqual() { + StructuredGraph graph = parse("testVirtualEqualSnippet"); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + + Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 1); + } + + public static boolean testVirtualEqualSnippet() { + int[] array1 = new int[]{1, 2, 3, 4}; + int[] array2 = new int[]{1, 2, 3, 4}; + return Arrays.equals(array1, array2); + } + + @Test + public void testVirtualNotEqual() { + StructuredGraph graph = parse("testVirtualNotEqualSnippet"); + Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + + Assert.assertTrue(graph.getNodes(ReturnNode.class).first().result().asConstant().asLong() == 0); + } + + public static boolean testVirtualNotEqualSnippet(int x) { + int[] array1 = new int[]{1, 2, 100, x}; + int[] array2 = new int[]{1, 2, 3, 4}; + return Arrays.equals(array1, array2); + } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Mar 20 13:50:21 2014 +0100 @@ -99,7 +99,7 @@ FrameStateProcessing frameStateProcessing = method.getAnnotation(Snippet.class).removeAllFrameStates() ? FrameStateProcessing.Removal : FrameStateProcessing.CollapseFrameForSingleSideEffect; StructuredGraph newGraph = makeGraph(method, recursiveEntry, recursiveEntry, inliningPolicy(method), frameStateProcessing); - Debug.metric("SnippetNodeCount[" + method.getName() + "]").add(newGraph.getNodeCount()); + Debug.metric("SnippetNodeCount[%#s]", method).add(newGraph.getNodeCount()); if (!UseSnippetGraphCache) { return newGraph; } @@ -201,8 +201,8 @@ } } } - // We don't have per method guards for macro substitutions but at least respect the - // defaultGuard if there is one. + // We don't have per method guards for macro substitutions but at + // least respect the defaultGuard if there is one. if (macroSubstitution != null && (defaultGuard == null || defaultGuard.execute())) { String originalName = originalName(substituteMethod, macroSubstitution.value()); JavaSignature originalSignature = originalSignature(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic()); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Mar 20 13:50:21 2014 +0100 @@ -24,6 +24,8 @@ import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.debug.Debug.*; +import static java.util.FormattableFlags.*; import java.io.*; import java.lang.reflect.*; @@ -97,8 +99,8 @@ protected SnippetInfo(ResolvedJavaMethod method) { this.method = method; - instantiationCounter = Debug.metric("SnippetInstantiationCount[" + method.getName() + "]"); - instantiationTimer = Debug.timer("SnippetInstantiationTime[" + method.getName() + "]"); + instantiationCounter = Debug.metric("SnippetInstantiationCount[%#s]", method); + instantiationTimer = Debug.timer("SnippetInstantiationTime[%#s]", method); assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); int count = method.getSignature().getParameterCount(false); constantParameters = new boolean[count]; @@ -176,7 +178,7 @@ * {@link SnippetTemplate#instantiate instantiated} *

*/ - public static class Arguments { + public static class Arguments implements Formattable { protected final SnippetInfo info; protected final CacheKey cacheKey; @@ -243,6 +245,30 @@ result.append(">"); return result.toString(); } + + public void formatTo(Formatter formatter, int flags, int width, int precision) { + if ((flags & ALTERNATE) == 0) { + formatter.format(applyFormattingFlagsAndWidth(toString(), flags, width)); + } else { + StringBuilder sb = new StringBuilder(); + sb.append(info.method.getName()).append('('); + String sep = ""; + for (int i = 0; i < info.getParameterCount(); i++) { + if (info.isConstantParameter(i)) { + sb.append(sep); + if (info.names[i] != null) { + sb.append(info.names[i]); + } else { + sb.append(i); + } + sb.append('=').append(values[i]); + sep = ", "; + } + } + sb.append(")"); + formatter.format(applyFormattingFlagsAndWidth(sb.toString(), flags & ~ALTERNATE, width)); + } + } } /** @@ -440,38 +466,13 @@ return false; } - private static String debugValueName(String category, Arguments args) { - if (Debug.isEnabled()) { - StringBuilder result = new StringBuilder(category).append('['); - SnippetInfo info = args.info; - result.append(info.method.getName()).append('('); - String sep = ""; - for (int i = 0; i < info.getParameterCount(); i++) { - if (info.isConstantParameter(i)) { - result.append(sep); - if (info.names[i] != null) { - result.append(info.names[i]); - } else { - result.append(i); - } - result.append('=').append(args.values[i]); - sep = ", "; - } - } - result.append(")]"); - return result.toString(); - - } - return null; - } - /** * Creates a snippet template. */ protected SnippetTemplate(final Providers providers, Arguments args) { StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method); - instantiationTimer = Debug.timer(debugValueName("SnippetTemplateInstantiationTime", args)); - instantiationCounter = Debug.metric(debugValueName("SnippetTemplateInstantiationCount", args)); + instantiationTimer = Debug.timer("SnippetTemplateInstantiationTime[%#s]", args); + instantiationCounter = Debug.metric("SnippetTemplateInstantiationCount[%#s]", args); ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); @@ -665,7 +666,7 @@ } } - Debug.metric(debugValueName("SnippetTemplateNodeCount", args)).add(nodes.size()); + Debug.metric("SnippetTemplateNodeCount[%#s]", args).add(nodes.size()); args.info.notifyNewTemplate(); Debug.dump(snippet, "SnippetTemplate final state"); } @@ -876,10 +877,11 @@ @Override public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) { - if (mmap != null && newNode != null) { + if (mmap != null) { for (Node usage : oldNode.usages().snapshot()) { LocationIdentity identity = getLocationIdentity(usage); - if (identity != null && identity != LocationIdentity.FINAL_LOCATION) { + boolean usageReplaced = false; + if (identity != null && identity != FINAL_LOCATION) { // lastLocationAccess points into the snippet graph. find a proper // MemoryCheckPoint inside the snippet graph MemoryNode lastAccess = mmap.getLastLocationAccess(identity); @@ -888,17 +890,26 @@ if (usage instanceof MemoryAccess) { MemoryAccess access = (MemoryAccess) usage; if (access.getLastLocationAccess() == oldNode) { - assert newNode.graph().isAfterFloatingReadPhase(); + assert oldNode.graph().isAfterFloatingReadPhase(); access.setLastLocationAccess(lastAccess); + usageReplaced = true; } } else { assert usage instanceof MemoryProxy || usage instanceof MemoryPhiNode; usage.replaceFirstInput(oldNode, lastAccess.asNode()); + usageReplaced = true; } } + if (!usageReplaced) { + assert newNode != null : "this branch is only valid if we have a newNode for replacement"; + } } } - oldNode.replaceAtUsages(newNode); + if (newNode == null) { + assert oldNode.usages().isEmpty(); + } else { + oldNode.replaceAtUsages(newNode); + } } }; @@ -1002,12 +1013,6 @@ // Re-wire the control flow graph around the replacee FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); replacee.replaceAtPredecessor(firstCFGNodeDuplicate); - FixedNode next = null; - if (replacee instanceof FixedWithNextNode) { - FixedWithNextNode fwn = (FixedWithNextNode) replacee; - next = fwn.next(); - fwn.setNext(null); - } if (replacee instanceof StateSplit) { for (StateSplit sideEffectNode : sideEffectNodes) { @@ -1036,12 +1041,18 @@ returnValue = returnDuplicate.result(); MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start()); if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) { - replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap); + replacer.replace(replacee, null, mmap); } else { assert returnValue != null || replacee.usages().isEmpty(); replacer.replace(replacee, returnValue, mmap); } if (returnDuplicate.isAlive()) { + FixedNode next = null; + if (replacee instanceof FixedWithNextNode) { + FixedWithNextNode fwn = (FixedWithNextNode) replacee; + next = fwn.next(); + fwn.setNext(null); + } returnDuplicate.clearInputs(); returnDuplicate.replaceAndDelete(next); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.replacements.nodes; -import java.util.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; @@ -31,13 +29,14 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; /** * Compares two arrays with the same length. */ -public class ArrayEqualsNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class ArrayEqualsNode extends FixedWithNextNode implements LIRGenLowerable, Canonicalizable, Virtualizable { /** {@link Kind} of the arrays to compare. */ private final Kind kind; @@ -66,42 +65,45 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (!array1.isConstant() || !array2.isConstant()) { - return this; + if (usages().isEmpty()) { + return null; } + if (GraphUtil.unproxify(array1) == GraphUtil.unproxify(array2)) { + return ConstantNode.forBoolean(true, graph()); + } + return this; + } - Object a1 = array1.asConstant().asObject(); - Object a2 = array2.asConstant().asObject(); - boolean x; - switch (kind) { - case Boolean: - x = Arrays.equals((boolean[]) a1, (boolean[]) a2); - break; - case Byte: - x = Arrays.equals((byte[]) a1, (byte[]) a2); - break; - case Char: - x = Arrays.equals((char[]) a1, (char[]) a2); - break; - case Short: - x = Arrays.equals((short[]) a1, (short[]) a2); - break; - case Int: - x = Arrays.equals((int[]) a1, (int[]) a2); - break; - case Long: - x = Arrays.equals((long[]) a1, (long[]) a2); - break; - case Float: - x = Arrays.equals((float[]) a1, (float[]) a2); - break; - case Double: - x = Arrays.equals((double[]) a1, (double[]) a2); - break; - default: - throw GraalInternalError.shouldNotReachHere("unknown kind " + kind); + public void virtualize(VirtualizerTool tool) { + State state1 = tool.getObjectState(array1); + if (state1 != null) { + State state2 = tool.getObjectState(array2); + if (state2 != null) { + if (state1.getVirtualObject() == state2.getVirtualObject()) { + // the same virtual objects will always have the same contents + tool.replaceWithValue(ConstantNode.forBoolean(true, graph())); + } else if (state1.getVirtualObject().entryCount() == state2.getVirtualObject().entryCount()) { + int entryCount = state1.getVirtualObject().entryCount(); + boolean allEqual = true; + for (int i = 0; i < entryCount; i++) { + ValueNode entry1 = state1.getEntry(i); + ValueNode entry2 = state2.getEntry(i); + if (entry1 != entry2) { + // the contents might be different + allEqual = false; + } + if (entry1.stamp().alwaysDistinct(entry2.stamp())) { + // the contents are different + tool.replaceWithValue(ConstantNode.forBoolean(false, graph())); + return; + } + } + if (allEqual) { + tool.replaceWithValue(ConstantNode.forBoolean(true, graph())); + } + } + } } - return ConstantNode.forBoolean(x, graph()); } @NodeIntrinsic diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java --- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Thu Mar 20 13:50:21 2014 +0100 @@ -162,7 +162,6 @@ case Int: case Long: case Object: - case NarrowOop: return true; } } else if (category == FPU) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Thu Mar 20 13:50:21 2014 +0100 @@ -29,8 +29,8 @@ import com.oracle.graal.asm.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.truffle.*; @@ -51,10 +51,9 @@ @Override public Mark recordMark(Object id) { Mark mark = super.recordMark(id); - if (Integer.valueOf(Marks.MARK_VERIFIED_ENTRY).equals(id)) { - HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); + if (MarkId.getEnum((int) id) == MarkId.VERIFIED_ENTRY) { HotSpotRegistersProvider registers = HotSpotGraalRuntime.runtime().getHostProviders().getRegisters(); - injectTailCallCode(config, registers); + injectTailCallCode(HotSpotGraalRuntime.runtime().getConfig(), registers); } return mark; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ControlFlowExceptionPartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ControlFlowExceptionPartialEvaluationTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ControlFlowExceptionPartialEvaluationTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -62,7 +62,7 @@ @Child private AbstractTestNode child; public CatchControlFlowExceptionTestNode(AbstractTestNode child) { - this.child = adoptChild(child); + this.child = child; } @Override @@ -80,7 +80,7 @@ @Child private AbstractTestNode child; public CatchSlowPathAndControlFlowExceptionTestNode(AbstractTestNode child) { - this.child = adoptChild(child); + this.child = child; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -30,8 +30,8 @@ @Child private AbstractTestNode right; public AddTestNode(AbstractTestNode left, AbstractTestNode right) { - this.left = adoptChild(left); - this.right = adoptChild(right); + this.left = left; + this.right = right; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -30,7 +30,7 @@ @Children private final AbstractTestNode[] statements; public BlockTestNode(AbstractTestNode[] statements) { - this.statements = adoptChildren(statements); + this.statements = statements; } @ExplodeLoop diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -31,7 +31,7 @@ public LoopTestNode(int numberOfIterations, AbstractTestNode child) { this.numberOfIterations = numberOfIterations; - this.child = adoptChild(child); + this.child = child; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -22,13 +22,13 @@ */ package com.oracle.graal.truffle; -import java.util.concurrent.atomic.*; +import java.util.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; /** * Call target that is optimized by Graal upon surpassing a specific invocation threshold. @@ -60,7 +60,7 @@ } @SuppressWarnings("unused") - public void nodeReplaced(Node oldNode, Node newNode, String reason) { + public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) { } @Override @@ -85,6 +85,11 @@ return new DefaultOptimizedCallNode(target); } + @Override + public boolean isInlinable() { + return true; + } + private static final class DefaultOptimizedCallNode extends OptimizedCallNode { private boolean trySplit = true; @@ -120,54 +125,49 @@ if (!isSplittable()) { return false; } - int nodeCount = NodeUtil.countNodes(getCallTarget().getRootNode(), null, false); + int nodeCount = NodeUtil.countNodes(getCallTarget().getRootNode(), OptimizedCallNodeProfile.COUNT_FILTER, false); if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) { return false; } - // // is the only call target -> do not split - // if (getCallTarget().getRootNode().getCachedCallNodes().size() == 1 && - // getCallTarget().getRootNode().getCachedCallNodes().contains(this)) { - // return false; - // } + // disable recursive splitting for now + OptimizedCallTarget splitTarget = getCallTarget(); + List compilationRoots = OptimizedCallNodeProfile.findCompilationRoots(this); + for (OptimizedCallTarget compilationRoot : compilationRoots) { + if (compilationRoot == splitTarget || compilationRoot.getSplitSource() == splitTarget) { + // recursive call found + return false; + } + } // max one child call and callCount > 2 and kind of small number of nodes if (isMaxSingleCall()) { return true; } - return countPolymorphic() >= 1 || countGeneric() > 0; + return countPolymorphic() >= 1; } @Override - public void nodeReplaced(Node oldNode, Node newNode, String reason) { - trySplit = true; - } - - @Override - protected void notifyCallNodeAdded() { + public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) { trySplit = true; } private boolean isMaxSingleCall() { - final AtomicInteger count = new AtomicInteger(0); - getCurrentCallTarget().getRootNode().accept(new NodeVisitor() { - - public boolean visit(Node node) { - if (node instanceof CallNode) { - return count.incrementAndGet() > 1; - } - return true; + return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node instanceof CallNode; } - }); - return count.get() <= 1; + }) <= 1; } private int countPolymorphic() { - return NodeUtil.countNodes(getCallTarget().getRootNode(), null, Kind.POLYMORPHIC, false); - } - - private int countGeneric() { - return NodeUtil.countNodes(getCallTarget().getRootNode(), null, Kind.GENERIC, false); + return NodeUtil.countNodes(getCallTarget().getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + NodeCost cost = node.getCost(); + boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC; + return polymorphic; + } + }); } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNodeProfile.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNodeProfile.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNodeProfile.java Thu Mar 20 13:50:21 2014 +0100 @@ -27,11 +27,13 @@ import java.util.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.*; public class OptimizedCallNodeProfile implements TruffleInliningProfile { + static final CountFilter COUNT_FILTER = new CountFilter(); + private static final String REASON_RECURSION = "recursion"; - private static final String REASON_FREQUENCY_CUTOFF = "frequency < " + TruffleInliningMinFrequency.getValue(); private static final String REASON_MAXIMUM_NODE_COUNT = "shallowTargetCount > " + TruffleInliningMaxCalleeSize.getValue(); private static final String REASON_MAXIMUM_TOTAL_NODE_COUNT = "inlinedTotalCount > " + TruffleInliningMaxCallerSize.getValue(); @@ -49,8 +51,8 @@ this.callNode = callNode; RootNode inlineRoot = callNode.getCurrentCallTarget().getRootNode(); this.callTarget = target; - this.targetShallowNodeCount = NodeUtil.countNodes(inlineRoot, null, false); - this.targetDeepNodeCount = NodeUtil.countNodes(inlineRoot, null, true); + this.targetShallowNodeCount = NodeUtil.countNodes(inlineRoot, COUNT_FILTER, false); + this.targetDeepNodeCount = NodeUtil.countNodes(inlineRoot, COUNT_FILTER, true); this.compilationRoots = findCompilationRoots(callNode); this.averageFrequency = calculateFrequency(); this.score = calculateScore(); @@ -84,18 +86,12 @@ } } - // frequency cut-off - if (averageFrequency < TruffleInliningMinFrequency.getValue() && targetDeepNodeCount > TruffleInliningTrivialSize.getValue()) { - reason = REASON_FREQUENCY_CUTOFF; - return false; - } - if (targetShallowNodeCount > TruffleInliningMaxCalleeSize.getValue()) { reason = REASON_MAXIMUM_NODE_COUNT; return false; } - this.targetDeepNodeCount = NodeUtil.countNodes(inlineTarget.getRootNode(), null, true); + this.targetDeepNodeCount = NodeUtil.countNodes(inlineTarget.getRootNode(), COUNT_FILTER, true); // The maximum total node count cannot be cached since it may change during inlining. int nextNodeCount = calculateInlinedTotalNodeCount(getCallNode()); if (nextNodeCount > TruffleInliningMaxCallerSize.getValue()) { @@ -116,6 +112,20 @@ return currentNodeCount; } + static class CountFilter implements NodeCountFilter { + public boolean isCounted(Node node) { + return countNode(node) >= 1; + } + } + + static int countNode(Node node) { + NodeCost cost = node.getCost(); + if (cost != null && cost != NodeCost.NONE && cost != NodeCost.UNINITIALIZED) { + return 1; + } + return 0; + } + private static class TotalNodeCountVisitor implements NodeVisitor { private final OptimizedCallNode inlinedNode; @@ -129,7 +139,7 @@ } public boolean visit(Node node) { - count++; + count += countNode(node); if (node instanceof OptimizedCallNode) { OptimizedCallNode callNode = ((OptimizedCallNode) node); if (callNode == inlinedNode) { @@ -191,7 +201,7 @@ return callNode.getCallCount() / (double) callTarget.getCompilationProfile().getCallCount(); } - private static List findCompilationRoots(Node call) { + static List findCompilationRoots(Node call) { RootNode root = call.getRootNode(); if (root == null) { return Collections.emptyList(); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Thu Mar 20 13:50:21 2014 +0100 @@ -34,7 +34,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; /** * Call target that is optimized by Graal upon surpassing a specific invocation threshold. @@ -136,7 +136,7 @@ return call(caller, args); } - private void invalidate(Node oldNode, Node newNode, String reason) { + private void invalidate(Node oldNode, Node newNode, CharSequence reason) { InstalledCode m = this.installedCode; if (m != null) { CompilerAsserts.neverPartOfCompilation(); @@ -147,7 +147,7 @@ cancelInstalledTask(oldNode, newNode, reason); } - private void cancelInstalledTask(Node oldNode, Node newNode, String reason) { + private void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) { Future task = this.installedCodeTask; if (task != null) { task.cancel(true); @@ -298,7 +298,7 @@ } @Override - public void nodeReplaced(Node oldNode, Node newNode, String reason) { + public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) { compilationProfile.reportNodeReplaced(); invalidate(oldNode, newNode, reason); @@ -382,7 +382,7 @@ } } - private static void logOptimizingUnqueued(OptimizedCallTarget target, Node oldNode, Node newNode, String reason) { + private static void logOptimizingUnqueued(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) { if (TraceTruffleCompilationDetails.getValue()) { Map properties = new LinkedHashMap<>(); addReplaceProperties(properties, oldNode, newNode); @@ -405,7 +405,7 @@ } } - private static void logOptimizedInvalidated(OptimizedCallTarget target, Node oldNode, Node newNode, String reason) { + private static void logOptimizedInvalidated(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) { if (TraceTruffleCompilation.getValue()) { Map properties = new LinkedHashMap<>(); addReplaceProperties(properties, oldNode, newNode); @@ -414,7 +414,7 @@ } } - private static void logOptimizingFailed(OptimizedCallTarget callSite, String reason) { + private static void logOptimizingFailed(OptimizedCallTarget callSite, CharSequence reason) { Map properties = new LinkedHashMap<>(); properties.put("Reason", reason); log(0, "opt fail", callSite.toString(), properties); @@ -428,11 +428,11 @@ target.getRootNode().accept(new NodeVisitor() { public boolean visit(Node node) { - Kind kind = node.getKind(); - if (kind == Kind.POLYMORPHIC || kind == Kind.GENERIC) { + NodeCost kind = node.getCost(); + if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) { Map props = new LinkedHashMap<>(); props.put("simpleName", node.getClass().getSimpleName()); - String msg = kind == Kind.GENERIC ? "generic" : "polymorphic"; + String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic"; log(0, msg, node.toString(), props); } if (node instanceof CallNode) { @@ -461,8 +461,20 @@ } static void addASTSizeProperty(RootNode target, Map properties) { - String value = String.format("%4d (%d/%d)", NodeUtil.countNodes(target.getRootNode(), null, true), // - NodeUtil.countNodes(target.getRootNode(), null, Kind.POLYMORPHIC, true), NodeUtil.countNodes(target.getRootNode(), null, Kind.GENERIC, true)); // + int polymorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node.getCost() == NodeCost.POLYMORPHIC; + } + }, true); + + int megamorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node.getCost() == NodeCost.MEGAMORPHIC; + } + }, true); + + String value = String.format("%4d (%d/%d)", NodeUtil.countNodes(target.getRootNode(), OptimizedCallNodeProfile.COUNT_FILTER, true), // + polymorphicCount, megamorphicCount); // properties.put("ASTSize", value); } @@ -521,8 +533,8 @@ continue; } - int nodeCount = NodeUtil.countNodes(callTarget.getRootNode(), null, true); - int inlinedCallSiteCount = countInlinedNodes(callTarget.getRootNode()); + int nodeCount = NodeUtil.countNodes(callTarget.getRootNode(), OptimizedCallNodeProfile.COUNT_FILTER, false); + int inlinedCallSiteCount = NodeUtil.countNodes(callTarget.getRootNode(), OptimizedCallNodeProfile.COUNT_FILTER, true); String comment = callTarget.installedCode == null ? " int" : ""; comment += callTarget.compilationEnabled ? "" : " fail"; OUT.printf("%-50s | %10d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, inlinedCallSiteCount, nodeCount, @@ -536,21 +548,6 @@ OUT.printf("%-50s | %10d | %15d | %10d | %3d\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNodeCount, totalInvalidationCount); } - private static int countInlinedNodes(Node rootNode) { - List callers = NodeUtil.findAllNodeInstances(rootNode, CallNode.class); - int count = 0; - for (CallNode callNode : callers) { - if (callNode.isInlined()) { - count++; - RootNode root = callNode.getCurrentRootNode(); - if (root != null) { - count += countInlinedNodes(root); - } - } - } - return count; - } - private static void registerCallTarget(OptimizedCallTarget callTarget) { callTargets.put(callTarget, 0); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Mar 20 13:50:21 2014 +0100 @@ -100,7 +100,7 @@ final StructuredGraph graph = new StructuredGraph(executeHelperMethod); - try (Scope s = Debug.scope("createGraph", graph)) { + try (Scope s = Debug.scope("CreateGraph", graph)) { new GraphBuilderPhase.Instance(providers.getMetaAccess(), config, TruffleCompilerImpl.Optimizations).apply(graph); // Replace thisNode with constant. @@ -250,7 +250,7 @@ StructuredGraph graph = truffleCache.lookup(targetMethod, arguments, assumptions, canonicalizer); if (targetMethod.getAnnotation(ExplodeLoop.class) != null) { - assert graph.hasLoops(); + assert graph.hasLoops() : graph + " does not contain a loop"; final StructuredGraph graphCopy = graph.copy(); final List modifiedNodes = new ArrayList<>(); for (ParameterNode param : graphCopy.getNodes(ParameterNode.class)) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java Thu Mar 20 13:50:21 2014 +0100 @@ -24,6 +24,8 @@ import static com.oracle.graal.truffle.TruffleCompilerOptions.*; +import java.io.*; + public class TimedCompilationPolicy extends DefaultCompilationPolicy { @Override @@ -39,9 +41,8 @@ // maybe introduce another method? profile.reportTiminingFailed(timestamp); if (TruffleCompilationDecisionTimePrintFail.getValue()) { - // Checkstyle: stop - System.out.println(profile.getName() + ": timespan " + (timespan / 1000000) + " ms larger than threshold"); - // Checkstyle: resume + PrintStream out = System.out; + out.println(profile.getName() + ": timespan " + (timespan / 1000000) + " ms larger than threshold"); } } return false; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Mar 20 13:50:21 2014 +0100 @@ -117,7 +117,7 @@ lastUsed.put(key, counter++); cache.put(key, markerGraph); - try (Scope s = Debug.scope("TruffleCache", new Object[]{providers.getMetaAccess(), method})) { + try (Scope s = Debug.scope("TruffleCache", providers.getMetaAccess(), method)) { final StructuredGraph graph = new StructuredGraph(method); final PhaseContext phaseContext = new PhaseContext(providers, new Assumptions(false)); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Thu Mar 20 13:50:21 2014 +0100 @@ -58,7 +58,7 @@ @Option(help = "Stop inlining if caller's cumulative tree size would exceed this limit") public static final OptionValue TruffleInliningMaxCallerSize = new OptionValue<>(2250); @Option(help = "Skip inlining candidate if its tree size exceeds this limit") - public static final OptionValue TruffleInliningMaxCalleeSize = new OptionValue<>(250); + public static final OptionValue TruffleInliningMaxCalleeSize = new OptionValue<>(350); @Option(help = "Call frequency relative to call target") public static final OptionValue TruffleInliningMinFrequency = new OptionValue<>(0.3); @Option(help = "Allow inlining of less hot candidates if tree size is small") diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleDebugJavaMethod.java Thu Mar 20 13:50:21 2014 +0100 @@ -30,7 +30,7 @@ /** * Enables a Truffle compilable to masquerade as a {@link JavaMethod} for use as a context value in - * {@linkplain Debug#scope(String, Object...) debug scopes}. + * {@linkplain Debug#scope(Object) debug scopes}. */ public class TruffleDebugJavaMethod implements JavaMethod { private final RootCallTarget compilable; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.virtual.phases.ea; +import static com.oracle.graal.debug.Debug.*; + import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; @@ -59,8 +61,7 @@ public boolean runAnalysis(final StructuredGraph graph, final PhaseContextT context) { boolean changed = false; for (int iteration = 0; iteration < maxIterations; iteration++) { - - try (Scope s = Debug.scope("iteration " + iteration)) { + try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) { SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph, false); Closure closure = createEffectsClosure(context, schedule); @@ -78,7 +79,9 @@ graph.stopTrackingInputChange(); graph.stopTrackingUsagesDroppedZero(); - Debug.dump(graph, "after " + getName() + " iteration"); + if (Debug.isDumpEnabled()) { + Debug.dump(graph, "after " + getName() + " iteration"); + } new DeadCodeEliminationPhase().apply(graph); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Thu Mar 20 13:50:21 2014 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; +import static com.oracle.graal.debug.Debug.*; import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; @@ -54,7 +55,7 @@ private void runIterations(final StructuredGraph graph, final boolean simple, final HighTierContext context) { for (int iteration = 0; iteration < EscapeAnalysisIterations.getValue(); iteration++) { - try (Scope s = Debug.scope("iteration " + iteration)) { + try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) { boolean progress = false; PartialEscapePhase ea = new PartialEscapePhase(false, canonicalizer); boolean eaResult = ea.runAnalysis(graph, context); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Thu Mar 20 13:50:21 2014 +0100 @@ -162,7 +162,7 @@ } } if (phi) { - PhiNode phiNode = getCachedPhi(entry, value.getKind()); + PhiNode phiNode = getCachedPhi(entry, value.stamp().unrestricted()); mergeEffects.addFloatingNode(phiNode, "mergeReadCache"); for (int i = 0; i < states.size(); i++) { afterMergeEffects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity, PEReadEliminationClosure.this)); @@ -194,7 +194,7 @@ values[i] = value; } - PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].getKind()); + PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].stamp().unrestricted()); mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi"); for (int i = 0; i < values.length; i++) { afterMergeEffects.addPhiInput(phiNode, values[i]); diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Thu Mar 20 13:50:21 2014 +0100 @@ -35,6 +35,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.util.*; @@ -284,10 +285,10 @@ super(mergeBlock); } - protected PhiNode getCachedPhi(T virtual, Kind kind) { + protected PhiNode getCachedPhi(T virtual, Stamp stamp) { PhiNode result = materializedPhis.get(virtual); if (result == null) { - result = new PhiNode(kind, merge); + result = new PhiNode(stamp, merge); materializedPhis.put(virtual, result); } return result; @@ -334,8 +335,6 @@ ObjectState[] objStates = new ObjectState[states.size()]; boolean materialized; do { - mergeEffects.clear(); - afterMergeEffects.clear(); materialized = false; for (VirtualObjectNode object : virtualObjTemp) { for (int i = 0; i < objStates.length; i++) { @@ -363,7 +362,7 @@ if (uniqueMaterializedValue != null) { newState.addObject(object, new ObjectState(object, uniqueMaterializedValue, EscapeState.Materialized, null)); } else { - PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object); + PhiNode materializedValuePhi = getCachedPhi(object, StampFactory.forKind(Kind.Object)); mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi"); for (int i = 0; i < objStates.length; i++) { ObjectState obj = objStates[i]; @@ -381,6 +380,11 @@ materialized |= processPhi(phi, states, virtualObjTemp); } } + if (materialized) { + newState.objectStates.clear(); + mergeEffects.clear(); + afterMergeEffects.clear(); + } } while (materialized); } @@ -458,7 +462,7 @@ for (int i = 1; i < objStates.length; i++) { ValueNode[] fields = objStates[i].getEntries(); if (phis[valueIndex] == null && values[valueIndex] != fields[valueIndex]) { - phis[valueIndex] = new PhiNode(values[valueIndex].getKind(), merge); + phis[valueIndex] = new PhiNode(values[valueIndex].stamp().unrestricted(), merge); } } if (twoSlotKinds != null && twoSlotKinds[valueIndex] != null) { @@ -487,7 +491,7 @@ return materialized; } else { // not compatible: materialize in all predecessors - PhiNode materializedValuePhi = getCachedPhi(object, Kind.Object); + PhiNode materializedValuePhi = getCachedPhi(object, StampFactory.forKind(Kind.Object)); for (int i = 0; i < blockStates.size(); i++) { ObjectState obj = objStates[i]; Block predecessor = mergeBlock.getPredecessors().get(i); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Thu Mar 20 13:50:21 2014 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; @@ -196,10 +197,10 @@ super(mergeBlock); } - protected PhiNode getCachedPhi(T virtual, Kind kind) { + protected PhiNode getCachedPhi(T virtual, Stamp stamp) { PhiNode result = materializedPhis.get(virtual); if (result == null) { - result = new PhiNode(kind, merge); + result = new PhiNode(stamp, merge); materializedPhis.put(virtual, result); } return result; @@ -229,7 +230,7 @@ } } if (phi) { - PhiNode phiNode = getCachedPhi(entry, value.getKind()); + PhiNode phiNode = getCachedPhi(entry, value.stamp().unrestricted()); mergeEffects.addFloatingNode(phiNode, "mergeReadCache"); for (int i = 0; i < states.size(); i++) { afterMergeEffects.addPhiInput(phiNode, states.get(i).getCacheEntry(key)); @@ -262,7 +263,7 @@ } CacheEntry newIdentifier = identifier.duplicateWithObject(phi); - PhiNode phiNode = getCachedPhi(newIdentifier, values[0].getKind()); + PhiNode phiNode = getCachedPhi(newIdentifier, values[0].stamp().unrestricted()); mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi"); for (int i = 0; i < values.length; i++) { afterMergeEffects.addPhiInput(phiNode, values[i]); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -69,7 +69,7 @@ @Override public void generate(LIRGeneratorTool generator) { assert getKind() != input.getKind(); - assert generator.target().arch.getSizeInBytes(getKind()) == generator.target().arch.getSizeInBytes(input.getKind()); + assert generator.target().getSizeInBytes(getKind()) == generator.target().getSizeInBytes(input.getKind()); AllocatableValue result = generator.newVariable(getKind()); generator.emitMove(result, generator.operand(input)); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -71,6 +71,7 @@ public void testImplicitCast0() { ImplicitCast0Node node = ImplicitCast0NodeFactory.create(null); TestRootNode root = new TestRootNode<>(node); + root.adoptChildren(); Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2")); Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1)); Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1")); @@ -106,6 +107,7 @@ public void testImplicitCast1() { ImplicitCast1Node node = ImplicitCast1NodeFactory.create(null); TestRootNode root = new TestRootNode<>(node); + root.adoptChildren(); Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2")); Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1)); Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1")); @@ -146,6 +148,7 @@ public void testImplicitCast2() { ImplicitCast2Node node = ImplicitCast2NodeFactory.create(null, null); TestRootNode root = new TestRootNode<>(node); + root.adoptChildren(); Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2")); Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1, 1)); Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2")); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -33,7 +33,6 @@ import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; public class PolymorphicTest { @@ -55,7 +54,7 @@ assertEquals("(boolean,boolean)", executeWith(node, false, false)); assertEquals("(int,boolean)", executeWith(node, 42, false)); assertEquals("(boolean,int)", executeWith(node, false, 42)); - assertEquals(Kind.SPECIALIZED, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost()); assertParent(node.getNode(), node.getNode().getLeft()); assertParent(node.getNode(), node.getNode().getRight()); } @@ -65,7 +64,7 @@ TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); assertEquals("(int,boolean)", executeWith(node, 42, false)); assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + assertEquals(NodeCost.NONE, node.getNode().getCost()); assertParent(node.getNode(), node.getNode().getLeft()); assertParent(node.getNode(), node.getNode().getRight()); } @@ -76,7 +75,7 @@ assertEquals("(int,boolean)", executeWith(node, 42, false)); assertEquals("(boolean,boolean)", executeWith(node, true, false)); assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + assertEquals(NodeCost.NONE, node.getNode().getCost()); assertParent(node.getNode(), node.getNode().getLeft()); assertParent(node.getNode(), node.getNode().getRight()); } @@ -88,7 +87,7 @@ assertEquals("(int,boolean)", executeWith(node, 42, false)); assertEquals("(boolean,boolean)", executeWith(node, true, false)); assertEquals("(int,int)", executeWith(node, 42, 42)); - assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost()); assertParent(node.getNode(), node.getNode().getLeft()); assertParent(node.getNode(), node.getNode().getRight()); } @@ -97,7 +96,7 @@ public void testGenericInitial() { TestRootNode node = TestHelper.createRoot(Node1Factory.getInstance()); assertEquals("(generic,generic)", executeWith(node, "1", "1")); - assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost()); assertParent(node.getNode(), node.getNode().getLeft()); assertParent(node.getNode(), node.getNode().getRight()); } @@ -108,7 +107,7 @@ assertEquals("(boolean,int)", executeWith(node, false, 42)); assertEquals("(boolean,boolean)", executeWith(node, false, false)); assertEquals("(generic,generic)", executeWith(node, "", "")); - assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost()); /* Assertions for bug GRAAL-425 */ assertParent(node.getNode(), node.getNode().getLeft()); assertParent(node.getNode(), node.getNode().getRight()); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java Thu Mar 20 13:50:21 2014 +0100 @@ -32,7 +32,6 @@ import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Node1Factory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; public class PolymorphicTest2 { @@ -43,7 +42,7 @@ assertEquals(21, executeWith(node, false, false)); assertEquals(42, executeWith(node, 21, 21)); assertEquals("(boolean,int)", executeWith(node, false, 42)); - assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind()); + assertEquals(NodeCost.NONE, node.getNode().getCost()); } @SuppressWarnings("unused") diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Thu Mar 20 13:50:21 2014 +0100 @@ -76,11 +76,15 @@ } static TestRootNode createRoot(NodeFactory factory, Object... constants) { - return new TestRootNode<>(createNode(factory, constants)); + TestRootNode rootNode = new TestRootNode<>(createNode(factory, constants)); + rootNode.adoptChildren(); + return rootNode; } static TestRootNode createGenericRoot(NodeFactory factory, Object... constants) { - return new TestRootNode<>(createGenericNode(factory, constants)); + TestRootNode rootNode = new TestRootNode<>(createGenericNode(factory, constants)); + rootNode.adoptChildren(); + return rootNode; } static CallTarget createCallTarget(ValueNode node) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -100,7 +100,7 @@ public TestRootNode(E node) { super(null); - this.node = adoptChild(node); + this.node = node; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -61,7 +61,7 @@ Assert.assertEquals(42, result); } - class TestArguments extends Arguments { + private static class TestArguments extends Arguments { final int[] values; @@ -70,13 +70,13 @@ } } - class TestRootNode extends RootNode { + private static class TestRootNode extends RootNode { - @Children private TestArgumentNode[] children; + @Children private final TestArgumentNode[] children; TestRootNode(TestArgumentNode[] children) { super(null); - this.children = adoptChildren(children); + this.children = children; } @Override @@ -89,7 +89,7 @@ } } - class TestArgumentNode extends Node { + private static class TestArgumentNode extends Node { private final int index; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -61,13 +61,13 @@ TestChildNode leftChild = new TestChildNode(); TestChildNode rightChild = new TestChildNode(); TestRootNode rootNode = new TestRootNode(leftChild, rightChild); + CallTarget target = runtime.createCallTarget(rootNode); Assert.assertEquals(rootNode, leftChild.getParent()); Assert.assertEquals(rootNode, rightChild.getParent()); Iterator iterator = rootNode.getChildren().iterator(); Assert.assertEquals(leftChild, iterator.next()); Assert.assertEquals(rightChild, iterator.next()); Assert.assertFalse(iterator.hasNext()); - CallTarget target = runtime.createCallTarget(rootNode); Object result = target.call(); Assert.assertEquals(42, result); } @@ -79,8 +79,8 @@ public TestRootNode(TestChildNode left, TestChildNode right) { super(null); - this.left = adoptChild(left); - this.right = adoptChild(right); + this.left = left; + this.right = right; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -55,13 +55,13 @@ TestChildNode firstChild = new TestChildNode(); TestChildNode secondChild = new TestChildNode(); TestRootNode rootNode = new TestRootNode(new TestChildNode[]{firstChild, secondChild}); + CallTarget target = runtime.createCallTarget(rootNode); Assert.assertEquals(rootNode, firstChild.getParent()); Assert.assertEquals(rootNode, secondChild.getParent()); Iterator iterator = rootNode.getChildren().iterator(); Assert.assertEquals(firstChild, iterator.next()); Assert.assertEquals(secondChild, iterator.next()); Assert.assertFalse(iterator.hasNext()); - CallTarget target = runtime.createCallTarget(rootNode); Object result = target.call(); Assert.assertEquals(42, result); } @@ -72,7 +72,7 @@ public TestRootNode(TestChildNode[] children) { super(null); - this.children = adoptChildren(children); + this.children = children; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -60,13 +60,13 @@ Assert.assertEquals(42, result); } - class TestRootNode extends RootNode { + private static class TestRootNode extends RootNode { - @Children TestChildNode[] children; + @Children private final TestChildNode[] children; public TestRootNode(TestChildNode[] children) { super(null); - this.children = adoptChildren(children); + this.children = children; } @Override @@ -79,7 +79,7 @@ } } - class TestChildNode extends Node { + private static class TestChildNode extends Node { private final int value; diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -64,8 +64,8 @@ public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) { super(null, descriptor); - this.left = adoptChild(left); - this.right = adoptChild(right); + this.left = left; + this.right = right; } @Override @@ -108,7 +108,7 @@ IntAssignLocal(FrameSlot slot, TestChildNode value) { super(slot); - this.value = adoptChild(value); + this.value = value; } @Override @@ -130,7 +130,7 @@ ObjectAssignLocal(FrameSlot slot, TestChildNode value) { super(slot); - this.value = adoptChild(value); + this.value = value; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -88,8 +88,8 @@ public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) { super(null, descriptor); - this.left = adoptChild(left); - this.right = adoptChild(right); + this.left = left; + this.right = right; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -59,13 +59,13 @@ UnresolvedNode leftChild = new UnresolvedNode("20"); UnresolvedNode rightChild = new UnresolvedNode("22"); TestRootNode rootNode = new TestRootNode(new ValueNode[]{leftChild, rightChild}); + CallTarget target = runtime.createCallTarget(rootNode); assertEquals(rootNode, leftChild.getParent()); assertEquals(rootNode, rightChild.getParent()); Iterator iterator = rootNode.getChildren().iterator(); Assert.assertEquals(leftChild, iterator.next()); Assert.assertEquals(rightChild, iterator.next()); Assert.assertFalse(iterator.hasNext()); - CallTarget target = runtime.createCallTarget(rootNode); Object result = target.call(); assertEquals(42, result); assertEquals(42, target.call()); @@ -85,7 +85,7 @@ public TestRootNode(ValueNode[] children) { super(null); - this.children = adoptChildren(children); + this.children = children; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -63,8 +63,8 @@ public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) { super(null, descriptor); - this.left = adoptChild(left); - this.right = adoptChild(right); + this.left = left; + this.right = right; } @Override @@ -115,7 +115,7 @@ IntAssignLocal(FrameSlot slot, TestChildNode value) { super(slot); - this.value = adoptChild(value); + this.value = value; } @Override @@ -137,7 +137,7 @@ ObjectAssignLocal(FrameSlot slot, TestChildNode value) { super(slot); - this.value = adoptChild(value); + this.value = value; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.test; + +import static org.junit.Assert.*; + +import java.io.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Test node rewriting in a tree shared across multiple threads (run with -ea). + */ +public class ThreadSafetyTest { + + @Test + public void test() throws InterruptedException { + TruffleRuntime runtime = Truffle.getRuntime(); + TestRootNode rootNode1 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new ConstNode(42))))))); + final CallTarget target1 = runtime.createCallTarget(rootNode1); + NodeUtil.verify(rootNode1); + + RecursiveCallNode callNode = new RecursiveCallNode(new ConstNode(42)); + TestRootNode rootNode2 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(callNode)))))); + final CallTarget target2 = runtime.createCallTarget(rootNode2); + callNode.setCallNode(runtime.createCallNode(target2)); + NodeUtil.verify(rootNode2); + + testTarget(target1, 47, 1_000_000); + testTarget(target2, 72, 1_000_000); + } + + private static void testTarget(final CallTarget target, final int expectedResult, final int numberOfIterations) throws InterruptedException { + ExecutorService executorService = Executors.newFixedThreadPool(20); + final AtomicInteger ai = new AtomicInteger(); + for (int i = 0; i < numberOfIterations; i++) { + executorService.submit(new Runnable() { + public void run() { + try { + Object result = target.call(new TestArguments(5)); + assertEquals(expectedResult, result); + ai.incrementAndGet(); + } catch (Throwable t) { + PrintStream out = System.out; + out.println(t); + } + } + }); + } + executorService.shutdown(); + executorService.awaitTermination(30, TimeUnit.SECONDS); + assertEquals(numberOfIterations, ai.get()); + } + + static class TestArguments extends Arguments { + final int arg; + + public TestArguments(int arg) { + this.arg = arg; + } + } + + static class TestRootNode extends RootNode { + + @Child private ValueNode child; + + public TestRootNode(ValueNode child) { + super(null); + this.child = child; + } + + @Override + public Object execute(VirtualFrame frame) { + return child.execute(frame); + } + } + + abstract static class ValueNode extends Node { + + public ValueNode() { + super(null); + } + + abstract int execute(VirtualFrame frame); + } + + static class RewritingNode extends ValueNode { + + @Child private ValueNode child; + private final Random random; + + public RewritingNode(ValueNode child) { + this(child, new Random()); + } + + public RewritingNode(ValueNode child, Random random) { + this.child = child; + this.random = random; + } + + @Override + int execute(VirtualFrame frame) { + boolean replace = random.nextBoolean(); + if (replace) { + ValueNode newNode = this.replace(new OtherRewritingNode(child, random)); + return newNode.execute(frame); + } + return 1 + child.execute(frame); + } + } + + static class OtherRewritingNode extends ValueNode { + + @Child private ValueNode child; + private final Random random; + + public OtherRewritingNode(ValueNode child, Random random) { + this.child = child; + this.random = random; + } + + @Override + int execute(VirtualFrame frame) { + boolean replace = random.nextBoolean(); + if (replace) { + ValueNode newNode = this.replace(new RewritingNode(child, random)); + return newNode.execute(frame); + } + return 1 + child.execute(frame); + } + } + + static class ConstNode extends ValueNode { + + private final int value; + + ConstNode(int value) { + this.value = value; + } + + @Override + int execute(VirtualFrame frame) { + return value; + } + } + + static class RecursiveCallNode extends ValueNode { + @Child CallNode callNode; + @Child private ValueNode valueNode; + + RecursiveCallNode(ValueNode value) { + this.valueNode = value; + } + + @Override + int execute(VirtualFrame frame) { + int arg = frame.getArguments(TestArguments.class).arg; + if (arg > 0) { + return (int) callNode.call(frame.pack(), new TestArguments(arg - 1)); + } else { + return valueNode.execute(frame); + } + } + + void setCallNode(CallNode callNode) { + this.callNode = insert(callNode); + } + } +} diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java Thu Mar 20 13:50:21 2014 +0100 @@ -151,6 +151,8 @@ return; } + expectedAst.adoptChildren(); + Assert.assertNotNull(actualAst); // fields are asserted using the corresponding equals implementation Assert.assertEquals(expectedAst, actualAst); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java Thu Mar 20 13:50:21 2014 +0100 @@ -84,7 +84,7 @@ @Child Node child; public NodeWithOneChild(Node child) { - this.child = adoptChild(child); + this.child = child; } } @@ -95,8 +95,8 @@ @Child Node child2; public NodeWithTwoChilds(Node child1, Node child2) { - this.child1 = adoptChild(child1); - this.child2 = adoptChild(child2); + this.child1 = child1; + this.child2 = child2; } } @@ -108,9 +108,9 @@ @Child Node child3; public NodeWithThreeChilds(Node child1, Node child2, Node child3) { - this.child1 = adoptChild(child1); - this.child2 = adoptChild(child2); - this.child3 = adoptChild(child3); + this.child1 = child1; + this.child2 = child2; + this.child3 = child3; } } @@ -120,7 +120,7 @@ @Children private final Node[] childNodes; NodeWithArray(Node[] children) { - this.childNodes = adoptChildren(children); + this.childNodes = children; } Node[] getChildNodes() { @@ -134,8 +134,8 @@ @Children private final Node[] childNodes2; NodeWithTwoArray(Node[] childs1, Node[] childs2) { - this.childNodes1 = adoptChildren(childs1); - this.childNodes2 = adoptChildren(childs2); + this.childNodes1 = childs1; + this.childNodes2 = childs2; } Node[] getChildNodes1() { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java Thu Mar 20 13:50:21 2014 +0100 @@ -31,5 +31,5 @@ */ public interface ReplaceObserver { - void nodeReplaced(Node oldNode, Node newNode, String reason); + void nodeReplaced(Node oldNode, Node newNode, CharSequence reason); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java Thu Mar 20 13:50:21 2014 +0100 @@ -37,6 +37,7 @@ public RootCallTarget(RootNode function) { this.rootNode = function; this.rootNode.setCallTarget(this); + this.rootNode.adoptChildren(); } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java Thu Mar 20 13:50:21 2014 +0100 @@ -25,7 +25,6 @@ package com.oracle.truffle.api; import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; /** * Class containing general Truffle options. @@ -56,29 +55,29 @@ public static String TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass"); /** - * Filters rewrites which does not contain the {@link Kind} in its source {@link NodeInfo}. If - * no {@link NodeInfo} is defined the element is filtered if the filter value is set. + * Filters rewrites which does not contain the {@link NodeCost} in its source {@link NodeInfo}. + * If no {@link NodeInfo} is defined the element is filtered if the filter value is set. *

* Can be set with - * {@code -Dtruffle.TraceRewritesFilterFromKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}. + * {@code -Dtruffle.TraceRewritesFilterFromCost=NONE|MONOMORPHIC|POLYMORPHIC|MEGAMORPHIC}. */ - public static NodeInfo.Kind TraceRewritesFilterFromKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromKind")); + public static NodeCost TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost")); /** - * Filters rewrites which does not contain the {@link Kind} in its target {@link NodeInfo}. If - * no {@link NodeInfo} is defined the element is filtered if the filter value is set. + * Filters rewrites which does not contain the {@link NodeCost} in its target {@link NodeInfo}. + * If no {@link NodeInfo} is defined the element is filtered if the filter value is set. *

* Can be set with * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}. */ - public static NodeInfo.Kind TraceRewritesFilterToKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToKind")); + public static NodeCost TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost")); - private static NodeInfo.Kind parseNodeInfoKind(String kind) { + private static NodeCost parseNodeInfoKind(String kind) { if (kind == null) { return null; } - return NodeInfo.Kind.valueOf(kind); + return NodeCost.valueOf(kind); } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java Thu Mar 20 13:50:21 2014 +0100 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.nodes.*; -// TODO (mlvdv) does this need to extend ControlFlowException? It was originally part of the Ruby Shell. /** * Controls breaking out of an execution context, such as a shell or eval. */ diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java Thu Mar 20 13:50:21 2014 +0100 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.nodes.*; -//TODO (mlvdv) does this need to extend ControlFlowException? It was originally part of the Ruby execution environment. /** * Controls breaking out of all executions and ending Truffle execution. */ diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -64,6 +64,11 @@ } @Override + public boolean isInlinable() { + return false; + } + + @Override public String toString() { return getParent() != null ? getParent().toString() : super.toString(); } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -28,13 +28,18 @@ import com.oracle.truffle.api.frame.*; /** - * This node represents a call to a static {@link CallTarget}. This node should be used whenever a - * {@link CallTarget} is considered constant at a certain location in the tree. This enables the - * Truffle runtime to perform inlining or other optimizations for this call-site. This class is - * intended to be implemented by truffle runtime implementors and not by guest language - * implementors. + * Represents a call to a {@link CallTarget} in the Truffle AST. Addtionally to calling the + * {@link CallTarget} this {@link Node} enables the runtime system to implement further + * optimizations. Optimizations that can possibly applied to a {@link CallNode} are inlining and + * splitting. Inlining inlines this call site into the call graph of the parent {@link CallTarget}. + * Splitting duplicates the {@link CallTarget} using {@link RootNode#split()} to collect call site + * sensitive profiling information. * - * @see #create(CallTarget) to create a CallNode instance. + * Please note: This class is not intended to be subclassed by guest language implementations. + * + * @see TruffleRuntime#createCallNode(CallTarget) + * @see #inline() + * @see #split() */ public abstract class CallNode extends Node { @@ -45,7 +50,7 @@ } /** - * Calls this constant target passing a caller frame and arguments. + * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}. * * @param caller the caller frame * @param arguments the arguments that should be passed to the callee @@ -65,27 +70,63 @@ } /** - * @return true if this {@link CallNode} was already inlined. + * Returns true if the underlying runtime system supports inlining for the + * {@link CallTarget} in this {@link CallNode}. + * + * @return true if inlining is supported. + */ + public abstract boolean isInlinable(); + + /** + * Returns true if the {@link CallTarget} in this {@link CallNode} is inlined. A + * {@link CallNode} can either be inlined manually by invoking {@link #inline()} or by the + * runtime system which may at any point decide to inline. + * + * @return true if this method was inlined else false. */ public abstract boolean isInlined(); + /** + * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the + * runtime system does not support inlining or it is already inlined this method has no effect. + */ public abstract void inline(); + /** + * Returns true if this {@link CallNode} can be split. A {@link CallNode} can only + * be split if the runtime system supports splitting and if the {@link RootNode} contained the + * {@link CallTarget} returns true for {@link RootNode#isSplittable()}. + * + * @return true if the target can be split + */ public abstract boolean isSplittable(); + /** + * Enforces the runtime system to split the {@link CallTarget}. If the {@link CallNode} is not + * splittable this methods has no effect. + */ public abstract boolean split(); + /** + * Returns true if the target of the {@link CallNode} was split. + * + * @return if the target was split + */ public final boolean isSplit() { return getSplitCallTarget() != null; } + /** + * Returns the splitted {@link CallTarget} if this method is split. + * + * @return the split {@link CallTarget} + */ public abstract CallTarget getSplitCallTarget(); /** * Returns the used call target when {@link #call(PackedFrame, Arguments)} is invoked. If the - * {@link CallNode} was split this method returns the {@link CallTarget} returned by - * {@link #getSplitCallTarget()}. If not split this method returns the original supplied - * {@link CallTarget}. + * {@link CallTarget} was split this method returns the {@link CallTarget} returned by + * {@link #getSplitCallTarget()}. * * @return the used {@link CallTarget} when node is called */ @@ -98,8 +139,24 @@ } } + /** + * Returns the {@link RootNode} associated with {@link CallTarget} returned by + * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a + * {@link RootNode} this method returns null. + * + * @see #getCurrentCallTarget() + * @return the root node of the used call target + */ + public final RootNode getCurrentRootNode() { + CallTarget target = getCurrentCallTarget(); + if (target instanceof RootCallTarget) { + return ((RootCallTarget) target).getRootNode(); + } + return null; + } + @Override - protected void onReplace(Node newNode, String reason) { + protected void onReplace(Node newNode, CharSequence reason) { super.onReplace(newNode, reason); /* @@ -114,6 +171,9 @@ registerCallTarget((CallNode) newNode); } + /** + * Internal API for the runtime system. + */ protected static final void registerCallTarget(CallNode newNode) { RootNode newRoot = newNode.getCurrentRootNode(); if (newRoot != null) { @@ -121,51 +181,4 @@ } } - protected void notifyCallNodeAdded() { - - } - - /** - * Returns the {@link RootNode} associated with {@link CallTarget} returned by - * {@link #getCurrentCallTarget()}. - * - * @see #getCurrentCallTarget() - * @return the root node of the used call target - */ - public final RootNode getCurrentRootNode() { - CallTarget target = getCurrentCallTarget(); - if (target instanceof RootCallTarget) { - return ((RootCallTarget) target).getRootNode(); - } - return null; - } - - /** - * @deprecated always returns true now. - */ - @Deprecated - public boolean isInlinable() { - return true; - } - - /** - * @deprecated instead use {@link #getCurrentRootNode()} and check for {@link #isInlined()} for - * true. - */ - @Deprecated - public RootNode getInlinedRoot() { - if (!isInlined()) { - return null; - } - return getCurrentRootNode(); - } - - /** - * @deprecated use {@link TruffleRuntime#createCallNode(CallTarget)} instead - */ - @Deprecated - public static CallNode create(CallTarget target) { - return Truffle.getRuntime().createCallNode(target); - } - } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Thu Mar 20 13:50:21 2014 +0100 @@ -214,7 +214,7 @@ setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", "")); NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class); if (nodeInfo != null) { - setNodeProperty(node, "kind", nodeInfo.kind()); + setNodeProperty(node, "cost", nodeInfo.cost()); if (!nodeInfo.shortName().isEmpty()) { setNodeProperty(node, "shortName", nodeInfo.shortName()); } diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Thu Mar 20 13:50:21 2014 +0100 @@ -27,9 +27,9 @@ import java.io.*; import java.lang.annotation.*; import java.util.*; +import java.util.concurrent.*; import com.oracle.truffle.api.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; /** * Abstract base class for all Truffle nodes. @@ -82,12 +82,20 @@ this.sourceSection = section; } - public Kind getKind() { + /** + * Returns a rough estimate for the cost of this {@link Node}. This estimate can be used by + * runtime systems or guest languages to implement heuristics based on Truffle ASTs. This method + * is intended to be overridden by subclasses. The default implementation returns the value of + * {@link NodeInfo#cost()} of the {@link NodeInfo} annotation declared at the subclass. If no + * {@link NodeInfo} annotation is declared the method returns {@link NodeCost#MONOMORPHIC} as a + * default value. + */ + public NodeCost getCost() { NodeInfo info = getClass().getAnnotation(NodeInfo.class); if (info != null) { - return info.kind(); + return info.cost(); } - return Kind.SPECIALIZED; + return NodeCost.MONOMORPHIC; } /** @@ -126,11 +134,36 @@ * @param newChildren the array of new children whose parent should be updated * @return the array of new children */ - protected final T[] adoptChildren(T[] newChildren) { - if (newChildren != null) { - for (T n : newChildren) { - adoptChild(n); - } + @SuppressWarnings("static-method") + @Deprecated + protected final T[] adoptChildren(final T[] newChildren) { + return newChildren; + } + + /** + * Method that updates the link to the parent in the specified new child node to this node. + * + * @param newChild the new child whose parent should be updated + * @return the new child + */ + @SuppressWarnings("static-method") + @Deprecated + protected final T adoptChild(final T newChild) { + return newChild; + } + + /** + * Method that updates the link to the parent in the array of specified new child nodes to this + * node. + * + * @param newChildren the array of new children whose parent should be updated + * @return the array of new children + */ + protected final T[] insert(final T[] newChildren) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + assert newChildren != null; + for (Node newChild : newChildren) { + adoptHelper(newChild); } return newChildren; } @@ -141,14 +174,52 @@ * @param newChild the new child whose parent should be updated * @return the new child */ - protected final T adoptChild(T newChild) { - if (newChild != null) { - if (newChild == this) { - throw new IllegalStateException("The parent of a node can never be the node itself."); + protected final T insert(final T newChild) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + assert newChild != null; + adoptHelper(newChild); + return newChild; + } + + public final void adoptChildren() { + CompilerDirectives.transferToInterpreterAndInvalidate(); + adoptHelper(); + } + + private void adoptHelper(final Node newChild) { + assert newChild != null; + if (newChild == this) { + throw new IllegalStateException("The parent of a node can never be the node itself."); + } + newChild.parent = this; + newChild.adoptHelper(); + } + + private void adoptHelper() { + Iterable children = this.getChildren(); + for (Node child : children) { + if (child != null && child.getParent() != this) { + this.adoptHelper(child); } - ((Node) newChild).parent = this; + } + } + + private void adoptUnadoptedHelper(final Node newChild) { + assert newChild != null; + if (newChild == this) { + throw new IllegalStateException("The parent of a node can never be the node itself."); } - return newChild; + newChild.parent = this; + newChild.adoptUnadoptedHelper(); + } + + private void adoptUnadoptedHelper() { + Iterable children = this.getChildren(); + for (Node child : children) { + if (child != null && child.getParent() == null) { + this.adoptUnadoptedHelper(child); + } + } } /** @@ -179,54 +250,17 @@ * @param reason a description of the reason for the replacement * @return the new node */ - public final T replace(T newNode, String reason) { + public final T replace(final T newNode, final CharSequence reason) { CompilerDirectives.transferToInterpreterAndInvalidate(); - if (this.getParent() == null) { - throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); - } - if (sourceSection != null && newNode.getSourceSection() == null) { - // Pass on the source section to the new node. - newNode.assignSourceSection(sourceSection); - } - onReplace(newNode, reason); - ((Node) newNode).parent = this.parent; - if (!NodeUtil.replaceChild(this.parent, this, newNode)) { - fixupTree(); - } - reportReplace(this, newNode, reason); + atomic(new Runnable() { + public void run() { + replaceHelper(newNode, reason); + } + }); return newNode; } /** - * Rewrite has failed; the tree is likely inconsistent, so fix any stale parent references. - * - * This is a rather expensive operation but rare to occur. - */ - private void fixupTree() { - Node rootNode = getRootNode(); - if (rootNode == null) { - throw new UnsupportedOperationException("Tree does not have a root node."); - } - int fixCount = rootNode.fixupChildren(); - assert fixCount != 0 : "sanity check failed: missing @Child[ren] or adoptChild?"; - // if nothing had to be fixed, rewrite failed due to node not being a proper child. - } - - private int fixupChildren() { - int fixCount = 0; - for (Node child : getChildren()) { - if (child != null) { - if (child.parent != this) { - child.parent = this; - fixCount++; - } - fixCount += child.fixupChildren(); - } - } - return fixCount; - } - - /** * Replaces this node with another node. If there is a source section (see * {@link #getSourceSection()}) associated with this node, it is transferred to the new node. * @@ -237,6 +271,27 @@ return replace(newNode, ""); } + private void replaceHelper(Node newNode, CharSequence reason) { + CompilerAsserts.neverPartOfCompilation(); + if (this.getParent() == null) { + throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); + } + if (sourceSection != null && newNode.getSourceSection() == null) { + // Pass on the source section to the new node. + newNode.assignSourceSection(sourceSection); + } + // (aw) need to set parent *before* replace, so that (unsynchronized) getRootNode() + // will always find the root node + newNode.parent = this.parent; + if (NodeUtil.replaceChild(this.parent, this, newNode)) { + this.parent.adoptHelper(newNode); + } else { + this.parent.adoptUnadoptedHelper(newNode); + } + reportReplace(this, newNode, reason); + onReplace(newNode, reason); + } + /** * Checks if this node is properly adopted by a parent and can be replaced. * @@ -253,7 +308,7 @@ return false; } - private void reportReplace(Node oldNode, Node newNode, String reason) { + private void reportReplace(Node oldNode, Node newNode, CharSequence reason) { RootNode rootNode = getRootNode(); if (rootNode != null) { CallTarget target = rootNode.getCallTarget(); @@ -270,68 +325,61 @@ * @param newNode the replacement node * @param reason the reason the replace supplied */ - protected void onReplace(Node newNode, String reason) { + protected void onReplace(Node newNode, CharSequence reason) { if (TruffleOptions.TraceRewrites) { traceRewrite(newNode, reason); } } - private void traceRewrite(Node newNode, String reason) { - Class from = getClass(); - Class to = newNode.getClass(); + private void traceRewrite(Node newNode, CharSequence reason) { - if (TruffleOptions.TraceRewritesFilterFromKind != null) { - if (filterByKind(from, TruffleOptions.TraceRewritesFilterFromKind)) { + if (TruffleOptions.TraceRewritesFilterFromCost != null) { + if (filterByKind(this, TruffleOptions.TraceRewritesFilterFromCost)) { return; } } - if (TruffleOptions.TraceRewritesFilterToKind != null) { - if (filterByKind(to, TruffleOptions.TraceRewritesFilterToKind)) { + if (TruffleOptions.TraceRewritesFilterToCost != null) { + if (filterByKind(newNode, TruffleOptions.TraceRewritesFilterToCost)) { return; } } String filter = TruffleOptions.TraceRewritesFilterClass; + Class from = getClass(); + Class to = newNode.getClass(); if (filter != null && (filterByContainsClassName(from, filter) || filterByContainsClassName(to, filter))) { return; } PrintStream out = System.out; - out.printf("[truffle] rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(from), formatNodeInfo(to), reason); + out.printf("[truffle] rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason); } - private static String formatNodeInfo(Class clazz) { - NodeInfo nodeInfo = clazz.getAnnotation(NodeInfo.class); - String kind = "?"; - if (nodeInfo != null) { - switch (nodeInfo.kind()) { - case GENERIC: - kind = "G"; - break; - case SPECIALIZED: - kind = "S"; - break; - case UNINITIALIZED: - kind = "U"; - break; - case POLYMORPHIC: - kind = "P"; - break; - default: - kind = "?"; - break; - } + private static String formatNodeInfo(Node node) { + String cost = "?"; + switch (node.getCost()) { + case NONE: + cost = "G"; + break; + case MONOMORPHIC: + cost = "M"; + break; + case POLYMORPHIC: + cost = "P"; + break; + case MEGAMORPHIC: + cost = "G"; + break; + default: + cost = "?"; + break; } - return kind + " " + clazz.getSimpleName(); + return cost + " " + node.getClass().getSimpleName(); } - private static boolean filterByKind(Class clazz, Kind kind) { - NodeInfo info = clazz.getAnnotation(NodeInfo.class); - if (info != null) { - return info.kind() != kind; - } - return true; + private static boolean filterByKind(Node node, NodeCost cost) { + return node.getCost() == cost; } private static boolean filterByContainsClassName(Class from, String filter) { @@ -435,4 +483,32 @@ sb.append("@").append(Integer.toHexString(hashCode())); return sb.toString(); } + + public final void atomic(Runnable closure) { + RootNode rootNode = getRootNode(); + if (rootNode != null) { + synchronized (rootNode) { + closure.run(); + } + } else { + closure.run(); + } + } + + public final T atomic(Callable closure) { + try { + RootNode rootNode = getRootNode(); + if (rootNode != null) { + synchronized (rootNode) { + return closure.call(); + } + } else { + return closure.call(); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCost.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCost.java Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,69 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.nodes; + +import com.oracle.truffle.api.*; + +/** + * Represents a rough estimate for the cost of a {@link Node}. This estimate can be used by runtime + * systems or guest languages to implement heuristics based on Truffle ASTs. + * + * @see Node#getCost() + */ +public enum NodeCost { + + /** + * This node has literally no costs and should be ignored for heuristics. This is particularly + * useful for wrapper and profiling nodes which should not influence the heuristics. + */ + NONE, + + /** + * This node has a {@link CompilerDirectives#transferToInterpreter()} or + * {@link CompilerDirectives#transferToInterpreterAndInvalidate()} as its first unconditional + * statement. + */ + UNINITIALIZED, + + /** + * This node represents a specialized monomorphic version of an operation. + */ + MONOMORPHIC, + + /** + * This node represents a polymorphic version of an operation. For multiple chained polymorphic + * nodes the first may return {@link #MONOMORPHIC} and all addtional nodes should return + * {@link #POLYMORPHIC}. + */ + POLYMORPHIC, + + /** + * This node represents a megamorphic version of an operation. This value should only be used if + * the operation implementation supports monomorphism and polymorphism otherwise + * {@link #MONOMORPHIC} should be used instead. + */ + MEGAMORPHIC; + +} diff -r 5ddfdc13027a -r 17a735726670 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 Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java Thu Mar 20 13:50:21 2014 +0100 @@ -40,10 +40,13 @@ */ String shortName() default ""; - Kind kind() default Kind.SPECIALIZED; - - public enum Kind { - UNINITIALIZED, SPECIALIZED, POLYMORPHIC, GENERIC - } + /** + * Provides a rough estimate for the cost of the annotated {@link Node}. This estimate can be + * used by runtime systems or guest languages to implement heuristics based on Truffle ASTs. + * + * @see Node#getCost() + * @see NodeCost + */ + NodeCost cost() default NodeCost.MONOMORPHIC; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Thu Mar 20 13:50:21 2014 +0100 @@ -34,7 +34,6 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.Node.Children; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; /** * Utility class that manages the special access methods for node instances. @@ -452,48 +451,6 @@ return null; } - /** - * @deprecated will be removed, exposed Truffle runtime specific functionality. - */ - @Deprecated - public static List findOutermostCallTargets(Node node) { - RootNode root = node.getRootNode(); - if (root == null) { - return Collections.emptyList(); - } - List roots = new ArrayList<>(); - roots.add(root.getCallTarget()); - for (CallNode callNode : root.getCachedCallNodes()) { - if (callNode.isInlined()) { - roots.addAll(findOutermostCallTargets(callNode)); - } - } - return roots; - } - - /** - * @deprecated will be removed, exposed Truffle runtime specific functionality. - */ - @Deprecated - public static RootNode findOutermostRootNode(Node node) { - Node parent = node; - while (parent != null) { - if (parent instanceof RootNode) { - RootNode root = (RootNode) parent; - @SuppressWarnings("deprecation") - Node next = root.getParentInlinedCall(); - if (next != null) { - parent = next; - } else { - return root; - } - } else { - parent = parent.getParent(); - } - } - return null; - } - public static T findParent(Node start, Class clazz) { Node parent = start.getParent(); if (parent == null) { @@ -614,39 +571,43 @@ } public static int countNodes(Node root) { - return countNodes(root, null, null, false); + return countNodes(root, null, false); } - public static int countNodes(Node root, Class clazz, Kind nodeKind, boolean countInlinedCallNodes) { - NodeCountVisitor nodeCount = new NodeCountVisitor(clazz, nodeKind, countInlinedCallNodes); + public static int countNodes(Node root, NodeCountFilter filter) { + return countNodes(root, filter, false); + } + + public static int countNodes(Node root, NodeCountFilter filter, boolean visitInlinedCallNodes) { + NodeCountVisitor nodeCount = new NodeCountVisitor(filter, visitInlinedCallNodes); root.accept(nodeCount); return nodeCount.nodeCount; } - public static int countNodes(Node root, Class clazz, boolean countInlinedCallNodes) { - return countNodes(root, clazz, null, countInlinedCallNodes); + public interface NodeCountFilter { + + boolean isCounted(Node node); + } private static final class NodeCountVisitor implements NodeVisitor { - private final boolean inspectInlinedCalls; + private final boolean visitInlinedCallNodes; int nodeCount; - private final Kind kind; - private final Class clazz; + private final NodeCountFilter filter; - private NodeCountVisitor(Class clazz, Kind kind, boolean inspectInlinedCalls) { - this.clazz = clazz; - this.kind = kind; - this.inspectInlinedCalls = inspectInlinedCalls; + private NodeCountVisitor(NodeCountFilter filter, boolean visitInlinedCallNodes) { + this.filter = filter; + this.visitInlinedCallNodes = visitInlinedCallNodes; } @Override public boolean visit(Node node) { - if ((clazz == null || clazz.isInstance(node)) && (kind == null || isKind(node))) { + if (filter == null || filter.isCounted(node)) { nodeCount++; } - if (inspectInlinedCalls && node instanceof CallNode) { + if (visitInlinedCallNodes && node instanceof CallNode) { CallNode call = (CallNode) node; if (call.isInlined()) { Node target = ((RootCallTarget) call.getCurrentCallTarget()).getRootNode(); @@ -659,9 +620,6 @@ return true; } - private boolean isKind(Node n) { - return kind == n.getKind(); - } } public static void printInliningTree(final PrintStream stream, RootNode root) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -36,7 +36,7 @@ */ public abstract class RootNode extends Node { - private CallTarget callTarget; + private RootCallTarget callTarget; private final FrameDescriptor frameDescriptor; /* @@ -62,36 +62,24 @@ } /** - * @deprecated Not required anymore. Do not use. + * Creates a split {@link RootNode} based on the current {@link RootNode}. This method should + * return an AST that was never executed and must not be shared with other {@link RootNode} or + * {@link CallTarget} instances. This method is intended to be overridden by a subclass. + * + * @return the split {@link RootNode} */ - @Deprecated - public RootNode inline() { - if (!isInlinable()) { - throw new UnsupportedOperationException("Inlining is not enabled."); - } - return split(); + public RootNode split() { + throw new UnsupportedOperationException(); } /** - * @deprecated Not required anymore. Do not use. - */ - @Deprecated - public int getInlineNodeCount() { - return 0; - } - - /** - * @deprecated Not required anymore. Do not use. + * Returns true if this {@link RootNode} can be split. A {@link RootNode} can be + * split inside of a {@link CallTarget} that is invoked using a {@link CallNode}. If this method + * returns true a proper implementation of {@link #split()} must also be provided. + * This method is intended to be overridden by a subclass. + * + * @return true if splittable else false. */ - @Deprecated - public boolean isInlinable() { - return true; - } - - public RootNode split() { - return NodeUtil.cloneNode(this); - } - public boolean isSplittable() { return false; } @@ -100,7 +88,7 @@ * Reports the execution count of a loop that is a child of this node. The optimization * heuristics can use the loop count to guide compilation and inlining. */ - public void reportLoopCount(int count) { + public final void reportLoopCount(int count) { if (getCallTarget() instanceof LoopCountReceiver) { ((LoopCountReceiver) getCallTarget()).reportLoopCount(count); } @@ -114,7 +102,7 @@ */ public abstract Object execute(VirtualFrame frame); - public CallTarget getCallTarget() { + public final RootCallTarget getCallTarget() { return callTarget; } @@ -122,17 +110,17 @@ return frameDescriptor; } - public final void setCallTarget(CallTarget callTarget) { + public final void setCallTarget(RootCallTarget callTarget) { this.callTarget = callTarget; } /* Internal API. Do not use. */ - void addCachedCallNode(CallNode callSite) { + final void addCachedCallNode(CallNode callSite) { this.cachedCallNodes.add(callSite); } /* Internal API. Do not use. */ - void removeCachedCallNode(CallNode callSite) { + final void removeCachedCallNode(CallNode callSite) { this.cachedCallNodes.remove(callSite); } @@ -148,11 +136,4 @@ return Collections.unmodifiableSet(cachedCallNodes); } - /** - * @deprecated use {@link #getCachedCallNodes()} instead. - */ - @Deprecated - public final CallNode getParentInlinedCall() { - return cachedCallNodes.isEmpty() ? null : cachedCallNodes.iterator().next(); - } } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -62,7 +62,7 @@ */ protected void internalAppendProbe(InstrumentationProbeNode newProbeNode) { if (next == null) { - this.next = adoptChild(newProbeNode); + this.next = newProbeNode; } else { next.internalAppendProbe(newProbeNode); } @@ -75,7 +75,7 @@ if (oldProbeNode.next == null) { this.next = null; } else { - this.next = adoptChild(oldProbeNode.next); + this.next = oldProbeNode.next; oldProbeNode.next = null; } } else { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Thu Mar 20 13:50:21 2014 +0100 @@ -52,7 +52,7 @@ private final DeclaredType childAnnotation; private final DeclaredType childrenAnnotation; private final DeclaredType nodeInfoAnnotation; - private final DeclaredType nodeInfoKind; + private final DeclaredType nodeCost; private final TypeMirror compilerDirectives; private final TypeMirror compilerAsserts; private final DeclaredType slowPath; @@ -75,7 +75,7 @@ assumption = getRequired(context, Assumption.class); invalidAssumption = getRequired(context, InvalidAssumptionException.class); nodeInfoAnnotation = getRequired(context, NodeInfo.class); - nodeInfoKind = getRequired(context, NodeInfo.Kind.class); + nodeCost = getRequired(context, NodeCost.class); slowPath = getRequired(context, SlowPath.class); sourceSection = getRequired(context, SourceSection.class); truffleOptions = getRequired(context, TruffleOptions.class); @@ -107,8 +107,8 @@ return false; } - public DeclaredType getNodeInfoKind() { - return nodeInfoKind; + public DeclaredType getNodeCost() { + return nodeCost; } private DeclaredType getRequired(ProcessorContext context, Class clazz) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/codewriter/AbstractCodeWriter.java Thu Mar 20 13:50:21 2014 +0100 @@ -267,11 +267,9 @@ if (parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) { write(f.getSimpleName()); if (init != null) { - if (init != null) { - write("("); - init.acceptCodeElementScanner(this, p); - write(")"); - } + write("("); + init.acceptCodeElementScanner(this, p); + write(")"); } } else { Element enclosing = f.getEnclosingElement(); diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Thu Mar 20 13:50:21 2014 +0100 @@ -32,7 +32,6 @@ import javax.lang.model.util.*; import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.nodes.NodeInfo.Kind; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.dsl.processor.*; import com.oracle.truffle.dsl.processor.ast.*; @@ -215,20 +214,23 @@ if (method.getModifiers().contains(STATIC)) { builder.type(targetClass.asType()); } else { - ActualParameter parameter = null; + ActualParameter firstParameter = null; for (ActualParameter searchParameter : targetMethod.getParameters()) { if (searchParameter.getSpecification().isSignature()) { - parameter = searchParameter; + firstParameter = searchParameter; break; } } - ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName()); - assert parameter != null; + if (firstParameter == null) { + throw new AssertionError(); + } + + ActualParameter sourceParameter = sourceMethod.findParameter(firstParameter.getLocalName()); if (castedValues && sourceParameter != null) { - builder.string(valueName(sourceParameter, parameter)); + builder.string(valueName(sourceParameter, firstParameter)); } else { - builder.string(valueName(parameter)); + builder.string(valueName(firstParameter)); } } } @@ -929,7 +931,7 @@ CodeExecutableElement setter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(void.class), "setNext0"); setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0")); CodeTreeBuilder builder = setter.createBuilder(); - builder.statement("this.next0 = adoptChild(next0)"); + builder.statement("this.next0 = insert(next0)"); clazz.add(setter); CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization()); @@ -954,28 +956,28 @@ clazz.add(createGenericExecute(node, rootGroup)); } - clazz.add(createGetKind(node, null, Kind.SPECIALIZED)); + clazz.add(createGetCost(node, null, NodeCost.MONOMORPHIC)); } protected boolean needsInvokeCopyConstructorMethod() { return getModel().getNode().isPolymorphic(); } - protected CodeExecutableElement createGetKind(NodeData node, SpecializationData specialization, Kind kind) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getNodeInfoKind(), "getKind"); - - TypeMirror nodeInfoKind = context.getTruffleTypes().getNodeInfoKind(); + protected CodeExecutableElement createGetCost(NodeData node, SpecializationData specialization, NodeCost cost) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getNodeCost(), "getCost"); + + TypeMirror nodeInfoKind = context.getTruffleTypes().getNodeCost(); CodeTreeBuilder builder = method.createBuilder(); if (node.isPolymorphic() && specialization == null) { // assume next0 exists - builder.startIf().string("next0 != null && next0.getKind() == ").staticReference(nodeInfoKind, "SPECIALIZED").end(); + builder.startIf().string("next0 != null && next0.getCost() != ").staticReference(nodeInfoKind, "UNINITIALIZED").end(); builder.startBlock(); builder.startReturn().staticReference(nodeInfoKind, "POLYMORPHIC").end(); builder.end(); } - builder.startReturn().staticReference(nodeInfoKind, kind.name()).end(); + builder.startReturn().staticReference(nodeInfoKind, cost.name()).end(); return method; } @@ -1208,7 +1210,6 @@ String fieldName = var.getSimpleName().toString(); CodeTree init = createStaticCast(builder, child, fieldName); - init = createAdoptChild(builder, var.asType(), init); builder.string("this.").string(fieldName).string(" = ").tree(init); builder.end(); @@ -1227,18 +1228,6 @@ return CodeTreeBuilder.singleString(fieldName); } - private CodeTree createAdoptChild(CodeTreeBuilder parent, TypeMirror type, CodeTree value) { - CodeTreeBuilder builder = new CodeTreeBuilder(parent); - if (Utils.isAssignable(getContext(), type, getContext().getTruffleTypes().getNode())) { - builder.string("adoptChild(").tree(value).string(")"); - } else if (Utils.isAssignable(getContext(), type, getContext().getTruffleTypes().getNodeArray())) { - builder.string("adoptChildren(").tree(value).string(")"); - } else { - builder.tree(value); - } - return builder.getRoot(); - } - private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) { CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); CodeTreeBuilder builder = method.createBuilder(); @@ -1259,7 +1248,7 @@ if (Utils.isAssignable(getContext(), varType, getContext().getTruffleTypes().getNodeArray())) { copyAccess += ".clone()"; } - CodeTree init = createAdoptChild(builder, varType, CodeTreeBuilder.singleString(copyAccess)); + CodeTree init = CodeTreeBuilder.singleString(copyAccess); builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end(); } @@ -2476,7 +2465,7 @@ } CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false); - clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC)); + clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.NONE)); for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) { if (!polymorphParameter.getTypeSystemType().isGeneric()) { @@ -2523,7 +2512,7 @@ } createCachedExecuteMethods(specialization); - clazz.add(createGetKind(specialization.getNode(), specialization, Kind.SPECIALIZED)); + clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.NONE)); } private ExecutableElement createUpdateType(ActualParameter parameter) { @@ -2563,34 +2552,34 @@ } CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false); - Kind kind; + NodeCost cost; if (specialization.isGeneric()) { - kind = Kind.GENERIC; + cost = NodeCost.MEGAMORPHIC; } else if (specialization.isUninitialized()) { - kind = Kind.UNINITIALIZED; + cost = NodeCost.UNINITIALIZED; } else if (specialization.isPolymorphic()) { - kind = Kind.POLYMORPHIC; + cost = NodeCost.NONE; } else if (specialization.isSpecialized()) { - kind = Kind.SPECIALIZED; + cost = NodeCost.MONOMORPHIC; } else { throw new AssertionError(); } - clazz.getAnnotationMirrors().add(createNodeInfo(node, kind)); + clazz.getAnnotationMirrors().add(createNodeInfo(node, cost)); return clazz; } - protected CodeAnnotationMirror createNodeInfo(NodeData node, Kind kind) { + protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) { String shortName = node.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 varKind = Utils.findVariableElement(nodeinfoKind, kind.name()); - - nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(varKind)); + DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost(); + VariableElement varKind = Utils.findVariableElement(nodeinfoCost, cost.name()); + + nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind)); return nodeInfoMirror; } @@ -2609,9 +2598,9 @@ } if (specialization.isGeneric()) { - clazz.add(createGetKind(specialization.getNode(), specialization, Kind.GENERIC)); + clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.MEGAMORPHIC)); } else if (specialization.isUninitialized()) { - clazz.add(createGetKind(specialization.getNode(), specialization, Kind.UNINITIALIZED)); + clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.UNINITIALIZED)); } } @@ -2633,13 +2622,16 @@ } CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor); + if (superConstructor == null) { + continue; + } CodeTree body = superConstructor.getBodyTree(); CodeTreeBuilder builder = superConstructor.createBuilder(); builder.tree(body); if (node.isPolymorphic()) { if (specialization.isSpecialized() || specialization.isPolymorphic()) { - builder.statement("this.next0 = adoptChild(copy.next0)"); + builder.statement("this.next0 = copy.next0"); } } if (superConstructor != null) { diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -52,7 +52,7 @@ super(null, frameDescriptor); /* Deep copy the body before any specialization occurs during execution. */ this.uninitializedBodyNode = NodeUtil.cloneNode(bodyNode); - this.bodyNode = adoptChild(bodyNode); + this.bodyNode = bodyNode; this.name = name; } diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -53,9 +53,9 @@ protected SLDirectDispatchNode(SLAbstractDispatchNode next, SLFunction cachedFunction) { this.cachedFunction = cachedFunction; - this.callCachedTargetNode = adoptChild(Truffle.getRuntime().createCallNode(cachedFunction.getCallTarget())); + this.callCachedTargetNode = Truffle.getRuntime().createCallNode(cachedFunction.getCallTarget()); this.cachedTargetStable = cachedFunction.getCallTargetStable(); - this.nextNode = adoptChild(next); + this.nextNode = next; } /** diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -48,9 +48,9 @@ @Child protected SLAbstractDispatchNode dispatchNode; private SLInvokeNode(SLExpressionNode functionNode, SLExpressionNode[] argumentNodes, SLAbstractDispatchNode dispatchNode) { - this.functionNode = adoptChild(functionNode); - this.argumentNodes = adoptChildren(argumentNodes); - this.dispatchNode = adoptChild(dispatchNode); + this.functionNode = functionNode; + this.argumentNodes = argumentNodes; + this.dispatchNode = dispatchNode; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -45,7 +45,7 @@ * It is a Truffle requirement to call adoptChildren(), which performs all the necessary * steps to add the new children to the node tree. */ - this.bodyNodes = adoptChildren(bodyNodes); + this.bodyNodes = bodyNodes; } /** diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -54,7 +54,7 @@ * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps * to add the new child to the node tree. */ - this.bodyNode = adoptChild(bodyNode); + this.bodyNode = bodyNode; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -57,9 +57,9 @@ * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps * to add the new child to the node tree. */ - this.conditionNode = adoptChild(conditionNode); - this.thenPartNode = adoptChild(thenPartNode); - this.elsePartNode = adoptChild(elsePartNode); + this.conditionNode = conditionNode; + this.thenPartNode = thenPartNode; + this.elsePartNode = elsePartNode; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -40,7 +40,7 @@ @Child private SLExpressionNode valueNode; public SLReturnNode(SLExpressionNode valueNode) { - this.valueNode = adoptChild(valueNode); + this.valueNode = valueNode; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -55,8 +55,8 @@ * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps * to add the new child to the node tree. */ - this.conditionNode = adoptChild(conditionNode); - this.bodyNode = adoptChild(bodyNode); + this.conditionNode = conditionNode; + this.bodyNode = bodyNode; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java Wed Mar 19 19:02:29 2014 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java Thu Mar 20 13:50:21 2014 +0100 @@ -42,8 +42,8 @@ @Child private SLExpressionNode rightNode; public SLAddWithoutSpecializationNode(SLExpressionNode leftNode, SLExpressionNode rightNode) { - this.leftNode = adoptChild(leftNode); - this.rightNode = adoptChild(rightNode); + this.leftNode = leftNode; + this.rightNode = rightNode; } @Override diff -r 5ddfdc13027a -r 17a735726670 graal/findbugsExcludeFilter.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/findbugsExcludeFilter.xml Thu Mar 20 13:50:21 2014 +0100 @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 5ddfdc13027a -r 17a735726670 mx/mx_graal.py --- a/mx/mx_graal.py Wed Mar 19 19:02:29 2014 +0100 +++ b/mx/mx_graal.py Thu Mar 20 13:50:21 2014 +0100 @@ -83,6 +83,12 @@ JDK_UNIX_PERMISSIONS = 0755 +def isVMSupported(vm): + if 'client' in vm and len(platform.mac_ver()[0]) != 0: + # Client VM not supported: java launcher on Mac OS X translates '-client' to '-server' + return False + return True + def _get_vm(): """ Gets the configured VM, presenting a dialogue if there is no currently configured VM. @@ -569,6 +575,10 @@ mx.log('only product build of original VM exists') continue + if not isVMSupported(vm): + mx.log('The ' + vm + ' VM is not supported on this platform - skipping') + continue + vmDir = join(_vmLibDirInJdk(jdk), vm) if not exists(vmDir): if mx.get_os() != 'windows': @@ -718,8 +728,8 @@ if vm is None: vm = _get_vm() - if 'client' in vm and len(platform.mac_ver()[0]) != 0: - mx.abort("Client VM not supported: java launcher on Mac OS X translates '-client' to '-server'") + if not isVMSupported(vm): + mx.abort('The ' + vm + ' is not supported on this platform') if cwd is None: cwd = _vm_cwd @@ -927,6 +937,10 @@ allStart = time.time() for v in vms: + if not isVMSupported(v): + mx.log('The ' + v + ' VM is not supported on this platform - skipping') + continue + for vmbuild in builds: if v == 'original' and vmbuild != 'product': continue @@ -1043,6 +1057,9 @@ for vmbuild in ['product', 'fastdebug']: for theVm in ['client', 'server']: + if not isVMSupported(theVm): + mx.log('The' + theVm + ' VM is not supported on this platform') + continue with VM(theVm, vmbuild): t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild) dacapo(['pmd']) @@ -1175,7 +1192,7 @@ env = os.environ proxy = os.environ.get('http_proxy') if not (proxy is None) and len(proxy) > 0: - if proxy.contains('://'): + if '://' in proxy: # Remove the http:// prefix (or any other protocol prefix) proxy = proxy.split('://', 1)[1] # Separate proxy server name and port number @@ -1638,6 +1655,38 @@ valueMap = parser.parse(output.getvalue()) return valueMap +def findbugs(args): + '''run FindBugs against non-test Java projects''' + findBugsHome = mx.get_env('FINDBUGS_HOME', None) + if findBugsHome: + findbugsJar = join(findBugsHome, 'lib', 'findbugs.jar') + else: + findbugsLib = join(_graal_home, 'lib', 'findbugs-3.0.0') + if not exists(findbugsLib): + tmp = tempfile.mkdtemp(prefix='findbugs-download-tmp', dir=_graal_home) + try: + findbugsDist = join(tmp, 'findbugs.zip') + mx.download(findbugsDist, ['http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0-dev-20131204-e3cbbd5.zip']) + with zipfile.ZipFile(findbugsDist) as zf: + candidates = [e for e in zf.namelist() if e.endswith('/lib/findbugs.jar')] + assert len(candidates) == 1, candidates + libDirInZip = os.path.dirname(candidates[0]) + zf.extractall(tmp) + shutil.copytree(join(tmp, libDirInZip), findbugsLib) + finally: + shutil.rmtree(tmp) + findbugsJar = join(findbugsLib, 'findbugs.jar') + assert exists(findbugsJar) + nonTestProjects = [p for p in mx.projects() if not p.name.endswith('.test') and not p.name.endswith('.jtt')] + outputDirs = [p.output_dir() for p in nonTestProjects] + findbugsResults = join(_graal_home, 'findbugs.results') + exitcode = mx.run_java(['-jar', findbugsJar, '-textui', '-low', '-maxRank', '15', '-exclude', join(_graal_home, 'graal', 'findbugsExcludeFilter.xml'), + '-auxclasspath', mx.classpath([p.name for p in nonTestProjects]), '-output', findbugsResults, '-progress', '-exitcode'] + args + outputDirs, nonZeroIsFatal=False) + if exitcode != 0: + with open(findbugsResults) as fp: + mx.log(fp.read()) + os.unlink(findbugsResults) + return exitcode def mx_init(suite): commands = { @@ -1646,6 +1695,7 @@ 'buildvms': [buildvms, '[-options]'], 'c1visualizer' : [c1visualizer, ''], 'clean': [clean, ''], + 'findbugs': [findbugs, ''], 'generateZshCompletion' : [generateZshCompletion, ''], 'hsdis': [hsdis, '[att]'], 'hcfdis': [hcfdis, ''], diff -r 5ddfdc13027a -r 17a735726670 mx/projects --- a/mx/projects Wed Mar 19 19:02:29 2014 +0100 +++ b/mx/projects Thu Mar 20 13:50:21 2014 +0100 @@ -13,9 +13,6 @@ library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar -library@FINDBUGS@path=lib/findbugs-3.0.0-dev-20131204-e3cbbd5.jar -library@FINDBUGS@urls=jar:http://sourceforge.net/projects/findbugs/files/findbugs/3.0.0/findbugs-3.0.0-dev-20131204-e3cbbd5.zip/download!/findbugs-3.0.0-dev-20131204-e3cbbd5/lib/findbugs.jar - library@DACAPO@path=lib/dacapo-9.12-bach.jar library@DACAPO@urls=http://softlayer.dl.sourceforge.net/project/dacapobench/9.12-bach/dacapo-9.12-bach.jar @@ -41,6 +38,10 @@ library@OKRA_WITH_SIM@sourcePath=lib/okra-1.8-with-sim-src.jar library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim-src.jar +library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar +library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter.jar +library@JAVA_ALLOCATION_INSTRUMENTER@sha1=1cd4073f57d7d461a53b0ddc1ea4ee2aa0c60e66 + distribution@GRAAL@path=graal.jar distribution@GRAAL@dependencies=\ com.oracle.graal.hotspot.amd64,\ @@ -498,7 +499,7 @@ # graal.java.decompiler.test project@com.oracle.graal.java.decompiler.test@subDir=graal project@com.oracle.graal.java.decompiler.test@sourceDirs=src -project@com.oracle.graal.java.decompiler.test@dependencies=com.oracle.graal.printer,com.oracle.graal.runtime +project@com.oracle.graal.java.decompiler.test@dependencies=JUNIT,com.oracle.graal.printer,com.oracle.graal.runtime project@com.oracle.graal.java.decompiler.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.java.decompiler.test@javaCompliance=1.7 project@com.oracle.graal.java.decompiler.test@workingSets=Graal,Test @@ -522,7 +523,7 @@ # graal.compiler.test project@com.oracle.graal.compiler.test@subDir=graal project@com.oracle.graal.compiler.test@sourceDirs=src -project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer,com.oracle.graal.runtime,com.oracle.graal.baseline +project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer,com.oracle.graal.runtime,com.oracle.graal.baseline,JAVA_ALLOCATION_INSTRUMENTER project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.test@javaCompliance=1.7 project@com.oracle.graal.compiler.test@workingSets=Graal,Test diff -r 5ddfdc13027a -r 17a735726670 mxtool/mx.py --- a/mxtool/mx.py Wed Mar 19 19:02:29 2014 +0100 +++ b/mxtool/mx.py Thu Mar 20 13:50:21 2014 +0100 @@ -40,6 +40,7 @@ import xml.parsers.expat import shutil, re, xml.dom.minidom import pipes +import difflib from collections import Callable from threading import Thread from argparse import ArgumentParser, REMAINDER @@ -1894,10 +1895,13 @@ abort('Could not find Eclipse executable. Use -e option or ensure ECLIPSE_EXE environment variable is set.') # Maybe an Eclipse installation dir was specified - look for the executable in it - if join(args.eclipse_exe, exe_suffix('eclipse')): + if isdir(args.eclipse_exe): args.eclipse_exe = join(args.eclipse_exe, exe_suffix('eclipse')) - - if not os.path.isfile(args.eclipse_exe) or not os.access(args.eclipse_exe, os.X_OK): + warn("The eclipse-exe was a directory, now using " + args.eclipse_exe) + + if not os.path.isfile(args.eclipse_exe): + abort('File does not exist: ' + args.eclipse_exe) + if not os.access(args.eclipse_exe, os.X_OK): abort('Not an executable file: ' + args.eclipse_exe) eclipseinit([], buildProcessorJars=False) @@ -1927,6 +1931,7 @@ with open(self.path) as fp: content = fp.read() if self.content != content: + self.diff = difflib.unified_diff(self.content.splitlines(1), content.splitlines(1)) self.content = content return True os.utime(self.path, self.times) @@ -1964,6 +1969,7 @@ modified.append(fi) log('{0} files were modified'.format(len(modified))) + if len(modified) != 0: arcbase = _primary_suite.dir if args.backup: @@ -1972,6 +1978,8 @@ for fi in modified: name = os.path.relpath(fi.path, arcbase) log(' - {0}'.format(name)) + log('Changes:') + log(''.join(fi.diff)) if args.backup: arcname = name.replace(os.sep, '/') zf.writestr(arcname, fi.content) diff -r 5ddfdc13027a -r 17a735726670 src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp --- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -41,55 +41,32 @@ } } -inline void CodeInstaller::pd_site_DataPatch(int pc_offset, oop site) { - oop inlineData = CompilationResult_DataPatch::inlineData(site); - address pc = _instructions->start() + pc_offset; +inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) { + if (OopData::compressed(obj)) { + fatal("unimplemented: narrow oop relocation"); + } else { + address pc = _instructions->start() + pc_offset; + Handle obj = OopData::object(data); + jobject value = JNIHandles::make_local(obj()); - if (inlineData != NULL) { - oop kind = Constant::kind(inlineData); - char typeChar = Kind::typeChar(kind); + NativeMovConstReg* move = nativeMovConstReg_at(pc); + move->set_data((intptr_t) value); - switch (typeChar) { - case 'z': - case 'b': - case 's': - case 'c': - case 'i': - fatal("int-sized values not expected in DataPatch"); - break; - case 'f': - case 'j': - case 'd': { - NativeMovConstReg* move = nativeMovConstReg_at(pc); - uint64_t value = Constant::primitive(inlineData); - move->set_data(value); - break; - } - case 'a': { - NativeMovConstReg* move = nativeMovConstReg_at(pc); - Handle obj = Constant::object(inlineData); - jobject value = JNIHandles::make_local(obj()); - move->set_data((intptr_t) value); + // We need two relocations: one on the sethi and one on the add. + int oop_index = _oop_recorder->find_index(value); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec); + _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec); + } +} - // We need two relocations: one on the sethi and one on the add. - int oop_index = _oop_recorder->find_index(value); - RelocationHolder rspec = oop_Relocation::spec(oop_index); - _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec); - _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec); - break; - } - default: - fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar)); - break; - } - } else { - oop dataRef = CompilationResult_DataPatch::externalData(site); - jint offset = HotSpotCompiledCode_HotSpotData::offset(dataRef); +inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) { + address pc = _instructions->start() + pc_offset; + jint offset = DataSectionReference::offset(data); - NativeMovRegMem* load = nativeMovRegMem_at(pc); - int disp = _constants_size + pc_offset - offset - BytesPerInstWord; - load->set_offset(-disp); - } + NativeMovRegMem* load = nativeMovRegMem_at(pc); + int disp = _constants_size + pc_offset - offset - BytesPerInstWord; + load->set_offset(-disp); } inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { @@ -121,24 +98,24 @@ } #endif switch (_next_call_type) { - case MARK_INLINE_INVOKE: + case INLINE_INVOKE: break; - case MARK_INVOKEVIRTUAL: - case MARK_INVOKEINTERFACE: { + case INVOKEVIRTUAL: + case INVOKEINTERFACE: { assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc)); break; } - case MARK_INVOKESTATIC: { + case INVOKESTATIC: { assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::static_call_type); break; } - case MARK_INVOKESPECIAL: { + case INVOKESPECIAL: { assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); @@ -153,16 +130,16 @@ inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) { switch (mark) { - case MARK_POLL_NEAR: { + case POLL_NEAR: { fatal("unimplemented"); } - case MARK_POLL_FAR: + case POLL_FAR: _instructions->relocate(pc, relocInfo::poll_type); break; - case MARK_POLL_RETURN_NEAR: { + case POLL_RETURN_NEAR: { fatal("unimplemented"); } - case MARK_POLL_RETURN_FAR: + case POLL_RETURN_FAR: _instructions->relocate(pc, relocInfo::poll_return_type); break; default: diff -r 5ddfdc13027a -r 17a735726670 src/cpu/x86/vm/graalCodeInstaller_x86.hpp --- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -59,68 +59,49 @@ } } -inline void CodeInstaller::pd_site_DataPatch(int pc_offset, oop site) { - oop inlineData = CompilationResult_DataPatch::inlineData(site); +inline bool check_metaspace_data(address pc, oop data) { + jlong value = MetaspaceData::value(data); + address operand = Assembler::locate_operand(pc, Assembler::imm_operand); + if (MetaspaceData::compressed(data)) { + assert(*((jint*) operand) == value, err_msg("wrong compressed metaspace pointer: %p != %p", *((jint*) operand), value)); + } else { + assert(*((jlong*) operand) == value, err_msg("wrong metaspace pointer: %p != %p", *((jlong*) operand), value)); + } + return true; +} + +inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) { address pc = _instructions->start() + pc_offset; - if (inlineData != NULL) { - oop kind = Constant::kind(inlineData); - char typeChar = Kind::typeChar(kind); - - switch (typeChar) { - case 'z': - case 'b': - case 's': - case 'c': - case 'i': - fatal("int-sized values not expected in DataPatch"); - break; - case 'n': { - address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); - Handle obj = Constant::object(inlineData); + Handle obj = OopData::object(data); + jobject value = JNIHandles::make_local(obj()); + if (OopData::compressed(data)) { + address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); + int oop_index = _oop_recorder->find_index(value); + _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand); + TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand); + } else { + address operand = Assembler::locate_operand(pc, Assembler::imm_operand); + *((jobject*) operand) = value; + _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); + TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand); + } +} - jobject value = JNIHandles::make_local(obj()); - int oop_index = _oop_recorder->find_index(value); - _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand); - TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand); - break; - } - case 'f': - case 'j': - case 'd': - case '*': { - address operand = Assembler::locate_operand(pc, Assembler::imm_operand); - *((jlong*) operand) = Constant::primitive(inlineData); - break; - } - case 'a': { - address operand = Assembler::locate_operand(pc, Assembler::imm_operand); - Handle obj = Constant::object(inlineData); +inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) { + address pc = _instructions->start() + pc_offset; + jint offset = DataSectionReference::offset(data); - jobject value = JNIHandles::make_local(obj()); - *((jobject*) operand) = value; - _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand); - break; - } - default: - fatal(err_msg("unexpected Kind (%d) in DataPatch", typeChar)); - break; - } - } else { - oop dataRef = CompilationResult_DataPatch::externalData(site); - jint offset = HotSpotCompiledCode_HotSpotData::offset(dataRef); - address operand = Assembler::locate_operand(pc, Assembler::disp32_operand); - address next_instruction = Assembler::locate_next_instruction(pc); - address dest = _constants->start() + offset; + address operand = Assembler::locate_operand(pc, Assembler::disp32_operand); + address next_instruction = Assembler::locate_next_instruction(pc); + address dest = _constants->start() + offset; - long disp = dest - next_instruction; - assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); - *((jint*) operand) = (jint) disp; + long disp = dest - next_instruction; + assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); + *((jint*) operand) = (jint) disp; - _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); - TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset); - } + _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); + TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset); } inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { @@ -170,10 +151,10 @@ } #endif switch (_next_call_type) { - case MARK_INLINE_INVOKE: + case INLINE_INVOKE: break; - case MARK_INVOKEVIRTUAL: - case MARK_INVOKEINTERFACE: { + case INVOKEVIRTUAL: + case INVOKEINTERFACE: { assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); @@ -183,7 +164,7 @@ Assembler::call32_operand); break; } - case MARK_INVOKESTATIC: { + case INVOKESTATIC: { assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); @@ -192,7 +173,7 @@ relocInfo::static_call_type, Assembler::call32_operand); break; } - case MARK_INVOKESPECIAL: { + case INVOKESPECIAL: { assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); @@ -216,24 +197,24 @@ inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) { switch (mark) { - case MARK_POLL_NEAR: { + case POLL_NEAR: { relocate_poll_near(pc); _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand); break; } - case MARK_POLL_FAR: + case POLL_FAR: // This is a load from a register so there is no relocatable operand. // We just have to ensure that the format is not disp32_operand // so that poll_Relocation::fix_relocation_after_move does the right // thing (i.e. ignores this relocation record) _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand); break; - case MARK_POLL_RETURN_NEAR: { + case POLL_RETURN_NEAR: { relocate_poll_near(pc); _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand); break; } - case MARK_POLL_RETURN_FAR: + case POLL_RETURN_FAR: // see comment above for MARK_POLL_FAR _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand); break; diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -187,12 +187,15 @@ do_klass(BitSet_klass, java_util_BitSet, Opt) \ /* graal.hotspot */ \ do_klass(HotSpotCompiledCode_klass, com_oracle_graal_hotspot_HotSpotCompiledCode, Opt) \ - do_klass(HotSpotCompiledCode_HotSpotData_klass, com_oracle_graal_hotspot_HotSpotCompiledCode_HotSpotData, Opt) \ - do_klass(HotSpotCompiledCode_DataSection_klass, com_oracle_graal_hotspot_HotSpotCompiledCode_DataSection, Opt) \ do_klass(HotSpotCompiledCode_Comment_klass, com_oracle_graal_hotspot_HotSpotCompiledCode_Comment, Opt) \ do_klass(HotSpotCompiledNmethod_klass, com_oracle_graal_hotspot_HotSpotCompiledNmethod, Opt) \ do_klass(HotSpotCompiledRuntimeStub_klass, com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub, Opt) \ do_klass(HotSpotForeignCallLinkage_klass, com_oracle_graal_hotspot_HotSpotForeignCallLinkage, Opt) \ + do_klass(HotSpotReferenceMap_klass, com_oracle_graal_hotspot_HotSpotReferenceMap, Opt) \ + do_klass(DataSection_klass, com_oracle_graal_hotspot_data_DataSection, Opt) \ + do_klass(DataSectionReference_klass, com_oracle_graal_hotspot_data_DataSectionReference, Opt) \ + do_klass(MetaspaceData_klass, com_oracle_graal_hotspot_data_MetaspaceData, Opt) \ + do_klass(OopData_klass, com_oracle_graal_hotspot_data_OopData, Opt) \ do_klass(HotSpotCodeInfo_klass, com_oracle_graal_hotspot_meta_HotSpotCodeInfo, Opt) \ do_klass(HotSpotInstalledCode_klass, com_oracle_graal_hotspot_meta_HotSpotInstalledCode, Opt) \ do_klass(HotSpotNmethod_klass, com_oracle_graal_hotspot_meta_HotSpotNmethod, Opt) \ @@ -210,7 +213,6 @@ do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue, Opt) \ do_klass(BytecodePosition_klass, com_oracle_graal_api_code_BytecodePosition, Opt) \ do_klass(DebugInfo_klass, com_oracle_graal_api_code_DebugInfo, Opt) \ - do_klass(ReferenceMap_klass, com_oracle_graal_api_code_ReferenceMap, Opt) \ do_klass(RegisterSaveLayout_klass, com_oracle_graal_api_code_RegisterSaveLayout, Opt) \ do_klass(BytecodeFrame_klass, com_oracle_graal_api_code_BytecodeFrame, Opt) \ do_klass(CompilationResult_klass, com_oracle_graal_api_code_CompilationResult, Opt) \ diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -296,14 +296,17 @@ template(com_oracle_graal_hotspot_HotSpotKlassOop, "com/oracle/graal/hotspot/HotSpotKlassOop") \ template(com_oracle_graal_hotspot_HotSpotOptions, "com/oracle/graal/hotspot/HotSpotOptions") \ template(com_oracle_graal_hotspot_HotSpotCompiledCode, "com/oracle/graal/hotspot/HotSpotCompiledCode") \ - template(com_oracle_graal_hotspot_HotSpotCompiledCode_HotSpotData, "com/oracle/graal/hotspot/HotSpotCompiledCode$HotSpotData") \ - template(com_oracle_graal_hotspot_HotSpotCompiledCode_DataSection, "com/oracle/graal/hotspot/HotSpotCompiledCode$DataSection") \ template(com_oracle_graal_hotspot_HotSpotCompiledCode_Comment, "com/oracle/graal/hotspot/HotSpotCompiledCode$Comment") \ template(com_oracle_graal_hotspot_HotSpotCompiledNmethod, "com/oracle/graal/hotspot/HotSpotCompiledNmethod") \ template(com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub, "com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub") \ template(com_oracle_graal_hotspot_HotSpotForeignCallLinkage, "com/oracle/graal/hotspot/HotSpotForeignCallLinkage") \ + template(com_oracle_graal_hotspot_HotSpotReferenceMap, "com/oracle/graal/hotspot/HotSpotReferenceMap") \ template(com_oracle_graal_hotspot_bridge_VMToCompiler, "com/oracle/graal/hotspot/bridge/VMToCompiler") \ template(com_oracle_graal_hotspot_bridge_CompilerToVMImpl, "com/oracle/graal/hotspot/bridge/CompilerToVMImpl") \ + template(com_oracle_graal_hotspot_data_DataSection, "com/oracle/graal/hotspot/data/DataSection") \ + template(com_oracle_graal_hotspot_data_DataSectionReference, "com/oracle/graal/hotspot/data/DataSectionReference") \ + template(com_oracle_graal_hotspot_data_MetaspaceData, "com/oracle/graal/hotspot/data/MetaspaceData") \ + template(com_oracle_graal_hotspot_data_OopData, "com/oracle/graal/hotspot/data/OopData") \ template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo, "com/oracle/graal/hotspot/meta/HotSpotCodeInfo") \ template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode, "com/oracle/graal/hotspot/meta/HotSpotInstalledCode") \ template(com_oracle_graal_hotspot_meta_HotSpotNmethod, "com/oracle/graal/hotspot/meta/HotSpotNmethod") \ @@ -340,7 +343,6 @@ template(com_oracle_graal_api_code_BytecodeFrame, "com/oracle/graal/api/code/BytecodeFrame") \ template(com_oracle_graal_api_code_BytecodePosition, "com/oracle/graal/api/code/BytecodePosition") \ template(com_oracle_graal_api_code_DebugInfo, "com/oracle/graal/api/code/DebugInfo") \ - template(com_oracle_graal_api_code_ReferenceMap, "com/oracle/graal/api/code/ReferenceMap") \ template(com_oracle_graal_api_code_Register, "com/oracle/graal/api/code/Register") \ template(com_oracle_graal_api_code_RegisterValue, "com/oracle/graal/api/code/RegisterValue") \ template(com_oracle_graal_api_code_StackSlot, "com/oracle/graal/api/code/StackSlot") \ diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/code/nmethod.cpp Thu Mar 20 13:50:21 2014 +0100 @@ -1025,6 +1025,7 @@ void nmethod::print_on(outputStream* st, const char* msg) const { if (st != NULL) { ttyLocker ttyl; + if (CIPrintCompilerName) st->print("%s:", compiler()->name()); if (WizardMode) { CompileTask::print_compilation(st, this, msg, /*short_form:*/ true); st->print_cr(" (" INTPTR_FORMAT ")", this); diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu Mar 20 13:50:21 2014 +0100 @@ -91,8 +91,8 @@ static OopMap* create_oop_map(jint total_frame_size, jint parameter_count, oop debug_info) { OopMap* map = new OopMap(total_frame_size, parameter_count); oop reference_map = DebugInfo::referenceMap(debug_info); - oop register_map = ReferenceMap::registerRefMap(reference_map); - oop frame_map = ReferenceMap::frameRefMap(reference_map); + oop register_map = HotSpotReferenceMap::registerRefMap(reference_map); + oop frame_map = HotSpotReferenceMap::frameRefMap(reference_map); oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info); if (register_map != NULL) { @@ -157,6 +157,27 @@ return map; } +static void record_metadata_reference(oop obj, jlong prim, bool compressed, OopRecorder* oop_recorder) { + if (obj->is_a(HotSpotResolvedObjectType::klass())) { + Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaClass(obj)); + if (compressed) { + assert(Klass::decode_klass((narrowKlass) prim) == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim)); + } else { + 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 if (obj->is_a(HotSpotResolvedJavaMethod::klass())) { + Method* method = (Method*) (address) HotSpotResolvedJavaMethod::metaspaceMethod(obj); + assert(!compressed, err_msg("unexpected compressed method pointer %s @ %p = %p", method->name()->as_C_string(), method, prim)); + int index = oop_recorder->find_index(method); + TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string()); + } else { + assert(java_lang_String::is_instance(obj), + err_msg("unexpected metadata reference (%s) for constant %ld (%p)", obj->klass()->name()->as_C_string(), prim, prim)); + } +} + // Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedObjectType.klass()). static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) { char kind = Kind::typeChar(Constant::kind(constant)); @@ -165,23 +186,15 @@ oop obj = Constant::object(constant); jlong prim = Constant::primitive(constant); if (obj != NULL) { - if (obj->is_a(HotSpotResolvedObjectType::klass())) { - Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaClass(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 if (obj->is_a(HotSpotResolvedJavaMethod::klass())) { - Method* method = (Method*) (address) HotSpotResolvedJavaMethod::metaspaceMethod(obj); - int index = oop_recorder->find_index(method); - TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->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)); - } + record_metadata_reference(obj, prim, false, oop_recorder); } } } +static void record_metadata_in_patch(oop data, OopRecorder* oop_recorder) { + record_metadata_reference(MetaspaceData::annotation(data), MetaspaceData::value(data), MetaspaceData::compressed(data) != 0, oop_recorder); +} + ScopeValue* CodeInstaller::get_scope_value(oop value, int total_frame_size, GrowableArray* objects, ScopeValue* &second, OopRecorder* oop_recorder) { second = NULL; if (value == Value::ILLEGAL()) { @@ -445,8 +458,8 @@ // Pre-calculate the constants section size. This is required for PC-relative addressing. _dataSection = HotSpotCompiledCode::dataSection(compiled_code); - guarantee(HotSpotCompiledCode_DataSection::sectionAlignment(_dataSection) <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); - arrayOop data = (arrayOop) HotSpotCompiledCode_DataSection::data(_dataSection); + guarantee(DataSection::sectionAlignment(_dataSection) <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin"); + arrayOop data = (arrayOop) DataSection::data(_dataSection); _constants_size = data->length(); if (_constants_size > 0) { _constants_size = align_size_up(_constants_size, _constants->alignment()); @@ -456,7 +469,7 @@ _comments = (arrayOop) HotSpotCompiledCode::comments(compiled_code); #endif - _next_call_type = MARK_INVOKE_INVALID; + _next_call_type = INVOKE_INVALID; } // perform data and call relocation on the CodeBuffer @@ -482,30 +495,24 @@ // copy the constant data into the newly created CodeBuffer address end_data = _constants->start() + _constants_size; - arrayOop data = (arrayOop) HotSpotCompiledCode_DataSection::data(_dataSection); + arrayOop data = (arrayOop) DataSection::data(_dataSection); memcpy(_constants->start(), data->base(T_BYTE), data->length()); _constants->set_end(end_data); - objArrayOop patches = (objArrayOop) HotSpotCompiledCode_DataSection::patches(_dataSection); + objArrayOop patches = (objArrayOop) DataSection::patches(_dataSection); for (int i = 0; i < patches->length(); i++) { oop patch = patches->obj_at(i); - oop constant = HotSpotCompiledCode_HotSpotData::constant(patch); - oop kind = Constant::kind(constant); - char typeChar = Kind::typeChar(kind); - switch (typeChar) { - case 'f': - case 'j': - case 'd': - record_metadata_in_constant(constant, _oop_recorder); - break; - case 'a': - Handle obj = Constant::object(constant); - jobject value = JNIHandles::make_local(obj()); - int oop_index = _oop_recorder->find_index(value); + oop data = CompilationResult_DataPatch::data(patch); + if (data->is_a(MetaspaceData::klass())) { + record_metadata_in_patch(data, _oop_recorder); + } else if (data->is_a(OopData::klass())) { + Handle obj = OopData::object(data); + jobject value = JNIHandles::make_local(obj()); + int oop_index = _oop_recorder->find_index(value); - address dest = _constants->start() + HotSpotCompiledCode_HotSpotData::offset(patch); - _constants->relocate(dest, oop_Relocation::spec(oop_index)); - break; + address dest = _constants->start() + CompilationResult_Site::pcOffset(patch); + assert(!OopData::compressed(data), err_msg("unexpected compressed oop in data section")); + _constants->relocate(dest, oop_Relocation::spec(oop_index)); } } @@ -769,7 +776,7 @@ CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset); } - _next_call_type = MARK_INVOKE_INVALID; + _next_call_type = INVOKE_INVALID; if (debug_info != NULL) { _debug_recorder->end_safepoint(next_pc_offset); @@ -777,19 +784,16 @@ } void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) { - oop inlineData = CompilationResult_DataPatch::inlineData(site); - if (inlineData != NULL) { - oop kind = Constant::kind(inlineData); - char typeChar = Kind::typeChar(kind); - switch (typeChar) { - case 'f': - case 'j': - case 'd': - record_metadata_in_constant(inlineData, _oop_recorder); - break; - } + oop data = CompilationResult_DataPatch::data(site); + if (data->is_a(MetaspaceData::klass())) { + record_metadata_in_patch(data, _oop_recorder); + } else if (data->is_a(OopData::klass())) { + pd_patch_OopData(pc_offset, data); + } else if (data->is_a(DataSectionReference::klass())) { + pd_patch_DataSectionReference(pc_offset, data); + } else { + fatal("unknown data patch type"); } - CodeInstaller::pd_site_DataPatch(pc_offset, site); } void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { @@ -802,33 +806,33 @@ address pc = _instructions->start() + pc_offset; switch (id) { - case MARK_UNVERIFIED_ENTRY: + case UNVERIFIED_ENTRY: _offsets.set_value(CodeOffsets::Entry, pc_offset); break; - case MARK_VERIFIED_ENTRY: + case VERIFIED_ENTRY: _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset); break; - case MARK_OSR_ENTRY: + case OSR_ENTRY: _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset); break; - case MARK_EXCEPTION_HANDLER_ENTRY: + case EXCEPTION_HANDLER_ENTRY: _offsets.set_value(CodeOffsets::Exceptions, pc_offset); break; - case MARK_DEOPT_HANDLER_ENTRY: + case DEOPT_HANDLER_ENTRY: _offsets.set_value(CodeOffsets::Deopt, pc_offset); break; - case MARK_INVOKEVIRTUAL: - case MARK_INVOKEINTERFACE: - case MARK_INLINE_INVOKE: - case MARK_INVOKESTATIC: - case MARK_INVOKESPECIAL: + case INVOKEVIRTUAL: + case INVOKEINTERFACE: + case INLINE_INVOKE: + case INVOKESTATIC: + case INVOKESPECIAL: _next_call_type = (MarkId) id; _invoke_mark_pc = pc; break; - case MARK_POLL_NEAR: - case MARK_POLL_FAR: - case MARK_POLL_RETURN_NEAR: - case MARK_POLL_RETURN_FAR: + case POLL_NEAR: + case POLL_FAR: + case POLL_RETURN_NEAR: + case POLL_RETURN_FAR: pd_relocate_poll(pc, id); break; default: diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -24,28 +24,30 @@ #ifndef SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP #define SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP +#include "graal/graalEnv.hpp" + /* * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod. */ class CodeInstaller { + friend class VMStructs; private: - // these need to correspond to Marks.java enum MarkId { - MARK_VERIFIED_ENTRY = 1, - MARK_UNVERIFIED_ENTRY = 2, - MARK_OSR_ENTRY = 3, - MARK_EXCEPTION_HANDLER_ENTRY = 4, - MARK_DEOPT_HANDLER_ENTRY = 5, - MARK_INVOKEINTERFACE = 6, - MARK_INVOKEVIRTUAL = 7, - MARK_INVOKESTATIC = 8, - MARK_INVOKESPECIAL = 9, - MARK_INLINE_INVOKE = 10, - MARK_POLL_NEAR = 11, - MARK_POLL_RETURN_NEAR = 12, - MARK_POLL_FAR = 13, - MARK_POLL_RETURN_FAR = 14, - MARK_INVOKE_INVALID = -1 + VERIFIED_ENTRY = 1, + UNVERIFIED_ENTRY = 2, + OSR_ENTRY = 3, + EXCEPTION_HANDLER_ENTRY = 4, + DEOPT_HANDLER_ENTRY = 5, + INVOKEINTERFACE = 6, + INVOKEVIRTUAL = 7, + INVOKESTATIC = 8, + INVOKESPECIAL = 9, + INLINE_INVOKE = 10, + POLL_NEAR = 11, + POLL_RETURN_NEAR = 12, + POLL_FAR = 13, + POLL_RETURN_FAR = 14, + INVOKE_INVALID = -1 }; Arena _arena; @@ -77,7 +79,8 @@ ExceptionHandlerTable _exception_handler_table; jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method); - void pd_site_DataPatch(int pc_offset, oop site); + void pd_patch_OopData(int pc_offset, oop data); + void pd_patch_DataSectionReference(int pc_offset, oop data); void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst); void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination); void pd_relocate_JavaMethod(oop method, jint pc_offset); diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Thu Mar 20 13:50:21 2014 +0100 @@ -348,11 +348,6 @@ return CompilerOracle::should_inline(method) || method->force_inline(); C2V_END -C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jlong metaspace_method)) - nmethod* code = (asMethod(metaspace_method))->code(); - return code == NULL ? 0 : code->insts_size(); -C2V_END - C2V_VMENTRY(jlong, lookupType, (JNIEnv *env, jobject, jstring jname, jclass accessing_class, jboolean resolve)) ResourceMark rm; Handle name = JNIHandles::resolve(jname); @@ -814,7 +809,6 @@ {CC"doNotInlineOrCompile", CC"("METASPACE_METHOD")V", FN_PTR(doNotInlineOrCompile)}, {CC"canInlineMethod", CC"("METASPACE_METHOD")Z", FN_PTR(canInlineMethod)}, {CC"shouldInlineMethod", CC"("METASPACE_METHOD")Z", FN_PTR(shouldInlineMethod)}, - {CC"getCompiledCodeSize", CC"("METASPACE_METHOD")I", FN_PTR(getCompiledCodeSize)}, {CC"lookupType", CC"("STRING CLASS"Z)"METASPACE_KLASS, FN_PTR(lookupType)}, {CC"resolveConstantInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolveConstantInPool)}, {CC"resolvePossiblyCachedConstantInPool", CC"("METASPACE_CONSTANT_POOL"I)"OBJECT, FN_PTR(resolvePossiblyCachedConstantInPool)}, diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -79,16 +79,7 @@ oop_field(HotSpotCompiledCode, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ oop_field(HotSpotCompiledCode, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \ oop_field(HotSpotCompiledCode, comments, "[Lcom/oracle/graal/hotspot/HotSpotCompiledCode$Comment;") \ - oop_field(HotSpotCompiledCode, dataSection, "Lcom/oracle/graal/hotspot/HotSpotCompiledCode$DataSection;") \ - end_class \ - start_class(HotSpotCompiledCode_HotSpotData) \ - int_field(HotSpotCompiledCode_HotSpotData, offset) \ - oop_field(HotSpotCompiledCode_HotSpotData, constant, "Lcom/oracle/graal/api/meta/Constant;") \ - end_class \ - start_class(HotSpotCompiledCode_DataSection) \ - int_field(HotSpotCompiledCode_DataSection, sectionAlignment) \ - oop_field(HotSpotCompiledCode_DataSection, data, "[B") \ - oop_field(HotSpotCompiledCode_DataSection, patches, "[Lcom/oracle/graal/hotspot/HotSpotCompiledCode$HotSpotData;") \ + oop_field(HotSpotCompiledCode, dataSection, "Lcom/oracle/graal/hotspot/data/DataSection;") \ end_class \ start_class(HotSpotCompiledCode_Comment) \ oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;") \ @@ -97,7 +88,7 @@ start_class(HotSpotCompiledNmethod) \ oop_field(HotSpotCompiledNmethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ int_field(HotSpotCompiledNmethod, entryBCI) \ - int_field(HotSpotCompiledNmethod, id) \ + int_field(HotSpotCompiledNmethod, id) \ end_class \ start_class(HotSpotCompiledRuntimeStub) \ oop_field(HotSpotCompiledRuntimeStub, stubName, "Ljava/lang/String;") \ @@ -105,6 +96,23 @@ start_class(HotSpotForeignCallLinkage) \ long_field(HotSpotForeignCallLinkage, address) \ end_class \ + start_class(DataSection) \ + int_field(DataSection, sectionAlignment) \ + oop_field(DataSection, data, "[B") \ + oop_field(DataSection, patches, "[Lcom/oracle/graal/api/code/CompilationResult$DataPatch;") \ + end_class \ + start_class(DataSectionReference) \ + int_field(DataSectionReference, offset) \ + end_class \ + start_class(MetaspaceData) \ + long_field(MetaspaceData, value) \ + oop_field(MetaspaceData, annotation, "Ljava/lang/Object;") \ + boolean_field(MetaspaceData, compressed) \ + end_class \ + start_class(OopData) \ + oop_field(OopData, object, "Ljava/lang/Object;") \ + boolean_field(OopData, compressed) \ + end_class \ start_class(ExternalCompilationResult) \ long_field(ExternalCompilationResult, entryPoint) \ end_class \ @@ -145,8 +153,7 @@ oop_field(CompilationResult_Call, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ end_class \ start_class(CompilationResult_DataPatch) \ - oop_field(CompilationResult_DataPatch, externalData, "Lcom/oracle/graal/api/code/CompilationResult$Data;") \ - oop_field(CompilationResult_DataPatch, inlineData, "Lcom/oracle/graal/api/meta/Constant;") \ + oop_field(CompilationResult_DataPatch, data, "Lcom/oracle/graal/api/code/CompilationResult$Data;") \ end_class \ start_class(InfopointReason) \ static_oop_field(InfopointReason, UNKNOWN, "Lcom/oracle/graal/api/code/InfopointReason;") \ @@ -172,9 +179,9 @@ oop_field(DebugInfo, referenceMap, "Lcom/oracle/graal/api/code/ReferenceMap;") \ oop_field(DebugInfo, calleeSaveInfo, "Lcom/oracle/graal/api/code/RegisterSaveLayout;") \ end_class \ - start_class(ReferenceMap) \ - oop_field(ReferenceMap, registerRefMap, "Ljava/util/BitSet;") \ - oop_field(ReferenceMap, frameRefMap, "Ljava/util/BitSet;") \ + start_class(HotSpotReferenceMap) \ + oop_field(HotSpotReferenceMap, registerRefMap, "Ljava/util/BitSet;") \ + oop_field(HotSpotReferenceMap, frameRefMap, "Ljava/util/BitSet;") \ end_class \ start_class(RegisterSaveLayout) \ oop_field(RegisterSaveLayout, registers, "[Lcom/oracle/graal/api/code/Register;") \ diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Thu Mar 20 13:50:21 2014 +0100 @@ -539,7 +539,12 @@ Handle receiverHandle(thread, receiver); MutexLockerEx ml(thread->threadObj() == (void*)receiver ? NULL : Threads_lock); JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle()); - return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0); + if (receiverThread == NULL) { + // The other thread may exit during this process, which is ok so return false. + return JNI_FALSE; + } else { + return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0); + } JRT_END // JVM_InitializeGraalRuntime diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/graal/vmStructs_graal.hpp --- a/src/share/vm/graal/vmStructs_graal.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/graal/vmStructs_graal.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,14 @@ #define SHARE_VM_GRAAL_VMSTRUCTS_GRAAL_HPP #include "compiler/abstractCompiler.hpp" +#include "graal/graalCodeInstaller.hpp" #include "graal/graalCompilerToVM.hpp" #include "graal/graalEnv.hpp" #define VM_STRUCTS_GRAAL(nonstatic_field, static_field) \ nonstatic_field(ThreadShadow, _pending_deoptimization, int) \ nonstatic_field(ThreadShadow, _pending_failed_speculation, oop) \ + nonstatic_field(MethodData, _graal_node_count, int) \ #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type) \ @@ -47,5 +49,21 @@ \ declare_constant(CompilerToVM::KLASS_TAG) \ declare_constant(CompilerToVM::SYMBOL_TAG) \ + \ + declare_constant(CodeInstaller::VERIFIED_ENTRY) \ + declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \ + declare_constant(CodeInstaller::OSR_ENTRY) \ + declare_constant(CodeInstaller::EXCEPTION_HANDLER_ENTRY) \ + declare_constant(CodeInstaller::DEOPT_HANDLER_ENTRY) \ + declare_constant(CodeInstaller::INVOKEINTERFACE) \ + declare_constant(CodeInstaller::INVOKEVIRTUAL) \ + declare_constant(CodeInstaller::INVOKESTATIC) \ + declare_constant(CodeInstaller::INVOKESPECIAL) \ + declare_constant(CodeInstaller::INLINE_INVOKE) \ + declare_constant(CodeInstaller::POLL_NEAR) \ + declare_constant(CodeInstaller::POLL_RETURN_NEAR) \ + declare_constant(CodeInstaller::POLL_FAR) \ + declare_constant(CodeInstaller::POLL_RETURN_FAR) \ + declare_constant(CodeInstaller::INVOKE_INVALID) \ #endif // SHARE_VM_GRAAL_VMSTRUCTS_GRAAL_HPP diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/oops/methodData.cpp --- a/src/share/vm/oops/methodData.cpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/oops/methodData.cpp Thu Mar 20 13:50:21 2014 +0100 @@ -1216,6 +1216,9 @@ _highest_comp_level = 0; _highest_osr_comp_level = 0; _would_profile = true; +#ifdef GRAAL + _graal_node_count = 0; +#endif // Initialize flags and trap history. _nof_decompiles = 0; diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/oops/methodData.hpp --- a/src/share/vm/oops/methodData.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/oops/methodData.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -2203,6 +2203,11 @@ // Does this method contain anything worth profiling? bool _would_profile; +#ifdef GRAAL + // Support for HotSpotMethodData.setCompiledGraphSize(int) + int _graal_node_count; +#endif + // Size of _data array in bytes. (Excludes header and extra_data fields.) int _data_size; diff -r 5ddfdc13027a -r 17a735726670 src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Wed Mar 19 19:02:29 2014 +0100 +++ b/src/share/vm/utilities/globalDefinitions.hpp Thu Mar 20 13:50:21 2014 +0100 @@ -834,7 +834,7 @@ CompLevel_full_profile = 3, // C1, invocation & backedge counters + mdo CompLevel_full_optimization = 4, // C2, Shark or Graal -#if defined(COMPILER2) || defined(SHARK) || defined(GRAAL) +#if defined(COMPILER2) || defined(SHARK) || defined(COMPILERGRAAL) CompLevel_highest_tier = CompLevel_full_optimization, // pure C2 and tiered or Graal and tiered #elif defined(COMPILER1) CompLevel_highest_tier = CompLevel_simple, // pure C1 or Graal @@ -844,7 +844,7 @@ #if defined(TIERED) CompLevel_initial_compile = CompLevel_full_profile // tiered -#elif defined(COMPILER1) || defined(GRAAL) +#elif defined(COMPILER1) || defined(COMPILERGRAAL) CompLevel_initial_compile = CompLevel_simple // pure C1 or Graal #elif defined(COMPILER2) || defined(SHARK) CompLevel_initial_compile = CompLevel_full_optimization // pure C2