# HG changeset patch # User Thomas Wuerthinger # Date 1400884703 -7200 # Node ID 9b6d4507118780c5e247540bf2df7d0f272741e2 # Parent e751da27fd48f98d464436b9ba2fac3402cb6bce# Parent fe608a56e3f7740f662a60048b1551903f3a0960 Merge. diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Sat May 24 00:38:23 2014 +0200 @@ -84,11 +84,11 @@ // structure changes significantly StructuredGraph graph = parse(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); - new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); new OptimizeGuardAnchorsPhase().apply(graph); - new ReadEliminationPhase().apply(graph); - new CanonicalizerPhase(true).apply(graph, context); + canonicalizer.apply(graph, context); Debug.dump(graph, "After lowering"); diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Sat May 24 00:38:23 2014 +0200 @@ -52,9 +52,6 @@ if (OptFloatingReads.getValue()) { appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase())); - if (OptReadElimination.getValue()) { - appendPhase(new ReadEliminationPhase()); - } } appendPhase(new RemoveValueProxyPhase()); diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Sat May 24 00:38:23 2014 +0200 @@ -20,103 +20,38 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.GraalDebugConfig.*; +import static com.oracle.graal.hotspot.HotSpotOptionsLoader.*; import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*; -import static java.nio.file.Files.*; +import static java.lang.Double.*; -import java.io.*; import java.lang.reflect.*; -import java.nio.charset.*; -import java.nio.file.*; import java.util.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; -import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.common.inlining.*; /** - * Called from {@code graalCompiler.cpp} to parse any Graal specific options. Such options are - * (currently) distinguished by a {@code "-G:"} prefix. + * Called from {@code graalCompiler.cpp} to set Graal options from the HotSpot command line. Such + * options are (currently) distinguished by a {@code "-G:"} prefix. */ public class HotSpotOptions { - private static final Map options = new HashMap<>(); - /** - * Initializes {@link #options} from {@link Options} services. - */ - private static void initializeOptions() { - ServiceLoader sl = ServiceLoader.loadInstalled(Options.class); - for (Options opts : sl) { - for (OptionDescriptor desc : opts) { - if (isHotSpotOption(desc)) { - String name = desc.getName(); - OptionDescriptor existing = options.put(name, desc); - assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); - } - } - } - } - - /** - * Determines if a given option is a HotSpot command line option. + * Parses the Graal specific options specified to HotSpot (e.g., on the command line). + * + * @return true if the CITime or CITimeEach HotSpot VM options are set */ - public static boolean isHotSpotOption(OptionDescriptor desc) { - return desc.getClass().getName().startsWith("com.oracle.graal"); - } - - /** - * Loads default option value overrides from a {@code graal.options} file if it exists. Each - * line in this file starts with {@code "#"} and is ignored or must have the format of a Graal - * command line option without the leading {@code "-G:"} prefix. These option value are set - * prior to processing of any Graal options present on the command line. - */ - private static void loadOptionOverrides() throws InternalError { - String javaHome = System.getProperty("java.home"); - Path graalDotOptions = Paths.get(javaHome, "lib", "graal.options"); - if (!exists(graalDotOptions)) { - graalDotOptions = Paths.get(javaHome, "jre", "lib", "graal.options"); - } - if (exists(graalDotOptions)) { - try { - for (String line : Files.readAllLines(graalDotOptions, Charset.defaultCharset())) { - if (!line.startsWith("#")) { - if (!parseOption(line, null)) { - throw new InternalError("Invalid option \"" + line + "\" specified in " + graalDotOptions); - } - } - } - } catch (IOException e) { - throw (InternalError) new InternalError().initCause(e); - } - } - } - - /** - * Gets the Graal specific options specified to HotSpot (e.g., on the command line). - * - * @param timeCompilations (out) true if the CITime or CITimeEach HotSpot VM options are set - */ - private static native String[] getVMOptions(boolean[] timeCompilations); + private static native boolean parseVMOptions(); static { - initializeOptions(); - loadOptionOverrides(); - - boolean[] timeCompilations = {false}; - for (String option : getVMOptions(timeCompilations)) { - if (!parseOption(option, null)) { - throw new InternalError("Invalid Graal option \"-G:" + option + "\""); - } - } - - if (timeCompilations[0] || PrintCompRate.getValue() != 0) { + boolean timeCompilations = parseVMOptions(); + if (timeCompilations || PrintCompRate.getValue() != 0) { unconditionallyEnableTimerOrMetric(InliningUtil.class, "InlinedBytecodes"); unconditionallyEnableTimerOrMetric(CompilationTask.class, "CompilationTime"); } @@ -138,6 +73,42 @@ } /** + * Helper for the VM code called by {@link #parseVMOptions()}. + * + * @param name the name of a parsed option + * @param option the object encapsulating the option + * @param spec specification of boolean option value, type of option value or action to take + */ + static void setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) { + switch (spec) { + case '+': + option.setValue(Boolean.TRUE); + break; + case '-': + option.setValue(Boolean.FALSE); + break; + case '?': + printFlags(); + break; + case ' ': + printNoMatchMessage(name); + break; + case 'i': + option.setValue((int) primitiveValue); + break; + case 'f': + option.setValue((float) longBitsToDouble(primitiveValue)); + break; + case 'd': + option.setValue(longBitsToDouble(primitiveValue)); + break; + case 's': + option.setValue(stringValue); + break; + } + } + + /** * Parses a given option value specification. * * @param option the specification of an option and its value @@ -176,15 +147,7 @@ OptionDescriptor desc = options.get(optionName); if (desc == null) { - Logger.info("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)"); - List matches = fuzzyMatch(optionName); - if (!matches.isEmpty()) { - Logger.info("Did you mean one of the following?"); - for (OptionDescriptor match : matches) { - boolean isBoolean = match.getType() == boolean.class; - Logger.info(String.format(" %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=")); - } - } + printNoMatchMessage(optionName); return false; } @@ -192,12 +155,12 @@ if (value == null) { if (optionType == Boolean.TYPE || optionType == Boolean.class) { - Logger.info("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format"); + System.out.println("Value for boolean option '" + optionName + "' must use '-G:+" + optionName + "' or '-G:-" + optionName + "' format"); return false; } if (valueString == null) { - Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=' format"); + System.out.println("Value for option '" + optionName + "' must use '-G:" + optionName + "=' format"); return false; } @@ -212,7 +175,7 @@ } } else { if (optionType != Boolean.class) { - Logger.info("Value for option '" + optionName + "' must use '-G:" + optionName + "=' format"); + System.out.println("Value for option '" + optionName + "' must use '-G:" + optionName + "=' format"); return false; } } @@ -223,16 +186,28 @@ } else { OptionValue optionValue = desc.getOptionValue(); optionValue.setValue(value); - // Logger.info("Set option " + desc.getName() + " to " + value); + // System.out.println("Set option " + desc.getName() + " to " + value); } } else { - Logger.info("Wrong value \"" + valueString + "\" for option " + optionName); + System.out.println("Wrong value \"" + valueString + "\" for option " + optionName); return false; } return true; } + protected static void printNoMatchMessage(String optionName) { + System.out.println("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)"); + List matches = fuzzyMatch(optionName); + if (!matches.isEmpty()) { + System.out.println("Did you mean one of the following?"); + for (OptionDescriptor match : matches) { + boolean isBoolean = match.getType() == boolean.class; + System.out.println(String.format(" %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=")); + } + } + } + /** * Sets the relevant system property such that a {@link DebugTimer} or {@link DebugMetric} * associated with a field in a class will be unconditionally enabled when it is created. @@ -255,7 +230,7 @@ } String previous = System.setProperty(propertyName, "true"); if (previous != null) { - Logger.info("Overrode value \"" + previous + "\" of system property \"" + propertyName + "\" with \"true\""); + System.out.println("Overrode value \"" + previous + "\" of system property \"" + propertyName + "\" with \"true\""); } } catch (Exception e) { throw new GraalInternalError(e); @@ -305,16 +280,16 @@ } private static void printFlags() { - Logger.info("[Graal flags]"); - SortedMap sortedOptions = new TreeMap<>(options); + System.out.println("[Graal flags]"); + SortedMap sortedOptions = options; for (Map.Entry e : sortedOptions.entrySet()) { e.getKey(); OptionDescriptor desc = e.getValue(); Object value = desc.getOptionValue().getValue(); List helpLines = wrap(desc.getHelp(), 70); - Logger.info(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0))); + System.out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0))); for (int i = 1; i < helpLines.size(); i++) { - Logger.info(String.format("%67s %s", " ", helpLines.get(i))); + System.out.println(String.format("%67s %s", " ", helpLines.get(i))); } } diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java Sat May 24 00:38:23 2014 +0200 @@ -0,0 +1,155 @@ +/* + * 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 java.io.*; +import java.util.*; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.options.*; + +/** + * Helper class for separating loading of options from option initialization at runtime. + */ +class HotSpotOptionsLoader { + static final SortedMap options = new TreeMap<>(); + + /** + * Initializes {@link #options} from {@link Options} services. + */ + static { + ServiceLoader sl = ServiceLoader.load(Options.class); + for (Options opts : sl) { + for (OptionDescriptor desc : opts) { + if (isHotSpotOption(desc)) { + String name = desc.getName(); + OptionDescriptor existing = options.put(name, desc); + assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); + } + } + } + } + + /** + * Determines if a given option is a HotSpot command line option. + */ + private static boolean isHotSpotOption(OptionDescriptor desc) { + return desc.getClass().getName().startsWith("com.oracle.graal"); + } + + /** + * Command line utility for generating the source code of GraalRuntime::set_option(). + * + * @param args one element array with the path of the source file to be created + */ + public static void main(String[] args) throws Exception { + File outputFile = new File(args[0]); + PrintStream out = new PrintStream(outputFile); + Set lengths = new TreeSet<>(); + for (String s : options.keySet()) { + lengths.add(s.length()); + } + lengths.add("PrintFlags".length()); + + out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS) {"); + out.println(" if (value[0] == '+' || value[0] == '-') {"); + out.println(" // boolean options"); + genMatchers(out, lengths, true); + out.println(" } else {"); + out.println(" // non-boolean options"); + genMatchers(out, lengths, false); + out.println(" }"); + out.println(" return false;"); + out.println("}"); + + out.flush(); + } + + protected static void genMatchers(PrintStream out, Set lengths, boolean isBoolean) throws Exception { + out.println(" switch (name_len) {"); + for (int len : lengths) { + boolean printedCase = false; + + if (len == "PrintFlags".length() && isBoolean) { + printedCase = true; + out.println(" case " + len + ":"); + out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {\n", len); + out.println(" if (value[0] == '+') {"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);"); + out.println(" }"); + out.println(" return true;"); + out.println(" }"); + } + for (Map.Entry e : options.entrySet()) { + OptionDescriptor desc = e.getValue(); + if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) { + if (!printedCase) { + printedCase = true; + out.println(" case " + len + ":"); + } + out.printf(" if (strncmp(name, \"%s\", %d) == 0) {\n", e.getKey(), len); + Class declaringClass = desc.getDeclaringClass(); + out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));\n", toInternalName(declaringClass), desc.getFieldName(), + toInternalName(getFieldType(desc))); + if (isBoolean) { + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);"); + } else if (desc.getType() == String.class) { + out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);"); + } else { + char spec = getPrimitiveSpecChar(desc); + out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name_handle, value, CHECK_(true));"); + out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);"); + } + out.println(" return true;"); + out.println(" }"); + } + } + } + out.println(" }"); + } + + private static Class getFieldType(OptionDescriptor desc) throws Exception { + return desc.getDeclaringClass().getDeclaredField(desc.getFieldName()).getType(); + } + + private static String toInternalName(Class c) { + return c.getName().replace('.', '/'); + } + + /** + * @see HotSpotOptions#setOption(String, OptionValue, char, String, long) + */ + private static char getPrimitiveSpecChar(OptionDescriptor desc) { + if (desc.getType() == Integer.class) { + return 'i'; + } + if (desc.getType() == Float.class) { + return 'f'; + } + if (desc.getType() == Double.class) { + return 'd'; + } + throw GraalInternalError.shouldNotReachHere("Unexpected primitive option type: " + desc.getType().getName()); + } +} \ No newline at end of file diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Sat May 24 00:38:23 2014 +0200 @@ -482,30 +482,23 @@ AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next(); AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next(); MergeNode merge = trueEnd.merge(); - if (merge == falseEnd.merge() && merge.forwardEndCount() == 2 && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) { + if (merge == falseEnd.merge() && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) { Iterator phis = merge.phis().iterator(); if (!phis.hasNext()) { - // empty if construct with no phis: remove it - removeEmptyIf(tool); + tool.addToWorkList(condition()); + removeThroughFalseBranch(tool); return true; } else { PhiNode singlePhi = phis.next(); if (!phis.hasNext()) { // one phi at the merge of an otherwise empty if construct: try to convert // into a MaterializeNode - boolean inverted = trueEnd == merge.forwardEndAt(1); - ValueNode trueValue = singlePhi.valueAt(inverted ? 1 : 0); - ValueNode falseValue = singlePhi.valueAt(inverted ? 0 : 1); - if (trueValue.getKind() != falseValue.getKind()) { - return false; - } - if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) { - return false; - } + ValueNode trueValue = singlePhi.valueAt(trueEnd); + ValueNode falseValue = singlePhi.valueAt(falseEnd); ConditionalNode conditional = canonicalizeConditionalCascade(trueValue, falseValue); if (conditional != null) { - graph().replaceFloating(singlePhi, conditional); - removeEmptyIf(tool); + singlePhi.setValueAt(trueEnd, conditional); + removeThroughFalseBranch(tool); return true; } } @@ -519,12 +512,6 @@ ValueNode falseValue = falseEnd.result(); ConditionalNode conditional = null; if (trueValue != null) { - if (trueValue.getKind() != falseValue.getKind()) { - return false; - } - if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) { - return false; - } conditional = canonicalizeConditionalCascade(trueValue, falseValue); if (conditional == null) { return false; @@ -538,7 +525,19 @@ return false; } + protected void removeThroughFalseBranch(SimplifierTool tool) { + BeginNode trueBegin = trueSuccessor(); + graph().removeSplitPropagate(this, trueBegin, tool); + tool.addToWorkList(trueBegin); + } + private ConditionalNode canonicalizeConditionalCascade(ValueNode trueValue, ValueNode falseValue) { + if (trueValue.getKind() != falseValue.getKind()) { + return null; + } + if (trueValue.getKind() != Kind.Int && trueValue.getKind() != Kind.Long) { + return null; + } if (trueValue.isConstant() && falseValue.isConstant()) { return graph().unique(new ConditionalNode(condition(), trueValue, falseValue)); } else { @@ -884,38 +883,4 @@ return null; } - - private void removeEmptyIf(SimplifierTool tool) { - BeginNode originalTrueSuccessor = trueSuccessor(); - BeginNode originalFalseSuccessor = falseSuccessor(); - assert originalTrueSuccessor.next() instanceof AbstractEndNode && originalFalseSuccessor.next() instanceof AbstractEndNode; - - AbstractEndNode trueEnd = (AbstractEndNode) originalTrueSuccessor.next(); - AbstractEndNode falseEnd = (AbstractEndNode) originalFalseSuccessor.next(); - assert trueEnd.merge() == falseEnd.merge(); - - FixedWithNextNode pred = (FixedWithNextNode) predecessor(); - MergeNode merge = trueEnd.merge(); - merge.prepareDelete(pred); - assert merge.usages().isEmpty(); - originalTrueSuccessor.prepareDelete(); - originalFalseSuccessor.prepareDelete(); - - FixedNode next = merge.next(); - FrameState state = merge.stateAfter(); - merge.setNext(null); - setTrueSuccessor(null); - setFalseSuccessor(null); - pred.setNext(next); - safeDelete(); - originalTrueSuccessor.safeDelete(); - originalFalseSuccessor.safeDelete(); - merge.safeDelete(); - trueEnd.safeDelete(); - falseEnd.safeDelete(); - if (state != null) { - tool.removeIfUnused(state); - } - tool.addToWorkList(next); - } } diff -r e751da27fd48 -r 9b6d45071187 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 Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Sat May 24 00:38:23 2014 +0200 @@ -82,6 +82,10 @@ values().set(i, x); } + public void setValueAt(AbstractEndNode end, ValueNode x) { + setValueAt(merge().phiPredecessorIndex(end), x); + } + public ValueNode valueAt(AbstractEndNode pred) { return valueAt(merge().phiPredecessorIndex(pred)); } diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Sat May 24 00:38:23 2014 +0200 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; @@ -303,6 +304,10 @@ } public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) { + removeSplitPropagate(node, survivingSuccessor, null); + } + + public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor, SimplifierTool tool) { assert node != null; assert node.usages().isEmpty(); assert survivingSuccessor != null; @@ -313,7 +318,7 @@ for (Node successor : snapshot) { if (successor != null && successor.isAlive()) { if (successor != survivingSuccessor) { - GraphUtil.killCFG(successor); + GraphUtil.killCFG(successor, tool); } } } diff -r e751da27fd48 -r 9b6d45071187 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 Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Sat May 24 00:38:23 2014 +0200 @@ -189,7 +189,9 @@ GraphUtil.tryKillUnused(valueNode); } else if (improvedStamp) { // the improved stamp may enable additional canonicalization - tryCanonicalize(valueNode, nodeClass); + if (!tryCanonicalize(valueNode, nodeClass)) { + valueNode.usages().forEach(workList::add); + } } } } diff -r e751da27fd48 -r 9b6d45071187 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 Thu May 22 18:10:04 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.phases.*; - -public class ReadEliminationPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) { - if (isReadEliminable(n)) { - NodeMap nodeMap = n.graph().createNodeMap(); - ValueNode value = getValue(n, n.getLastLocationAccess(), nodeMap); - Debug.log("Eliminated memory read %1.1s and replaced with node %s", n, value); - graph.replaceFloating(n, value); - } - } - } - - private static boolean isReadEliminable(FloatingReadNode n) { - return isWrites(n, n.getLastLocationAccess(), n.graph().createNodeBitMap()); - } - - private static boolean isWrites(FloatingReadNode n, MemoryNode lastLocationAccess, NodeBitMap visited) { - if (lastLocationAccess == null) { - return false; - } - if (visited.isMarked(ValueNodeUtil.asNode(lastLocationAccess))) { - return true; // dataflow loops must come from Phis assume them ok until proven wrong - } - if (lastLocationAccess instanceof ProxyNode) { - return isWrites(n, (MemoryNode) ((ProxyNode) lastLocationAccess).value(), visited); - } - if (lastLocationAccess instanceof WriteNode) { - WriteNode other = (WriteNode) lastLocationAccess; - return other.object() == n.object() && other.location() == n.location(); - } - if (lastLocationAccess instanceof MemoryPhiNode) { - visited.mark(ValueNodeUtil.asNode(lastLocationAccess)); - for (ValueNode value : ((MemoryPhiNode) lastLocationAccess).values()) { - if (!isWrites(n, (MemoryNode) value, visited)) { - return false; - } - } - return true; - } - return false; - } - - private static ValueNode getValue(FloatingReadNode n, MemoryNode lastLocationAccess, NodeMap nodeMap) { - ValueNode exisiting = nodeMap.get(ValueNodeUtil.asNode(lastLocationAccess)); - if (exisiting != null) { - return exisiting; - } - if (lastLocationAccess instanceof MemoryProxyNode) { - MemoryProxyNode proxy = (MemoryProxyNode) lastLocationAccess; - ValueNode value = getValue(n, proxy.getOriginalMemoryNode(), nodeMap); - return ProxyNode.forValue(value, proxy.proxyPoint(), proxy.graph()); - } - if (lastLocationAccess instanceof WriteNode) { - return ((WriteNode) lastLocationAccess).value(); - } - if (lastLocationAccess instanceof MemoryPhiNode) { - MemoryPhiNode phi = (MemoryPhiNode) lastLocationAccess; - ValuePhiNode newPhi = phi.graph().addWithoutUnique(new ValuePhiNode(n.stamp().unrestricted(), phi.merge())); - nodeMap.set(phi, newPhi); - for (ValueNode value : phi.values()) { - newPhi.addInput(getValue(n, (MemoryNode) value, nodeMap)); - } - return newPhi; - } - throw GraalInternalError.shouldNotReachHere(); - } -} diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Sat May 24 00:38:23 2014 +0200 @@ -332,13 +332,13 @@ assert concretes.size() > 0; Debug.log("Method check cascade with %d methods", concretes.size()); - ValueNode[] constantMethods = new ValueNode[concretes.size()]; + ConstantNode[] constantMethods = new ConstantNode[concretes.size()]; double[] probability = new double[concretes.size()]; for (int i = 0; i < concretes.size(); ++i) { ResolvedJavaMethod firstMethod = concretes.get(i); Constant firstMethodConstant = firstMethod.getEncoding(); - ValueNode firstMethodConstantNode = ConstantNode.forConstant(firstMethodConstant, metaAccess, graph); + ConstantNode firstMethodConstantNode = ConstantNode.forConstant(firstMethodConstant, metaAccess, graph); constantMethods[i] = firstMethodConstantNode; double concretesProbability = concretesProbabilities.get(i); assert concretesProbability >= 0.0; diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolder.java Sat May 24 00:38:23 2014 +0200 @@ -51,23 +51,23 @@ public CallsiteHolder(StructuredGraph graph, double probability, double relevance) { this.graph = graph; - if (graph == null) { - this.remainingInvokes = new LinkedList<>(); - } else { - LinkedList invokes = new InliningIterator(graph).apply(); - assert invokes.size() == count(graph.getInvokes()); - this.remainingInvokes = invokes; - } this.probability = probability; this.relevance = relevance; - - if (graph != null && !remainingInvokes.isEmpty()) { - probabilities = new FixedNodeProbabilityCache(); - computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); - computeProbabilities(); - } else { + if (graph == null) { + remainingInvokes = new LinkedList<>(); probabilities = null; computeInliningRelevance = null; + } else { + remainingInvokes = new InliningIterator(graph).apply(); + assert remainingInvokes.size() == count(graph.getInvokes()); + if (remainingInvokes.isEmpty()) { + probabilities = null; + computeInliningRelevance = null; + } else { + probabilities = new FixedNodeProbabilityCache(); + computeInliningRelevance = new ComputeInliningRelevance(graph, probabilities); + computeProbabilities(); + } } } diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Sat May 24 00:38:23 2014 +0200 @@ -264,11 +264,6 @@ } } - if (concreteMethods.size() > maxMethodPerInlining) { - InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining); - return null; - } - // Clear methods that fall below the threshold. if (notRecordedTypeProbability > 0) { ArrayList newConcreteMethods = new ArrayList<>(); @@ -280,7 +275,7 @@ } } - if (newConcreteMethods.size() == 0) { + if (newConcreteMethods.isEmpty()) { // No method left that is worth inlining. InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "no methods remaining after filtering less frequent methods (%d methods previously)", concreteMethods.size()); @@ -291,6 +286,11 @@ concreteMethodsProbabilities = newConcreteMethodsProbabilities; } + if (concreteMethods.size() > maxMethodPerInlining) { + InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining); + return null; + } + // Clean out types whose methods are no longer available. ArrayList usedTypes = new ArrayList<>(); ArrayList typesToConcretes = new ArrayList<>(); @@ -306,7 +306,7 @@ } } - if (usedTypes.size() == 0) { + if (usedTypes.isEmpty()) { // No type left that is worth checking for. InliningUtil.logNotInlinedInvoke(invoke, inliningDepth(), targetMethod, "no types remaining after filtering less frequent types (%d types previously)", ptypes.length); return null; @@ -410,17 +410,7 @@ double invokeProbability = callsiteHolder.invokeProbability(invoke); double invokeRelevance = callsiteHolder.invokeRelevance(invoke); MethodInvocation methodInvocation = new MethodInvocation(info, calleeAssumptions, invokeProbability, invokeRelevance); - pushInvocation(methodInvocation); - - for (int i = 0; i < info.numberOfMethods(); i++) { - Inlineable elem = info.inlineableElementAt(i); - if (elem instanceof InlineableGraph) { - pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); - } else { - assert elem instanceof InlineableMacroNode; - pushDummyGraph(); - } - } + pushInvocationAndGraphs(methodInvocation); } } @@ -449,6 +439,7 @@ private void pushDummyGraph() { graphQueue.push(DUMMY_CALLSITE_HOLDER); + assert graphQueue.size() <= maxGraphs; } public boolean hasUnprocessedGraphs() { @@ -492,10 +483,22 @@ return invocationQueue.peekFirst(); } - private void pushInvocation(MethodInvocation methodInvocation) { + private void pushInvocationAndGraphs(MethodInvocation methodInvocation) { invocationQueue.addFirst(methodInvocation); - maxGraphs += methodInvocation.callee().numberOfMethods(); + InlineInfo info = methodInvocation.callee(); + maxGraphs += info.numberOfMethods(); assert graphQueue.size() <= maxGraphs; + double invokeProbability = methodInvocation.probability(); + double invokeRelevance = methodInvocation.relevance(); + for (int i = 0; i < info.numberOfMethods(); i++) { + Inlineable elem = info.inlineableElementAt(i); + if (elem instanceof InlineableGraph) { + pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); + } else { + assert elem instanceof InlineableMacroNode; + pushDummyGraph(); + } + } } private void popInvocation() { diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Sat May 24 00:38:23 2014 +0200 @@ -34,8 +34,13 @@ public static class LoopInfo { - public final List endStates = new ArrayList<>(); - public final List exitStates = new ArrayList<>(); + public final List endStates; + public final List exitStates; + + public LoopInfo(int endCount, int exitCount) { + endStates = new ArrayList<>(endCount); + exitStates = new ArrayList<>(exitCount); + } } public abstract static class BlockIteratorClosure { @@ -58,8 +63,8 @@ public static LoopInfo processLoop(BlockIteratorClosure closure, Loop loop, StateT initialState) { Map blockEndStates = apply(closure, loop.getHeader(), initialState, new HashSet<>(loop.getBlocks())); - LoopInfo info = new LoopInfo<>(); List predecessors = loop.getHeader().getPredecessors(); + LoopInfo info = new LoopInfo<>(predecessors.size() - 1, loop.getExits().size()); for (int i = 1; i < predecessors.size(); i++) { StateT endState = blockEndStates.get(predecessors.get(i).getEndNode()); // make sure all end states are unique objects @@ -67,7 +72,7 @@ } for (Block loopExit : loop.getExits()) { assert loopExit.getPredecessorCount() == 1; - assert blockEndStates.containsKey(loopExit.getBeginNode()); + assert blockEndStates.containsKey(loopExit.getBeginNode()) : loopExit.getBeginNode() + " " + blockEndStates; StateT exitState = blockEndStates.get(loopExit.getBeginNode()); // make sure all exit states are unique objects info.exitStates.add(closure.cloneState(exitState)); @@ -90,7 +95,9 @@ Block current = start; while (true) { - if (boundary == null || boundary.contains(current)) { + if (boundary != null && !boundary.contains(current)) { + states.put(current.getBeginNode(), state); + } else { state = closure.processBlock(current, state); if (current.getSuccessors().isEmpty()) { @@ -117,45 +124,47 @@ blockQueue.addFirst(exit); } } - } else { - if (successor.getBeginNode() instanceof LoopExitNode) { - assert successor.getPredecessors().size() == 1; - states.put(successor.getBeginNode(), state); + } else if (current.getEndNode() instanceof AbstractEndNode) { + assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode(); + AbstractEndNode end = (AbstractEndNode) current.getEndNode(); + + // add the end node and see if the merge is ready for processing + MergeNode merge = end.merge(); + boolean endsVisited = true; + for (AbstractEndNode forwardEnd : merge.forwardEnds()) { + if (forwardEnd != current.getEndNode() && !states.containsKey(forwardEnd)) { + endsVisited = false; + break; + } + } + if (endsVisited) { + ArrayList mergedStates = new ArrayList<>(merge.forwardEndCount()); + for (Block predecessor : successor.getPredecessors()) { + assert predecessor == current || states.containsKey(predecessor.getEndNode()); + StateT endState = predecessor == current ? state : states.remove(predecessor.getEndNode()); + mergedStates.add(endState); + } + state = closure.merge(successor, mergedStates); current = successor; continue; } else { - if (current.getEndNode() instanceof AbstractEndNode) { - assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode(); - AbstractEndNode end = (AbstractEndNode) current.getEndNode(); - - // add the end node and see if the merge is ready for processing - assert !states.containsKey(end); - states.put(end, state); - MergeNode merge = end.merge(); - boolean endsVisited = true; - for (AbstractEndNode forwardEnd : merge.forwardEnds()) { - if (!states.containsKey(forwardEnd)) { - endsVisited = false; - break; - } - } - if (endsVisited) { - blockQueue.addFirst(successor); - } - } else { - assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode(); - current = successor; - continue; - } + assert !states.containsKey(end); + states.put(end, state); } + } else { + assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode(); + current = successor; + continue; } } else { assert current.getSuccessors().size() > 1; - for (int i = 0; i < current.getSuccessors().size(); i++) { + for (int i = 1; i < current.getSuccessors().size(); i++) { Block successor = current.getSuccessors().get(i); blockQueue.addFirst(successor); - states.put(successor.getBeginNode(), i == 0 ? state : closure.cloneState(state)); + states.put(successor.getBeginNode(), closure.cloneState(state)); } + current = current.getSuccessors().get(0); + continue; } } @@ -164,20 +173,9 @@ return states; } else { current = blockQueue.removeFirst(); - if (current.getPredecessors().size() == 1) { - assert states.containsKey(current.getBeginNode()); - state = states.get(current.getBeginNode()); - } else { - assert current.getPredecessors().size() > 1; - MergeNode merge = (MergeNode) current.getBeginNode(); - ArrayList mergedStates = new ArrayList<>(merge.forwardEndCount()); - for (Block predecessor : current.getPredecessors()) { - AbstractEndNode end = (AbstractEndNode) predecessor.getEndNode(); - mergedStates.add(states.get(end)); - } - state = closure.merge(current, mergedStates); - states.put(merge, state); - } + assert current.getPredecessorCount() == 1; + assert states.containsKey(current.getBeginNode()); + state = states.remove(current.getBeginNode()); } } } diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Sat May 24 00:38:23 2014 +0200 @@ -33,8 +33,13 @@ public static class LoopInfo { - public final Map endStates = newNodeIdentityMap(4); - public final Map exitStates = newNodeIdentityMap(2); + public final Map endStates; + public final Map exitStates; + + public LoopInfo(int endCount, int exitCount) { + endStates = newNodeIdentityMap(endCount); + exitStates = newNodeIdentityMap(exitCount); + } } public abstract static class NodeIteratorClosure { @@ -64,7 +69,7 @@ public static LoopInfo processLoop(NodeIteratorClosure closure, LoopBeginNode loop, StateT initialState) { Map blockEndStates = apply(closure, loop, initialState, loop); - LoopInfo info = new LoopInfo<>(); + LoopInfo info = new LoopInfo<>(loop.loopEnds().count(), loop.loopExits().count()); for (LoopEndNode end : loop.loopEnds()) { if (blockEndStates.containsKey(end)) { info.endStates.put(end, blockEndStates.get(end)); @@ -119,11 +124,9 @@ nodeQueue.add(entry.getKey()); } } else { - assert !blockEndStates.containsKey(current); - blockEndStates.put(current, state); boolean endsVisited = true; for (AbstractEndNode forwardEnd : merge.forwardEnds()) { - if (!blockEndStates.containsKey(forwardEnd)) { + if (forwardEnd != current && !blockEndStates.containsKey(forwardEnd)) { endsVisited = false; break; } @@ -132,13 +135,16 @@ ArrayList states = new ArrayList<>(merge.forwardEndCount()); for (int i = 0; i < merge.forwardEndCount(); i++) { AbstractEndNode forwardEnd = merge.forwardEndAt(i); - assert blockEndStates.containsKey(forwardEnd); - StateT other = blockEndStates.get(forwardEnd); + assert forwardEnd == current || blockEndStates.containsKey(forwardEnd); + StateT other = forwardEnd == current ? state : blockEndStates.remove(forwardEnd); states.add(other); } state = closure.merge(merge, states); current = closure.continueIteration(state) ? merge : null; continue; + } else { + assert !blockEndStates.containsKey(current); + blockEndStates.put(current, state); } } } @@ -148,14 +154,15 @@ current = firstSuccessor; continue; } else { - while (successors.hasNext()) { + do { BeginNode successor = (BeginNode) successors.next(); StateT successorState = closure.afterSplit(successor, state); if (closure.continueIteration(successorState)) { blockEndStates.put(successor, successorState); nodeQueue.add(successor); } - } + } while (successors.hasNext()); + state = closure.afterSplit((BeginNode) firstSuccessor, state); current = closure.continueIteration(state) ? firstSuccessor : null; continue; @@ -169,7 +176,8 @@ return blockEndStates; } else { current = nodeQueue.removeFirst(); - state = blockEndStates.get(current); + assert blockEndStates.containsKey(current); + state = blockEndStates.remove(current); assert !(current instanceof MergeNode) && current instanceof BeginNode; } } while (true); diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Sat May 24 00:38:23 2014 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; @@ -32,7 +33,7 @@ public class EarlyReadEliminationPhase extends EffectsPhase { public EarlyReadEliminationPhase(CanonicalizerPhase canonicalizer) { - super(1, canonicalizer); + super(1, canonicalizer, true); } @Override @@ -43,7 +44,8 @@ } @Override - protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule) { - return new ReadEliminationClosure(schedule); + protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) { + assert schedule == null; + return new ReadEliminationClosure(cfg); } } diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Sat May 24 00:38:23 2014 +0200 @@ -42,6 +42,7 @@ public abstract class EffectsClosure> extends EffectsPhase.Closure { + private final ControlFlowGraph cfg; private final SchedulePhase schedule; protected final NodeMap aliases; @@ -51,11 +52,12 @@ private boolean changed; - public EffectsClosure(SchedulePhase schedule) { + public EffectsClosure(SchedulePhase schedule, ControlFlowGraph cfg) { this.schedule = schedule; - this.aliases = schedule.getCFG().graph.createNodeMap(); - this.blockEffects = new BlockMap<>(schedule.getCFG()); - for (Block block : schedule.getCFG().getBlocks()) { + this.cfg = cfg; + this.aliases = cfg.graph.createNodeMap(); + this.blockEffects = new BlockMap<>(cfg); + for (Block block : cfg.getBlocks()) { blockEffects.put(block, new GraphEffectList()); } } @@ -67,7 +69,7 @@ @Override public void applyEffects() { - final StructuredGraph graph = schedule.getCFG().graph; + final StructuredGraph graph = cfg.graph; final ArrayList obsoleteNodes = new ArrayList<>(0); BlockIteratorClosure closure = new BlockIteratorClosure() { @@ -114,7 +116,7 @@ return info.exitStates; } }; - ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); + ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); assert VirtualUtil.assertNonReachable(graph, obsoleteNodes); } @@ -124,7 +126,8 @@ GraphEffectList effects = blockEffects.get(block); FixedWithNextNode lastFixedNode = null; - for (Node node : schedule.getBlockToNodesMap().get(block)) { + Iterable nodes = schedule != null ? schedule.getBlockToNodesMap().get(block) : block.getNodes(); + for (Node node : nodes) { aliases.set(node, null); if (node instanceof LoopExitNode) { LoopExitNode loopExit = (LoopExitNode) node; diff -r e751da27fd48 -r 9b6d45071187 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 Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Sat May 24 00:38:23 2014 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.util.*; @@ -49,10 +50,16 @@ private final int maxIterations; protected final CanonicalizerPhase canonicalizer; + private final boolean unscheduled; - public EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) { + protected EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) { + this(maxIterations, canonicalizer, false); + } + + protected EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer, boolean unscheduled) { this.maxIterations = maxIterations; this.canonicalizer = canonicalizer; + this.unscheduled = unscheduled; } @Override @@ -64,10 +71,19 @@ boolean changed = false; for (int iteration = 0; iteration < maxIterations; iteration++) { try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) { - SchedulePhase schedule = new SchedulePhase(); - schedule.apply(graph, false); - Closure closure = createEffectsClosure(context, schedule); - ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); + SchedulePhase schedule; + ControlFlowGraph cfg; + if (unscheduled) { + schedule = null; + cfg = ControlFlowGraph.compute(graph, true, true, false, false); + } else { + schedule = new SchedulePhase(); + schedule.apply(graph, false); + cfg = schedule.getCFG(); + } + + Closure closure = createEffectsClosure(context, schedule, cfg); + ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); if (!closure.hasChanged()) { break; @@ -106,5 +122,5 @@ } } - protected abstract Closure createEffectsClosure(PhaseContextT context, SchedulePhase schedule); + protected abstract Closure createEffectsClosure(PhaseContextT context, SchedulePhase schedule, ControlFlowGraph cfg); } diff -r e751da27fd48 -r 9b6d45071187 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 Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Sat May 24 00:38:23 2014 +0200 @@ -79,7 +79,7 @@ } public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Assumptions assumptions) { - super(schedule); + super(schedule, schedule.getCFG()); this.usages = schedule.getCFG().graph.createNodeBitMap(); this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, assumptions, this); } diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Sat May 24 00:38:23 2014 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; @@ -84,7 +85,8 @@ } @Override - protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule) { + protected Closure createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) { + assert schedule != null; if (readElimination) { return new PEReadEliminationClosure(schedule, context.getMetaAccess(), context.getConstantReflection(), context.getAssumptions()); } else { diff -r e751da27fd48 -r 9b6d45071187 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java Sat May 24 00:38:23 2014 +0200 @@ -132,13 +132,7 @@ } public void killReadCache(LocationIdentity identity) { - Iterator, ValueNode>> iter = readCache.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry, ValueNode> entry = iter.next(); - if (entry.getKey().conflicts(identity)) { - iter.remove(); - } - } + readCache.entrySet().removeIf(entry -> entry.getKey().conflicts(identity)); } public Map, ValueNode> getReadCache() { diff -r e751da27fd48 -r 9b6d45071187 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 Thu May 22 18:10:04 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Sat May 24 00:38:23 2014 +0200 @@ -34,15 +34,14 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry; public class ReadEliminationClosure extends EffectsClosure { - public ReadEliminationClosure(SchedulePhase schedule) { - super(schedule); + public ReadEliminationClosure(ControlFlowGraph cfg) { + super(null, cfg); } @Override @@ -53,104 +52,104 @@ @Override protected boolean processNode(Node node, ReadEliminationBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) { boolean deleted = false; - if (node instanceof LoadFieldNode) { - LoadFieldNode load = (LoadFieldNode) node; - if (!load.isVolatile()) { - ValueNode object = GraphUtil.unproxify(load.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, load.field()); + if (node instanceof AccessFieldNode) { + AccessFieldNode access = (AccessFieldNode) node; + if (access.isVolatile()) { + processIdentity(state, ANY_LOCATION); + } else { + ValueNode object = GraphUtil.unproxify(access.object()); + LoadCacheEntry identifier = new LoadCacheEntry(object, access.field()); ValueNode cachedValue = state.getCacheEntry(identifier); - if (cachedValue != null) { - effects.replaceAtUsages(load, cachedValue); - addScalarAlias(load, cachedValue); - deleted = true; + if (node instanceof LoadFieldNode) { + if (cachedValue != null) { + effects.replaceAtUsages(access, cachedValue); + addScalarAlias(access, cachedValue); + deleted = true; + } else { + state.addCacheEntry(identifier, access); + } } else { - state.addCacheEntry(identifier, load); + assert node instanceof StoreFieldNode; + StoreFieldNode store = (StoreFieldNode) node; + ValueNode value = getScalarAlias(store.value()); + if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { + effects.deleteFixedNode(store); + deleted = true; + } + state.killReadCache(store.field()); + state.addCacheEntry(identifier, value); + } + } + } else if (node instanceof FixedAccessNode) { + if (node instanceof ReadNode) { + ReadNode read = (ReadNode) node; + if (read.location() instanceof ConstantLocationNode) { + ValueNode object = GraphUtil.unproxify(read.object()); + ReadCacheEntry identifier = new ReadCacheEntry(object, read.location()); + ValueNode cachedValue = state.getCacheEntry(identifier); + if (cachedValue != null) { + if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) { + effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read); + } + effects.replaceAtUsages(read, cachedValue); + addScalarAlias(read, cachedValue); + deleted = true; + } else { + state.addCacheEntry(identifier, read); + } + } + } else if (node instanceof WriteNode) { + WriteNode write = (WriteNode) node; + if (write.location() instanceof ConstantLocationNode) { + ValueNode object = GraphUtil.unproxify(write.object()); + ReadCacheEntry identifier = new ReadCacheEntry(object, write.location()); + ValueNode cachedValue = state.getCacheEntry(identifier); + + ValueNode value = getScalarAlias(write.value()); + if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { + effects.deleteFixedNode(write); + deleted = true; + } + processIdentity(state, write.location().getLocationIdentity()); + state.addCacheEntry(identifier, value); + } else { + processIdentity(state, write.location().getLocationIdentity()); + } + } + } else if (node instanceof UnsafeAccessNode) { + if (node instanceof UnsafeLoadNode) { + UnsafeLoadNode load = (UnsafeLoadNode) node; + if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { + ValueNode object = GraphUtil.unproxify(load.object()); + LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity()); + ValueNode cachedValue = state.getCacheEntry(identifier); + if (cachedValue != null) { + effects.replaceAtUsages(load, cachedValue); + addScalarAlias(load, cachedValue); + deleted = true; + } else { + state.addCacheEntry(identifier, load); + } } } else { - processIdentity(state, ANY_LOCATION); - } - } else if (node instanceof StoreFieldNode) { - StoreFieldNode store = (StoreFieldNode) node; - if (!store.isVolatile()) { - ValueNode object = GraphUtil.unproxify(store.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, store.field()); - ValueNode cachedValue = state.getCacheEntry(identifier); + assert node instanceof UnsafeStoreNode; + UnsafeStoreNode write = (UnsafeStoreNode) node; + if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { + ValueNode object = GraphUtil.unproxify(write.object()); + LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity()); + ValueNode cachedValue = state.getCacheEntry(identifier); - ValueNode value = getScalarAlias(store.value()); - if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(store); - deleted = true; - } - state.killReadCache(store.field()); - state.addCacheEntry(identifier, value); - } else { - processIdentity(state, ANY_LOCATION); - } - } else if (node instanceof ReadNode) { - ReadNode read = (ReadNode) node; - if (read.location() instanceof ConstantLocationNode) { - ValueNode object = GraphUtil.unproxify(read.object()); - ReadCacheEntry identifier = new ReadCacheEntry(object, read.location()); - ValueNode cachedValue = state.getCacheEntry(identifier); - if (cachedValue != null) { - if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) { - effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read); + ValueNode value = getScalarAlias(write.value()); + if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { + effects.deleteFixedNode(write); + deleted = true; } - effects.replaceAtUsages(read, cachedValue); - addScalarAlias(read, cachedValue); - deleted = true; + processIdentity(state, write.getLocationIdentity()); + state.addCacheEntry(identifier, value); } else { - state.addCacheEntry(identifier, read); + processIdentity(state, write.getLocationIdentity()); } } - } else if (node instanceof UnsafeLoadNode) { - UnsafeLoadNode load = (UnsafeLoadNode) node; - if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { - ValueNode object = GraphUtil.unproxify(load.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity()); - ValueNode cachedValue = state.getCacheEntry(identifier); - if (cachedValue != null) { - effects.replaceAtUsages(load, cachedValue); - addScalarAlias(load, cachedValue); - deleted = true; - } else { - state.addCacheEntry(identifier, load); - } - } - } else if (node instanceof WriteNode) { - WriteNode write = (WriteNode) node; - if (write.location() instanceof ConstantLocationNode) { - ValueNode object = GraphUtil.unproxify(write.object()); - ReadCacheEntry identifier = new ReadCacheEntry(object, write.location()); - ValueNode cachedValue = state.getCacheEntry(identifier); - - ValueNode value = getScalarAlias(write.value()); - if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(write); - deleted = true; - } - processIdentity(state, write.location().getLocationIdentity()); - state.addCacheEntry(identifier, value); - } else { - processIdentity(state, write.location().getLocationIdentity()); - } - } else if (node instanceof UnsafeStoreNode) { - UnsafeStoreNode write = (UnsafeStoreNode) node; - if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) { - ValueNode object = GraphUtil.unproxify(write.object()); - LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity()); - ValueNode cachedValue = state.getCacheEntry(identifier); - - ValueNode value = getScalarAlias(write.value()); - if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { - effects.deleteFixedNode(write); - deleted = true; - } - processIdentity(state, write.getLocationIdentity()); - state.addCacheEntry(identifier, value); - } else { - processIdentity(state, write.getLocationIdentity()); - } } else if (node instanceof MemoryCheckpoint.Single) { LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); processIdentity(state, identity); diff -r e751da27fd48 -r 9b6d45071187 mx/mx_graal.py --- a/mx/mx_graal.py Thu May 22 18:10:04 2014 +0200 +++ b/mx/mx_graal.py Sat May 24 00:38:23 2014 +0200 @@ -46,8 +46,8 @@ """ The VMs that can be built and run along with an optional description. Only VMs with a description are listed in the dialogue for setting the default VM (see _get_vm()). """ _vmChoices = { - 'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.', - 'server' : 'Normal compilation is performed with the tiered system (i.e., client + server), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.', + 'graal' : 'Normal compilation is performed with a tiered system (C1 + Graal), Truffle compilation is performed with Graal.', + 'server' : 'Normal compilation is performed with a tiered system (C1 + C2), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.', 'client' : None, # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal 'server-nograal' : None, # all compilation with tiered system (i.e., client + server), Graal omitted 'client-nograal' : None, # all compilation with client compiler, Graal omitted @@ -154,7 +154,7 @@ def handleRemoveReadonly(func, path, exc): excvalue = exc[1] if mx.get_os() == 'windows' and func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES: - os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 + os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 func(path) else: raise @@ -212,7 +212,7 @@ def _genFileName(archivtype, middle): idPrefix = infos['revision'] + '_' idSuffix = '.tar.gz' - return join(_graal_home, "graalvm_" + archivtype + "_" + idPrefix + middle + idSuffix) + return join(_graal_home, "graalvm_" + archivtype + "_" + idPrefix + middle + idSuffix) def _genFileArchPlatformName(archivtype, middle): return _genFileName(archivtype, infos['platform'] + '_' + infos['architecture'] + '_' + middle) @@ -484,8 +484,34 @@ if exists(toDelete): os.unlink(toDelete) +def _update_HotSpotOptions_inline_hpp(graalJar): + p = mx.project('com.oracle.graal.hotspot') + mainClass = 'com.oracle.graal.hotspot.HotSpotOptionsLoader' + assert exists(join(p.source_dirs()[0], mainClass.replace('.', os.sep) + '.java')) + hsSrcGenDir = join(p.source_gen_dir(), 'hotspot') + if not exists(hsSrcGenDir): + os.makedirs(hsSrcGenDir) + path = join(hsSrcGenDir, 'HotSpotOptions.inline.hpp') + fd, tmp = tempfile.mkstemp(suffix='', prefix='HotSpotOptions.inline.hpp', dir=hsSrcGenDir) + os.close(fd) + try: + retcode = mx.run_java(['-cp', graalJar, mainClass, tmp], nonZeroIsFatal=False) + if retcode != 0: + # Suppress the error if it's because the utility class isn't compiled yet + with zipfile.ZipFile(graalJar, 'r') as zf: + mainClassFile = mainClass.replace('.', '/') + '.class' + if mainClassFile not in zf.namelist(): + return + mx.abort(retcode) + with open(tmp) as fp: + content = fp.read() + mx.update_file(path, content) + finally: + os.remove(tmp) + def _installGraalJarInJdks(graalDist): graalJar = graalDist.path + _update_HotSpotOptions_inline_hpp(graalJar) jdks = _jdksDir() if exists(jdks): diff -r e751da27fd48 -r 9b6d45071187 mxtool/mx.py --- a/mxtool/mx.py Thu May 22 18:10:04 2014 +0200 +++ b/mxtool/mx.py Sat May 24 00:38:23 2014 +0200 @@ -1673,6 +1673,7 @@ self.javac = exe_suffix(join(self.jdk, 'bin', 'javac')) self.javap = exe_suffix(join(self.jdk, 'bin', 'javap')) self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc')) + self.pack200 = exe_suffix(join(self.jdk, 'bin', 'pack200')) self.toolsjar = join(self.jdk, 'lib', 'tools.jar') self._bootclasspath = None self._extdirs = None @@ -3398,13 +3399,12 @@ for ap in p.annotation_processors(): for dep in dependency(ap).all_deps([], True): if dep.isLibrary(): - if not hasattr(dep, 'eclipse.container') and not hasattr(dep, 'eclipse.project'): - # Relative paths for "lib" class path entries have various semantics depending on the Eclipse - # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's - # safest to simply use absolute paths. - path = _make_absolute(dep.get_path(resolve=True), p.suite.dir) - out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'}) - files.append(path) + # Relative paths for "lib" class path entries have various semantics depending on the Eclipse + # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's + # safest to simply use absolute paths. + path = _make_absolute(dep.get_path(resolve=True), p.suite.dir) + out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'}) + files.append(path) elif dep.isProject(): out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'}) out.close('factorypath') diff -r e751da27fd48 -r 9b6d45071187 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Thu May 22 18:10:04 2014 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Sat May 24 00:38:23 2014 +0200 @@ -651,17 +651,166 @@ GraalRuntime::initialize_natives(env, c2vmClass); JVM_END -// private static String[] HotSpotOptions.getVMOptions(boolean[] timeCompilations) -JVM_ENTRY(jobject, JVM_GetGraalOptions(JNIEnv *env, jclass c, jobject timeCompilations)) +// private static boolean HotSpotOptions.parseVMOptions() +JVM_ENTRY(jboolean, JVM_ParseGraalOptions(JNIEnv *env, jclass c)) HandleMark hm; + KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c))); + return GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false); +JVM_END + +bool GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) { + ResourceMark rm(THREAD); + + // Process option overrides from graal.options first + parse_graal_options_file(hotSpotOptionsClass, CHECK_false); + + // Now process options on the command line int numOptions = Arguments::num_graal_args(); - objArrayOop options = oopFactory::new_objArray(SystemDictionary::String_klass(), - numOptions, CHECK_NULL); - objArrayHandle optionsHandle(THREAD, options); for (int i = 0; i < numOptions; i++) { - Handle option = java_lang_String::create_from_str(Arguments::graal_args_array()[i], CHECK_NULL); - optionsHandle->obj_at_put(i, option()); + char* arg = Arguments::graal_args_array()[i]; + parse_argument(hotSpotOptionsClass, arg, CHECK_false); + } + return CITime || CITimeEach; +} + +void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) { + char first = arg[0]; + char* name; + size_t name_len; + Handle name_handle; + bool valid = true; + if (first == '+' || first == '-') { + name = arg + 1; + name_len = strlen(name); + name_handle = java_lang_String::create_from_str(name, CHECK); + valid = set_option(hotSpotOptionsClass, name, name_len, name_handle, arg, CHECK); + } else { + char* sep = strchr(arg, '='); + if (sep != NULL) { + name = arg; + name_len = sep - name; + // Temporarily replace '=' with NULL to create the Java string for the option name + *sep = '\0'; + name_handle = java_lang_String::create_from_str(arg, THREAD); + *sep = '='; + if (HAS_PENDING_EXCEPTION) { + return; + } + valid = set_option(hotSpotOptionsClass, name, name_len, name_handle, sep + 1, CHECK); + } else { + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Value for option %s must use '-G:%s=' format", arg, arg); + THROW_MSG(vmSymbols::java_lang_InternalError(), buf); + } + } + + if (!valid) { + VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), ' ', Handle(), 0L); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Invalid Graal option %s", arg); + THROW_MSG(vmSymbols::java_lang_InternalError(), buf); } - ((typeArrayOop) JNIHandles::resolve(timeCompilations))->bool_at_put(0, CITime || CITimeEach); - return JNIHandles::make_local(THREAD, optionsHandle()); -JVM_END +} + +void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) { + const char* home = Arguments::get_java_home(); + int path_len = strlen(home) + strlen("/lib/graal.options") + 1; + char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); + char sep = os::file_separator()[0]; + sprintf(path, "%s%clib%cgraal.options", home, sep, sep); + + struct stat st; + if (os::stat(path, &st) == 0) { + int file_handle = os::open(path, 0, 0); + if (file_handle != -1) { + char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size); + int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); + if (num_read == -1) { + warning("Error reading file %s due to %s", path, strerror(errno)); + } else if (num_read != st.st_size) { + warning("Only read %d of %d bytes from %s", num_read, st.st_size, path); + } + os::close(file_handle); + if (num_read == st.st_size) { + char* line = buffer; + int lineNo = 1; + while (line - buffer < num_read) { + char* nl = strchr(line, '\n'); + if (nl != NULL) { + *nl = '\0'; + } + parse_argument(hotSpotOptionsClass, line, THREAD); + if (HAS_PENDING_EXCEPTION) { + warning("Error in %s:%d", path, lineNo); + return; + } + if (nl != NULL) { + line = nl + 1; + lineNo++; + } else { + // File without newline at the end + break; + } + } + } + } else { + warning("Error opening file %s due to %s", path, strerror(errno)); + } + } +} + +jlong GraalRuntime::parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS) { + union { + jint i; + jlong l; + double d; + } uu; + uu.l = 0L; + char dummy; + switch (spec) { + case 'd': + case 'f': { + if (sscanf(value, "%lf%c", &uu.d, &dummy) == 1) { + return uu.l; + } + break; + } + case 'i': { + if (sscanf(value, "%d%c", &uu.i, &dummy) == 1) { + return uu.l; + } + break; + } + default: + ShouldNotReachHere(); + } + ResourceMark rm(THREAD); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %s: %s", (spec == 'i' ? "numeric" : "float/double"), java_lang_String::as_utf8_string(name()), value); + THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L); +} + +Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) { + TempNewSymbol name = SymbolTable::new_symbol(declaringClass, THREAD); + Klass* klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); + + // The class has been loaded so the field and signature should already be in the symbol + // table. If they're not there, the field doesn't exist. + TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName)); + TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)strlen(fieldSig)); + if (fieldname == NULL || signame == NULL) { + THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle()); + } + // Make sure class is initialized before handing id's out to fields + klass->initialize(CHECK_NH); + + fieldDescriptor fd; + if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) { + THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle()); + } + + Handle ret = klass->java_mirror()->obj_field(fd.offset()); + return ret; +} + +#include "HotSpotOptions.inline.hpp" diff -r e751da27fd48 -r 9b6d45071187 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Thu May 22 18:10:04 2014 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Sat May 24 00:38:23 2014 +0200 @@ -31,12 +31,55 @@ class GraalRuntime: public CHeapObj { private: - static address _external_deopt_i2c_entry; + static address _external_deopt_i2c_entry; + + /** + * Reads the OptionValue object from a specified static field. + * + * @throws LinkageError if the field could not be resolved + */ + static Handle get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS); + + /** + * Parses the string form of a numeric, float or double option into a jlong (using raw bits for floats/doubles). + * + * @param spec 'i', 'f' or 'd' (see HotSpotOptions.setOption()) + * @param name name option option + * @param value string value to parse + * @throws InternalError if value could not be parsed according to spec + */ + static jlong parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS); + + /** + * Loads default option value overrides from a /lib/graal.options if it exists. Each + * line in this file must have the format of a Graal command line option without the + * leading "-G:" prefix. These option values are set prior to processing of any Graal + * options present on the command line. + */ + static void parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS); + + /** + * Parses a given argument and sets the denoted Graal option. + * + * @throws InternalError if there was a problem parsing or setting the option + */ + static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS); + + /** + * Searches for a Graal option denoted by a given name and sets it value. + * + * @returns true if the option was found + * @throws InternalError if there was a problem setting the option's value + */ + static bool set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS); public: static void initialize_natives(JNIEnv *env, jclass c2vmClass); static BufferBlob* initialize_buffer_blob(); + + static bool parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS); + static BasicType kindToBasicType(jchar ch); static address create_external_deopt_i2c(); static address get_external_deopt_i2c_entry() {return _external_deopt_i2c_entry;} diff -r e751da27fd48 -r 9b6d45071187 src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Thu May 22 18:10:04 2014 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Sat May 24 00:38:23 2014 +0200 @@ -94,48 +94,20 @@ return Handle(JNIHandles::resolve_non_null(_VMToCompiler_instance)); } -void VMToCompiler::initOptions() { +void VMToCompiler::setOption(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { + assert(!option.is_null(), "npe"); Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD); - KlassHandle optionsKlass = loadClass(name); - optionsKlass->initialize(THREAD); - check_pending_exception("Error while calling initOptions"); -} - -jboolean VMToCompiler::setOption(Handle option) { - assert(!option.is_null(), ""); - Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD); TempNewSymbol setOption = SymbolTable::new_symbol("setOption", THREAD); - TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;)Z", THREAD); - KlassHandle optionsKlass = loadClass(name); - JavaValue result(T_BOOLEAN); - JavaCalls::call_static(&result, optionsKlass, setOption, sig, option, THREAD); - check_pending_exception("Error while calling setOption"); - return result.get_jboolean(); -} - -void VMToCompiler::finalizeOptions(jboolean ciTime) { - Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", THREAD); - TempNewSymbol finalizeOptions = SymbolTable::new_symbol("finalizeOptions", THREAD); - TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;)Z", THREAD); - KlassHandle optionsKlass = loadClass(name); + TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", THREAD); JavaValue result(T_VOID); JavaCallArguments args; - args.push_int(ciTime); - JavaCalls::call_static(&result, optionsKlass, finalizeOptions, vmSymbols::bool_void_signature(), &args, THREAD); - check_pending_exception("Error while calling finalizeOptions"); -} - -void VMToCompiler::startRuntime() { - JavaThread* THREAD = JavaThread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - TempNewSymbol startRuntime = SymbolTable::new_symbol("startRuntime", THREAD); - args.push_oop(VMToCompiler_instance()); - JavaCalls::call_interface(&result, VMToCompiler_klass(), startRuntime, vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling startRuntime"); + args.push_oop(name()); + args.push_oop(option()); + args.push_int(spec); + args.push_oop(stringValue()); + args.push_long(primitiveValue); + JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, THREAD); + check_pending_exception("Error while calling setOption"); } #ifdef COMPILERGRAAL diff -r e751da27fd48 -r 9b6d45071187 src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Thu May 22 18:10:04 2014 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Sat May 24 00:38:23 2014 +0200 @@ -55,17 +55,8 @@ return _HotSpotGraalRuntime_instance; } - // public static boolean HotSpotOptions.(); - static void initOptions(); - - // public static boolean HotSpotOptions.setOption(String option); - static jboolean setOption(Handle option); - - // public static void HotSpotOptions.finalizeOptions(boolean ciTime); - static void finalizeOptions(jboolean ciTime); - - // public abstract void startRuntime(); - static void startRuntime(); + // public static void HotSpotOptions.setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue); + static void setOption(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); #ifdef COMPILERGRAAL // public abstract void startCompiler(boolean bootstrapEnabled); diff -r e751da27fd48 -r 9b6d45071187 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Thu May 22 18:10:04 2014 +0200 +++ b/src/share/vm/prims/nativeLookup.cpp Sat May 24 00:38:23 2014 +0200 @@ -124,10 +124,10 @@ void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); #ifdef GRAAL - void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass); - jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); - jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); - jobject JNICALL JVM_GetGraalOptions(JNIEnv *env, jclass hotspotOptionsClass, jobject timeCompilations); + void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass); + jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); + jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); + jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass); #endif } @@ -140,10 +140,10 @@ { CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, #ifdef GRAAL - { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, - { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_getVMOptions", NULL, FN_PTR(JVM_GetGraalOptions) }, + { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, + { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, + { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, + { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, #endif };