# HG changeset patch # User Thomas Wuerthinger # Date 1357666211 -3600 # Node ID c41c58f93f7551e1198a96475f52d756e4e4f5c4 # Parent 570d8e4c6dfbcb9805364f0f3866099ec8f21b12# Parent 91b52ccdb8b7c7d16201b978bd58b1e9ee6af867 Merge. diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LineNumberTable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LineNumberTable.java Tue Jan 08 18:30:11 2013 +0100 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.meta; + + +public interface LineNumberTable { + int[] getLineNumberEntries(); + int[] getBciEntries(); + int getLineNumber(int bci); +} diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Tue Jan 08 18:30:11 2013 +0100 @@ -24,6 +24,7 @@ import java.lang.annotation.*; import java.lang.reflect.*; +import java.lang.reflect.Method; import java.util.*; /** @@ -159,4 +160,10 @@ * Returns {@code true} if this method can be inlined. */ boolean canBeInlined(); + + + /** + * Returns the LineNumberTable of this method. + */ + LineNumberTable getLineNumberTable(); } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Tue Jan 08 18:30:11 2013 +0100 @@ -241,4 +241,9 @@ * @return the field with the given offset, or {@code null} if there is no such field. */ ResolvedJavaField findInstanceFieldWithOffset(long offset); + + /** + * Returns name of source file of this type. + */ + String getSourceFileName(); } diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Jan 08 18:30:11 2013 +0100 @@ -168,7 +168,7 @@ if (GraalOptions.OptFloatingReads) { int mark = graph.getMark(); new FloatingReadPhase().apply(graph); - new CanonicalizerPhase(target, runtime, assumptions, mark).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); if (GraalOptions.OptReadElimination) { new ReadEliminationPhase().apply(graph); } @@ -228,6 +228,7 @@ } }); + } public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) { diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Jan 08 18:30:11 2013 +0100 @@ -200,4 +200,10 @@ long[] getDeoptedLeafGraphIds(); String decodePC(long pc); + + + long[] getLineNumberTable(HotSpotResolvedJavaMethod method); + + + String getFileName(HotSpotResolvedJavaType method); } diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Jan 08 18:30:11 2013 +0100 @@ -142,4 +142,10 @@ @Override public native String decodePC(long pc); + + @Override + public native long[] getLineNumberTable(HotSpotResolvedJavaMethod method); + + @Override + public native String getFileName(HotSpotResolvedJavaType method); } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/LineNumberTableImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/LineNumberTableImpl.java Tue Jan 08 18:30:11 2013 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.debug; + +import com.oracle.graal.api.meta.*; + + +public class LineNumberTableImpl implements LineNumberTable { + private final int[] lineNumbers; + private final int[] bci; + + public LineNumberTableImpl(int[] lineNumbers, int[] bci) { + this.lineNumbers = lineNumbers; + this.bci = bci; + } + + @Override + public int[] getLineNumberEntries() { + return lineNumbers; + } + + @Override + public int[] getBciEntries() { + return bci; + } + + @Override + public int getLineNumber(@SuppressWarnings("hiding") int bci) { + for (int i = 0; i < this.bci.length - 1; i++) { + if (this.bci[i] <= bci && bci < this.bci[i + 1]) { + return lineNumbers[i]; + } + } + return lineNumbers[lineNumbers.length - 1]; + } +} diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Jan 08 18:30:11 2013 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.api.meta.ProfilingInfo.ExceptionSeen; import com.oracle.graal.bytecode.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.phases.*; /** @@ -290,6 +291,21 @@ return HotSpotGraalRuntime.getInstance().getCompilerToVM().isMethodCompilable(metaspaceMethod); } + @Override + public LineNumberTable getLineNumberTable() { + long[] values = HotSpotGraalRuntime.getInstance().getCompilerToVM().getLineNumberTable(this); + assert values.length % 2 == 0; + int[] bci = new int[values.length / 2]; + int[] line = new int[values.length / 2]; + + for (int i = 0; i < values.length / 2; i++) { + bci[i] = (int) values[i * 2]; + line[i] = (int) values[i * 2 + 1]; + } + + return new LineNumberTableImpl(line, bci); + } + /** * Returns the offset of this method into the v-table. * If the holder is not initialized, returns -1 @@ -309,4 +325,5 @@ public CompilationTask currentTask() { return currentTask; } + } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Tue Jan 08 18:30:11 2013 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType { @@ -33,4 +34,9 @@ } public abstract Class mirror(); + + @Override + public String getSourceFileName() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getFileName(this); + } } diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Tue Jan 08 18:30:11 2013 +0100 @@ -446,6 +446,11 @@ } @Override + public String getSourceFileName() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getFileName(this); + } + + @Override public T getAnnotation(Class annotationClass) { return javaMirror.getAnnotation(annotationClass); } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Tue Jan 08 18:30:11 2013 +0100 @@ -181,7 +181,12 @@ } @Override - public Class mirror() { + public String getSourceFileName() { + throw GraalInternalError.shouldNotReachHere(); + } + + @Override + public Class< ? > mirror() { return javaMirror; } } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Tue Jan 08 18:30:11 2013 +0100 @@ -60,7 +60,7 @@ while (!loopBegin.isDeleted()) { int mark = graph.getMark(); peel(loop); - new CanonicalizerPhase(null, runtime, assumptions, mark).apply(graph); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph); if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) { throw new BailoutException("FullUnroll : Graph seems to grow out of proportion"); } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Tue Jan 08 18:30:11 2013 +0100 @@ -65,6 +65,33 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { + + if (source.isConstant()) { + Constant sourceConstant = source.asConstant(); + switch (sourceKind) { + case Boolean: + return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asBoolean()), tool.runtime(), graph()); + case Byte: + return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), tool.runtime(), graph()); + case Char: + return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), tool.runtime(), graph()); + case Short: + return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), tool.runtime(), graph()); + case Int: + return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), tool.runtime(), graph()); + case Long: + return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), tool.runtime(), graph()); + case Float: + return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), tool.runtime(), graph()); + case Double: + return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), tool.runtime(), graph()); + default: + assert false : "Unexpected source kind for boxing"; + break; + + } + } + for (Node usage : usages()) { if (usage != stateAfter()) { return this; diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Tue Jan 08 18:30:11 2013 +0100 @@ -148,4 +148,13 @@ } return targetMethod().getName(); } + + public static MethodCallTargetNode find(StructuredGraph graph, ResolvedJavaMethod method) { + for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.class)) { + if (target.targetMethod == method) { + return target; + } + } + return null; + } } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Tue Jan 08 18:30:11 2013 +0100 @@ -186,30 +186,67 @@ /** * Gets an approximate source code location for a node if possible. * - * @return a file name and source line number in stack trace format (e.g. "String.java:32") - * if an approximate source location is found, null otherwise + * @return the StackTraceElements if an approximate source location is found, null otherwise */ - public static String approxSourceLocation(Node node) { + public static StackTraceElement[] approxSourceStackTraceElement(Node node) { + ArrayList elements = new ArrayList<>(); Node n = node; while (n != null) { if (n instanceof MethodCallTargetNode) { + elements.add(((MethodCallTargetNode) n).targetMethod().asStackTraceElement(-1)); n = ((MethodCallTargetNode) n).invoke().node(); } if (n instanceof StateSplit) { - FrameState stateAfter = ((StateSplit) n).stateAfter(); - if (stateAfter != null) { - ResolvedJavaMethod method = stateAfter.method(); + FrameState state = ((StateSplit) n).stateAfter(); + while (state != null) { + ResolvedJavaMethod method = state.method(); if (method != null) { - StackTraceElement stackTraceElement = method.asStackTraceElement(stateAfter.bci); - if (stackTraceElement.getFileName() != null && stackTraceElement.getLineNumber() >= 0) { - return stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber(); - } + elements.add(method.asStackTraceElement(state.bci - 1)); } + state = state.outerFrameState(); } + break; } n = n.predecessor(); } + return elements.toArray(new StackTraceElement[elements.size()]); + } + + + /** + * Gets an approximate source code location for a node, encoded as an exception, if possible. + * + * @return the exception with the location + */ + public static RuntimeException approxSourceException(Node node, Throwable cause) { + final StackTraceElement[] elements = approxSourceStackTraceElement(node); + @SuppressWarnings("serial") + RuntimeException exception = new RuntimeException(cause.getMessage(), cause) { + + @Override + public synchronized Throwable fillInStackTrace() { + setStackTrace(elements); + return this; + } + }; + return exception; + } + + /** + * Gets an approximate source code location for a node if possible. + * + * @return a file name and source line number in stack trace format (e.g. "String.java:32") if an approximate source + * location is found, null otherwise + */ + public static String approxSourceLocation(Node node) { + StackTraceElement[] stackTraceElements = approxSourceStackTraceElement(node); + if (stackTraceElements != null && stackTraceElements.length > 0) { + StackTraceElement top = stackTraceElements[0]; + if (top.getFileName() != null && top.getLineNumber() >= 0) { + return top.getFileName() + ":" + top.getLineNumber(); + } + } return null; } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Tue Jan 08 18:30:11 2013 +0100 @@ -50,14 +50,19 @@ private final TargetDescription target; private final Assumptions assumptions; private final MetaAccessProvider runtime; + private final CustomCanonicalizer customCanonicalizer; private final Iterable initWorkingSet; private NodeWorkList workList; private Tool tool; private List snapshotTemp; + public interface CustomCanonicalizer { + ValueNode canonicalize(Node node); + } + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { - this(target, runtime, assumptions, null, 0); + this(target, runtime, assumptions, null, 0, null); } /** @@ -65,24 +70,26 @@ * @param runtime * @param assumptions * @param workingSet the initial working set of nodes on which the canonicalizer works, should be an auto-grow node bitmap + * @param customCanonicalizer */ - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet) { - this(target, runtime, assumptions, workingSet, 0); + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { + this(target, runtime, assumptions, workingSet, 0, customCanonicalizer); } /** * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by * this mark are processed otherwise all nodes in the graph are processed */ - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark) { - this(target, runtime, assumptions, null, newNodesMark); + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + this(target, runtime, assumptions, null, newNodesMark, customCanonicalizer); } - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, int newNodesMark) { + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { this.newNodesMark = newNodesMark; this.target = target; this.assumptions = assumptions; this.runtime = runtime; + this.customCanonicalizer = customCanonicalizer; this.initWorkingSet = workingSet; this.snapshotTemp = new ArrayList<>(); } @@ -111,13 +118,15 @@ }); for (Node n : workList) { - processNode(n, graph); + if (n instanceof ValueNode) { + processNode((ValueNode) n, graph); + } } graph.stopTrackingInputChange(); } - private void processNode(Node node, StructuredGraph graph) { + private void processNode(ValueNode node, StructuredGraph graph) { if (node.isAlive()) { METRIC_PROCESSED_NODES.increment(); @@ -127,7 +136,7 @@ int mark = graph.getMark(); if (!tryKillUnused(node)) { node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); - if (!tryCanonicalize(node, graph, tool)) { + if (!tryCanonicalize(node, graph)) { tryInferStamp(node, graph); } else { for (Node in : snapshotTemp) { @@ -168,7 +177,19 @@ return false; } - public static boolean tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) { + public boolean tryCanonicalize(final ValueNode node, final StructuredGraph graph) { + boolean result = baseTryCanonicalize(node, graph); + if (!result && customCanonicalizer != null) { + ValueNode canonical = customCanonicalizer.canonicalize(node); + if (canonical == node && customCanonicalizer != null) { + canonical = customCanonicalizer.canonicalize(node); + } + result = performReplacement(node, graph, canonical); + } + return result; + } + + public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) { if (node instanceof Canonicalizable) { assert !(node instanceof Simplifiable); METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); @@ -187,52 +208,9 @@ // Fixed-connected| 2 | X | 6 | // -------------------------------------------- // X: must not happen (checked with assertions) - if (canonical == node) { - Debug.log("Canonicalizer: work on %s", node); - return false; - } else { - Debug.log("Canonicalizer: replacing %s with %s", node, canonical); - METRIC_CANONICALIZED_NODES.increment(); - if (node instanceof FloatingNode) { - if (canonical == null) { - // case 1 - graph.removeFloating((FloatingNode) node); - } else { - // case 2 - assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + - " : replacement should be floating or fixed and connected"; - graph.replaceFloating((FloatingNode) node, canonical); - } - } else { - assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; - FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; + - // When removing a fixed node, new canonicalization opportunities for its successor may arise - assert fixedWithNext.next() != null; - tool.addToWorkList(fixedWithNext.next()); - - if (canonical == null) { - // case 3 - graph.removeFixed(fixedWithNext); - } else if (canonical instanceof FloatingNode) { - // case 4 - graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); - } else { - assert canonical instanceof FixedNode; - if (canonical.predecessor() == null) { - assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; - // case 5 - graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); - } else { - assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; - // case 6 - node.replaceAtUsages(canonical); - graph.removeFixed(fixedWithNext); - } - } - } - return true; - } + return performReplacement(node, graph, canonical); } }); } else if (node instanceof Simplifiable) { @@ -247,6 +225,55 @@ return node.isDeleted(); } + private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) { + if (canonical == node) { + Debug.log("Canonicalizer: work on %s", node); + return false; + } else { + Debug.log("Canonicalizer: replacing %s with %s", node, canonical); + METRIC_CANONICALIZED_NODES.increment(); + if (node instanceof FloatingNode) { + if (canonical == null) { + // case 1 + graph.removeFloating((FloatingNode) node); + } else { + // case 2 + assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + + " : replacement should be floating or fixed and connected"; + graph.replaceFloating((FloatingNode) node, canonical); + } + } else { + assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; + FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; + + // When removing a fixed node, new canonicalization opportunities for its successor may arise + assert fixedWithNext.next() != null; + tool.addToWorkList(fixedWithNext.next()); + + if (canonical == null) { + // case 3 + graph.removeFixed(fixedWithNext); + } else if (canonical instanceof FloatingNode) { + // case 4 + graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); + } else { + assert canonical instanceof FixedNode; + if (canonical.predecessor() == null) { + assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; + // case 5 + graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + } else { + assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; + // case 6 + node.replaceAtUsages(canonical); + graph.removeFixed(fixedWithNext); + } + } + } + return true; + } + } + /** * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that the stamp has * changed), re-queues the node's usages . If the stamp has changed then this method also checks if the stamp diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Tue Jan 08 18:30:11 2013 +0100 @@ -32,11 +32,9 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; -import com.oracle.graal.phases.common.InliningUtil.InlineInfo; -import com.oracle.graal.phases.common.InliningUtil.InliningCallback; -import com.oracle.graal.phases.common.InliningUtil.InliningPolicy; -import com.oracle.graal.phases.common.InliningUtil.WeightComputationPolicy; +import com.oracle.graal.phases.PhasePlan.*; +import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; +import com.oracle.graal.phases.common.InliningUtil.*; public class InliningPhase extends Phase implements InliningCallback { /* @@ -52,6 +50,7 @@ private final Assumptions assumptions; private final GraphCache cache; private final InliningPolicy inliningPolicy; + private CustomCanonicalizer customCanonicalizer; // Metrics private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed"); @@ -63,6 +62,10 @@ this(target, runtime, assumptions, cache, plan, createInliningPolicy(assumptions, optimisticOpts, hints)); } + public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) { + this.customCanonicalizer = customCanonicalizer; + } + public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy) { this.target = target; this.runtime = runtime; @@ -90,7 +93,7 @@ Debug.dump(graph, "after %s", candidate); Iterable newNodes = graph.getNewNodes(mark); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); } metricInliningPerformed.increment(); diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Jan 08 18:30:11 2013 +0100 @@ -886,7 +886,7 @@ * @param inlineGraph the graph that the invoke will be replaced with * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, false if no such check is required */ - public static void inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { + public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { NodeInputList parameters = invoke.callTarget().arguments(); StructuredGraph graph = (StructuredGraph) invoke.node().graph(); @@ -915,7 +915,7 @@ } } } - replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that where anchored to the StartNode + replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that were anchored to the StartNode assert invoke.node().successors().first() != null : invoke; assert invoke.node().predecessor() != null; @@ -1018,6 +1018,8 @@ invoke.node().replaceAtUsages(null); GraphUtil.killCFG(invoke.node()); + + return duplicates; } public static void receiverNullCheck(Invoke invoke) { diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Tue Jan 08 18:30:11 2013 +0100 @@ -55,7 +55,7 @@ if (canonicalizationRoots.isEmpty()) { break; } - new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph); canonicalizationRoots.clear(); } } diff -r 91b52ccdb8b7 -r c41c58f93f75 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 Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Tue Jan 08 18:30:11 2013 +0100 @@ -132,7 +132,7 @@ deferred = false; processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed); Debug.dump(graph, "Lowering iteration %d", i++); - new CanonicalizerPhase(null, runtime, assumptions, mark).apply(graph); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph); if (!deferred && !containsLowerable(graph.getNewNodes(mark))) { // No new lowerable nodes - done! diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Tue Jan 08 18:30:11 2013 +0100 @@ -282,7 +282,7 @@ new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); - new CanonicalizerPhase(null, runtime, assumptions, 0).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, assumptions, 0, null).apply(snippetCopy); } // Gather the template parameters @@ -340,7 +340,7 @@ LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); int mark = snippetCopy.getMark(); LoopTransformations.fullUnroll(loop, runtime, null); - new CanonicalizerPhase(null, runtime, assumptions, mark).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(snippetCopy); } FixedNode explodeLoopNext = explodeLoop.next(); explodeLoop.clearSuccessors(); diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Tue Jan 08 18:30:11 2013 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.CanonicalizerPhase.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.phases.ea.EffectList.Effect; @@ -42,6 +43,7 @@ private final TargetDescription target; private final MetaAccessProvider runtime; private final Assumptions assumptions; + private CustomCanonicalizer customCanonicalizer; private final boolean iterative; public PartialEscapeAnalysisPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, boolean iterative) { @@ -51,6 +53,10 @@ this.iterative = iterative; } + public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) { + this.customCanonicalizer = customCanonicalizer; + } + public static final void trace(String format, Object... obj) { if (GraalOptions.TraceEscapeAnalysis) { Debug.log(format, obj); @@ -108,7 +114,7 @@ return false; } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, null, customCanonicalizer).apply(graph); } return true; } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java Tue Jan 08 18:30:11 2013 +0100 @@ -26,12 +26,12 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; -final class DefaultCallTarget extends CallTarget { +public class DefaultCallTarget extends CallTarget { protected final RootNode rootNode; protected final FrameDescriptor frameDescriptor; - DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) { + protected DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) { this.rootNode = function; this.frameDescriptor = frameDescriptor; } diff -r 91b52ccdb8b7 -r c41c58f93f75 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Mon Jan 07 19:10:25 2013 -0800 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Tue Jan 08 18:30:11 2013 +0100 @@ -27,7 +27,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; -final class DefaultVirtualFrame implements VirtualFrame { +public final class DefaultVirtualFrame implements VirtualFrame { private static final Object UNDEFINED_OBJECT = null; private static final Boolean UNDEFINED_BOOLEAN = false; @@ -43,7 +43,7 @@ protected Object[] locals; protected Class[] tags; - DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) { + public DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) { this.descriptor = descriptor; this.caller = caller; this.arguments = arguments; diff -r 91b52ccdb8b7 -r c41c58f93f75 src/cpu/x86/vm/jniTypes_x86.hpp --- a/src/cpu/x86/vm/jniTypes_x86.hpp Mon Jan 07 19:10:25 2013 -0800 +++ b/src/cpu/x86/vm/jniTypes_x86.hpp Tue Jan 08 18:30:11 2013 +0100 @@ -128,11 +128,25 @@ static inline jfloat get_float (intptr_t *from) { return *(jfloat *) from; } static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + _JNI_SLOT_OFFSET); } - static inline jint get_int (intptr_t *from, int& pos) { return get_int(from + pos++); } - static inline jlong get_long (intptr_t *from, int& pos) { return get_long(from + pos); pos += 2; } - static inline oop get_obj (intptr_t *from, int& pos) { return get_obj(from + pos++); } - static inline jfloat get_float (intptr_t *from, int& pos) { return get_float(from + pos++); } - static inline jdouble get_double(intptr_t *from, int& pos) { return get_double(from + pos); pos += 2; } + static inline jint get_int (intptr_t *from, int& pos) { + return get_int(from + pos++); + } + static inline jlong get_long (intptr_t *from, int& pos) { + jlong result = get_long(from + pos); + pos += 2; + return result; + } + static inline oop get_obj (intptr_t *from, int& pos) { + return get_obj(from + pos++); + } + static inline jfloat get_float (intptr_t *from, int& pos) { + return get_float(from + pos++); + } + static inline jdouble get_double(intptr_t *from, int& pos) { + jdouble result = get_double(from + pos); + pos += 2; + return result; + } #undef _JNI_SLOT_OFFSET }; diff -r 91b52ccdb8b7 -r c41c58f93f75 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Jan 07 19:10:25 2013 -0800 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Jan 08 18:30:11 2013 +0100 @@ -938,6 +938,47 @@ return JNIHandles::make_local(result()); C2V_END +C2V_ENTRY(jlongArray, getLineNumberTable, (JNIEnv *env, jobject, jobject hotspot_method)) +// XXX: Attention: it seEms that the line number table of a method just contains lines that are important, means that +// empty lines are left out or lines that can't have a breakpoint on it; eg int a; or try { + Method* method = getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method)); + if(!method->has_linenumber_table()) { + return NULL; + } + u2 num_entries = 0; + CompressedLineNumberReadStream streamForSize(method->compressed_linenumber_table()); + while (streamForSize.read_pair()) { + num_entries++; + } + + CompressedLineNumberReadStream stream(method->compressed_linenumber_table()); + jlongArray result = env->NewLongArray(2 * num_entries); + + int i = 0; + jlong value; + while (stream.read_pair()) { + value = ((long) stream.bci()); + env->SetLongArrayRegion(result,i,1,&value); + value = ((long) stream.line()); + env->SetLongArrayRegion(result,i + 1,1,&value); + i += 2; + } + + return result; +C2V_END + + +C2V_VMENTRY(jobject, getFileName, (JNIEnv *, jobject, jobject klass)) + ResourceMark rm; + InstanceKlass* k = (InstanceKlass*) asKlass(HotSpotResolvedObjectType::metaspaceKlass(klass)); + Symbol *s = k->source_file_name(); + int length; + jchar *name = s->as_unicode(length); + + Handle result = java_lang_String::create_from_unicode(name, length, CHECK_NULL); + return JNIHandles::make_local(result()); + +C2V_END #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) @@ -960,6 +1001,7 @@ #define CLASS "Ljava/lang/Class;" #define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;" #define HS_RESOLVED_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;" +#define HS_RESOLVED_JAVA_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaType;" #define HS_RESOLVED_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;" #define HS_RESOLVED_FIELD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaField;" #define HS_COMP_RESULT "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;" @@ -1008,6 +1050,8 @@ {CC"executeCompiledMethodVarargs", CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, + {CC"getLineNumberTable", CC"("HS_RESOLVED_METHOD")[J", FN_PTR(getLineNumberTable)}, + {CC"getFileName", CC"("HS_RESOLVED_JAVA_TYPE")"STRING, FN_PTR(getFileName)}, }; int CompilerToVM_methods_count() {