8146001: Remove support for command line options from JVMCI

Reviewed-by: twisti
This commit is contained in:
Doug Simon 2016-01-05 10:57:15 -10:00
parent ea1091ca76
commit c1d5c540ac
28 changed files with 49 additions and 2258 deletions

View File

@ -677,12 +677,6 @@ class JVMCIArchiveParticipant:
assert service
self.services.setdefault(service, []).append(provider)
return True
elif arcname.endswith('_OptionDescriptors.class'):
# Need to create service files for the providers of the
# jdk.vm.ci.options.Options service created by
# jdk.vm.ci.options.processor.OptionProcessor.
provider = arcname[:-len('.class'):].replace('/', '.')
self.services.setdefault('jdk.vm.ci.options.OptionDescriptors', []).append(provider)
return False
def __addsrc__(self, arcname, contents):
@ -761,21 +755,6 @@ class JVMCI9JDKConfig(mx.JDKConfig):
if jacocoArgs:
args = jacocoArgs + args
# Support for -G: options
def translateGOption(arg):
if arg.startswith('-G:+'):
if '=' in arg:
mx.abort('Mixing + and = in -G: option specification: ' + arg)
arg = '-Djvmci.option.' + arg[len('-G:+'):] + '=true'
elif arg.startswith('-G:-'):
if '=' in arg:
mx.abort('Mixing - and = in -G: option specification: ' + arg)
arg = '-Djvmci.option.' + arg[len('-G:+'):] + '=false'
elif arg.startswith('-G:'):
arg = '-Djvmci.option.' + arg[len('-G:'):]
return arg
args = map(translateGOption, args)
args = ['-Xbootclasspath/p:' + dep.classpath_repr() for dep in _jvmci_bootclasspath_prepends] + args
jvmciModeArgs = _jvmciModes[_vm.jvmciMode]

View File

