# HG changeset patch # User Christos Kotselidis # Date 1370967235 -7200 # Node ID e85afceb39e76008a71fcb87a0bce696e0205139 # Parent 4abd6387a6123df88665992ab2f176cfa327d8ab# Parent 3754bb5aab2fac07ce8c80b3bdaa885103f90969 Merge diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Tue Jun 11 18:13:55 2013 +0200 @@ -132,6 +132,18 @@ } @Test + public void isSyntheticTest() { + for (Map.Entry e : methods.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertEquals(e.getKey().isSynthetic(), m.isSynthetic()); + } + for (Map.Entry e : constructors.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertEquals(e.getKey().isSynthetic(), m.isSynthetic()); + } + } + + @Test public void canBeStaticallyBoundTest() { for (Map.Entry e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Tue Jun 11 18:13:55 2013 +0200 @@ -45,6 +45,11 @@ boolean isInternal(); /** + * Determines if this field is a synthetic field as defined by the Java Language Specification. + */ + boolean isSynthetic(); + + /** * Gets the constant value of this field for a given object, if available. * * @param receiver object from which this field's value is to be read. This value is ignored if diff -r 4abd6387a612 -r e85afceb39e7 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 Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Tue Jun 11 18:13:55 2013 +0200 @@ -80,6 +80,12 @@ int getModifiers(); /** + * Determines if this method is a synthetic method as defined by the Java Language + * Specification. + */ + boolean isSynthetic(); + + /** * Checks whether this method is a class initializer. * * @return {@code true} if the method is a class initializer diff -r 4abd6387a612 -r e85afceb39e7 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 Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Tue Jun 11 18:13:55 2013 +0200 @@ -48,7 +48,7 @@ ServiceLoader sl = ServiceLoader.loadInstalled(Options.class); for (Options opts : sl) { for (OptionDescriptor desc : opts) { - if (desc.getClass().getName().startsWith("com.oracle.graal")) { + 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(); @@ -58,6 +58,13 @@ } /** + * Determines if a given option is a HotSpot command line option. + */ + 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 diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Jun 11 18:13:55 2013 +0200 @@ -384,8 +384,6 @@ public int typeProfileWidth; public int methodProfileWidth; - public int interpreterProfilingThreshold; - public long inlineCacheMissStub; public long handleDeoptStub; public long uncommonTrapStub; diff -r 4abd6387a612 -r e85afceb39e7 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 Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Jun 11 18:13:55 2013 +0200 @@ -168,6 +168,8 @@ HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedObjectType klass); + HotSpotResolvedJavaMethod[] getMethods(HotSpotResolvedObjectType klass); + boolean hasFinalizableSubclass(HotSpotResolvedObjectType klass); /** diff -r 4abd6387a612 -r e85afceb39e7 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 Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Jun 11 18:13:55 2013 +0200 @@ -124,6 +124,9 @@ public native HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedObjectType klass); @Override + public native HotSpotResolvedJavaMethod[] getMethods(HotSpotResolvedObjectType klass); + + @Override public native int getCompiledCodeSize(long metaspaceMethod); @Override diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Jun 11 18:13:55 2013 +0200 @@ -183,6 +183,8 @@ DebugEnvironment.initialize(log); } + assert VerifyHotSpotOptionsPhase.checkOptions(); + // Install intrinsics. final HotSpotRuntime runtime = graalRuntime.getCapability(HotSpotRuntime.class); final Replacements replacements = graalRuntime.getCapability(Replacements.class); diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java Tue Jun 11 18:13:55 2013 +0200 @@ -22,9 +22,6 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.phases.GraalOptions.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; @@ -163,7 +160,7 @@ @Override public boolean isMature() { - return method.invocationCount() >= graalRuntime().getConfig().interpreterProfilingThreshold + MatureProfilingInformationThreshold.getValue(); + return true; } @Override diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Tue Jun 11 18:13:55 2013 +0200 @@ -160,6 +160,15 @@ } @Override + public boolean isSynthetic() { + Field javaField = toJava(); + if (javaField != null) { + return javaField.isSynthetic(); + } + return false; + } + + @Override public T getAnnotation(Class annotationClass) { Field javaField = toJava(); if (javaField != null) { diff -r 4abd6387a612 -r e85afceb39e7 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 Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Jun 11 18:13:55 2013 +0200 @@ -332,6 +332,29 @@ } @Override + public boolean isSynthetic() { + if (isConstructor()) { + Constructor javaConstructor = toJavaConstructor(); + return javaConstructor == null ? false : javaConstructor.isSynthetic(); + } + + // Cannot use toJava() as it ignores the return type + HotSpotSignature sig = getSignature(); + JavaType[] sigTypes = MetaUtil.signatureToTypes(sig, null); + HotSpotRuntime runtime = graalRuntime().getRuntime(); + for (Method method : holder.mirror().getDeclaredMethods()) { + if (method.getName().equals(name)) { + if (runtime.lookupJavaType(method.getReturnType()).equals(sig.getReturnType(holder))) { + if (matches(runtime, sigTypes, method.getParameterTypes())) { + return method.isSynthetic(); + } + } + } + } + return false; + } + + @Override public Type[] getGenericParameterTypes() { if (isConstructor()) { Constructor javaConstructor = toJavaConstructor(); @@ -351,6 +374,18 @@ return result; } + private static boolean matches(HotSpotRuntime runtime, JavaType[] sigTypes, Class[] parameterTypes) { + if (parameterTypes.length == sigTypes.length) { + for (int i = 0; i < parameterTypes.length; i++) { + if (!runtime.lookupJavaType(parameterTypes[i]).equals(sigTypes[i])) { + return false; + } + } + return true; + } + return false; + } + private Method toJava() { try { return holder.mirror().getDeclaredMethod(name, signatureToTypes()); diff -r 4abd6387a612 -r e85afceb39e7 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 Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Tue Jun 11 18:13:55 2013 +0200 @@ -541,6 +541,15 @@ return result; } + /** + * Gets all methods and constructors declared by this class, including the {@code } + * method if there is one. The latter is not made accessible via standard Java reflection. + */ + public ResolvedJavaMethod[] getMethods() { + HotSpotResolvedJavaMethod[] methods = graalRuntime().getCompilerToVM().getMethods(this); + return methods; + } + @Override public Constant newArray(int length) { return Constant.forObject(Array.newInstance(javaMirror, length)); diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java Tue Jun 11 18:13:55 2013 +0200 @@ -0,0 +1,142 @@ +/* + * 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.phases; + +import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static java.lang.reflect.Modifier.*; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.options.*; +import com.oracle.graal.phases.*; + +/** + * Verifies that a class that declares one or more HotSpot {@linkplain OptionValue options} has a + * class initializer that only initializes the option(s). This sanity check prevents an option being + * read to initialize some global state before it is parsed on the command line. The latter occurs + * if an option declaring class has a class initializer that reads options or triggers other class + * initializers that read options. + */ +public class VerifyHotSpotOptionsPhase extends Phase { + + public static boolean checkOptions() { + HotSpotRuntime runtime = graalRuntime().getRuntime(); + ServiceLoader sl = ServiceLoader.loadInstalled(Options.class); + Set checked = new HashSet<>(); + for (Options opts : sl) { + for (OptionDescriptor desc : opts) { + if (HotSpotOptions.isHotSpotOption(desc)) { + HotSpotResolvedObjectType holder = (HotSpotResolvedObjectType) runtime.lookupJavaType(desc.getDeclaringClass()); + if (!checked.contains(holder)) { + checked.add(holder); + for (ResolvedJavaMethod method : holder.getMethods()) { + if (method.isClassInitializer()) { + StructuredGraph graph = new StructuredGraph(method); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + new VerifyHotSpotOptionsPhase(holder, runtime).apply(graph); + } + } + } + } + } + } + return true; + } + + private final HotSpotRuntime runtime; + private final ResolvedJavaType declaringClass; + private final ResolvedJavaType optionValueType; + private final Set boxingTypes; + + public VerifyHotSpotOptionsPhase(ResolvedJavaType declaringClass, HotSpotRuntime runtime) { + this.runtime = runtime; + this.declaringClass = declaringClass; + this.optionValueType = runtime.lookupJavaType(OptionValue.class); + this.boxingTypes = new HashSet<>(); + for (Class c : new Class[]{Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}) { + this.boxingTypes.add(runtime.lookupJavaType(c)); + } + } + + /** + * Checks whether a given method is allowed to be called. + */ + private boolean checkInvokeTarget(ResolvedJavaMethod method) { + ResolvedJavaType holder = method.getDeclaringClass(); + if (method.isConstructor()) { + if (optionValueType.isAssignableFrom(holder)) { + return true; + } + } else if (boxingTypes.contains(holder)) { + return method.getName().equals("valueOf"); + } else if (method.getDeclaringClass() == runtime.lookupJavaType(Class.class)) { + return method.getName().equals("desiredAssertionStatus"); + } else if (method.getDeclaringClass().equals(declaringClass)) { + return (method.getName().equals("$jacocoInit")); + } + return false; + } + + @Override + protected void run(StructuredGraph graph) { + for (ValueNode node : graph.getNodes().filter(ValueNode.class)) { + if (node instanceof StoreFieldNode) { + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) ((StoreFieldNode) node).field(); + verify(field.getDeclaringClass() == declaringClass, node, "store to field " + format("%H.%n", field)); + verify(isStatic(field.getModifiers()), node, "store to field " + format("%H.%n", field)); + if (optionValueType.isAssignableFrom((ResolvedJavaType) field.getType())) { + verify(isFinal(field.getModifiers()), node, "option field " + format("%H.%n", field) + " not final"); + } else { + verify((field.isSynthetic()), node, "store to non-synthetic field " + format("%H.%n", field)); + } + } else if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + ResolvedJavaMethod targetMethod = callTarget.targetMethod(); + verify(checkInvokeTarget(targetMethod), node, "invocation of " + format("%H.%n(%p)", targetMethod)); + } + } + } + + private void verify(boolean condition, Node node, String message) { + if (!condition) { + error(node, message); + } + } + + private void error(Node node, String message) { + String loc = GraphUtil.approxSourceLocation(node); + throw new GraalInternalError(String.format("HotSpot option declarer %s contains code pattern implying action other than initialization of an option:%n %s%n %s", + toJavaName(declaringClass), loc, message)); + } +} diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Tue Jun 11 18:13:55 2013 +0200 @@ -35,4 +35,6 @@ } public abstract double probability(AbstractBeginNode successor); + + public abstract void setProbability(AbstractBeginNode successor, double value); } diff -r 4abd6387a612 -r e85afceb39e7 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 Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Jun 11 18:13:55 2013 +0200 @@ -132,6 +132,12 @@ } @Override + public void setProbability(AbstractBeginNode successor, double value) { + assert successor == trueSuccessor || successor == falseSuccessor; + setTrueSuccessorProbability(successor == trueSuccessor ? value : 1 - value); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.emitIf(this); } diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Tue Jun 11 18:13:55 2013 +0200 @@ -36,6 +36,8 @@ @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}") public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint, LIRLowerable { + private static final double EXCEPTION_PROBA = 1e-5; + @Successor private AbstractBeginNode next; @Successor private DispatchBeginNode exceptionEdge; @Input private CallTargetNode callTarget; @@ -45,6 +47,7 @@ private final int bci; private boolean polymorphic; private boolean useForInlining; + private double exceptionProbability; public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci) { super(callTarget.returnStamp()); @@ -53,6 +56,7 @@ this.callTarget = callTarget; this.polymorphic = false; this.useForInlining = true; + this.exceptionProbability = EXCEPTION_PROBA; } public DispatchBeginNode exceptionEdge() { @@ -205,11 +209,15 @@ } } - private static final double EXCEPTION_PROBA = 1e-5; + @Override + public double probability(AbstractBeginNode successor) { + return successor == next ? 1 - exceptionProbability : exceptionProbability; + } @Override - public double probability(AbstractBeginNode successor) { - return successor == next ? 1 - EXCEPTION_PROBA : EXCEPTION_PROBA; + public void setProbability(AbstractBeginNode successor, double value) { + assert successor == next || successor == exceptionEdge; + this.exceptionProbability = successor == next ? 1 - value : value; } @Override diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Tue Jun 11 18:13:55 2013 +0200 @@ -76,7 +76,8 @@ return sum; } - public void setProbability(Node successor, double value) { + @Override + public void setProbability(AbstractBeginNode successor, double value) { double changeInProbability = 0; int nonZeroProbabilityCases = 0; for (int i = 0; i < keySuccessors.length; i++) { diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java Tue Jun 11 18:13:55 2013 +0200 @@ -32,14 +32,16 @@ protected final Class type; protected final String help; protected final OptionValue option; - protected final String location; + protected final Class declaringClass; + protected final String fieldName; - public OptionDescriptor(String name, Class type, String help, String location, OptionValue option) { + public OptionDescriptor(String name, Class type, String help, Class declaringClass, String fieldName, OptionValue option) { this.name = name; this.type = type; this.help = help; this.option = option; - this.location = location; + this.declaringClass = declaringClass; + this.fieldName = fieldName; } /** @@ -71,11 +73,18 @@ return option; } + public Class getDeclaringClass() { + return declaringClass; + } + + public String getFieldName() { + return fieldName; + } + /** * Gets a description of the location where this option is stored. */ public String getLocation() { - return location; - + return getDeclaringClass().getName() + "." + getFieldName(); } } diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Tue Jun 11 18:13:55 2013 +0200 @@ -123,9 +123,9 @@ private void createFiles(OptionsInfo info) { String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString(); - Name declaringClass = info.topDeclaringType.getSimpleName(); + Name topDeclaringClass = info.topDeclaringType.getSimpleName(); - String optionsClassName = declaringClass + "_" + Options.class.getSimpleName(); + String optionsClassName = topDeclaringClass + "_" + Options.class.getSimpleName(); Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]); Filer filer = processingEnv.getFiler(); @@ -133,7 +133,7 @@ out.println("// CheckStyle: stop header check"); out.println("// GENERATED CONTENT - DO NOT EDIT"); - out.println("// Source: " + declaringClass + ".java"); + out.println("// Source: " + topDeclaringClass + ".java"); out.println("package " + pkg + ";"); out.println(""); out.println("import java.util.*;"); @@ -141,8 +141,9 @@ out.println(""); out.println("public class " + optionsClassName + " implements " + Options.class.getSimpleName() + " {"); out.println(" @Override"); - out.println(" public Iterator<" + OptionDescriptor.class.getSimpleName() + "> iterator() {"); - out.println(" List<" + OptionDescriptor.class.getSimpleName() + "> options = Arrays.asList("); + String desc = OptionDescriptor.class.getSimpleName(); + out.println(" public Iterator<" + desc + "> iterator() {"); + out.println(" List<" + desc + "> options = Arrays.asList("); boolean needPrivateFieldAccessor = false; int i = 0; @@ -157,9 +158,10 @@ String name = option.name; String type = option.type; String help = option.help; - String location = pkg + "." + option.declaringClass + "." + option.field.getSimpleName(); + String declaringClass = option.declaringClass; + Name fieldName = option.field.getSimpleName(); String comma = i == info.options.size() - 1 ? "" : ","; - out.printf(" new %s(\"%s\", %s.class, \"%s\", \"%s\", %s)%s\n", OptionDescriptor.class.getSimpleName(), name, type, help, location, optionValue, comma); + out.printf(" new %s(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s\n", desc, name, type, help, declaringClass, fieldName, optionValue, comma); i++; } out.println(" );"); diff -r 4abd6387a612 -r e85afceb39e7 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 Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Tue Jun 11 18:13:55 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.phases.common; import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.phases.common.InliningPhase.Options.*; import java.util.*; import java.util.concurrent.*; @@ -48,10 +49,13 @@ public class InliningPhase extends Phase { - // @formatter:off - @Option(help = "Unconditionally inline intrinsics") - public static final OptionValue AlwaysInlineIntrinsics = new OptionValue<>(false); - // @formatter:on + static class Options { + + // @formatter:off + @Option(help = "Unconditionally inline intrinsics") + public static final OptionValue AlwaysInlineIntrinsics = new OptionValue<>(false); + // @formatter:on + } private final PhasePlan plan; private final MetaAccessProvider runtime; diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Jun 11 18:13:55 2013 +0200 @@ -86,8 +86,6 @@ // profiling information @Option(help = "") public static final OptionValue DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); - @Option(help = "") - public static final OptionValue MatureProfilingInformationThreshold = new OptionValue<>(100); // comilation queue @Option(help = "") diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Tue Jun 11 18:13:55 2013 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @@ -63,12 +64,98 @@ } public NodesToDoubles apply() { + adjustControlSplitProbabilities(); new PropagateProbability(graph.start()).apply(); computeLoopFactors(); new PropagateLoopFrequency(graph.start()).apply(); + assert verifyProbabilities(); return nodeProbabilities; } + /** + * Assume that paths with a DeoptimizeNode at their end are taken infrequently. + */ + private void adjustControlSplitProbabilities() { + HashSet result = new HashSet<>(); + NodeBitMap visitedNodes = new NodeBitMap(graph); + for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) { + if (n.action().doesInvalidateCompilation()) { + findParentControlSplitNodes(result, n, visitedNodes); + } + } + + for (ControlSplitNode n : result) { + if (!allSuxVisited(n, visitedNodes)) { + modifyProbabilities(n, visitedNodes); + } + } + } + + private static void findParentControlSplitNodes(HashSet result, DeoptimizeNode n, NodeBitMap visitedNodes) { + ArrayDeque nodes = new ArrayDeque<>(); + nodes.push(n); + + Node currentNode; + do { + currentNode = nodes.pop(); + visitedNodes.mark(currentNode); + + for (Node pred : currentNode.cfgPredecessors()) { + FixedNode fixedPred = (FixedNode) pred; + if (visitedNodes.isMarked(fixedPred) && allPredsVisited(fixedPred, visitedNodes)) { + DebugScope.dump(n.graph(), "ComputeProbabilityClosure"); + GraalInternalError.shouldNotReachHere(String.format("Endless loop because %s was already visited", fixedPred)); + } else if (allSuxVisited(fixedPred, visitedNodes)) { + nodes.push(fixedPred); + } else { + assert fixedPred instanceof ControlSplitNode : "only control splits can have more than one sux"; + result.add((ControlSplitNode) fixedPred); + } + } + } while (!nodes.isEmpty()); + } + + private static void modifyProbabilities(ControlSplitNode controlSplit, NodeBitMap visitedNodes) { + assert !allSuxVisited(controlSplit, visitedNodes); + for (Node sux : controlSplit.successors()) { + if (visitedNodes.isMarked(sux)) { + controlSplit.setProbability((AbstractBeginNode) sux, 0); + } + } + } + + private static boolean allSuxVisited(FixedNode node, NodeBitMap visitedNodes) { + return allVisited(node.successors(), visitedNodes); + } + + private static boolean allPredsVisited(FixedNode node, NodeBitMap visitedNodes) { + return allVisited(node.cfgPredecessors(), visitedNodes); + } + + private static boolean allVisited(Iterable nodes, NodeBitMap visitedNodes) { + for (Node sux : nodes) { + if (!visitedNodes.contains(sux)) { + return false; + } + } + return true; + } + + private boolean verifyProbabilities() { + if (doesNotAlwaysDeopt(graph)) { + for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) { + if (n.action().doesInvalidateCompilation() && nodeProbabilities.get(n) > 0.01) { + throw new AssertionError(String.format("%s with reason %s and probability %f in graph %s", n, n.reason(), nodeProbabilities.get(n), graph)); + } + } + } + return true; + } + + private static boolean doesNotAlwaysDeopt(StructuredGraph graph) { + return graph.getNodes(ReturnNode.class).iterator().hasNext(); + } + private void computeLoopFactors() { for (LoopInfo info : loopInfos) { double frequency = info.loopFrequency(nodeProbabilities); diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Tue Jun 11 18:13:55 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.phases.tiers; +import static com.oracle.graal.phases.tiers.Suites.Options.*; + import java.util.*; import com.oracle.graal.graph.*; @@ -30,10 +32,13 @@ public final class Suites { - // @formatter:off - @Option(help = "The compiler configuration to use") - private static final OptionValue CompilerConfiguration = new OptionValue<>("basic"); - // @formatter:on + static class Options { + + // @formatter:off + @Option(help = "The compiler configuration to use") + static final OptionValue CompilerConfiguration = new OptionValue<>("basic"); + // @formatter:on + } private final PhaseSuite highTier; private final PhaseSuite midTier; diff -r 4abd6387a612 -r e85afceb39e7 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Tue Jun 11 17:45:31 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Tue Jun 11 18:13:55 2013 +0200 @@ -23,7 +23,7 @@ package com.oracle.truffle.api; /** - * Represents a section in the source code of a guest language program. + * Represents a contiguous text section within the source code of a guest language program. */ public class SourceSection { @@ -35,13 +35,26 @@ private final int charLength; /** - * Creates a new object representing a section in the source code of a guest language program. + * Creates a new object representing a contiguous text section within the source code of a guest + * language program. + *

+ * The starting location of the section is specified using two different coordinate: + *

    + *
  • (row, column): rows and columns are 1-based, so the first character in a source + * file is at position {@code (1,1)}.
  • + *
  • character index: 0-based offset of the character from the beginning of the source, + * so the first character in a file is at index {@code 0}.
  • + *
+ * The newline that terminates each line counts as a single character for the purpose of + * a character index. The (row,column) coordinates of a newline character should never appear in + * a text section. + *

* - * @param source object representing the source program this is should be a section of + * @param source object representing the complete source program that contains this section * @param identifier an identifier used when printing the section - * @param startLine the index of the start line of the section - * @param startColumn the index of the start column of the section - * @param charIndex the index of the first character of the section + * @param startLine the 1-based number of the start line of the section + * @param startColumn the 1-based number of the start column of the section + * @param charIndex the 0-based index of the first character of the section * @param charLength the length of the section in number of characters */ public SourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) { @@ -54,7 +67,7 @@ } /** - * Returns the source object representing the source program this is a section of. + * Returns the object representing the source program that contains this section. * * @return the source object */ @@ -63,38 +76,42 @@ } /** - * Returns the index of the start line of this source section (inclusive). + * Returns 1-based line number of the first character in this source section (inclusive). * - * @return the start line + * @return the starting line number */ public final int getStartLine() { return startLine; } /** - * Returns the index of the start column of this source section (inclusive). + * Returns the 1-based column number of the first character in this source section (inclusive). * - * @return the start column + * @return the starting column number */ public final int getStartColumn() { return startColumn; } /** - * Returns the index of the first character of this section. All characters of the source can be - * retrieved via the {@link Source#getCode()} method. + * Returns the 0-based index of the first character in this source section. + *

+ * The complete text of the source that contains this section can be retrieved via + * {@link Source#getCode()}. * - * @return the character index + * @return the starting character index */ public final int getCharIndex() { return charIndex; } /** - * Returns the length of this section in characters. All characters of the source can be - * retrieved via the {@link Source#getCode()} method. + * Returns the length of this source section in characters. + *

+ * The complete text of the source that contains this section can be retrieved via + * {@link Source#getCode()}. * - * @return the character length + * @return the number of characters in the section */ public final int getCharLength() { return charLength; @@ -110,7 +127,7 @@ } /** - * Returns the code represented by this code section. + * Returns text of the code represented by this source section. * * @return the code as a String object */ diff -r 4abd6387a612 -r e85afceb39e7 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Jun 11 17:45:31 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Jun 11 18:13:55 2013 +0200 @@ -591,11 +591,11 @@ for (AllFieldStream fs(k()); !fs.done(); fs.next()) { if (!fs.access_flags().is_static()) { - Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, Thread::current()); + Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, THREAD); int flags = fs.access_flags().as_int(); bool internal = fs.access_flags().is_internal(); - Handle name = java_lang_String::create_from_symbol(fs.name(), Thread::current()); - Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, Thread::current()); + Handle name = java_lang_String::create_from_symbol(fs.name(), THREAD); + Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, THREAD); fields.append(field()); } } @@ -603,7 +603,28 @@ for (int i = 0; i < fields.length(); ++i) { field_array->obj_at_put(i, fields.at(i)()); } - return JNIHandles::make_local(field_array()); + return JNIHandles::make_local(THREAD, field_array()); +C2V_END + +C2V_VMENTRY(jobject, getMethods, (JNIEnv *, jobject, jobject klass)) + ResourceMark rm; + + instanceKlassHandle k(THREAD, java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(klass))); + Array* methods = k->methods(); + int methods_length = methods->length(); + + // Allocate result + objArrayOop r = oopFactory::new_objArray(SystemDictionary::HotSpotResolvedJavaMethod_klass(), methods_length, CHECK_NULL); + objArrayHandle result (THREAD, r); + + for (int i = 0; i < methods_length; i++) { + methodHandle method(THREAD, methods->at(i)); + Handle holder = JNIHandles::resolve(klass); + oop m = VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD); + result->obj_at_put(i, m); + } + + return JNIHandles::make_local(THREAD, result()); C2V_END C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jlong addr)) @@ -738,8 +759,6 @@ set_int("typeProfileWidth", TypeProfileWidth); set_int("methodProfileWidth", MethodProfileWidth); - set_int("interpreterProfilingThreshold", InvocationCounter::get_ProfileLimit()); - set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); set_long("heapTopAddress", (jlong)(address) Universe::heap()->top_addr()); @@ -1209,6 +1228,7 @@ {CC"lookupFieldInPool", CC"("HS_RESOLVED_TYPE"IB)"FIELD, FN_PTR(lookupFieldInPool)}, {CC"resolveMethod", CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(resolveMethod)}, {CC"getInstanceFields", CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD, FN_PTR(getInstanceFields)}, + {CC"getMethods", CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_METHOD, FN_PTR(getMethods)}, {CC"isTypeInitialized", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(isTypeInitialized)}, {CC"hasFinalizableSubclass", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(hasFinalizableSubclass)}, {CC"initializeType", CC"("HS_RESOLVED_TYPE")V", FN_PTR(initializeType)}, diff -r 4abd6387a612 -r e85afceb39e7 src/share/vm/interpreter/invocationCounter.hpp --- a/src/share/vm/interpreter/invocationCounter.hpp Tue Jun 11 17:45:31 2013 +0200 +++ b/src/share/vm/interpreter/invocationCounter.hpp Tue Jun 11 18:13:55 2013 +0200 @@ -95,9 +95,9 @@ Action action() const { return _action[state()]; } int count() const { return _counter >> number_of_noncount_bits; } - static int get_InvocationLimit() { return InterpreterInvocationLimit >> number_of_noncount_bits; } - static int get_BackwardBranchLimit() { return InterpreterBackwardBranchLimit >> number_of_noncount_bits; } - static int get_ProfileLimit() { return InterpreterProfileLimit >> number_of_noncount_bits; } + int get_InvocationLimit() const { return InterpreterInvocationLimit >> number_of_noncount_bits; } + int get_BackwardBranchLimit() const { return InterpreterBackwardBranchLimit >> number_of_noncount_bits; } + int get_ProfileLimit() const { return InterpreterProfileLimit >> number_of_noncount_bits; } // Test counter using scaled limits like the asm interpreter would do rather than doing // the shifts to normalize the counter.