@ -109,7 +109,6 @@ suite = {
"jdk.vm.ci.code",
],
"checkstyle" : "jdk.vm.ci.service",
"annotationProcessors" : ["JVMCI_OPTIONS_PROCESSOR"],
"javaCompliance" : "1.8",
"workingSets" : "API,JVMCI",
},
@ -135,38 +134,6 @@ suite = {
"workingSets" : "JVMCI",
},
"jdk.vm.ci.options" : {
"subDir" : "src/jdk.vm.ci/share/classes",
"sourceDirs" : ["src"],
"checkstyle" : "jdk.vm.ci.service",
"dependencies" : ["jdk.vm.ci.inittimer"],
"javaCompliance" : "1.8",
"workingSets" : "JVMCI",
},
"jdk.vm.ci.options.processor" : {
"subDir" : "src/jdk.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
"jdk.vm.ci.options",
],
"checkstyle" : "jdk.vm.ci.service",
"javaCompliance" : "1.8",
"workingSets" : "JVMCI,Codegen",
},
"jdk.vm.ci.options.test" : {
"subDir" : "test/compiler/jvmci",
"sourceDirs" : ["src"],
"dependencies" : [
"jdk.vm.ci.options",
"mx:JUNIT",
],
"checkstyle" : "jdk.vm.ci.service",
"javaCompliance" : "1.8",
"workingSets" : "JVMCI",
},
# ------------- JVMCI:HotSpot -------------
"jdk.vm.ci.aarch64" : {
@ -200,15 +167,12 @@ suite = {
"subDir" : "src/jdk.vm.ci/share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
"jdk.vm.ci.options",
"jdk.vm.ci.hotspotvmconfig",
"jdk.vm.ci.common",
"jdk.vm.ci.inittimer",
"jdk.vm.ci.runtime",
"jdk.vm.ci.service",
],
"annotationProcessors" : [
"JVMCI_OPTIONS_PROCESSOR",
],
"checkstyle" : "jdk.vm.ci.service",
"javaCompliance" : "1.8",
"workingSets" : "JVMCI",
@ -282,11 +246,6 @@ suite = {
"dependencies" : ["jdk.vm.ci.service"],
},
"JVMCI_OPTIONS" : {
"subDir" : "src/jdk.vm.ci/share/classes",
"dependencies" : ["jdk.vm.ci.options"],
},
"JVMCI_API" : {
"subDir" : "src/jdk.vm.ci/share/classes",
"dependencies" : [
@ -298,7 +257,6 @@ suite = {
"jdk.vm.ci.sparc",
],
"distDependencies" : [
"JVMCI_OPTIONS",
"JVMCI_SERVICE",
],
},
@ -327,7 +285,6 @@ suite = {
"JVMCI_TEST" : {
"subDir" : "test/compiler/jvmci",
"dependencies" : [
"jdk.vm.ci.options.test",
"jdk.vm.ci.runtime.test",
],
"distDependencies" : [
@ -336,13 +293,6 @@ suite = {
"exclude" : ["mx:JUNIT"],
},
"JVMCI_OPTIONS_PROCESSOR" : {
"subDir" : "src/jdk.vm.ci/share/classes",
"dependencies" : ["jdk.vm.ci.options.processor"],
"distDependencies" : [
"JVMCI_OPTIONS",
],
},
"JVMCI_SERVICE_PROCESSOR" : {
"subDir" : "src/jdk.vm.ci/share/classes",
@ -358,15 +308,12 @@ suite = {
"subDir" : "src/jdk.vm.ci/share/classes",
"overlaps" : [
"JVMCI_API",
"JVMCI_OPTIONS",
"JVMCI_SERVICE",
"JVMCI_HOTSPOT",
"JVMCI_HOTSPOTVMCONFIG",
"JVMCI_SERVICE_PROCESSOR",
"JVMCI_OPTIONS_PROCESSOR"
],
"dependencies" : [
"jdk.vm.ci.options",
"jdk.vm.ci.service",
"jdk.vm.ci.inittimer",
"jdk.vm.ci.runtime",
@ -378,7 +325,6 @@ suite = {
"jdk.vm.ci.hotspot.aarch64",
"jdk.vm.ci.hotspot.amd64",
"jdk.vm.ci.hotspot.sparc",
"jdk.vm.ci.options.processor",
"jdk.vm.ci.service.processor"
],
},

View File

@ -36,15 +36,6 @@ SRC_DIR := $(HOTSPOT_TOPDIR)/src/jdk.vm.ci/share/classes
################################################################################
# Compile the annotation processor
$(eval $(call SetupJavaCompilation, BUILD_JVMCI_OPTIONS, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := $(SRC_DIR)/jdk.vm.ci.options/src \
$(SRC_DIR)/jdk.vm.ci.options.processor/src \
$(SRC_DIR)/jdk.vm.ci.inittimer/src, \
BIN := $(BUILDTOOLS_OUTPUTDIR)/jvmci_options, \
JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.options.jar, \
))
$(eval $(call SetupJavaCompilation, BUILD_JVMCI_SERVICE, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := $(SRC_DIR)/jdk.vm.ci.service/src \
@ -70,11 +61,10 @@ PROC_SRCS := $(filter %.java, $(call CacheFind, $(PROC_SRC_DIRS)))
ALL_SRC_DIRS := $(wildcard $(SRC_DIR)/*/src)
SOURCEPATH := $(call PathList, $(ALL_SRC_DIRS))
PROCESSOR_PATH := $(call PathList, \
$(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.options.jar \
$(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.service.jar)
$(GENSRC_DIR)/_gensrc_proc_done: $(PROC_SRCS) \
$(BUILD_JVMCI_OPTIONS) $(BUILD_JVMCI_SERVICE)
$(BUILD_JVMCI_SERVICE)
$(MKDIR) -p $(@D)
$(eval $(call ListPathsSafely,PROC_SRCS,$(@D)/_gensrc_proc_files))
$(JAVA_SMALL) $(NEW_JAVAC) \
@ -92,15 +82,6 @@ TARGETS += $(GENSRC_DIR)/_gensrc_proc_done
################################################################################
$(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors: \
$(GENSRC_DIR)/_gensrc_proc_done
$(MKDIR) -p $(@D)
$(FIND) $(GENSRC_DIR) -name '*_OptionDescriptors.java' | $(SED) 's:.*/jdk\.vm\.ci/\(.*\)\.java:\1:' | $(TR) '/' '.' > $@
TARGETS += $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors
################################################################################
$(GENSRC_DIR)/_providers_converted: $(GENSRC_DIR)/_gensrc_proc_done
$(MKDIR) -p $(GENSRC_DIR)/META-INF/services
($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \

View File

@ -30,28 +30,22 @@ import java.lang.reflect.Array;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaField;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MemoryAccessProvider;
import jdk.vm.ci.meta.MethodHandleAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.options.Option;
import jdk.vm.ci.options.OptionType;
import jdk.vm.ci.options.OptionValue;
import jdk.vm.ci.options.StableOptionValue;
/**
* HotSpot implementation of {@link ConstantReflectionProvider}.
*/
public class HotSpotConstantReflectionProvider implements ConstantReflectionProvider, HotSpotProxified {
static class Options {
//@formatter:off
@Option(help = "Constant fold final fields with default values.", type = OptionType.Debug)
public static final OptionValue<Boolean> TrustFinalDefaultFields = new OptionValue<>(true);
//@formatter:on
}
/**
* Determines whether to treat {@code final} fields with default values as constant.
*/
private static final boolean TrustFinalDefaultFields = HotSpotJVMCIRuntime.getBooleanProperty("TrustFinalDefaultFields", true);
protected final HotSpotJVMCIRuntimeProvider runtime;
protected final HotSpotMethodHandleAccessProvider methodHandleAccess;
@ -239,7 +233,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
/**
* Determines if a static field is constant for the purpose of
* {@link #readConstantFieldValue(JavaField, JavaConstant)}.
* {@link #readConstantFieldValue(ResolvedJavaField, JavaConstant)}.
*/
protected boolean isStaticFieldConstant(HotSpotResolvedJavaField staticField) {
if (staticField.isFinal() || (staticField.isStable() && runtime.getConfig().foldStableValues)) {
@ -255,14 +249,14 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
* Determines if a value read from a {@code final} instance field is considered constant. The
* implementation in {@link HotSpotConstantReflectionProvider} returns true if {@code value} is
* not the {@link JavaConstant#isDefaultForKind default value} for its kind or if
* {@link Options#TrustFinalDefaultFields} is true.
* {@link #TrustFinalDefaultFields} is true.
*
* @param value a value read from a {@code final} instance field
* @param receiverClass the {@link Object#getClass() class} of object from which the
* {@code value} was read
*/
protected boolean isFinalInstanceFieldValueConstant(JavaConstant value, Class<?> receiverClass) {
return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue();
return !value.isDefaultForKind() || TrustFinalDefaultFields;
}
/**
@ -278,13 +272,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
return !value.isDefaultForKind();
}
/**
* {@inheritDoc}
* <p>
* The {@code value} field in {@link OptionValue} is considered constant if the type of
* {@code receiver} is (assignable to) {@link StableOptionValue}.
*/
public JavaConstant readConstantFieldValue(JavaField field, JavaConstant receiver) {
public JavaConstant readConstantFieldValue(ResolvedJavaField field, JavaConstant receiver) {
HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
if (hotspotField.isStatic()) {
@ -319,21 +307,13 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
return value;
}
}
} else {
Class<?> clazz = object.getClass();
if (StableOptionValue.class.isAssignableFrom(clazz)) {
if (hotspotField.isInObject(object) && hotspotField.getName().equals("value")) {
StableOptionValue<?> option = (StableOptionValue<?>) object;
return HotSpotObjectConstantImpl.forObject(option.getValue());
}
}
}
}
}
return null;
}
public JavaConstant readFieldValue(JavaField field, JavaConstant receiver) {
public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) {
HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
if (!hotspotField.isStable()) {
return readNonStableFieldValue(field, receiver);
@ -344,7 +324,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
}
}
private JavaConstant readNonStableFieldValue(JavaField field, JavaConstant receiver) {
private JavaConstant readNonStableFieldValue(ResolvedJavaField field, JavaConstant receiver) {
HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
if (hotspotField.isStatic()) {
HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass();
@ -359,7 +339,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
return null;
}
public JavaConstant readStableFieldValue(JavaField field, JavaConstant receiver, boolean isDefaultStable) {
public JavaConstant readStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefaultStable) {
JavaConstant fieldValue = readNonStableFieldValue(field, receiver);
if (fieldValue.isNonNull()) {
JavaType declaredType = field.getType();

View File

@ -49,6 +49,7 @@ import jdk.vm.ci.runtime.JVMCI;
import jdk.vm.ci.runtime.JVMCIBackend;
import jdk.vm.ci.runtime.JVMCICompiler;
import jdk.vm.ci.service.Services;
import sun.misc.VM;
//JaCoCo Exclude
@ -83,6 +84,22 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H
return DelayedInit.instance;
}
/**
* Gets a boolean value based on a system property {@linkplain VM#getSavedProperty(String)
* saved} at system initialization time. The property name is prefixed with "{@code jvmci.}".
*
* @param name the name of the system property to derive a boolean value from using
* {@link Boolean#parseBoolean(String)}
* @param def the value to return if there is no system property corresponding to {@code name}
*/
public static boolean getBooleanProperty(String name, boolean def) {
String value = VM.getSavedProperty("jvmci." + name);
if (value == null) {
return def;
}
return Boolean.parseBoolean(value);
}
public static HotSpotJVMCIBackendFactory findFactory(String architecture) {
for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) {
if (factory.getArchitecture().equalsIgnoreCase(architecture)) {

View File

@ -35,21 +35,16 @@ import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ModifiersProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.options.Option;
import jdk.vm.ci.options.OptionType;
import jdk.vm.ci.options.OptionValue;
/**
* Represents a field in a HotSpot type.
*/
class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotProxified {
static class Options {
//@formatter:off
@Option(help = "Mark well-known stable fields as such.", type = OptionType.Debug)
public static final OptionValue<Boolean> ImplicitStableValues = new OptionValue<>(true);
//@formatter:on
}
/**
* Mark well-known stable fields as such.
*/
private static final boolean ImplicitStableValues = HotSpotJVMCIRuntime.getBooleanProperty("ImplicitStableValues", true);
private final HotSpotResolvedObjectTypeImpl holder;
private final String name;
@ -203,7 +198,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotP
return true;
}
assert getAnnotation(Stable.class) == null;
if (Options.ImplicitStableValues.getValue() && isImplicitStableField()) {
if (ImplicitStableValues && isImplicitStableField()) {
return true;
}
return false;

View File

@ -27,22 +27,12 @@ import java.lang.reflect.Modifier;
import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.options.Option;
import jdk.vm.ci.options.OptionType;
import jdk.vm.ci.options.OptionValue;
/**
* Implementation of {@link JavaMethod} for resolved HotSpot methods.
*/
public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod {
public static class Options {
// @formatter:off
@Option(help = "", type = OptionType.Debug)
public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
// @formatter:on
}
/**
* Returns true if this method has a {@code CallerSensitive} annotation.
*

View File

@ -24,7 +24,6 @@ package jdk.vm.ci.hotspot;
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import static jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod.Options.UseProfilingInformation;
import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
@ -424,7 +423,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) {
ProfilingInfo info;
if (UseProfilingInformation.getValue() && methodData == null) {
if (methodData == null) {
long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + config().methodDataOffset);
if (metaspaceMethodData != 0) {
methodData = new HotSpotMethodData(metaspaceMethodData, this);

View File

@ -80,29 +80,31 @@ public interface ConstantReflectionProvider {
* @return the constant value of this field or {@code null} if this field is not considered
* constant by the runtime
*/
JavaConstant readConstantFieldValue(JavaField field, JavaConstant receiver);
JavaConstant readConstantFieldValue(ResolvedJavaField field, JavaConstant receiver);
/**
* Gets the current value of this field for a given object, if available.
*
* There is no guarantee that the same value will be returned by this method for a field unless
* the field is considered to be {@linkplain #readConstantFieldValue(JavaField, JavaConstant)
* constant} by the runtime.
* the field is considered to be
* {@linkplain #readConstantFieldValue(ResolvedJavaField, JavaConstant) constant} by the
* runtime.
*
* @param receiver object from which this field's value is to be read. This value is ignored if
* this field is static.
* @return the value of this field or {@code null} if the value is not available (e.g., because
* the field holder is not yet initialized).
*/
JavaConstant readFieldValue(JavaField field, JavaConstant receiver);
JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver);
/**
* Gets the current value of this field for a given object, if available. Like
* {@link #readFieldValue(JavaField, JavaConstant)} but treats array fields as stable.
* {@link #readFieldValue(ResolvedJavaField, JavaConstant)} but treats array fields as stable.
*
* There is no guarantee that the same value will be returned by this method for a field unless
* the field is considered to be {@linkplain #readConstantFieldValue(JavaField, JavaConstant)
* constant} by the runtime.
* the field is considered to be
* {@linkplain #readConstantFieldValue(ResolvedJavaField, JavaConstant) constant} by the
* runtime.
*
* @param receiver object from which this field's value is to be read. This value is ignored if
* this field is static.
@ -110,7 +112,7 @@ public interface ConstantReflectionProvider {
* @return the value of this field or {@code null} if the value is not available (e.g., because
* the field holder is not yet initialized).
*/
JavaConstant readStableFieldValue(JavaField field, JavaConstant receiver, boolean isDefaultStable);
JavaConstant readStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefaultStable);
/**
* Converts the given {@link JavaKind#isPrimitive() primitive} constant to a boxed

View File

@ -1,369 +0,0 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.options.processor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileObject;
import jdk.vm.ci.options.Option;
import jdk.vm.ci.options.OptionDescriptor;
import jdk.vm.ci.options.OptionDescriptors;
import jdk.vm.ci.options.OptionValue;
/**
* Processes static fields annotated with {@link Option}. An {@link OptionDescriptors}
* implementation is generated for each top level class containing at least one such field. The name
* of the generated class for top level class {@code com.foo.Bar} is
* {@code com.foo.Bar_OptionDescriptors}.
*/
@SupportedAnnotationTypes({"jdk.vm.ci.options.Option"})
public class OptionProcessor extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
private final Set<Element> processed = new HashSet<>();
private void processElement(Element element, OptionsInfo info) {
if (!element.getModifiers().contains(Modifier.STATIC)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
return;
}
Option annotation = element.getAnnotation(Option.class);
assert annotation != null;
assert element instanceof VariableElement;
assert element.getKind() == ElementKind.FIELD;
VariableElement field = (VariableElement) element;
String fieldName = field.getSimpleName().toString();
Elements elements = processingEnv.getElementUtils();
Types types = processingEnv.getTypeUtils();
TypeMirror fieldType = field.asType();
if (fieldType.getKind() != TypeKind.DECLARED) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + OptionValue.class.getName(), element);
return;
}
DeclaredType declaredFieldType = (DeclaredType) fieldType;
TypeMirror optionValueType = elements.getTypeElement(OptionValue.class.getName()).asType();
if (!types.isSubtype(fieldType, types.erasure(optionValueType))) {
String msg = String.format("Option field type %s is not a subclass of %s", fieldType, optionValueType);
processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
return;
}
if (!field.getModifiers().contains(Modifier.STATIC)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element);
return;
}
String help = annotation.help();
if (help.length() != 0) {
char firstChar = help.charAt(0);
if (!Character.isUpperCase(firstChar)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Option help text must start with upper case letter", element);
return;
}
}
String optionName = annotation.name();
if (optionName.equals("")) {
optionName = fieldName;
}
DeclaredType declaredOptionValueType = declaredFieldType;
while (!types.isSameType(types.erasure(declaredOptionValueType), types.erasure(optionValueType))) {
List<? extends TypeMirror> directSupertypes = types.directSupertypes(declaredFieldType);
assert !directSupertypes.isEmpty();
declaredOptionValueType = (DeclaredType) directSupertypes.get(0);
}
assert !declaredOptionValueType.getTypeArguments().isEmpty();
String optionType = declaredOptionValueType.getTypeArguments().get(0).toString();
if (optionType.startsWith("java.lang.")) {
optionType = optionType.substring("java.lang.".length());
}
Element enclosing = element.getEnclosingElement();
String declaringClass = "";
String separator = "";
Set<Element> originatingElementsList = info.originatingElements;
originatingElementsList.add(field);
while (enclosing != null) {
if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) {
if (enclosing.getModifiers().contains(Modifier.PRIVATE)) {
String msg = String.format("Option field cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing);
processingEnv.getMessager().printMessage(Kind.ERROR, msg, element);
return;
}
originatingElementsList.add(enclosing);
declaringClass = enclosing.getSimpleName() + separator + declaringClass;
separator = ".";
} else {
assert enclosing.getKind() == ElementKind.PACKAGE;
}
enclosing = enclosing.getEnclosingElement();
}
info.options.add(new OptionInfo(optionName, help, optionType, declaringClass, field));
}
private void createFiles(OptionsInfo info) {
String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString();
Name topDeclaringClass = info.topDeclaringType.getSimpleName();
Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]);
createOptionsDescriptorsFile(info, pkg, topDeclaringClass, originatingElements);
}
private void createOptionsDescriptorsFile(OptionsInfo info, String pkg, Name topDeclaringClass, Element[] originatingElements) {
String optionsClassName = topDeclaringClass + "_" + OptionDescriptors.class.getSimpleName();
Filer filer = processingEnv.getFiler();
try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) {
out.println("// CheckStyle: stop header check");
out.println("// CheckStyle: stop line length check");
out.println("// GENERATED CONTENT - DO NOT EDIT");
out.println("// Source: " + topDeclaringClass + ".java");
out.println("package " + pkg + ";");
out.println("");
out.println("import java.util.*;");
out.println("import " + OptionDescriptors.class.getPackage().getName() + ".*;");
out.println("");
out.println("public class " + optionsClassName + " implements " + OptionDescriptors.class.getSimpleName() + " {");
String desc = OptionDescriptor.class.getSimpleName();
boolean needPrivateFieldAccessor = false;
int i = 0;
Collections.sort(info.options);
out.println(" @Override");
out.println(" public OptionDescriptor get(String value) {");
out.println(" // CheckStyle: stop line length check");
if (info.options.size() == 1) {
out.println(" if (value.equals(\"" + info.options.get(0).name + "\")) {");
} else {
out.println(" switch (value) {");
}
for (OptionInfo option : info.options) {
String name = option.name;
String optionValue;
if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
needPrivateFieldAccessor = true;
optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")";
} else {
optionValue = option.declaringClass + "." + option.field.getSimpleName();
}
String type = option.type;
String help = option.help;
String declaringClass = option.declaringClass;
Name fieldName = option.field.getSimpleName();
if (info.options.size() == 1) {
out.printf(" return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
} else {
out.printf(" case \"" + name + "\": return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
}
}
out.println(" }");
out.println(" // CheckStyle: resume line length check");
out.println(" return null;");
out.println(" }");
out.println();
out.println(" @Override");
out.println(" public Iterator<" + desc + "> iterator() {");
out.println(" // CheckStyle: stop line length check");
out.println(" List<" + desc + "> options = Arrays.asList(");
for (OptionInfo option : info.options) {
String optionValue;
if (option.field.getModifiers().contains(Modifier.PRIVATE)) {
needPrivateFieldAccessor = true;
optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")";
} else {
optionValue = option.declaringClass + "." + option.field.getSimpleName();
}
String name = option.name;
String type = option.type;
String help = option.help;
String declaringClass = option.declaringClass;
Name fieldName = option.field.getSimpleName();
String comma = i == info.options.size() - 1 ? "" : ",";
out.printf(" %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s)%s\n", desc, name, type, help, declaringClass, fieldName, optionValue, comma);
i++;
}
out.println(" );");
out.println(" // CheckStyle: resume line length check");
out.println(" return options.iterator();");
out.println(" }");
if (needPrivateFieldAccessor) {
out.println(" private static " + OptionValue.class.getSimpleName() + "<?> field(Class<?> declaringClass, String fieldName) {");
out.println(" try {");
out.println(" java.lang.reflect.Field field = declaringClass.getDeclaredField(fieldName);");
out.println(" field.setAccessible(true);");
out.println(" return (" + OptionValue.class.getSimpleName() + "<?>) field.get(null);");
out.println(" } catch (Exception e) {");
out.println(" throw (InternalError) new InternalError().initCause(e);");
out.println(" }");
out.println(" }");
}
out.println("}");
}
}
protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) {
try {
// Ensure Unix line endings to comply with code style guide checked by Checkstyle
JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, originatingElements);
return new PrintWriter(sourceFile.openWriter()) {
@Override
public void println() {
print("\n");
}
};
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static class OptionInfo implements Comparable<OptionInfo> {
final String name;
final String help;
final String type;
final String declaringClass;
final VariableElement field;
public OptionInfo(String name, String help, String type, String declaringClass, VariableElement field) {
this.name = name;
this.help = help;
this.type = type;
this.declaringClass = declaringClass;
this.field = field;
}
@Override
public int compareTo(OptionInfo other) {
return name.compareTo(other.name);
}
@Override
public String toString() {
return declaringClass + "." + field;
}
}
static class OptionsInfo {
final Element topDeclaringType;
final List<OptionInfo> options = new ArrayList<>();
final Set<Element> originatingElements = new HashSet<>();
public OptionsInfo(Element topDeclaringType) {
this.topDeclaringType = topDeclaringType;
}
}
private static Element topDeclaringType(Element element) {
Element enclosing = element.getEnclosingElement();
if (enclosing == null || enclosing.getKind() == ElementKind.PACKAGE) {
assert element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE;
return element;
}
return topDeclaringType(enclosing);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
return true;
}
Map<Element, OptionsInfo> map = new HashMap<>();
for (Element element : roundEnv.getElementsAnnotatedWith(Option.class)) {
if (!processed.contains(element)) {
processed.add(element);
Element topDeclaringType = topDeclaringType(element);
OptionsInfo options = map.get(topDeclaringType);
if (options == null) {
options = new OptionsInfo(topDeclaringType);
map.put(topDeclaringType, options);
}
processElement(element, options);
}
}
boolean ok = true;
Map<String, OptionInfo> uniqueness = new HashMap<>();
for (OptionsInfo info : map.values()) {
for (OptionInfo option : info.options) {
OptionInfo conflict = uniqueness.put(option.name, option);
if (conflict != null) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Duplicate option names for " + option + " and " + conflict, option.field);
ok = false;
}
}
}
if (ok) {
for (OptionsInfo info : map.values()) {
createFiles(info);
}
}
return true;
}
}

View File

@ -1,59 +0,0 @@
/*
* 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 jdk.vm.ci.options;
import java.io.Serializable;
import java.util.function.Supplier;
import jdk.vm.ci.options.OptionValue.OverrideScope;
/**
* A cached value that needs to be recomputed when an option changes.
*/
public class DerivedOptionValue<T> {
public interface OptionSupplier<T> extends Supplier<T>, Serializable {
}
private final T initialValue;
private final OptionSupplier<T> supplier;
public DerivedOptionValue(OptionSupplier<T> supplier) {
this.supplier = supplier;
assert OptionValue.getOverrideScope() == null : "derived option value should be initialized outside any override scope";
this.initialValue = createValue();
}
public T getValue() {
OverrideScope overrideScope = OptionValue.getOverrideScope();
if (overrideScope != null) {
return overrideScope.getDerived(this);
} else {
return initialValue;
}
}
T createValue() {
return supplier.get();
}
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2015, 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 jdk.vm.ci.options;
/**
* A nested Boolean {@link OptionValue} that can be overridden by a {@link #masterOption master
* option}.
* <p>
* <li>If the option is present on the command line the specified value is used.
* <li>Otherwise {@link #getValue()} depends on the {@link #masterOption} and evaluates as follows:
* <ul>
* <li>If {@link #masterOption} is set, this value equals to {@link #initialValue}.
* <li>Otherwise, if {@link #masterOption} is {@code false}, this option is {@code false}.
*/
public class NestedBooleanOptionValue extends OptionValue<Boolean> {
private final OptionValue<Boolean> masterOption;
private final Boolean initialValue;
public NestedBooleanOptionValue(OptionValue<Boolean> masterOption, Boolean initialValue) {
super(null);
this.masterOption = masterOption;
this.initialValue = initialValue;
}
public OptionValue<Boolean> getMasterOption() {
return masterOption;
}
@Override
public Boolean getValue() {
Boolean v = super.getValue();
if (v == null) {
return initialValue && masterOption.getValue();
}
return v;
}
}

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.options;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Describes the attributes of an option whose {@link OptionValue value} is in a static field
* annotated by this annotation type.
*
* @see OptionDescriptor
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface Option {
/**
* Gets a help message for the option. New lines can be embedded in the message with
* {@code "%n"}.
*/
String help();
/**
* The name of the option. By default, the name of the annotated field should be used.
*/
String name() default "";
/**
* Specifies the type of the option.
*/
OptionType type() default OptionType.Debug;
}

View File

@ -1,102 +0,0 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.options;
/**
* Describes the attributes of a static field {@linkplain Option option} and provides access to its
* {@linkplain OptionValue value}.
*/
public final class OptionDescriptor {
protected final String name;
protected final Class<?> type;
protected final String help;
protected final OptionValue<?> option;
protected final Class<?> declaringClass;
protected final String fieldName;
public static OptionDescriptor create(String name, Class<?> type, String help, Class<?> declaringClass, String fieldName, OptionValue<?> option) {
OptionDescriptor result = option.getDescriptor();
if (result == null) {
result = new OptionDescriptor(name, type, help, declaringClass, fieldName, option);
option.setDescriptor(result);
}
assert result.name.equals(name) && result.type == type && result.declaringClass == declaringClass && result.fieldName.equals(fieldName) && result.option == option;
return result;
}
private 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.declaringClass = declaringClass;
this.fieldName = fieldName;
assert !type.isPrimitive() : "must used boxed type instead of " + type;
}
/**
* Gets the type of values stored in the option. This will be the boxed type for a primitive
* option.
*/
public Class<?> getType() {
return type;
}
/**
* Gets a descriptive help message for the option.
*/
public String getHelp() {
return help;
}
/**
* Gets the name of the option. It's up to the client of this object how to use the name to get
* a user specified value for the option from the environment.
*/
public String getName() {
return name;
}
/**
* Gets the boxed option value.
*/
public OptionValue<?> getOptionValue() {
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 getDeclaringClass().getName() + "." + getFieldName();
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.options;
/**
* An interface to a set of {@link OptionDescriptor}s.
*/
public interface OptionDescriptors extends Iterable<OptionDescriptor> {
/**
* Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option
* descriptor set doesn't contain a matching option.
*/
OptionDescriptor get(String value);
}

View File

@ -1,44 +0,0 @@
/*
* 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 jdk.vm.ci.options;
/**
* Classifies JVMCI options in several categories depending on who this option is relevant for.
*
*/
public enum OptionType {
/**
* An option common for users to apply.
*/
User,
/**
* An option only relevant in corner cases and for fine-tuning.
*/
Expert,
/**
* An option only relevant when debugging the compiler.
*/
Debug
}

View File

@ -1,484 +0,0 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.options;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
/**
* An option value.
*/
public class OptionValue<T> {
/**
* Temporarily changes the value for an option. The {@linkplain OptionValue#getValue() value} of
* {@code option} is set to {@code value} until {@link OverrideScope#close()} is called on the
* object returned by this method.
* <p>
* Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
* used:
*
* <pre>
* try (OverrideScope s = OptionValue.override(myOption, myValue) {
* // code that depends on myOption == myValue
* }
* </pre>
*/
public static OverrideScope override(OptionValue<?> option, Object value) {
OverrideScope current = getOverrideScope();
if (current == null) {
if (!value.equals(option.getValue())) {
return new SingleOverrideScope(option, value);
}
Map<OptionValue<?>, Object> overrides = Collections.emptyMap();
return new MultipleOverridesScope(current, overrides);
}
return new MultipleOverridesScope(current, option, value);
}
/**
* Temporarily changes the values for a set of options. The {@linkplain OptionValue#getValue()
* value} of each {@code option} in {@code overrides} is set to the corresponding {@code value}
* in {@code overrides} until {@link OverrideScope#close()} is called on the object returned by
* this method.
* <p>
* Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
* used:
*
* <pre>
* Map&lt;OptionValue, Object&gt; overrides = new HashMap&lt;&gt;();
* overrides.put(myOption1, myValue1);
* overrides.put(myOption2, myValue2);
* try (OverrideScope s = OptionValue.override(overrides) {
* // code that depends on myOption == myValue
* }
* </pre>
*/
public static OverrideScope override(Map<OptionValue<?>, Object> overrides) {
OverrideScope current = getOverrideScope();
if (current == null && overrides.size() == 1) {
Entry<OptionValue<?>, Object> single = overrides.entrySet().iterator().next();
OptionValue<?> option = single.getKey();
Object overrideValue = single.getValue();
if (!overrideValue.equals(option.getValue())) {
return new SingleOverrideScope(option, overrideValue);
}
}
return new MultipleOverridesScope(current, overrides);
}
/**
* Temporarily changes the values for a set of options. The {@linkplain OptionValue#getValue()
* value} of each {@code option} in {@code overrides} is set to the corresponding {@code value}
* in {@code overrides} until {@link OverrideScope#close()} is called on the object returned by
* this method.
* <p>
* Since the returned object is {@link AutoCloseable} the try-with-resource construct can be
* used:
*
* <pre>
* try (OverrideScope s = OptionValue.override(myOption1, myValue1, myOption2, myValue2) {
* // code that depends on myOption == myValue
* }
* </pre>
*
* @param overrides overrides in the form {@code [option1, override1, option2, override2, ...]}
*/
public static OverrideScope override(Object... overrides) {
OverrideScope current = getOverrideScope();
if (current == null && overrides.length == 2) {
OptionValue<?> option = (OptionValue<?>) overrides[0];
Object overrideValue = overrides[1];
if (!overrideValue.equals(option.getValue())) {
return new SingleOverrideScope(option, overrideValue);
}
}
Map<OptionValue<?>, Object> map = Collections.emptyMap();
for (int i = 0; i < overrides.length; i += 2) {
OptionValue<?> option = (OptionValue<?>) overrides[i];
Object overrideValue = overrides[i + 1];
if (!overrideValue.equals(option.getValue())) {
if (map.isEmpty()) {
map = new HashMap<>();
}
map.put(option, overrideValue);
}
}
return new MultipleOverridesScope(current, map);
}
private static final ThreadLocal<OverrideScope> overrideScopeTL = new ThreadLocal<>();
protected static OverrideScope getOverrideScope() {
return overrideScopeTL.get();
}
protected static void setOverrideScope(OverrideScope overrideScope) {
overrideScopeTL.set(overrideScope);
}
private T defaultValue;
/**
* The raw option value.
*/
protected T value;
private OptionDescriptor descriptor;
private long reads;
private OptionValue<?> next;
private static OptionValue<?> head;
private static final boolean ShowReadsHistogram = Boolean.getBoolean("jvmci.showOptionValueReadsHistogram");
private static void addToHistogram(OptionValue<?> option) {
if (ShowReadsHistogram) {
synchronized (OptionValue.class) {
option.next = head;
head = option;
}
}
}
@SuppressWarnings("unchecked")
public OptionValue(T value) {
this.defaultValue = value;
this.value = (T) DEFAULT;
addToHistogram(this);
}
private static final Object DEFAULT = "DEFAULT";
private static final Object UNINITIALIZED = "UNINITIALIZED";
/**
* Creates an uninitialized option value for a subclass that initializes itself
* {@link #defaultValue() lazily}.
*/
@SuppressWarnings("unchecked")
protected OptionValue() {
this.defaultValue = (T) UNINITIALIZED;
this.value = (T) DEFAULT;
addToHistogram(this);
}
/**
* Lazy initialization of default value.
*/
protected T defaultValue() {
throw new InternalError("Option without a default value value must override defaultValue()");
}
/**
* Sets the descriptor for this option.
*/
public void setDescriptor(OptionDescriptor descriptor) {
assert this.descriptor == null : "Overwriting existing descriptor";
this.descriptor = descriptor;
}
/**
* Returns the descriptor for this option, if it has been set by
* {@link #setDescriptor(OptionDescriptor)}.
*/
public OptionDescriptor getDescriptor() {
return descriptor;
}
/**
* Gets the name of this option. The name for an option value with a null
* {@linkplain #setDescriptor(OptionDescriptor) descriptor} is the value of
* {@link Object#toString()}.
*/
public String getName() {
return descriptor == null ? super.toString() : (descriptor.getDeclaringClass().getName() + "." + descriptor.getName());
}
@Override
public String toString() {
return getName() + "=" + getValue();
}
/**
* The initial value specified in source code. The returned value is not affected by calls to
* {@link #setValue(Object)} or registering {@link OverrideScope}s. Therefore, it is also not
* affected by options set on the command line.
*/
public T getDefaultValue() {
if (defaultValue == UNINITIALIZED) {
defaultValue = defaultValue();
}
return defaultValue;
}
/**
* Returns true if the option has the same value that was set in the source code.
*/
public boolean hasDefaultValue() {
if (!(this instanceof StableOptionValue)) {
getValue(); // ensure initialized
}
return value == DEFAULT || Objects.equals(value, getDefaultValue());
}
/**
* Gets the value of this option.
*/
public T getValue() {
if (ShowReadsHistogram) {
reads++;
}
if (!(this instanceof StableOptionValue)) {
OverrideScope overrideScope = getOverrideScope();
if (overrideScope != null) {
T override = overrideScope.getOverride(this);
if (override != null) {
return override;
}
}
}
if (value != DEFAULT) {
return value;
} else {
return getDefaultValue();
}
}
/**
* Gets the values of this option including overridden values.
*
* @param c the collection to which the values are added. If null, one is allocated.
* @return the collection to which the values were added in order from most overridden to
* current value
*/
@SuppressWarnings("unchecked")
public Collection<T> getValues(Collection<T> c) {
Collection<T> values = c == null ? new ArrayList<>() : c;
if (!(this instanceof StableOptionValue)) {
OverrideScope overrideScope = getOverrideScope();
if (overrideScope != null) {
overrideScope.getOverrides(this, (Collection<Object>) values);
}
}
if (value != DEFAULT) {
values.add(value);
} else {
values.add(getDefaultValue());
}
return values;
}
/**
* Sets the value of this option.
*/
@SuppressWarnings("unchecked")
public void setValue(Object v) {
this.value = (T) v;
}
/**
* An object whose {@link #close()} method reverts the option value overriding initiated by
* {@link OptionValue#override(OptionValue, Object)} or {@link OptionValue#override(Map)}.
*/
public abstract static class OverrideScope implements AutoCloseable {
private Map<DerivedOptionValue<?>, Object> derivedCache = null;
public <T> T getDerived(DerivedOptionValue<T> key) {
if (derivedCache == null) {
derivedCache = new HashMap<>();
}
@SuppressWarnings("unchecked")
T ret = (T) derivedCache.get(key);
if (ret == null) {
ret = key.createValue();
derivedCache.put(key, ret);
}
return ret;
}
abstract void addToInherited(Map<OptionValue<?>, Object> inherited);
abstract <T> T getOverride(OptionValue<T> option);
abstract void getOverrides(OptionValue<?> option, Collection<Object> c);
public abstract void close();
}
static class SingleOverrideScope extends OverrideScope {
private final OptionValue<?> option;
private final Object value;
public SingleOverrideScope(OptionValue<?> option, Object value) {
if (option instanceof StableOptionValue) {
throw new IllegalArgumentException("Cannot override stable option " + option);
}
this.option = option;
this.value = value;
setOverrideScope(this);
}
@Override
void addToInherited(Map<OptionValue<?>, Object> inherited) {
inherited.put(option, value);
}
@SuppressWarnings("unchecked")
@Override
<T> T getOverride(OptionValue<T> key) {
if (key == this.option) {
return (T) value;
}
return null;
}
@Override
void getOverrides(OptionValue<?> key, Collection<Object> c) {
if (key == this.option) {
c.add(value);
}
}
@Override
public void close() {
setOverrideScope(null);
}
}
static class MultipleOverridesScope extends OverrideScope {
final OverrideScope parent;
final Map<OptionValue<?>, Object> overrides;
public MultipleOverridesScope(OverrideScope parent, OptionValue<?> option, Object value) {
this.parent = parent;
this.overrides = new HashMap<>();
if (parent != null) {
parent.addToInherited(overrides);
}
if (option instanceof StableOptionValue) {
throw new IllegalArgumentException("Cannot override stable option " + option);
}
if (!value.equals(option.getValue())) {
this.overrides.put(option, value);
}
if (!overrides.isEmpty()) {
setOverrideScope(this);
}
}
MultipleOverridesScope(OverrideScope parent, Map<OptionValue<?>, Object> overrides) {
this.parent = parent;
if (overrides.isEmpty() && parent == null) {
this.overrides = Collections.emptyMap();
return;
}
this.overrides = new HashMap<>();
if (parent != null) {
parent.addToInherited(this.overrides);
}
for (Map.Entry<OptionValue<?>, Object> e : overrides.entrySet()) {
OptionValue<?> option = e.getKey();
if (option instanceof StableOptionValue) {
throw new IllegalArgumentException("Cannot override stable option " + option);
}
if (!e.getValue().equals(option.getValue())) {
this.overrides.put(option, e.getValue());
}
}
if (!this.overrides.isEmpty()) {
setOverrideScope(this);
}
}
@Override
void addToInherited(Map<OptionValue<?>, Object> inherited) {
if (parent != null) {
parent.addToInherited(inherited);
}
inherited.putAll(overrides);
}
@SuppressWarnings("unchecked")
@Override
<T> T getOverride(OptionValue<T> option) {
return (T) overrides.get(option);
}
@Override
void getOverrides(OptionValue<?> option, Collection<Object> c) {
Object v = overrides.get(option);
if (v != null) {
c.add(v);
}
if (parent != null) {
parent.getOverrides(option, c);
}
}
@Override
public void close() {
if (!overrides.isEmpty()) {
setOverrideScope(parent);
}
}
}
static {
if (ShowReadsHistogram) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
ArrayList<OptionValue<?>> options = new ArrayList<>();
for (OptionValue<?> option = head; option != null; option = option.next) {
options.add(option);
}
Collections.sort(options, new Comparator<OptionValue<?>>() {
public int compare(OptionValue<?> o1, OptionValue<?> o2) {
if (o1.reads < o2.reads) {
return -1;
} else if (o1.reads > o2.reads) {
return 1;
} else {
return o1.getName().compareTo(o2.getName());
}
}
});
PrintStream out = System.out;
out.println("=== OptionValue reads histogram ===");
for (OptionValue<?> option : options) {
out.println(option.reads + "\t" + option);
}
}
});
}
}
}

View File

@ -1,47 +0,0 @@
/*
* 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 jdk.vm.ci.options;
import java.util.ServiceLoader;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* Helper class used to load option descriptors. Only to be used in the slow-path.
*/
public class OptionsLoader {
public static final SortedMap<String, OptionDescriptor> options = new TreeMap<>();
/**
* Initializes {@link #options} from {@link Options} services.
*/
static {
for (OptionDescriptors opts : ServiceLoader.load(OptionDescriptors.class, OptionsLoader.class.getClassLoader())) {
for (OptionDescriptor desc : opts) {
String name = desc.getName();
OptionDescriptor existing = options.put(name, desc);
assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation();
}
}
}
}

View File

@ -1,382 +0,0 @@
/*
* 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 jdk.vm.ci.options;
import static jdk.vm.ci.inittimer.InitTimer.timer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Formatter;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.SortedMap;
import jdk.vm.ci.inittimer.InitTimer;
/**
* This class contains methods for parsing JVMCI options and matching them against a set of
* {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded via a {@link ServiceLoader}.
*/
public class OptionsParser {
private static final OptionValue<Boolean> PrintFlags = new OptionValue<>(false);
private static final OptionValue<Boolean> ShowFlags = new OptionValue<>(false);
/**
* A service for looking up {@link OptionDescriptor}s.
*/
public interface OptionDescriptorsProvider {
/**
* Gets the {@link OptionDescriptor} matching a given option {@linkplain Option#name() name}
* or null if no option of that name is provided by this object.
*/
OptionDescriptor get(String name);
}
public interface OptionConsumer {
void set(OptionDescriptor desc, Object value);
}
/**
* Parses the options in {@code <jdk>/lib/jvmci.options} if {@code parseOptionsFile == true} and
* the file exists followed by the JVMCI options in {@code options} if {@code options != null}.
*
* Called from VM. This method has an object return type to allow it to be called with a VM
* utility function used to call other static initialization methods.
*
* @param options JVMCI options as serialized (name, value) pairs
* @param parseOptionsFile specifies whether to look for and parse
* {@code <jdk>/lib/jvmci.options}
*/
@SuppressWarnings("try")
public static Boolean parseOptionsFromVM(String[] options, boolean parseOptionsFile) {
try (InitTimer t = timer("ParseOptions")) {
if (parseOptionsFile) {
File javaHome = new File(System.getProperty("java.home"));
File lib = new File(javaHome, "lib");
File jvmciOptions = new File(lib, "jvmci.options");
if (jvmciOptions.exists()) {
try (BufferedReader br = new BufferedReader(new FileReader(jvmciOptions))) {
String optionSetting = null;
int lineNo = 1;
List<String> optionSettings = new ArrayList<>();
while ((optionSetting = br.readLine()) != null) {
if (!optionSetting.isEmpty() && optionSetting.charAt(0) != '#') {
try {
parseOptionSettingTo(optionSetting, optionSettings);
} catch (Throwable e) {
throw new InternalError("Error parsing " + jvmciOptions + ", line " + lineNo, e);
}
}
lineNo++;
}
try {
parseOptions(optionSettings.toArray(new String[optionSettings.size()]), null, null, null);
} catch (Throwable e) {
throw new InternalError("Error parsing an option from " + jvmciOptions, e);
}
} catch (IOException e) {
throw new InternalError("Error reading " + jvmciOptions, e);
}
}
}
parseOptions(options, null, null, null);
}
return Boolean.TRUE;
}
/**
* Parses an ordered list of (name, value) pairs assigning values to JVMCI options.
*
* @param optionSettings JVMCI options as serialized (name, value) pairs
* @param setter the object to notify of the parsed option and value
* @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s
* @param options the options database to use if {@code odp == null}. If
* {@code options == null && odp == null}, {@link OptionsLoader#options} is used.
* @throws IllegalArgumentException if there's a problem parsing {@code option}
*/
public static void parseOptions(String[] optionSettings, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
if (optionSettings != null && optionSettings.length != 0) {
assert optionSettings.length % 2 == 0;
moveHelpFlagsToTail(optionSettings);
for (int i = 0; i < optionSettings.length / 2; i++) {
String name = optionSettings[i * 2];
String value = optionSettings[i * 2 + 1];
parseOption(name, value, setter, odp, options);
}
if (PrintFlags.getValue() || ShowFlags.getValue()) {
Set<String> explicitlyAssigned = new HashSet<>(optionSettings.length / 2);
for (int i = 0; i < optionSettings.length / 2; i++) {
String name = optionSettings[i * 2];
explicitlyAssigned.add(name);
}
printFlags(resolveOptions(options), "JVMCI", System.out, explicitlyAssigned);
if (PrintFlags.getValue()) {
System.exit(0);
}
}
}
}
/**
* Moves all {@code PrintFlags} and {@code ShowFlags} option settings to the back of
* {@code optionSettings}. This allows the help message to show which options had their value
* explicitly set (even if to their default value).
*/
private static void moveHelpFlagsToTail(String[] optionSettings) {
List<String> tail = null;
int insert = 0;
for (int i = 0; i < optionSettings.length / 2; i++) {
String name = optionSettings[i * 2];
String value = optionSettings[i * 2 + 1];
if (name.equals("ShowFlags") || name.equals("PrintFlags")) {
if (tail == null) {
tail = new ArrayList<>(4);
insert = i * 2;
}
tail.add(name);
tail.add(value);
} else if (tail != null) {
optionSettings[insert++] = name;
optionSettings[insert++] = value;
}
}
if (tail != null) {
assert tail.size() + insert == optionSettings.length;
String[] tailArr = tail.toArray(new String[tail.size()]);
System.arraycopy(tailArr, 0, optionSettings, insert, tailArr.length);
}
}
/**
* Parses a given option setting string to a list of (name, value) pairs.
*
* @param optionSetting a string matching the pattern {@code <name>=<value>}
*/
public static void parseOptionSettingTo(String optionSetting, List<String> dst) {
int eqIndex = optionSetting.indexOf('=');
if (eqIndex == -1) {
throw new InternalError("Option setting has does not match the pattern <name>=<value>: " + optionSetting);
}
dst.add(optionSetting.substring(0, eqIndex));
dst.add(optionSetting.substring(eqIndex + 1));
}
/**
* Resolves {@code options} to a non-null value. This ensures {@link OptionsLoader#options} is
* only loaded if necessary.
*/
private static SortedMap<String, OptionDescriptor> resolveOptions(SortedMap<String, OptionDescriptor> options) {
return options != null ? options : OptionsLoader.options;
}
/**
* Parses a given option name and value.
*
* @param name the option name
* @param valueString the option value as a string
* @param setter the object to notify of the parsed option and value
* @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s
* @param options the options database to use if {@code odp == null}. If
* {@code options == null && odp == null}, {@link OptionsLoader#options} is used.
* @throws IllegalArgumentException if there's a problem parsing {@code option}
*/
private static void parseOption(String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
OptionDescriptor desc = odp != null ? odp.get(name) : resolveOptions(options).get(name);
if (desc == null) {
if (name.equals("PrintFlags")) {
desc = OptionDescriptor.create("PrintFlags", Boolean.class, "Prints all JVMCI flags and exits", OptionsParser.class, "PrintFlags", PrintFlags);
} else if (name.equals("ShowFlags")) {
desc = OptionDescriptor.create("ShowFlags", Boolean.class, "Prints all JVMCI flags and continues", OptionsParser.class, "ShowFlags", ShowFlags);
}
}
if (desc == null) {
List<OptionDescriptor> matches = fuzzyMatch(resolveOptions(options), name);
Formatter msg = new Formatter();
msg.format("Could not find option %s", name);
if (!matches.isEmpty()) {
msg.format("%nDid you mean one of the following?");
for (OptionDescriptor match : matches) {
msg.format("%n %s=<value>", match.getName());
}
}
throw new IllegalArgumentException(msg.toString());
}
Class<?> optionType = desc.getType();
Object value;
if (optionType == Boolean.class) {
if ("true".equals(valueString)) {
value = Boolean.TRUE;
} else if ("false".equals(valueString)) {
value = Boolean.FALSE;
} else {
throw new IllegalArgumentException("Boolean option '" + name + "' must have value \"true\" or \"false\", not \"" + valueString + "\"");
}
} else if (optionType == Float.class) {
value = Float.parseFloat(valueString);
} else if (optionType == Double.class) {
value = Double.parseDouble(valueString);
} else if (optionType == Integer.class) {
value = Integer.valueOf((int) parseLong(valueString));
} else if (optionType == Long.class) {
value = Long.valueOf(parseLong(valueString));
} else if (optionType == String.class) {
value = valueString;
} else {
throw new IllegalArgumentException("Wrong value for option '" + name + "'");
}
if (setter == null) {
desc.getOptionValue().setValue(value);
} else {
setter.set(desc, value);
}
}
private static long parseLong(String v) {
String valueString = v.toLowerCase();
long scale = 1;
if (valueString.endsWith("k")) {
scale = 1024L;
} else if (valueString.endsWith("m")) {
scale = 1024L * 1024L;
} else if (valueString.endsWith("g")) {
scale = 1024L * 1024L * 1024L;
} else if (valueString.endsWith("t")) {
scale = 1024L * 1024L * 1024L * 1024L;
}
if (scale != 1) {
/* Remove trailing scale character. */
valueString = valueString.substring(0, valueString.length() - 1);
}
return Long.parseLong(valueString) * scale;
}
/**
* Wraps some given text to one or more lines of a given maximum width.
*
* @param text text to wrap
* @param width maximum width of an output line, exception for words in {@code text} longer than
* this value
* @return {@code text} broken into lines
*/
private static List<String> wrap(String text, int width) {
List<String> lines = Collections.singletonList(text);
if (text.length() > width) {
String[] chunks = text.split("\\s+");
lines = new ArrayList<>();
StringBuilder line = new StringBuilder();
for (String chunk : chunks) {
if (line.length() + chunk.length() > width) {
lines.add(line.toString());
line.setLength(0);
}
if (line.length() != 0) {
line.append(' ');
}
String[] embeddedLines = chunk.split("%n", -2);
if (embeddedLines.length == 1) {
line.append(chunk);
} else {
for (int i = 0; i < embeddedLines.length; i++) {
line.append(embeddedLines[i]);
if (i < embeddedLines.length - 1) {
lines.add(line.toString());
line.setLength(0);
}
}
}
}
if (line.length() != 0) {
lines.add(line.toString());
}
}
return lines;
}
private static void printFlags(SortedMap<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out, Set<String> explicitlyAssigned) {
out.println("[List of " + prefix + " options]");
for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
e.getKey();
OptionDescriptor desc = e.getValue();
Object value = desc.getOptionValue().getValue();
List<String> helpLines = wrap(desc.getHelp(), 70);
String name = e.getKey();
String assign = explicitlyAssigned.contains(name) ? ":=" : " =";
out.printf("%9s %-40s %s %-14s %s%n", desc.getType().getSimpleName(), name, assign, value, helpLines.get(0));
for (int i = 1; i < helpLines.size(); i++) {
out.printf("%67s %s%n", " ", helpLines.get(i));
}
}
}
/**
* Compute string similarity based on Dice's coefficient.
*
* Ported from str_similar() in globals.cpp.
*/
static float stringSimiliarity(String str1, String str2) {
int hit = 0;
for (int i = 0; i < str1.length() - 1; ++i) {
for (int j = 0; j < str2.length() - 1; ++j) {
if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) {
++hit;
break;
}
}
}
return 2.0f * hit / (str1.length() + str2.length());
}
private static final float FUZZY_MATCH_THRESHOLD = 0.7F;
/**
* Returns the set of options that fuzzy match a given option name.
*/
private static List<OptionDescriptor> fuzzyMatch(SortedMap<String, OptionDescriptor> options, String optionName) {
List<OptionDescriptor> matches = new ArrayList<>();
for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
float score = stringSimiliarity(e.getKey(), optionName);
if (score >= FUZZY_MATCH_THRESHOLD) {
matches.add(e.getValue());
}
}
return matches;
}
}

View File

@ -1,75 +0,0 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.options;
/**
* An option that always returns the same {@linkplain #getValue() value}.
*/
public class StableOptionValue<T> extends OptionValue<T> {
/**
* Creates a stable option value.
*/
public StableOptionValue(T value) {
super(value);
}
/**
* Used to assert the invariant for stability. Without using locks, this check is not safe
* against races and so it's only an assertion.
*/
private boolean getValueCalled;
/**
* Creates an uninitialized stable option value for a subclass that initializes itself
* {@link #defaultValue() lazily}.
*/
public StableOptionValue() {
}
/**
* Gets the value of this option.
*/
@Override
public final T getValue() {
T result = super.getValue();
assert initGetValueCalled();
return result;
}
private boolean initGetValueCalled() {
getValueCalled = true;
return true;
}
/**
* {@inheritDoc}
* <p>
* This must only be called if {@link #getValue()} has never been called.
*/
@Override
public final void setValue(Object v) {
assert !getValueCalled;
super.setValue(v);
}
}

View File

@ -50,15 +50,10 @@ jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false;
bool JVMCIRuntime::_well_known_classes_initialized = false;
const char* JVMCIRuntime::_compiler = NULL;
int JVMCIRuntime::_options_count = 0;
SystemProperty** JVMCIRuntime::_options = NULL;
int JVMCIRuntime::_trivial_prefixes_count = 0;
char** JVMCIRuntime::_trivial_prefixes = NULL;
bool JVMCIRuntime::_shutdown_called = false;
static const char* OPTION_PREFIX = "jvmci.option.";
static const size_t OPTION_PREFIX_LEN = strlen(OPTION_PREFIX);
BasicType JVMCIRuntime::kindToBasicType(Handle kind, TRAPS) {
if (kind.is_null()) {
THROW_(vmSymbols::java_lang_NullPointerException(), T_ILLEGAL);
@ -631,16 +626,6 @@ Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, c
return Handle((oop)result.get_jobject());
}
static bool jvmci_options_file_exists() {
const char* home = Arguments::get_java_home();
size_t path_len = strlen(home) + strlen("/lib/jvmci.options") + 1;
char path[JVM_MAXPATHLEN];
char sep = os::file_separator()[0];
jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cjvmci.options", home, sep, sep);
struct stat st;
return os::stat(path, &st) == 0;
}
void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) {
if (JNIHandles::resolve(_HotSpotJVMCIRuntime_instance) == NULL) {
#ifdef ASSERT
@ -652,30 +637,6 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) {
"HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization");
#endif
bool parseOptionsFile = jvmci_options_file_exists();
if (_options != NULL || parseOptionsFile) {
JavaCallArguments args;
objArrayOop options;
if (_options != NULL) {
options = oopFactory::new_objArray(SystemDictionary::String_klass(), _options_count * 2, CHECK);
for (int i = 0; i < _options_count; i++) {
SystemProperty* prop = _options[i];
oop name = java_lang_String::create_oop_from_str(prop->key() + OPTION_PREFIX_LEN, CHECK);
const char* prop_value = prop->value() != NULL ? prop->value() : "";
oop value = java_lang_String::create_oop_from_str(prop_value, CHECK);
options->obj_at_put(i * 2, name);
options->obj_at_put((i * 2) + 1, value);
}
} else {
options = NULL;
}
args.push_oop(options);
args.push_int(parseOptionsFile);
callStatic("jdk/vm/ci/options/OptionsParser",
"parseOptionsFromVM",
"([Ljava/lang/String;Z)Ljava/lang/Boolean;", &args, CHECK);
}
if (_compiler != NULL) {
JavaCallArguments args;
oop compiler = java_lang_String::create_oop_from_str(_compiler, CHECK);
@ -893,48 +854,6 @@ void JVMCIRuntime::save_compiler(const char* compiler) {
_compiler = compiler;
}
void JVMCIRuntime::maybe_print_flags(TRAPS) {
if (_options != NULL) {
for (int i = 0; i < _options_count; i++) {
SystemProperty* p = _options[i];
const char* name = p->key() + OPTION_PREFIX_LEN;
if (strcmp(name, "PrintFlags") == 0 || strcmp(name, "ShowFlags") == 0) {
JVMCIRuntime::initialize_well_known_classes(CHECK);
HandleMark hm;
ResourceMark rm;
JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK);
return;
}
}
}
}
void JVMCIRuntime::save_options(SystemProperty* props) {
int count = 0;
SystemProperty* first = NULL;
for (SystemProperty* p = props; p != NULL; p = p->next()) {
if (strncmp(p->key(), OPTION_PREFIX, OPTION_PREFIX_LEN) == 0) {
if (first == NULL) {
first = p;
}
count++;
}
}
if (count != 0) {
_options_count = count;
_options = NEW_C_HEAP_ARRAY(SystemProperty*, count, mtCompiler);
_options[0] = first;
SystemProperty** insert_pos = _options + 1;
for (SystemProperty* p = first->next(); p != NULL; p = p->next()) {
if (strncmp(p->key(), OPTION_PREFIX, OPTION_PREFIX_LEN) == 0) {
*insert_pos = p;
insert_pos++;
}
}
assert (insert_pos - _options == count, "must be");
}
}
void JVMCIRuntime::shutdown(TRAPS) {
if (_HotSpotJVMCIRuntime_instance != NULL) {
_shutdown_called = true;

View File

@ -71,8 +71,6 @@ class JVMCIRuntime: public AllStatic {
static bool _HotSpotJVMCIRuntime_initialized;
static bool _well_known_classes_initialized;
static const char* _compiler;
static int _options_count;
static SystemProperty** _options;
static int _trivial_prefixes_count;
static char** _trivial_prefixes;
@ -99,20 +97,6 @@ class JVMCIRuntime: public AllStatic {
*/
static void save_compiler(const char* compiler);
/**
* Saves the value of the system properties starting with "jvmci.option." for processing
* when JVMCI is initialized.
*
* @param props the head of the system property list
*/
static void save_options(SystemProperty* props);
/**
* If either the PrintFlags or ShowFlags JVMCI option is present,
* then JVMCI is initialized to show the help message.
*/
static void maybe_print_flags(TRAPS);
static bool is_HotSpotJVMCIRuntime_initialized() { return _HotSpotJVMCIRuntime_initialized; }
/**

View File

@ -3344,12 +3344,6 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req
const char* fileSep = os::file_separator();
sprintf(path, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep);
#if INCLUDE_JVMCI
if (EnableJVMCI) {
JVMCIRuntime::save_options(_system_properties);
}
#endif // INCLUDE_JVMCI
if (CheckEndorsedAndExtDirs) {
int nonEmptyDirs = 0;
// check endorsed directory

View File

@ -3657,7 +3657,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
if (jvmciCompiler != NULL) {
JVMCIRuntime::save_compiler(jvmciCompiler);
}
JVMCIRuntime::maybe_print_flags(CHECK_JNI_ERR);
}
#endif // INCLUDE_JVMCI

View File

@ -1,143 +0,0 @@
/*
* Copyright (c) 2013, 2015, 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.
*/
/**
* @test
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
* @run junit jdk.vm.ci.options.test.NestedBooleanOptionValueTest
*/
package jdk.vm.ci.options.test;
import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master0;
import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master1;
import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master2;
import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption0;
import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption1;
import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption2;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import jdk.vm.ci.options.NestedBooleanOptionValue;
import jdk.vm.ci.options.OptionDescriptor;
import jdk.vm.ci.options.OptionValue;
import jdk.vm.ci.options.OptionValue.OverrideScope;
import org.junit.Test;
public class NestedBooleanOptionValueTest {
public static class Options {
public static final OptionValue<Boolean> Master0 = new OptionValue<>(true);
public static final OptionValue<Boolean> NestedOption0 = new NestedBooleanOptionValue(Master0, true);
public static final OptionValue<Boolean> Master1 = new OptionValue<>(true);
public static final OptionValue<Boolean> NestedOption1 = new NestedBooleanOptionValue(Master1, true);
public static final OptionValue<Boolean> Master2 = new OptionValue<>(true);
public static final OptionValue<Boolean> NestedOption2 = new NestedBooleanOptionValue(Master2, false);
}
static final OptionDescriptor master0 = OptionDescriptor.create("Master0", Boolean.class, "", Options.class, "Master0", Master0);
static final OptionDescriptor nestedOption0 = OptionDescriptor.create("NestedOption0", Boolean.class, "", Options.class, "NestedOption0", NestedOption0);
static final OptionDescriptor master1 = OptionDescriptor.create("Master1", Boolean.class, "", Options.class, "Master1", Master1);
static final OptionDescriptor nestedOption1 = OptionDescriptor.create("NestedOption1", Boolean.class, "", Options.class, "NestedOption1", NestedOption1);
static final OptionDescriptor master2 = OptionDescriptor.create("Master2", Boolean.class, "", Options.class, "Master2", Master2);
static final OptionDescriptor nestedOption2 = OptionDescriptor.create("NestedOption2", Boolean.class, "", Options.class, "NestedOption2", NestedOption2);
@SuppressWarnings("try")
@Test
public void runOverrides() {
assertTrue(Master0.getValue());
assertTrue(NestedOption0.getValue());
try (OverrideScope s1 = OptionValue.override(Master0, false)) {
assertFalse(Master0.getValue());
assertFalse(NestedOption0.getValue());
try (OverrideScope s2 = OptionValue.override(NestedOption0, false)) {
assertFalse(NestedOption0.getValue());
}
try (OverrideScope s2 = OptionValue.override(NestedOption0, true)) {
assertTrue(NestedOption0.getValue());
}
}
assertTrue(Master0.getValue());
try (OverrideScope s1 = OptionValue.override(NestedOption0, false)) {
assertFalse(NestedOption0.getValue());
}
try (OverrideScope s1 = OptionValue.override(NestedOption0, true)) {
assertTrue(NestedOption0.getValue());
}
}
@Test
public void runDefaultTrue() {
Master1.setValue(true);
assertTrue(Master1.getValue());
assertTrue(NestedOption1.getValue());
// nested value unset
Master1.setValue(false);
assertFalse(Master1.getValue());
assertFalse(NestedOption1.getValue());
// set false
Master1.setValue(false);
NestedOption1.setValue(false);
assertFalse(Master1.getValue());
assertFalse(NestedOption1.getValue());
Master1.setValue(true);
assertTrue(Master1.getValue());
assertFalse(NestedOption1.getValue());
// set true
Master1.setValue(false);
NestedOption1.setValue(true);
assertFalse(Master1.getValue());
assertTrue(NestedOption1.getValue());
Master1.setValue(true);
assertTrue(Master1.getValue());
assertTrue(NestedOption1.getValue());
}
@Test
public void runDefaultFalse() {
Master2.setValue(true);
assertTrue(Master2.getValue());
assertFalse(NestedOption2.getValue());
// nested value unset
Master2.setValue(false);
assertFalse(Master2.getValue());
assertFalse(NestedOption2.getValue());
// set false
Master2.setValue(false);
NestedOption2.setValue(false);
assertFalse(Master2.getValue());
assertFalse(NestedOption2.getValue());
Master2.setValue(true);
assertTrue(Master2.getValue());
assertFalse(NestedOption2.getValue());
// set true
Master2.setValue(false);
NestedOption2.setValue(true);
assertFalse(Master2.getValue());
assertTrue(NestedOption2.getValue());
Master2.setValue(true);
assertTrue(Master2.getValue());
assertTrue(NestedOption2.getValue());
}
}

View File

@ -1,141 +0,0 @@
/*
* Copyright (c) 2013, 2015, 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.
*/
/**
* @test
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
* @run junit jdk.vm.ci.options.test.TestOptionValue
*/
package jdk.vm.ci.options.test;
import static jdk.vm.ci.options.test.TestOptionValue.Options.Mutable;
import static jdk.vm.ci.options.test.TestOptionValue.Options.SecondMutable;
import static jdk.vm.ci.options.test.TestOptionValue.Options.Stable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Arrays;
import jdk.vm.ci.options.OptionDescriptor;
import jdk.vm.ci.options.OptionValue;
import jdk.vm.ci.options.OptionValue.OverrideScope;
import jdk.vm.ci.options.StableOptionValue;
import org.junit.Test;
@SuppressWarnings("try")
public class TestOptionValue {
public static class Options {
public static final OptionValue<Boolean> Stable = new StableOptionValue<>(true);
public static final OptionValue<String> Mutable = new OptionValue<>("original");
public static final OptionValue<String> SecondMutable = new OptionValue<>("second");
}
static final OptionDescriptor stable = OptionDescriptor.create("Stable", Boolean.class, "", Options.class, "Stable", Stable);
static final OptionDescriptor mutable = OptionDescriptor.create("Mutable", String.class, "", Options.class, "Mutable", Mutable);
static final OptionDescriptor secondMutable = OptionDescriptor.create("SecondMutable", String.class, "", Options.class, "SecondMutable", SecondMutable);
@Test
public void testMutable() {
assertEquals("original", Mutable.getValue());
try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
assertEquals("override1", Mutable.getValue());
try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
assertEquals("override2", Mutable.getValue());
}
assertEquals("override1", Mutable.getValue());
try (OverrideScope s3 = OptionValue.override(Mutable, "override3")) {
assertEquals("override3", Mutable.getValue());
}
assertEquals("override1", Mutable.getValue());
}
assertEquals("original", Mutable.getValue());
try (OverrideScope s1 = OptionValue.override(Mutable, "original")) {
assertEquals("original", Mutable.getValue());
}
}
@Test
public void testMultiple() {
assertEquals("original", Mutable.getValue());
assertEquals("second", SecondMutable.getValue());
try (OverrideScope s1 = OptionValue.override(Mutable, "override1", SecondMutable, "secondOverride1")) {
assertEquals("override1", Mutable.getValue());
assertEquals("secondOverride1", SecondMutable.getValue());
try (OverrideScope s2 = OptionValue.override(Mutable, "override2", SecondMutable, "secondOverride2")) {
assertEquals("override2", Mutable.getValue());
assertEquals("secondOverride2", SecondMutable.getValue());
}
assertEquals("override1", Mutable.getValue());
assertEquals("secondOverride1", SecondMutable.getValue());
try (OverrideScope s3 = OptionValue.override(Mutable, "override3", SecondMutable, "secondOverride3")) {
assertEquals("override3", Mutable.getValue());
assertEquals("secondOverride3", SecondMutable.getValue());
}
assertEquals("override1", Mutable.getValue());
assertEquals("secondOverride1", SecondMutable.getValue());
}
assertEquals("original", Mutable.getValue());
assertEquals("second", SecondMutable.getValue());
try (OverrideScope s1 = OptionValue.override(Mutable, "original", SecondMutable, "second")) {
assertEquals("original", Mutable.getValue());
assertEquals("second", SecondMutable.getValue());
}
}
@Test
public void testStable() {
assertTrue(Stable.getValue());
try (OverrideScope s = OptionValue.override(Stable, false)) {
fail("cannot override stable option");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test
public void toStringTest() {
assertEquals("jdk.vm.ci.options.test.TestOptionValue$Options.Mutable=original", Mutable.toString());
try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
assertEquals("jdk.vm.ci.options.test.TestOptionValue$Options.Mutable=override1", Mutable.toString());
try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
assertEquals("jdk.vm.ci.options.test.TestOptionValue$Options.Mutable=override2", Mutable.toString());
}
}
}
@Test
public void getValuesTest() {
assertEquals(Arrays.asList("original"), Mutable.getValues(null));
assertEquals(Arrays.asList(true), Stable.getValues(null));
try (OverrideScope s1 = OptionValue.override(Mutable, "override1")) {
assertEquals(Arrays.asList("override1", "original"), Mutable.getValues(null));
try (OverrideScope s2 = OptionValue.override(Mutable, "override2")) {
assertEquals(Arrays.asList("override2", "override1", "original"), Mutable.getValues(null));
}
}
}
}

View File

@ -49,8 +49,8 @@ import java.util.stream.Collectors;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaField;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.TrustedInterface;
import jdk.vm.ci.runtime.JVMCI;
@ -179,7 +179,7 @@ public class TypeUniverse {
List<ConstantValue> res = new ArrayList<>();
for (Field field : fromClass.getDeclaredFields()) {
if (isStatic(field.getModifiers()) && isFinal(field.getModifiers())) {
JavaField javaField = metaAccess.lookupJavaField(field);
ResolvedJavaField javaField = metaAccess.lookupJavaField(field);
Object boxed = field.get(null);
if (boxed instanceof JavaConstant) {
res.add(new ConstantValue(javaField.format("%H.%n"), (JavaConstant) boxed, boxed));