8210031: implementation for JVM Constants API
Reviewed-by: jrose, mcimadamore, darcy, mchung, rriggs, dholmes, forax
Contributed-by: brian.goetz@oracle.com, vicente.romero@oracle.com
--- a/src/java.base/share/classes/java/lang/Class.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Class.java Sun Dec 09 12:36:24 2018 -0500
@@ -26,6 +26,8 @@
package java.lang;
import java.lang.annotation.Annotation;
+import java.lang.constant.ClassDesc;
+import java.lang.invoke.TypeDescriptor;
import java.lang.module.ModuleReader;
import java.lang.ref.SoftReference;
import java.io.IOException;
@@ -46,6 +48,7 @@
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
+import java.lang.constant.Constable;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -58,6 +61,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.StringJoiner;
import java.util.stream.Stream;
import java.util.stream.Collectors;
@@ -72,6 +76,7 @@
import jdk.internal.reflect.Reflection;
import jdk.internal.reflect.ReflectionFactory;
import jdk.internal.vm.annotation.ForceInline;
+import sun.invoke.util.Wrapper;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.repository.ClassRepository;
@@ -154,7 +159,9 @@
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
- AnnotatedElement {
+ AnnotatedElement,
+ TypeDescriptor.OfField<Class<?>>,
+ Constable {
private static final int ANNOTATION= 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000;
@@ -4027,4 +4034,68 @@
}
return members;
}
+
+ /**
+ * Returns the type descriptor string for this class.
+ * <p>
+ * Note that this is not a strict inverse of {@link #forName};
+ * distinct classes which share a common name but have different class loaders
+ * will have identical descriptor strings.
+ *
+ * @return the type descriptor representation
+ * @jvms 4.3.2 Field Descriptors
+ * @since 12
+ */
+ @Override
+ public String descriptorString() {
+ if (isPrimitive())
+ return Wrapper.forPrimitiveType(this).basicTypeString();
+ else if (isArray()) {
+ return "[" + componentType.descriptorString();
+ }
+ else {
+ return "L" + getName().replace('.', '/') + ";";
+ }
+ }
+
+ /**
+ * Returns the component type of this {@code Class}, if it describes
+ * an array type, or {@code null} otherwise.
+ *
+ * @implSpec
+ * Equivalent to {@link Class#getComponentType()}.
+ *
+ * @return a {@code Class} describing the component type, or {@code null}
+ * if this {@code Class} does not describe an array type
+ * @since 12
+ */
+ @Override
+ public Class<?> componentType() {
+ return isArray() ? componentType : null;
+ }
+
+ /**
+ * Returns a {@code Class} for an array type whose component type
+ * is described by this {@linkplain Class}.
+ *
+ * @return a {@code Class} describing the array type
+ * @since 12
+ */
+ @Override
+ public Class<?> arrayType() {
+ return Array.newInstance(this, 0).getClass();
+ }
+
+ /**
+ * Returns a nominal descriptor for this instance, if one can be
+ * constructed, or an empty {@link Optional} if one cannot be.
+ *
+ * @return An {@link Optional} containing the resulting nominal descriptor,
+ * or an empty {@link Optional} if one cannot be constructed.
+ * @since 12
+ */
+ @Override
+ public Optional<ClassDesc> describeConstable() {
+ return Optional.of(ClassDesc.ofDescriptor(descriptorString()));
+ }
}
--- a/src/java.base/share/classes/java/lang/Double.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Double.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, 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
@@ -25,6 +25,11 @@
package java.lang;
+import java.lang.invoke.MethodHandles;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
+import java.util.Optional;
+
import jdk.internal.math.FloatingDecimal;
import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
@@ -46,7 +51,8 @@
* @author Joseph D. Darcy
* @since 1.0
*/
-public final class Double extends Number implements Comparable<Double> {
+public final class Double extends Number
+ implements Comparable<Double>, Constable, ConstantDesc {
/**
* A constant holding the positive infinity of type
* {@code double}. It is equal to the value returned by
@@ -1070,6 +1076,31 @@
return Math.min(a, b);
}
+ /**
+ * Returns a nominal descriptor for this instance, which is the instance
+ * itself.
+ *
+ * @return an {@link Optional} describing the {@linkplain Double} instance
+ * @since 12
+ */
+ @Override
+ public Optional<Double> describeConstable() {
+ return Optional.of(this);
+ }
+
+ /**
+ * Resolves this instance as a {@link ConstantDesc}, the result of which is
+ * the instance itself.
+ *
+ * @param lookup ignored
+ * @return the {@linkplain Double} instance
+ * @since 12
+ */
+ @Override
+ public Double resolveConstantDesc(MethodHandles.Lookup lookup) {
+ return this;
+ }
+
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -9172774392245257468L;
}
--- a/src/java.base/share/classes/java/lang/Enum.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Enum.java Sun Dec 09 12:36:24 2018 -0500
@@ -25,11 +25,19 @@
package java.lang;
-import java.io.Serializable;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDescs;
+import java.lang.constant.DynamicConstantDesc;
+import java.lang.invoke.MethodHandles;
+import java.util.Optional;
+
+import static java.util.Objects.requireNonNull;
/**
* This is the common base class of all Java language enumeration types.
@@ -56,7 +64,7 @@
@SuppressWarnings("serial") // No serialVersionUID needed due to
// special-casing of enum types.
public abstract class Enum<E extends Enum<E>>
- implements Comparable<E>, Serializable {
+ implements Constable, Comparable<E>, Serializable {
/**
* The name of this enum constant, as declared in the enum declaration.
* Most programmers should use the {@link #toString} method rather than
@@ -204,6 +212,21 @@
}
/**
+ * Returns an enum descriptor {@code EnumDesc} for this instance, if one can be
+ * constructed, or an empty {@link Optional} if one cannot be.
+ *
+ * @return An {@link Optional} containing the resulting nominal descriptor,
+ * or an empty {@link Optional} if one cannot be constructed.
+ * @since 12
+ */
+ @Override
+ public final Optional<EnumDesc<E>> describeConstable() {
+ return getDeclaringClass()
+ .describeConstable()
+ .map(c -> EnumDesc.of(c, name));
+ }
+
+ /**
* Returns the enum constant of the specified enum type with the
* specified name. The name must match exactly an identifier used
* to declare an enum constant in this type. (Extraneous whitespace
@@ -258,4 +281,56 @@
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("can't deserialize enum");
}
+
+ /**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for an
+ * {@code enum} constant.
+ *
+ * @param <E> the type of the enum constant
+ *
+ * @since 12
+ */
+ public static final class EnumDesc<E extends Enum<E>>
+ extends DynamicConstantDesc<E> {
+
+ /**
+ * Constructs a nominal descriptor for the specified {@code enum} class and name.
+ *
+ * @param constantType a {@link ClassDesc} describing the {@code enum} class
+ * @param constantName the unqualified name of the enum constant
+ * @throws NullPointerException if any argument is null
+ * @jvms 4.2.2 Unqualified Names
+ */
+ private EnumDesc(ClassDesc constantType, String constantName) {
+ super(ConstantDescs.BSM_ENUM_CONSTANT, requireNonNull(constantName), requireNonNull(constantType));
+ }
+
+ /**
+ * Returns a nominal descriptor for the specified {@code enum} class and name
+ *
+ * @param <E> the type of the enum constant
+ * @param enumClass a {@link ClassDesc} describing the {@code enum} class
+ * @param constantName the unqualified name of the enum constant
+ * @return the nominal descriptor
+ * @throws NullPointerException if any argument is null
+ * @jvms 4.2.2 Unqualified Names
+ * @since 12
+ */
+ public static<E extends Enum<E>> EnumDesc<E> of(ClassDesc enumClass,
+ String constantName) {
+ return new EnumDesc<>(enumClass, constantName);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public E resolveConstantDesc(MethodHandles.Lookup lookup)
+ throws ReflectiveOperationException {
+ return Enum.valueOf((Class<E>) constantType().resolveConstantDesc(lookup), constantName());
+ }
+
+ @Override
+ public String toString() {
+ return String.format("EnumDesc[%s.%s]", constantType().displayName(), constantName());
+ }
+ }
}
--- a/src/java.base/share/classes/java/lang/Float.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Float.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, 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
@@ -25,6 +25,11 @@
package java.lang;
+import java.lang.invoke.MethodHandles;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
+import java.util.Optional;
+
import jdk.internal.math.FloatingDecimal;
import jdk.internal.HotSpotIntrinsicCandidate;
@@ -45,7 +50,8 @@
* @author Joseph D. Darcy
* @since 1.0
*/
-public final class Float extends Number implements Comparable<Float> {
+public final class Float extends Number
+ implements Comparable<Float>, Constable, ConstantDesc {
/**
* A constant holding the positive infinity of type
* {@code float}. It is equal to the value returned by
@@ -982,6 +988,31 @@
return Math.min(a, b);
}
+ /**
+ * Returns a nominal descriptor for this instance, which is the instance
+ * itself.
+ *
+ * @return an {@link Optional} describing the {@linkplain Float} instance
+ * @since 12
+ */
+ @Override
+ public Optional<Float> describeConstable() {
+ return Optional.of(this);
+ }
+
+ /**
+ * Resolves this instance as a {@link ConstantDesc}, the result of which is
+ * the instance itself.
+ *
+ * @param lookup ignored
+ * @return the {@linkplain Float} instance
+ * @since 12
+ */
+ @Override
+ public Float resolveConstantDesc(MethodHandles.Lookup lookup) {
+ return this;
+ }
+
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -2671257302660747028L;
}
--- a/src/java.base/share/classes/java/lang/Integer.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Integer.java Sun Dec 09 12:36:24 2018 -0500
@@ -26,7 +26,12 @@
package java.lang;
import java.lang.annotation.Native;
+import java.lang.invoke.MethodHandles;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
import java.util.Objects;
+import java.util.Optional;
+
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.VM;
@@ -56,7 +61,8 @@
* @author Joseph D. Darcy
* @since 1.0
*/
-public final class Integer extends Number implements Comparable<Integer> {
+public final class Integer extends Number
+ implements Comparable<Integer>, Constable, ConstantDesc {
/**
* A constant holding the minimum value an {@code int} can
* have, -2<sup>31</sup>.
@@ -1831,6 +1837,31 @@
return Math.min(a, b);
}
+ /**
+ * Returns a nominal descriptor for this instance, which is the instance
+ * itself.
+ *
+ * @return an {@link Optional} describing the {@linkplain Integer} instance
+ * @since 12
+ */
+ @Override
+ public Optional<Integer> describeConstable() {
+ return Optional.of(this);
+ }
+
+ /**
+ * Resolves this instance as a {@link ConstantDesc}, the result of which is
+ * the instance itself.
+ *
+ * @param lookup ignored
+ * @return the {@linkplain Integer} instance
+ * @since 12
+ */
+ @Override
+ public Integer resolveConstantDesc(MethodHandles.Lookup lookup) {
+ return this;
+ }
+
/** use serialVersionUID from JDK 1.0.2 for interoperability */
@Native private static final long serialVersionUID = 1360826667806852920L;
}
--- a/src/java.base/share/classes/java/lang/Long.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/Long.java Sun Dec 09 12:36:24 2018 -0500
@@ -26,8 +26,13 @@
package java.lang;
import java.lang.annotation.Native;
+import java.lang.invoke.MethodHandles;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
import java.math.*;
import java.util.Objects;
+import java.util.Optional;
+
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.VM;
@@ -57,7 +62,8 @@
* @author Joseph D. Darcy
* @since 1.0
*/
-public final class Long extends Number implements Comparable<Long> {
+public final class Long extends Number
+ implements Comparable<Long>, Constable, ConstantDesc {
/**
* A constant holding the minimum value a {@code long} can
* have, -2<sup>63</sup>.
@@ -1960,6 +1966,31 @@
return Math.min(a, b);
}
+ /**
+ * Returns a nominal descriptor for this instance, which is the instance
+ * itself.
+ *
+ * @return an {@link Optional} describing the {@linkplain Long} instance
+ * @since 12
+ */
+ @Override
+ public Optional<Long> describeConstable() {
+ return Optional.of(this);
+ }
+
+ /**
+ * Resolves this instance as a {@link ConstantDesc}, the result of which is
+ * the instance itself.
+ *
+ * @param lookup ignored
+ * @return the {@linkplain Long} instance
+ * @since 12
+ */
+ @Override
+ public Long resolveConstantDesc(MethodHandles.Lookup lookup) {
+ return this;
+ }
+
/** use serialVersionUID from JDK 1.0.2 for interoperability */
@Native private static final long serialVersionUID = 4290774380558885855L;
}
--- a/src/java.base/share/classes/java/lang/String.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/String.java Sun Dec 09 12:36:24 2018 -0500
@@ -28,6 +28,9 @@
import java.io.ObjectStreamField;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Native;
+import java.lang.invoke.MethodHandles;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
@@ -35,6 +38,7 @@
import java.util.Formatter;
import java.util.Locale;
import java.util.Objects;
+import java.util.Optional;
import java.util.Spliterator;
import java.util.StringJoiner;
import java.util.function.Function;
@@ -127,7 +131,8 @@
*/
public final class String
- implements java.io.Serializable, Comparable<String>, CharSequence {
+ implements java.io.Serializable, Comparable<String>, CharSequence,
+ Constable, ConstantDesc {
/**
* The value is used for character storage.
@@ -3538,4 +3543,30 @@
throw new IllegalArgumentException(
format("Not a valid Unicode code point: 0x%X", codePoint));
}
+
+ /**
+ * Returns a nominal descriptor for this instance, which is the instance
+ * itself.
+ *
+ * @return an {@link Optional} describing the {@linkplain String} instance
+ * @since 12
+ */
+ @Override
+ public Optional<String> describeConstable() {
+ return Optional.of(this);
+ }
+
+ /**
+ * Resolves this instance as a {@link ConstantDesc}, the result of which is
+ * the instance itself.
+ *
+ * @param lookup ignored
+ * @return the {@linkplain String} instance
+ * @since 12
+ */
+ @Override
+ public String resolveConstantDesc(MethodHandles.Lookup lookup) {
+ return this;
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/AsTypeMethodHandleDesc.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import static java.lang.constant.ConstantDescs.BSM_INVOKE;
+import static java.lang.constant.ConstantDescs.CD_MethodHandle;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
+ * {@link MethodHandle} constant that performs a {@link MethodHandle#asType(MethodType)}
+ * adaptation on another {@link MethodHandle}.
+ */
+final class AsTypeMethodHandleDesc extends DynamicConstantDesc<MethodHandle>
+ implements MethodHandleDesc {
+
+ private final MethodHandleDesc underlying;
+ private final MethodTypeDesc type;
+
+ AsTypeMethodHandleDesc(MethodHandleDesc underlying, MethodTypeDesc type) {
+ super(BSM_INVOKE, ConstantDescs.DEFAULT_NAME, CD_MethodHandle,
+ ConstantDescs.MHD_METHODHANDLE_ASTYPE, underlying, type);
+ this.underlying = requireNonNull(underlying);
+ this.type = requireNonNull(type);
+ }
+
+ @Override
+ public MethodTypeDesc invocationType() {
+ return type;
+ }
+
+ @Override
+ public MethodHandle resolveConstantDesc(MethodHandles.Lookup lookup)
+ throws ReflectiveOperationException {
+ MethodHandle handle = (MethodHandle) underlying.resolveConstantDesc(lookup);
+ MethodType methodType = (MethodType) type.resolveConstantDesc(lookup);
+ return handle.asType(methodType);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s.asType%s", underlying.toString(), type.displayDescriptor());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.TypeDescriptor;
+import java.util.stream.Stream;
+
+import sun.invoke.util.Wrapper;
+
+import static java.lang.constant.ConstantUtils.binaryToInternal;
+import static java.lang.constant.ConstantUtils.dropLastChar;
+import static java.lang.constant.ConstantUtils.internalToBinary;
+import static java.lang.constant.ConstantUtils.validateMemberName;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
+ * {@link Class} constant.
+ *
+ * <p>For common system types, including all the primitive types, there are
+ * predefined {@linkplain ClassDesc} constants in {@link ConstantDescs}.
+ * (The {@code java.lang.constant} APIs consider {@code void} to be a primitive type.)
+ * To create a {@linkplain ClassDesc} for a class or interface type, use {@link #of} or
+ * {@link #ofDescriptor(String)}; to create a {@linkplain ClassDesc} for an array
+ * type, use {@link #ofDescriptor(String)}, or first obtain a
+ * {@linkplain ClassDesc} for the component type and then call the {@link #arrayType()}
+ * or {@link #arrayType(int)} methods.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain ClassDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except
+ * by explicitly permitted types. Non-platform classes should not implement
+ * {@linkplain ClassDesc} directly.
+ *
+ * @see ConstantDescs
+ *
+ * @since 12
+ */
+public interface ClassDesc
+ extends ConstantDesc,
+ TypeDescriptor.OfField<ClassDesc> {
+
+ /**
+ * Returns a {@linkplain ClassDesc} for a class or interface type,
+ * given the name of the class or interface, such as {@code "java.lang.String"}.
+ * (To create a descriptor for an array type, either use {@link #ofDescriptor(String)}
+ * or {@link #arrayType()}; to create a descriptor for a primitive type, use
+ * {@link #ofDescriptor(String)} or use the predefined constants in
+ * {@link ConstantDescs}).
+ *
+ * @param name the fully qualified (dot-separated) binary class name
+ * @return a {@linkplain ClassDesc} describing the desired class
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IllegalArgumentException if the name string is not in the
+ * correct format
+ */
+ static ClassDesc of(String name) {
+ ConstantUtils.validateBinaryClassName(requireNonNull(name));
+ return ClassDesc.ofDescriptor("L" + binaryToInternal(name) + ";");
+ }
+
+ /**
+ * Returns a {@linkplain ClassDesc} for a class or interface type,
+ * given a package name and the unqualified (simple) name for the
+ * class or interface.
+ *
+ * @param packageName the package name (dot-separated); if the package
+ * name is the empty string, the class is considered to
+ * be in the unnamed package
+ * @param className the unqualified (simple) class name
+ * @return a {@linkplain ClassDesc} describing the desired class
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IllegalArgumentException if the package name or class name are
+ * not in the correct format
+ */
+ static ClassDesc of(String packageName, String className) {
+ ConstantUtils.validateBinaryClassName(requireNonNull(packageName));
+ validateMemberName(requireNonNull(className));
+ return ofDescriptor(String.format("L%s%s%s;",
+ binaryToInternal(packageName),
+ (packageName.length() > 0 ? "/" : ""),
+ className));
+ }
+
+ /**
+ * Returns a {@linkplain ClassDesc} given a descriptor string for a class,
+ * interface, array, or primitive type.
+ *
+ * @apiNote
+ *
+ * A field type descriptor string for a non-array type is either
+ * a one-letter code corresponding to a primitive type
+ * ({@code J,I,C,S,B,D,F,Z,V}), or the letter {@code L}, followed
+ * by the fully qualified binary name of a class, followed by {@code ;}.
+ * A field type descriptor for an array type is the character {@code [}
+ * followed by the field descriptor for the component type. Examples of
+ * valid type descriptor strings include {@code Ljava/lang/String;}, {@code I},
+ * {@code [I}, {@code V}, {@code [Ljava/lang/String;}, etc.
+ * for more detail.
+ *
+ * @param descriptor a field descriptor string
+ * @return a {@linkplain ClassDesc} describing the desired class
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IllegalArgumentException if the name string is not in the
+ * correct format
+ * @jvms 4.3.2 Field Descriptors
+ */
+ static ClassDesc ofDescriptor(String descriptor) {
+ requireNonNull(descriptor);
+ return (descriptor.length() == 1)
+ ? new PrimitiveClassDescImpl(descriptor)
+ : new ReferenceClassDescImpl(descriptor);
+ }
+
+ /**
+ * Returns a {@linkplain ClassDesc} for an array type whose component type
+ * is described by this {@linkplain ClassDesc}.
+ *
+ * @return a {@linkplain ClassDesc} describing the array type
+ */
+ default ClassDesc arrayType() {
+ return arrayType(1);
+ }
+
+ /**
+ * Returns a {@linkplain ClassDesc} for an array type of the specified rank,
+ * whose component type is described by this {@linkplain ClassDesc}.
+ *
+ * @param rank the rank of the array
+ * @return a {@linkplain ClassDesc} describing the array type
+ * @throws IllegalArgumentException if the rank is zero or negative
+ */
+ default ClassDesc arrayType(int rank) {
+ if (rank <= 0)
+ throw new IllegalArgumentException("rank: " + rank);
+ return ClassDesc.ofDescriptor("[".repeat(rank) + descriptorString());
+ }
+
+ /**
+ * Returns a {@linkplain ClassDesc} for a nested class of the class or
+ * interface type described by this {@linkplain ClassDesc}.
+ *
+ * @param nestedName the unqualified name of the nested class
+ * @return a {@linkplain ClassDesc} describing the nested class
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IllegalStateException if this {@linkplain ClassDesc} does not
+ * describe a class or interface type
+ * @throws IllegalArgumentException if the nested class name is invalid
+ */
+ default ClassDesc nested(String nestedName) {
+ validateMemberName(nestedName);
+ if (!isClassOrInterface())
+ throw new IllegalStateException("Outer class is not a class or interface type");
+ return ClassDesc.ofDescriptor(String.format("%s$%s;", dropLastChar(descriptorString()), nestedName));
+ }
+
+ /**
+ * Returns a {@linkplain ClassDesc} for a nested class of the class or
+ * interface type described by this {@linkplain ClassDesc}.
+ *
+ * @param firstNestedName the unqualified name of the first level of nested class
+ * @param moreNestedNames the unqualified name(s) of the remaining levels of
+ * nested class
+ * @return a {@linkplain ClassDesc} describing the nested class
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IllegalStateException if this {@linkplain ClassDesc} does not
+ * describe a class or interface type
+ * @throws IllegalArgumentException if the nested class name is invalid
+ */
+ default ClassDesc nested(String firstNestedName, String... moreNestedNames) {
+ if (!isClassOrInterface())
+ throw new IllegalStateException("Outer class is not a class or interface type");
+ return moreNestedNames.length == 0
+ ? nested(firstNestedName)
+ : nested(firstNestedName + Stream.of(moreNestedNames).collect(joining("$", "$", "")));
+ }
+
+ /**
+ * Returns whether this {@linkplain ClassDesc} describes an array type.
+ *
+ * @return whether this {@linkplain ClassDesc} describes an array type
+ */
+ default boolean isArray() {
+ return descriptorString().startsWith("[");
+ }
+
+ /**
+ * Returns whether this {@linkplain ClassDesc} describes a primitive type.
+ *
+ * @return whether this {@linkplain ClassDesc} describes a primitive type
+ */
+ default boolean isPrimitive() {
+ return descriptorString().length() == 1;
+ }
+
+ /**
+ * Returns whether this {@linkplain ClassDesc} describes a class or interface type.
+ *
+ * @return whether this {@linkplain ClassDesc} describes a class or interface type
+ */
+ default boolean isClassOrInterface() {
+ return descriptorString().startsWith("L");
+ }
+
+ /**
+ * Returns the component type of this {@linkplain ClassDesc}, if it describes
+ * an array type, or {@code null} otherwise.
+ *
+ * @return a {@linkplain ClassDesc} describing the component type, or {@code null}
+ * if this descriptor does not describe an array type
+ */
+ default ClassDesc componentType() {
+ return isArray() ? ClassDesc.ofDescriptor(descriptorString().substring(1)) : null;
+ }
+
+ /**
+ * Returns the package name of this {@linkplain ClassDesc}, if it describes
+ * a class or interface type.
+ *
+ * @return the package name, or the empty string if the class is in the
+ * default package, or this {@linkplain ClassDesc} does not describe a class or interface type
+ */
+ default String packageName() {
+ if (!isClassOrInterface())
+ return "";
+ String className = internalToBinary(ConstantUtils.dropFirstAndLastChar(descriptorString()));
+ int index = className.lastIndexOf('.');
+ return (index == -1) ? "" : className.substring(0, index);
+ }
+
+ /**
+ * Returns a human-readable name for the type described by this descriptor.
+ *
+ * @implSpec
+ * <p>The default implementation returns the simple name
+ * (e.g., {@code int}) for primitive types, the unqualified class name
+ * for class or interface types, or the display name of the component type
+ * suffixed with the appropriate number of {@code []} pairs for array types.
+ *
+ * @return the human-readable name
+ */
+ default String displayName() {
+ if (isPrimitive())
+ return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveSimpleName();
+ else if (isClassOrInterface()) {
+ return descriptorString().substring(Math.max(1, descriptorString().lastIndexOf('/') + 1),
+ descriptorString().length() - 1);
+ }
+ else if (isArray()) {
+ int depth = ConstantUtils.arrayDepth(descriptorString());
+ ClassDesc c = this;
+ for (int i=0; i<depth; i++)
+ c = c.componentType();
+ return c.displayName() + "[]".repeat(depth);
+ }
+ else
+ throw new IllegalStateException(descriptorString());
+ }
+
+ /**
+ * Returns a field type descriptor string for this type
+ *
+ * @return the descriptor string
+ * @jvms 4.3.2 Field Descriptors
+ */
+ String descriptorString();
+
+ /**
+ * Compare the specified object with this descriptor for equality. Returns
+ * {@code true} if and only if the specified object is also a
+ * {@linkplain ClassDesc} and both describe the same type.
+ *
+ * @param o the other object
+ * @return whether this descriptor is equal to the other object
+ */
+ boolean equals(Object o);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/Constable.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.util.Optional;
+
+/**
+ * Represents a type which is <em>constable</em>. A constable type is one whose
+ * values are constants that can be represented in the constant pool of a Java
+ * classfile as described in JVMS 4.4, and whose instances can describe themselves
+ * nominally as a {@link ConstantDesc}.
+ *
+ * <p>Some constable types have a native representation in the constant pool:
+ * {@link String}, {@link Integer}, {@link Long}, {@link Float},
+ * {@link Double}, {@link Class}, {@link MethodType}, and {@link MethodHandle}.
+ * The types {@link String}, {@link Integer}, {@link Long}, {@link Float},
+ * and {@link Double} serve as their own nominal descriptors; {@link Class},
+ * {@link MethodType}, and {@link MethodHandle} have corresponding nominal
+ * descriptors {@link ClassDesc}, {@link MethodTypeDesc}, and {@link MethodHandleDesc}.
+ *
+ * <p>Other reference types can be constable if their instances can describe
+ * themselves in nominal form as a {@link ConstantDesc}. Examples in the Java SE
+ * Platform API are types that support Java language features such as {@link Enum},
+ * and runtime support classes such as {@link VarHandle}. These are typically
+ * described with a {@link DynamicConstantDesc}, which describes dynamically
+ * generated constants (JVMS 4.4.10).
+ *
+ * <p>The nominal form of an instance of a constable type is obtained via
+ * {@link #describeConstable()}. A {@linkplain Constable} need
+ * not be able to (or may choose not to) describe all its instances in the form of
+ * a {@link ConstantDesc}; this method returns an {@link Optional} that can be
+ * empty to indicate that a nominal descriptor could not be created for an instance.
+ * (For example, {@link MethodHandle} will produce nominal descriptors for direct
+ * method handles, but not necessarily those produced by method handle
+ * combinators.)
+ * @jvms 4.4 The Constant Pool
+ * @jvms 4.4.10 The CONSTANT_InvokeDynamic_info Structure
+ *
+ * @since 12
+ */
+public interface Constable {
+ /**
+ * Returns a nominal descriptor for this instance, if one can be
+ * constructed, or an empty {@link Optional} if one cannot be constructed.
+ *
+ * @return An {@link Optional} containing the resulting nominal descriptor,
+ * or an empty {@link Optional} if one cannot be constructed.
+ */
+ Optional<? extends ConstantDesc> describeConstable();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/ConstantDesc.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.Enum.EnumDesc;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle.VarHandleDesc;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a loadable
+ * constant value, as defined in JVMS 4.4. Such a descriptor can be resolved via
+ * {@link ConstantDesc#resolveConstantDesc(MethodHandles.Lookup)} to yield the
+ * constant value itself.
+ *
+ * <p>Class names in a nominal descriptor, like class names in the constant pool
+ * of a classfile, must be interpreted with respect to a particular class
+ * loader, which is not part of the nominal descriptor.
+ *
+ * <p>Static constants that are expressible natively in the constant pool ({@link String},
+ * {@link Integer}, {@link Long}, {@link Float}, and {@link Double}) implement
+ * {@link ConstantDesc}, and serve as nominal descriptors for themselves.
+ * Native linkable constants ({@link Class}, {@link MethodType}, and
+ * {@link MethodHandle}) have counterpart {@linkplain ConstantDesc} types:
+ * {@link ClassDesc}, {@link MethodTypeDesc}, and {@link MethodHandleDesc}.
+ * Other constants are represented by subtypes of {@link DynamicConstantDesc}.
+ *
+ * <p>APIs that perform generation or parsing of bytecode are encouraged to use
+ * {@linkplain ConstantDesc} to describe the operand of an {@code ldc} instruction
+ * (including dynamic constants), the static bootstrap arguments of
+ * dynamic constants and {@code invokedynamic} instructions, and other
+ * bytecodes or classfile structures that make use of the constant pool.
+ *
+ * <p>Constants describing various common constants (such as {@link ClassDesc}
+ * instances for platform types) can be found in {@link ConstantDescs}.
+ *
+ * <p>Implementations of {@linkplain ConstantDesc} must be
+ * <a href="../doc-files/ValueBased.html">value-based</a> classes.
+ *
+ * <p>Non-platform classes should not implement {@linkplain ConstantDesc} directly.
+ * Instead, they should extend {@link DynamicConstantDesc} (as {@link EnumDesc}
+ * and {@link VarHandleDesc} do.)
+ *
+ * <p>Nominal descriptors should be compared using the
+ * {@link Object#equals(Object)} method. There is no guarantee that any
+ * particular entity will always be represented by the same descriptor instance.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain ConstantDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except by
+ * explicitly permitted types. Clients can assume that the following
+ * set of subtypes is exhaustive: {@link String}, {@link Integer},
+ * {@link Long}, {@link Float}, {@link Double}, {@link ClassDesc},
+ * {@link MethodTypeDesc}, {@link MethodHandleDesc}, and
+ * {@link DynamicConstantDesc}; this list may be extended to reflect future
+ * changes to the constant pool format as defined in JVMS 4.4.
+ *
+ * @see Constable
+ * @see ConstantDescs
+ *
+ * @jvms 4.4 The Constant Pool
+ *
+ * @since 12
+ */
+public interface ConstantDesc {
+ /**
+ * Resolves this descriptor reflectively, emulating the resolution behavior
+ * of JVMS 5.4.3 and the access control behavior of JVMS 5.4.4. The resolution
+ * and access control context is provided by the {@link MethodHandles.Lookup}
+ * parameter. No caching of the resulting value is performed.
+ *
+ * @param lookup The {@link MethodHandles.Lookup} to provide name resolution
+ * and access control context
+ * @return the resolved constant value
+ * @throws ReflectiveOperationException if a class, method, or field
+ * could not be reflectively resolved in the course of resolution
+ * @throws LinkageError if a linkage error occurs
+ * @jvms 5.4.3 Resolution
+ * @jvms 5.4.4 Access Control
+ */
+ Object resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/ConstantDescs.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.Enum.EnumDesc;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantBootstraps;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.VarHandle.VarHandleDesc;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static java.lang.constant.DirectMethodHandleDesc.*;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC;
+
+/**
+ * Predefined values of <a href="package-summary.html#nominal">nominal descriptor</a>
+ * for common constants, including descriptors for primitive class types and
+ * other common platform types, and descriptors for method handles for standard
+ * bootstrap methods.
+ *
+ * @see ConstantDesc
+ *
+ * @since 12
+ */
+public final class ConstantDescs {
+ // No instances
+ private ConstantDescs() { }
+
+ /** Invocation name to use when no name is needed, such as the name of a
+ * constructor, or the invocation name of a dynamic constant or dynamic
+ * callsite when the bootstrap is known to ignore the invocation name.
+ */
+ public static final String DEFAULT_NAME = "_";
+
+ // Don't change the order of these declarations!
+
+ /** {@link ClassDesc} representing {@link Object} */
+ public static final ClassDesc CD_Object = ClassDesc.of("java.lang.Object");
+
+ /** {@link ClassDesc} representing {@link String} */
+ public static final ClassDesc CD_String = ClassDesc.of("java.lang.String");
+
+ /** {@link ClassDesc} representing {@link Class} */
+ public static final ClassDesc CD_Class = ClassDesc.of("java.lang.Class");
+
+ /** {@link ClassDesc} representing {@link Number} */
+ public static final ClassDesc CD_Number = ClassDesc.of("java.lang.Number");
+
+ /** {@link ClassDesc} representing {@link Integer} */
+ public static final ClassDesc CD_Integer = ClassDesc.of("java.lang.Integer");
+
+ /** {@link ClassDesc} representing {@link Long} */
+ public static final ClassDesc CD_Long = ClassDesc.of("java.lang.Long");
+
+ /** {@link ClassDesc} representing {@link Float} */
+ public static final ClassDesc CD_Float = ClassDesc.of("java.lang.Float");
+
+ /** {@link ClassDesc} representing {@link Double} */
+ public static final ClassDesc CD_Double = ClassDesc.of("java.lang.Double");
+
+ /** {@link ClassDesc} representing {@link Short} */
+ public static final ClassDesc CD_Short = ClassDesc.of("java.lang.Short");
+
+ /** {@link ClassDesc} representing {@link Byte} */
+ public static final ClassDesc CD_Byte = ClassDesc.of("java.lang.Byte");
+
+ /** {@link ClassDesc} representing {@link Character} */
+ public static final ClassDesc CD_Character = ClassDesc.of("java.lang.Character");
+
+ /** {@link ClassDesc} representing {@link Boolean} */
+ public static final ClassDesc CD_Boolean = ClassDesc.of("java.lang.Boolean");
+
+ /** {@link ClassDesc} representing {@link Void} */
+ public static final ClassDesc CD_Void = ClassDesc.of("java.lang.Void");
+
+ /** {@link ClassDesc} representing {@link Throwable} */
+ public static final ClassDesc CD_Throwable = ClassDesc.of("java.lang.Throwable");
+
+ /** {@link ClassDesc} representing {@link Exception} */
+ public static final ClassDesc CD_Exception = ClassDesc.of("java.lang.Exception");
+
+ /** {@link ClassDesc} representing {@link Enum} */
+ public static final ClassDesc CD_Enum = ClassDesc.of("java.lang.Enum");
+
+ /** {@link ClassDesc} representing {@link VarHandle} */
+ public static final ClassDesc CD_VarHandle = ClassDesc.of("java.lang.invoke.VarHandle");
+
+ /** {@link ClassDesc} representing {@link MethodHandles} */
+ public static final ClassDesc CD_MethodHandles = ClassDesc.of("java.lang.invoke.MethodHandles");
+
+ /** {@link ClassDesc} representing {@link MethodHandles.Lookup} */
+ public static final ClassDesc CD_MethodHandles_Lookup = CD_MethodHandles.nested("Lookup");
+
+ /** {@link ClassDesc} representing {@link MethodHandle} */
+ public static final ClassDesc CD_MethodHandle = ClassDesc.of("java.lang.invoke.MethodHandle");
+
+ /** {@link ClassDesc} representing {@link MethodType} */
+ public static final ClassDesc CD_MethodType = ClassDesc.of("java.lang.invoke.MethodType");
+
+ /** {@link ClassDesc} representing {@link CallSite} */
+ public static final ClassDesc CD_CallSite = ClassDesc.of("java.lang.invoke.CallSite");
+
+ /** {@link ClassDesc} representing {@link Collection} */
+ public static final ClassDesc CD_Collection = ClassDesc.of("java.util.Collection");
+
+ /** {@link ClassDesc} representing {@link List} */
+ public static final ClassDesc CD_List = ClassDesc.of("java.util.List");
+
+ /** {@link ClassDesc} representing {@link Set} */
+ public static final ClassDesc CD_Set = ClassDesc.of("java.util.Set");
+
+ /** {@link ClassDesc} representing {@link Map} */
+ public static final ClassDesc CD_Map = ClassDesc.of("java.util.Map");
+
+ /** {@link ClassDesc} representing {@link ConstantDesc} */
+ public static final ClassDesc CD_ConstantDesc = ClassDesc.of("java.lang.constant.ConstantDesc");
+
+ /** {@link ClassDesc} representing {@link ClassDesc} */
+ public static final ClassDesc CD_ClassDesc = ClassDesc.of("java.lang.constant.ClassDesc");
+
+ /** {@link ClassDesc} representing {@link EnumDesc} */
+ public static final ClassDesc CD_EnumDesc = CD_Enum.nested("EnumDesc");
+
+ /** {@link ClassDesc} representing {@link MethodTypeDesc} */
+ public static final ClassDesc CD_MethodTypeDesc = ClassDesc.of("java.lang.constant.MethodTypeDesc");
+
+ /** {@link ClassDesc} representing {@link MethodHandleDesc} */
+ public static final ClassDesc CD_MethodHandleDesc = ClassDesc.of("java.lang.constant.MethodHandleDesc");
+
+ /** {@link ClassDesc} representing {@link DirectMethodHandleDesc} */
+ public static final ClassDesc CD_DirectMethodHandleDesc = ClassDesc.of("java.lang.constant.DirectMethodHandleDesc");
+
+ /** {@link ClassDesc} representing {@link VarHandleDesc} */
+ public static final ClassDesc CD_VarHandleDesc = CD_VarHandle.nested("VarHandleDesc");
+
+ /** {@link ClassDesc} representing {@link DirectMethodHandleDesc.Kind} */
+ public static final ClassDesc CD_MethodHandleDesc_Kind = CD_DirectMethodHandleDesc.nested("Kind");
+
+ /** {@link ClassDesc} representing {@link DynamicConstantDesc} */
+ public static final ClassDesc CD_DynamicConstantDesc = ClassDesc.of("java.lang.constant.DynamicConstantDesc");
+
+ /** {@link ClassDesc} representing {@link DynamicCallSiteDesc} */
+ public static final ClassDesc CD_DynamicCallSiteDesc = ClassDesc.of("java.lang.constant.DynamicCallSiteDesc");
+
+ /** {@link ClassDesc} representing {@link ConstantBootstraps} */
+ public static final ClassDesc CD_ConstantBootstraps = ClassDesc.of("java.lang.invoke.ConstantBootstraps");
+
+ private static final ClassDesc[] INDY_BOOTSTRAP_ARGS = {
+ ConstantDescs.CD_MethodHandles_Lookup,
+ ConstantDescs.CD_String,
+ ConstantDescs.CD_MethodType};
+
+ private static final ClassDesc[] CONDY_BOOTSTRAP_ARGS = {
+ ConstantDescs.CD_MethodHandles_Lookup,
+ ConstantDescs.CD_String,
+ ConstantDescs.CD_Class};
+
+ /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#primitiveClass(Lookup, String, Class) ConstantBootstraps.primitiveClass} */
+ public static final DirectMethodHandleDesc BSM_PRIMITIVE_CLASS
+ = ofConstantBootstrap(CD_ConstantBootstraps, "primitiveClass",
+ CD_Class);
+
+ /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#enumConstant(Lookup, String, Class) ConstantBootstraps.enumConstant} */
+ public static final DirectMethodHandleDesc BSM_ENUM_CONSTANT
+ = ofConstantBootstrap(CD_ConstantBootstraps, "enumConstant",
+ CD_Enum);
+
+ /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#nullConstant(Lookup, String, Class) ConstantBootstraps.nullConstant} */
+ public static final DirectMethodHandleDesc BSM_NULL_CONSTANT
+ = ofConstantBootstrap(CD_ConstantBootstraps, "nullConstant",
+ ConstantDescs.CD_Object);
+
+ /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#fieldVarHandle(Lookup, String, Class, Class, Class) ConstantBootstraps.fieldVarHandle} */
+ public static final DirectMethodHandleDesc BSM_VARHANDLE_FIELD
+ = ofConstantBootstrap(CD_ConstantBootstraps, "fieldVarHandle",
+ CD_VarHandle, CD_Class, CD_Class);
+
+ /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#staticFieldVarHandle(Lookup, String, Class, Class, Class) ConstantBootstraps.staticVarHandle} */
+ public static final DirectMethodHandleDesc BSM_VARHANDLE_STATIC_FIELD
+ = ofConstantBootstrap(CD_ConstantBootstraps, "staticFieldVarHandle",
+ CD_VarHandle, CD_Class, CD_Class);
+
+ /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#arrayVarHandle(Lookup, String, Class, Class) ConstantBootstraps.arrayVarHandle} */
+ public static final DirectMethodHandleDesc BSM_VARHANDLE_ARRAY
+ = ofConstantBootstrap(CD_ConstantBootstraps, "arrayVarHandle",
+ CD_VarHandle, CD_Class);
+
+ /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#invoke(Lookup, String, Class, MethodHandle, Object...) ConstantBootstraps.invoke} */
+ public static final DirectMethodHandleDesc BSM_INVOKE
+ = ofConstantBootstrap(CD_ConstantBootstraps, "invoke",
+ CD_Object, CD_MethodHandle, CD_Object.arrayType());
+
+ /** {@link ClassDesc} representing the primitive type {@code int} */
+ public static final ClassDesc CD_int = ClassDesc.ofDescriptor("I");
+
+ /** {@link ClassDesc} representing the primitive type {@code long} */
+ public static final ClassDesc CD_long = ClassDesc.ofDescriptor("J");
+
+ /** {@link ClassDesc} representing the primitive type {@code float} */
+ public static final ClassDesc CD_float = ClassDesc.ofDescriptor("F");
+
+ /** {@link ClassDesc} representing the primitive type {@code double} */
+ public static final ClassDesc CD_double = ClassDesc.ofDescriptor("D");
+
+ /** {@link ClassDesc} representing the primitive type {@code short} */
+ public static final ClassDesc CD_short = ClassDesc.ofDescriptor("S");
+
+ /** {@link ClassDesc} representing the primitive type {@code byte} */
+ public static final ClassDesc CD_byte = ClassDesc.ofDescriptor("B");
+
+ /** {@link ClassDesc} representing the primitive type {@code char} */
+ public static final ClassDesc CD_char = ClassDesc.ofDescriptor("C");
+
+ /** {@link ClassDesc} representing the primitive type {@code boolean} */
+ public static final ClassDesc CD_boolean = ClassDesc.ofDescriptor("Z");
+
+ /** {@link ClassDesc} representing the primitive type {@code void} */
+ public static final ClassDesc CD_void = ClassDesc.ofDescriptor("V");
+
+ /** Nominal descriptor representing the constant {@code null} */
+ public static final ConstantDesc NULL
+ = DynamicConstantDesc.ofNamed(ConstantDescs.BSM_NULL_CONSTANT,
+ DEFAULT_NAME, ConstantDescs.CD_Object);
+
+ static final DirectMethodHandleDesc MHD_METHODHANDLE_ASTYPE
+ = MethodHandleDesc.ofMethod(Kind.VIRTUAL, CD_MethodHandle, "asType",
+ MethodTypeDesc.of(CD_MethodHandle, CD_MethodType));
+ /**
+ * Returns a {@link MethodHandleDesc} corresponding to a bootstrap method for
+ * an {@code invokedynamic} callsite, which is a static method whose leading
+ * parameter types are {@code Lookup}, {@code String}, and {@code MethodType}.
+ *
+ * @param owner the class declaring the method
+ * @param name the unqualified name of the method
+ * @param returnType the return type of the method
+ * @param paramTypes the types of the static bootstrap arguments, if any
+ * @return the {@link MethodHandleDesc}
+ * @throws NullPointerException if any of the arguments are null
+ * @jvms 4.2.2 Unqualified Names
+ */
+ public static DirectMethodHandleDesc ofCallsiteBootstrap(ClassDesc owner,
+ String name,
+ ClassDesc returnType,
+ ClassDesc... paramTypes) {
+ return MethodHandleDesc.ofMethod(STATIC, owner, name, MethodTypeDesc.of(returnType, paramTypes)
+ .insertParameterTypes(0, INDY_BOOTSTRAP_ARGS));
+ }
+
+ /**
+ * Returns a {@link MethodHandleDesc} corresponding to a bootstrap method for a
+ * dynamic constant, which is a static method whose leading arguments are
+ * {@code Lookup}, {@code String}, and {@code Class}.
+ *
+ * @param owner the class declaring the method
+ * @param name the unqualified name of the method
+ * @param returnType the return type of the method
+ * @param paramTypes the types of the static bootstrap arguments, if any
+ * @return the {@link MethodHandleDesc}
+ * @throws NullPointerException if any of the arguments are null
+ * @jvms 4.2.2 Unqualified Names
+ */
+ public static DirectMethodHandleDesc ofConstantBootstrap(ClassDesc owner,
+ String name,
+ ClassDesc returnType,
+ ClassDesc... paramTypes) {
+ return MethodHandleDesc.ofMethod(STATIC, owner, name, MethodTypeDesc.of(returnType, paramTypes)
+ .insertParameterTypes(0, CONDY_BOOTSTRAP_ARGS));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/ConstantUtils.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Helper methods for the implementation of {@code java.lang.constant}.
+ */
+class ConstantUtils {
+ /** an empty constant descriptor */
+ public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0];
+ static final Constable[] EMPTY_CONSTABLE = new Constable[0];
+
+ private static final Set<String> pointyNames = Set.of("<init>", "<clinit>");
+
+ /**
+ * Validates the correctness of a binary class name. In particular checks for the presence of
+ * invalid characters in the name.
+ *
+ * @param name the class name
+ * @return the class name passed if valid
+ * @throws IllegalArgumentException if the class name is invalid
+ */
+ static String validateBinaryClassName(String name) {
+ for (int i=0; i<name.length(); i++) {
+ char ch = name.charAt(i);
+ if (ch == ';' || ch == '[' || ch == '/')
+ throw new IllegalArgumentException("Invalid class name: " + name);
+ }
+ return name;
+ }
+
+ /**
+ * Validates a member name
+ *
+ * @param name the name of the member
+ * @return the name passed if valid
+ * @throws IllegalArgumentException if the member name is invalid
+ */
+ public static String validateMemberName(String name) {
+ requireNonNull(name);
+ if (name.length() == 0)
+ throw new IllegalArgumentException("zero-length member name");
+ for (int i=0; i<name.length(); i++) {
+ char ch = name.charAt(i);
+ if (ch == '.' || ch == ';' || ch == '[' || ch == '/')
+ throw new IllegalArgumentException("Invalid member name: " + name);
+ if (ch == '<' || ch == '>') {
+ if (!pointyNames.contains(name))
+ throw new IllegalArgumentException("Invalid member name: " + name);
+ }
+ }
+ return name;
+ }
+
+ static void validateClassOrInterface(ClassDesc classDesc) {
+ if (!classDesc.isClassOrInterface())
+ throw new IllegalArgumentException("not a class or interface type: " + classDesc);
+ }
+
+ static int arrayDepth(String descriptorString) {
+ int depth = 0;
+ while (descriptorString.charAt(depth) == '[')
+ depth++;
+ return depth;
+ }
+
+ static String binaryToInternal(String name) {
+ return name.replace('.', '/');
+ }
+
+ static String internalToBinary(String name) {
+ return name.replace('/', '.');
+ }
+
+ static String dropLastChar(String s) {
+ return s.substring(0, s.length() - 1);
+ }
+
+ static String dropFirstAndLastChar(String s) {
+ return s.substring(1, s.length() - 1);
+ }
+
+ /**
+ * Parses a method descriptor string, and return a list of field descriptor
+ * strings, return type first, then parameter types
+ *
+ * @param descriptor the descriptor string
+ * @return the list of types
+ * @throws IllegalArgumentException if the descriptor string is not valid
+ */
+ static List<String> parseMethodDescriptor(String descriptor) {
+ int cur = 0, end = descriptor.length();
+ ArrayList<String> ptypes = new ArrayList<>();
+
+ if (cur >= end || descriptor.charAt(cur) != '(')
+ throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
+
+ ++cur; // skip '('
+ while (cur < end && descriptor.charAt(cur) != ')') {
+ int len = matchSig(descriptor, cur, end);
+ if (len == 0 || descriptor.charAt(cur) == 'V')
+ throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
+ ptypes.add(descriptor.substring(cur, cur + len));
+ cur += len;
+ }
+ if (cur >= end)
+ throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
+ ++cur; // skip ')'
+
+ int rLen = matchSig(descriptor, cur, end);
+ if (rLen == 0 || cur + rLen != end)
+ throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
+ ptypes.add(0, descriptor.substring(cur, cur + rLen));
+ return ptypes;
+ }
+
+ /**
+ * Validates that the characters at [start, end) within the provided string
+ * describe a valid field type descriptor.
+ *
+ * @param str the descriptor string
+ * @param start the starting index into the string
+ * @param end the ending index within the string
+ * @return the length of the descriptor, or 0 if it is not a descriptor
+ * @throws IllegalArgumentException if the descriptor string is not valid
+ */
+ static int matchSig(String str, int start, int end) {
+ if (start >= end || start >= str.length() || end > str.length())
+ return 0;
+ char c = str.charAt(start);
+ if (c == 'L') {
+ int endc = str.indexOf(';', start);
+ int badc = str.indexOf('.', start);
+ if (badc >= 0 && badc < endc)
+ return 0;
+ badc = str.indexOf('[', start);
+ if (badc >= 0 && badc < endc)
+ return 0;
+ return (endc < 0) ? 0 : endc - start + 1;
+ } else if (c == '[') {
+ int t = matchSig(str, start+1, end);
+ return (t > 0) ? t + 1 : 0;
+ } else {
+ return ("IJCSBFDZV".indexOf(c) >= 0) ? 1 : 0;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/DirectMethodHandleDesc.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.util.OptionalInt;
+import java.util.stream.Stream;
+
+import jdk.internal.vm.annotation.Stable;
+
+import static java.lang.invoke.MethodHandleInfo.REF_getField;
+import static java.lang.invoke.MethodHandleInfo.REF_getStatic;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeInterface;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeSpecial;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic;
+import static java.lang.invoke.MethodHandleInfo.REF_invokeVirtual;
+import static java.lang.invoke.MethodHandleInfo.REF_newInvokeSpecial;
+import static java.lang.invoke.MethodHandleInfo.REF_putField;
+import static java.lang.invoke.MethodHandleInfo.REF_putStatic;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct
+ * {@link MethodHandle}. A {@linkplain DirectMethodHandleDesc} corresponds to
+ * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain DirectMethodHandleDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except
+ * by explicitly permitted types. Non-platform classes should not implement
+ * {@linkplain DirectMethodHandleDesc} directly.
+ *
+ * @since 12
+ */
+public interface DirectMethodHandleDesc extends MethodHandleDesc {
+ /**
+ * Kinds of method handles that can be described with {@linkplain DirectMethodHandleDesc}.
+ *
+ * @since 12
+ */
+ enum Kind {
+ /** A method handle for a method invoked as with {@code invokestatic} */
+ STATIC(REF_invokeStatic),
+ /** A method handle for a method invoked as with {@code invokestatic} */
+ INTERFACE_STATIC(REF_invokeStatic, true),
+ /** A method handle for a method invoked as with {@code invokevirtual} */
+ VIRTUAL(REF_invokeVirtual),
+ /** A method handle for a method invoked as with {@code invokeinterface} */
+ INTERFACE_VIRTUAL(REF_invokeInterface, true),
+ /** A method handle for a method invoked as with {@code invokespecial} */
+ SPECIAL(REF_invokeSpecial),
+ /** A method handle for an interface method invoked as with {@code invokespecial} */
+ INTERFACE_SPECIAL(REF_invokeSpecial, true),
+ /** A method handle for a constructor */
+ CONSTRUCTOR(REF_newInvokeSpecial),
+ /** A method handle for a read accessor for an instance field */
+ GETTER(REF_getField),
+ /** A method handle for a write accessor for an instance field */
+ SETTER(REF_putField),
+ /** A method handle for a read accessor for a static field */
+ STATIC_GETTER(REF_getStatic),
+ /** A method handle for a write accessor for a static field */
+ STATIC_SETTER(REF_putStatic);
+
+ /** The corresponding {@code refKind} value for this kind of method handle,
+ * as defined by {@link MethodHandleInfo}
+ */
+ public final int refKind;
+
+ /** Is this an interface
+ */
+ public final boolean isInterface;
+ Kind(int refKind) {
+ this(refKind, false);
+ }
+
+ Kind(int refKind, boolean isInterface) { this.refKind = refKind; this.isInterface = isInterface; }
+
+ /**
+ * Returns the enumeration member with the given {@code refKind} field.
+ * Behaves as if {@code valueOf(refKind, false)}. As a special case,
+ * if {@code refKind} is {@code REF_invokeInterface} (9) then the
+ * {@code isInterface} field will be true.
+ *
+ * @param refKind refKind of desired member
+ * @return the matching enumeration member
+ * @throws IllegalArgumentException if there is no such member
+ */
+ public static Kind valueOf(int refKind) {
+ return valueOf(refKind, false);
+ }
+
+ /**
+ * Returns the enumeration member with the given the {@code refKind} and
+ * {@code isInterface} arguments.
+ * For most values of {@code refKind} there is an exact match regardless of the value of {@code isInterface}.
+ * These are:
+ * <UL>
+ * <LI>{@code REF_invokeVirtual} which matches to {@code VIRTUAL}
+ * <LI>{@code REF_invokeInterface} which matches to {@code INTERFACE_VIRTUAL}
+ * <LI>{@code REF_newInvokeSpecial} which matches to {@code CONSTRUCTOR}
+ * <LI>{@code REF_getField} which matches to {@code GETTER}
+ * <LI>{@code REF_putField} which matches to {@code SETTER}
+ * <LI>{@code REF_getStatic} which matches to {@code STATIC_GETTER}
+ * <LI>{@code REF_putStatic} which matches to {@code STATIC_SETTER}
+ * </UL>
+ * As for the rest, the returned kind will depend on the value (false or true accordingly) of {@code isInterface}:
+ * <UL>
+ * <LI>{@code REF_invokeStatic} which matches to {@code STATIC} or {@code INTERFACE_STATIC}
+ * <LI>{@code REF_invokeSpecial} which matches to {@code SPECIAL} or {@code INTERFACE_SPECIAL}
+ * </UL>
+ * @param refKind refKind of desired member
+ * @param isInterface whether desired member is for interface methods
+ * @return the matching enumeration member
+ * @throws IllegalArgumentException if there is no such member
+ */
+ public static Kind valueOf(int refKind, boolean isInterface) {
+ int i = tableIndex(refKind, isInterface);
+ if (i >= 0 && i < TABLE.length) {
+ Kind kind = TABLE[i];
+ if (kind == null) {
+ throw new IllegalArgumentException(String.format("refKind=%d", refKind));
+ }
+ if (kind.refKind == refKind && kind.isInterface == isInterface) {
+ return kind;
+ }
+ }
+ throw new IllegalArgumentException(String.format("refKind=%d", refKind));
+ }
+
+ private static int tableIndex(int refKind, boolean isInterface) {
+ if (refKind < 0) return refKind;
+ return (refKind * 2) + (isInterface ? 1 : 0);
+ }
+
+ private static final @Stable Kind[] TABLE;
+
+ static {
+ // Pack the static table.
+ int max = 0;
+ for (Kind k : values())
+ max = Math.max(max, tableIndex(k.refKind, true));
+
+ TABLE = new Kind[max+1];
+ for (Kind kind : values()) {
+ int i = tableIndex(kind.refKind, kind.isInterface);
+ if (i >= TABLE.length || TABLE[i] != null)
+ throw new AssertionError("TABLE entry for " + kind);
+ TABLE[i] = kind;
+ }
+
+ // Pack in some aliases also.
+ int ii = tableIndex(REF_invokeInterface, false);
+ if (TABLE[ii] != null)
+ throw new AssertionError("TABLE entry for (invokeInterface, false) used by " + TABLE[ii]);
+ TABLE[ii] = INTERFACE_VIRTUAL;
+
+ for (Kind kind : values()) {
+ if (!kind.isInterface) {
+ // Add extra cache entry to alias the isInterface case.
+ // For example, (REF_getStatic, X) will produce STATIC_GETTER
+ // for either truth value of X.
+ int i = tableIndex(kind.refKind, true);
+ if (TABLE[i] == null) {
+ // There is not a specific Kind for interfaces
+ if (kind == VIRTUAL) kind = INTERFACE_VIRTUAL;
+ if (TABLE[i] == null) TABLE[i] = kind;
+ }
+ }
+ }
+ }
+
+ /**
+ * Does this {@code Kind} correspond to a virtual method invocation?
+ *
+ * @return if this {@code Kind} corresponds to a virtual method invocation
+ */
+ boolean isVirtualMethod() {
+ switch (this) {
+ case VIRTUAL:
+ case SPECIAL:
+ case INTERFACE_VIRTUAL:
+ case INTERFACE_SPECIAL:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Returns the {@code kind} of the method handle described by this nominal
+ * descriptor.
+ *
+ * @return the {@link Kind}
+ */
+ Kind kind();
+
+ /**
+ * Returns the {@code refKind} of the method handle described by this nominal
+ * reference, as defined by {@link MethodHandleInfo}.
+ *
+ * @return the reference kind
+ */
+ int refKind();
+
+ /**
+ * Indicates if the method is declared by an interface
+ *
+ * @return true if the method is declared by an interface
+ */
+ boolean isOwnerInterface();
+
+ /**
+ * Returns a {@link ClassDesc} describing the class declaring the
+ * method or field described by this nominal descriptor.
+ *
+ * @return the class declaring the method or field
+ */
+ ClassDesc owner();
+
+ /**
+ * Returns the name of the method or field described by this nominal descriptor.
+ * For constructors, returns the reserved name {@code "<init>"}.
+ *
+ * @return the name of the method or field
+ */
+ String methodName();
+
+ /**
+ * Returns the lookup descriptor of the method handle described by this descriptor,
+ * after adjusting for the invocation mode. This will correspond to either
+ * a method type descriptor string (for methods and constructors), or a field
+ * descriptor string (for field access method handles). The lookup descriptor
+ * string is in the same format as accepted by {@link MethodHandleDesc#of(Kind, ClassDesc, String, String)}.
+ *
+ * @return the lookup descriptor string
+ */
+ String lookupDescriptor();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/DirectMethodHandleDescImpl.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Objects;
+
+import static java.lang.constant.ConstantDescs.CD_void;
+import static java.lang.constant.ConstantUtils.validateClassOrInterface;
+import static java.lang.constant.ConstantUtils.validateMemberName;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.CONSTRUCTOR;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct
+ * {@link MethodHandle}. A {@linkplain DirectMethodHandleDescImpl} corresponds to
+ * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
+ */
+final class DirectMethodHandleDescImpl implements DirectMethodHandleDesc {
+
+ private final Kind kind;
+ private final ClassDesc owner;
+ private final String name;
+ private final MethodTypeDesc invocationType;
+
+ /**
+ * Constructs a {@linkplain DirectMethodHandleDescImpl} for a method or field
+ * from a kind, owner, name, and type
+ *
+ * @param kind the kind of the method handle
+ * @param owner the declaring class or interface for the method
+ * @param name the unqualified name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
+ * @param type the lookup type of the method
+ * @throws NullPointerException if any non-ignored argument is null
+ * @throws IllegalArgumentException if {@code kind} describes a field accessor,
+ * and {@code type} is not consistent with that kind of field accessor, or if
+ * {@code kind} describes a constructor, and the return type of {@code type}
+ * is not {@code void}
+ * @jvms 4.2.2 Unqualified Names
+ */
+ DirectMethodHandleDescImpl(Kind kind, ClassDesc owner, String name, MethodTypeDesc type) {
+ if (kind == CONSTRUCTOR)
+ name = "<init>";
+
+ requireNonNull(kind);
+ validateClassOrInterface(requireNonNull(owner));
+ validateMemberName(requireNonNull(name));
+ requireNonNull(type);
+
+ switch (kind) {
+ case CONSTRUCTOR: validateConstructor(type); break;
+ case GETTER: validateFieldType(type, false, true); break;
+ case SETTER: validateFieldType(type, true, true); break;
+ case STATIC_GETTER: validateFieldType(type, false, false); break;
+ case STATIC_SETTER: validateFieldType(type, true, false); break;
+ }
+
+ this.kind = kind;
+ this.owner = owner;
+ this.name = name;
+ if (kind.isVirtualMethod())
+ this.invocationType = type.insertParameterTypes(0, owner);
+ else if (kind == CONSTRUCTOR)
+ this.invocationType = type.changeReturnType(owner);
+ else
+ this.invocationType = type;
+ }
+
+ private static void validateFieldType(MethodTypeDesc type, boolean isSetter, boolean isVirtual) {
+ boolean isVoid = type.returnType().descriptorString().equals("V");
+ int expectedParams = (isSetter ? 1 : 0) + (isVirtual ? 1 : 0);
+ if (isVoid != isSetter
+ || type.parameterCount() != expectedParams
+ || (isVirtual && type.parameterType(0).isPrimitive())) {
+ String expectedType = String.format("(%s%s)%s", (isVirtual ? "R" : ""),
+ (isSetter ? "T" : ""), (isSetter ? "V" : "T"));
+ throw new IllegalArgumentException(String.format("Expected type of %s for getter, found %s", expectedType, type));
+ }
+ }
+
+ private static void validateConstructor(MethodTypeDesc type) {
+ if (!type.returnType().descriptorString().equals("V")) {
+ throw new IllegalArgumentException(String.format("Expected type of (T*)V for constructor, found %s", type));
+ }
+ }
+
+ @Override
+ public Kind kind() { return kind; }
+
+ @Override
+ public int refKind() { return kind.refKind; }
+
+ @Override
+ public boolean isOwnerInterface() { return kind.isInterface; }
+
+ @Override
+ public ClassDesc owner() {
+ return owner;
+ }
+
+ @Override
+ public String methodName() {
+ return name;
+ }
+
+ @Override
+ public MethodTypeDesc invocationType() {
+ return invocationType;
+ }
+
+ @Override
+ public String lookupDescriptor() {
+ switch (kind) {
+ case VIRTUAL:
+ case SPECIAL:
+ case INTERFACE_VIRTUAL:
+ case INTERFACE_SPECIAL:
+ return invocationType.dropParameterTypes(0, 1).descriptorString();
+ case STATIC:
+ case INTERFACE_STATIC:
+ return invocationType.descriptorString();
+ case CONSTRUCTOR:
+ return invocationType.changeReturnType(CD_void).descriptorString();
+ case GETTER:
+ case STATIC_GETTER:
+ return invocationType.returnType().descriptorString();
+ case SETTER:
+ return invocationType.parameterType(1).descriptorString();
+ case STATIC_SETTER:
+ return invocationType.parameterType(0).descriptorString();
+ default:
+ throw new IllegalStateException(kind.toString());
+ }
+ }
+
+ public MethodHandle resolveConstantDesc(MethodHandles.Lookup lookup)
+ throws ReflectiveOperationException {
+ Class<?> resolvedOwner = (Class<?>) owner.resolveConstantDesc(lookup);
+ MethodType invocationType = (MethodType) this.invocationType().resolveConstantDesc(lookup);
+ switch (kind) {
+ case STATIC:
+ case INTERFACE_STATIC:
+ return lookup.findStatic(resolvedOwner, name, invocationType);
+ case INTERFACE_VIRTUAL:
+ case VIRTUAL:
+ return lookup.findVirtual(resolvedOwner, name, invocationType.dropParameterTypes(0, 1));
+ case SPECIAL:
+ case INTERFACE_SPECIAL:
+ return lookup.findSpecial(resolvedOwner, name, invocationType.dropParameterTypes(0, 1),
+ lookup.lookupClass());
+ case CONSTRUCTOR:
+ return lookup.findConstructor(resolvedOwner, invocationType.changeReturnType(void.class));
+ case GETTER:
+ return lookup.findGetter(resolvedOwner, name, invocationType.returnType());
+ case STATIC_GETTER:
+ return lookup.findStaticGetter(resolvedOwner, name, invocationType.returnType());
+ case SETTER:
+ return lookup.findSetter(resolvedOwner, name, invocationType.parameterType(1));
+ case STATIC_SETTER:
+ return lookup.findStaticSetter(resolvedOwner, name, invocationType.parameterType(0));
+ default:
+ throw new IllegalStateException(kind.name());
+ }
+ }
+
+ /**
+ * Returns {@code true} if this {@linkplain DirectMethodHandleDescImpl} is
+ * equal to another {@linkplain DirectMethodHandleDescImpl}. Equality is
+ * determined by the two descriptors having equal kind, owner, name, and type
+ * descriptor.
+ * @param o a {@code DirectMethodHandleDescImpl} to compare to this
+ * {@code DirectMethodHandleDescImpl}
+ * @return {@code true} if the specified {@code DirectMethodHandleDescImpl} is
+ * equals to this {@code DirectMethodHandleDescImpl}.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DirectMethodHandleDescImpl desc = (DirectMethodHandleDescImpl) o;
+ return kind == desc.kind &&
+ Objects.equals(owner, desc.owner) &&
+ Objects.equals(name, desc.name) &&
+ Objects.equals(invocationType, desc.invocationType);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(kind, owner, name, invocationType);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("MethodHandleDesc[%s/%s::%s%s]", kind, owner.displayName(), name, invocationType.displayDescriptor());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/DynamicCallSiteDesc.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import static java.lang.constant.ConstantDescs.CD_String;
+import static java.lang.constant.ConstantUtils.EMPTY_CONSTANTDESC;
+import static java.lang.constant.ConstantUtils.validateMemberName;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for an
+ * {@code invokedynamic} call site.
+ *
+ * <p>Concrete subtypes of {@linkplain DynamicCallSiteDesc} must be
+ * <a href="../doc-files/ValueBased.html">value-based</a>.
+ *
+ * @since 12
+ */
+public class DynamicCallSiteDesc {
+
+ private final DirectMethodHandleDesc bootstrapMethod;
+ private final ConstantDesc[] bootstrapArgs;
+ private final String invocationName;
+ private final MethodTypeDesc invocationType;
+
+ /**
+ * Creates a nominal descriptor for an {@code invokedynamic} call site.
+ *
+ * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
+ * bootstrap method for the {@code invokedynamic}
+ * @param invocationName The unqualified name that would appear in the {@code NameAndType}
+ * operand of the {@code invokedynamic}
+ * @param invocationType a {@link MethodTypeDesc} describing the invocation
+ * type that would appear in the {@code NameAndType}
+ * operand of the {@code invokedynamic}
+ * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
+ * to the bootstrap, that would appear in the
+ * {@code BootstrapMethods} attribute
+ * @throws NullPointerException if any parameter is null
+ * @throws IllegalArgumentException if the invocation name has the incorrect
+ * format
+ * @jvms 4.2.2 Unqualified Names
+ */
+ private DynamicCallSiteDesc(DirectMethodHandleDesc bootstrapMethod,
+ String invocationName,
+ MethodTypeDesc invocationType,
+ ConstantDesc[] bootstrapArgs) {
+ this.invocationName = validateMemberName(requireNonNull(invocationName));
+ this.invocationType = requireNonNull(invocationType);
+ this.bootstrapMethod = requireNonNull(bootstrapMethod);
+ this.bootstrapArgs = requireNonNull(bootstrapArgs.clone());
+ if (invocationName.length() == 0)
+ throw new IllegalArgumentException("Illegal invocation name: " + invocationName);
+ }
+
+ /**
+ * Creates a nominal descriptor for an {@code invokedynamic} call site.
+ *
+ * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
+ * bootstrap method for the {@code invokedynamic}
+ * @param invocationName The unqualified name that would appear in the {@code NameAndType}
+ * operand of the {@code invokedynamic}
+ * @param invocationType a {@link MethodTypeDesc} describing the invocation
+ * type that would appear in the {@code NameAndType}
+ * operand of the {@code invokedynamic}
+ * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
+ * to the bootstrap, that would appear in the
+ * {@code BootstrapMethods} attribute
+ * @return the nominal descriptor
+ * @throws NullPointerException if any parameter is null
+ * @throws IllegalArgumentException if the invocation name has the incorrect
+ * format
+ * @jvms 4.2.2 Unqualified Names
+ */
+ public static DynamicCallSiteDesc of(DirectMethodHandleDesc bootstrapMethod,
+ String invocationName,
+ MethodTypeDesc invocationType,
+ ConstantDesc... bootstrapArgs) {
+ return new DynamicCallSiteDesc(bootstrapMethod, invocationName, invocationType, bootstrapArgs);
+ }
+
+ /**
+ * Creates a nominal descriptor for an {@code invokedynamic} call site whose
+ * bootstrap method has no static arguments.
+ *
+ * @param bootstrapMethod The bootstrap method for the {@code invokedynamic}
+ * @param invocationName The invocationName that would appear in the
+ * {@code NameAndType} operand of the {@code invokedynamic}
+ * @param invocationType The invocation invocationType that would appear
+ * in the {@code NameAndType} operand of the {@code invokedynamic}
+ * @return the nominal descriptor
+ * @throws NullPointerException if any parameter is null
+ * @throws IllegalArgumentException if the invocation name has the incorrect
+ * format
+ */
+ public static DynamicCallSiteDesc of(DirectMethodHandleDesc bootstrapMethod,
+ String invocationName,
+ MethodTypeDesc invocationType) {
+ return new DynamicCallSiteDesc(bootstrapMethod, invocationName, invocationType, EMPTY_CONSTANTDESC);
+ }
+
+ /**
+ * Creates a nominal descriptor for an {@code invokedynamic} call site whose
+ * bootstrap method has no static arguments and for which the name parameter
+ * is {@link ConstantDescs#DEFAULT_NAME}.
+ *
+ * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
+ * bootstrap method for the {@code invokedynamic}
+ * @param invocationType a {@link MethodTypeDesc} describing the invocation
+ * type that would appear in the {@code NameAndType}
+ * operand of the {@code invokedynamic}
+ * @return the nominal descriptor
+ * @throws NullPointerException if any parameter is null
+ */
+ public static DynamicCallSiteDesc of(DirectMethodHandleDesc bootstrapMethod,
+ MethodTypeDesc invocationType) {
+ return of(bootstrapMethod, ConstantDescs.DEFAULT_NAME, invocationType);
+ }
+
+ /**
+ * Returns a nominal descriptor for an {@code invokedynamic} call site whose
+ * bootstrap method, name, and invocation type are the same as this one, but
+ * with the specified bootstrap arguments.
+ *
+ * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
+ * to the bootstrap, that would appear in the
+ * {@code BootstrapMethods} attribute
+ * @return the nominal descriptor
+ * @throws NullPointerException if any parameter is null
+ */
+ public DynamicCallSiteDesc withArgs(ConstantDesc... bootstrapArgs) {
+ return new DynamicCallSiteDesc(bootstrapMethod, invocationName, invocationType, bootstrapArgs);
+ }
+
+ /**
+ * Returns a nominal descriptor for an {@code invokedynamic} call site whose
+ * bootstrap and bootstrap arguments are the same as this one, but with the
+ * specified invocationName and invocation invocationType
+ *
+ * @param invocationName The unqualified name that would appear in the {@code NameAndType}
+ * operand of the {@code invokedynamic}
+ * @param invocationType a {@link MethodTypeDesc} describing the invocation
+ * type that would appear in the {@code NameAndType}
+ * operand of the {@code invokedynamic}
+ * @return the nominal descriptor
+ * @throws NullPointerException if any parameter is null
+ * @throws IllegalArgumentException if the invocation name has the incorrect
+ * format
+ * @jvms 4.2.2 Unqualified Names
+ */
+ public DynamicCallSiteDesc withNameAndType(String invocationName,
+ MethodTypeDesc invocationType) {
+ return new DynamicCallSiteDesc(bootstrapMethod, invocationName, invocationType, bootstrapArgs);
+ }
+
+ /**
+ * Returns the invocation name that would appear in the {@code NameAndType}
+ * operand of the {@code invokedynamic}.
+ *
+ * @return the invocation name
+ */
+ public String invocationName() {
+ return invocationName;
+ }
+
+ /**
+ * Returns a {@link MethodTypeDesc} describing the invocation type that
+ * would appear in the {@code NameAndType} operand of the {@code invokedynamic}.
+ *
+ * @return the invocation type
+ */
+ public MethodTypeDesc invocationType() {
+ return invocationType;
+ }
+
+ /**
+ * Returns a {@link MethodHandleDesc} describing the bootstrap method for
+ * the {@code invokedynamic}.
+ *
+ * @return the bootstrap method for the {@code invokedynamic}
+ */
+ public MethodHandleDesc bootstrapMethod() { return bootstrapMethod; }
+
+ /**
+ * Returns {@link ConstantDesc}s describing the bootstrap arguments for the
+ * {@code invokedynamic}. The returned array is always non-null. A zero
+ * length array is returned if this {@linkplain DynamicCallSiteDesc} has no
+ * bootstrap arguments.
+ *
+ * @return the bootstrap arguments for the {@code invokedynamic}
+ */
+ public ConstantDesc[] bootstrapArgs() { return bootstrapArgs.clone(); }
+
+ /**
+ * Reflectively invokes the bootstrap method with the specified arguments,
+ * and return the resulting {@link CallSite}
+ *
+ * @param lookup The {@link MethodHandles.Lookup} used to resolve class names
+ * @return the {@link CallSite}
+ * @throws Throwable if any exception is thrown by the bootstrap method
+ */
+ public CallSite resolveCallSiteDesc(MethodHandles.Lookup lookup) throws Throwable {
+ assert bootstrapMethod.invocationType().parameterType(1).equals(CD_String);
+ MethodHandle bsm = (MethodHandle) bootstrapMethod.resolveConstantDesc(lookup);
+ Object[] args = new Object[bootstrapArgs.length + 3];
+ args[0] = lookup;
+ args[1] = invocationName;
+ args[2] = invocationType.resolveConstantDesc(lookup);
+ System.arraycopy(bootstrapArgs, 0, args, 3, bootstrapArgs.length);
+ return (CallSite) bsm.invokeWithArguments(args);
+ }
+
+ /**
+ * Compares the specified object with this descriptor for equality. Returns
+ * {@code true} if and only if the specified object is also a
+ * {@linkplain DynamicCallSiteDesc}, and both descriptors have equal
+ * bootstrap methods, bootstrap argument lists, invocation name, and
+ * invocation type.
+ *
+ * @param o the {@code DynamicCallSiteDesc} to compare to this
+ * {@code DynamicCallSiteDesc}
+ * @return {@code true} if the specified {@code DynamicCallSiteDesc} is
+ * equals to this {@code DynamicCallSiteDesc}.
+ */
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DynamicCallSiteDesc specifier = (DynamicCallSiteDesc) o;
+ return Objects.equals(bootstrapMethod, specifier.bootstrapMethod) &&
+ Arrays.equals(bootstrapArgs, specifier.bootstrapArgs) &&
+ Objects.equals(invocationName, specifier.invocationName) &&
+ Objects.equals(invocationType, specifier.invocationType);
+ }
+
+ @Override
+ public final int hashCode() {
+ int result = Objects.hash(bootstrapMethod, invocationName, invocationType);
+ result = 31 * result + Arrays.hashCode(bootstrapArgs);
+ return result;
+ }
+
+ /**
+ * Returns a compact textual description of this call site description,
+ * including the bootstrap method, the invocation name and type, and
+ * the static bootstrap arguments.
+ *
+ * @return A compact textual description of this call site descriptor
+ */
+ @Override
+ public String toString() {
+ return String.format("DynamicCallSiteDesc[%s::%s(%s%s):%s]",
+ bootstrapMethod.owner().displayName(),
+ bootstrapMethod.methodName(),
+ invocationName.equals(ConstantDescs.DEFAULT_NAME) ? "" : invocationName + "/",
+ Stream.of(bootstrapArgs).map(Object::toString).collect(joining(",")),
+ invocationType.displayDescriptor());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.Enum.EnumDesc;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.VarHandle.VarHandleDesc;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static java.lang.constant.ConstantDescs.CD_Class;
+import static java.lang.constant.ConstantDescs.CD_VarHandle;
+import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
+import static java.lang.constant.ConstantUtils.EMPTY_CONSTANTDESC;
+import static java.lang.constant.ConstantUtils.validateMemberName;
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.joining;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
+ * dynamic constant (one described in the constant pool with
+ * {@code Constant_Dynamic_info}.)
+ *
+ * <p>Concrete subtypes of {@linkplain DynamicConstantDesc} must be
+ * <a href="../doc-files/ValueBased.html">value-based</a>.
+ *
+ * @param <T> the type of the dynamic constant
+ *
+ * @since 12
+ */
+public abstract class DynamicConstantDesc<T>
+ implements ConstantDesc {
+
+ private final DirectMethodHandleDesc bootstrapMethod;
+ private final ConstantDesc[] bootstrapArgs;
+ private final String constantName;
+ private final ClassDesc constantType;
+
+ private static final Map<MethodHandleDesc, Function<DynamicConstantDesc<?>, ConstantDesc>> canonicalMap
+ = Map.ofEntries(Map.entry(ConstantDescs.BSM_PRIMITIVE_CLASS, DynamicConstantDesc::canonicalizePrimitiveClass),
+ Map.entry(ConstantDescs.BSM_ENUM_CONSTANT, DynamicConstantDesc::canonicalizeEnum),
+ Map.entry(ConstantDescs.BSM_NULL_CONSTANT, DynamicConstantDesc::canonicalizeNull),
+ Map.entry(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, DynamicConstantDesc::canonicalizeStaticFieldVarHandle),
+ Map.entry(ConstantDescs.BSM_VARHANDLE_FIELD, DynamicConstantDesc::canonicalizeFieldVarHandle),
+ Map.entry(ConstantDescs.BSM_VARHANDLE_ARRAY, DynamicConstantDesc::canonicalizeArrayVarHandle)
+ );
+
+ /**
+ * Creates a nominal descriptor for a dynamic constant.
+ *
+ * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
+ * bootstrap method for the constant
+ * @param constantName The unqualified name that would appear in the {@code NameAndType}
+ * operand of the {@code LDC} for this constant
+ * @param constantType a {@link ClassDesc} describing the type
+ * that would appear in the {@code NameAndType} operand
+ * of the {@code LDC} for this constant
+ * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
+ * to the bootstrap, that would appear in the
+ * {@code BootstrapMethods} attribute
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if the {@code name} has the incorrect
+ * format
+ * @jvms 4.2.2 Unqualified Names
+ */
+ protected DynamicConstantDesc(DirectMethodHandleDesc bootstrapMethod,
+ String constantName,
+ ClassDesc constantType,
+ ConstantDesc... bootstrapArgs) {
+ this.bootstrapMethod = requireNonNull(bootstrapMethod);
+ this.constantName = validateMemberName(requireNonNull(constantName));
+ this.constantType = requireNonNull(constantType);
+ this.bootstrapArgs = requireNonNull(bootstrapArgs).clone();
+
+ if (constantName.length() == 0)
+ throw new IllegalArgumentException("Illegal invocation name: " + constantName);
+ }
+
+ /**
+ * Returns a nominal descriptor for a dynamic constant, transforming it into
+ * a more specific type if the constant bootstrap is a well-known one and a
+ * more specific nominal descriptor type (e.g., ClassDesc) is available.
+ *
+ * <p>Classes whose {@link Constable#describeConstable()} method produce
+ * a {@linkplain DynamicConstantDesc} with a well-known bootstrap including
+ * {@link Class} (for instances describing primitive types), {@link Enum},
+ * and {@link VarHandle}.
+ *
+ * <p>Bytecode-reading APIs that process the constant pool and wish to expose
+ * entries as {@link ConstantDesc} to their callers should generally use this
+ * method in preference to {@link #ofNamed(DirectMethodHandleDesc, String, ClassDesc, ConstantDesc...)}
+ * because this may result in a more specific type that can be provided to
+ * callers.
+ *
+ * @param <T> the type of the dynamic constant
+ * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
+ * bootstrap method for the constant
+ * @param constantName The unqualified name that would appear in the {@code NameAndType}
+ * operand of the {@code LDC} for this constant
+ * @param constantType a {@link ClassDesc} describing the type
+ * that would appear in the {@code NameAndType} operand
+ * of the {@code LDC} for this constant
+ * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
+ * to the bootstrap, that would appear in the
+ * {@code BootstrapMethods} attribute
+ * @return the nominal descriptor
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if the {@code name} has the incorrect
+ * format
+ * @jvms 4.2.2 Unqualified Names
+ */
+ public static<T> ConstantDesc ofCanonical(DirectMethodHandleDesc bootstrapMethod,
+ String constantName,
+ ClassDesc constantType,
+ ConstantDesc[] bootstrapArgs) {
+ return DynamicConstantDesc.<T>ofNamed(bootstrapMethod, constantName, constantType, bootstrapArgs)
+ .tryCanonicalize();
+ }
+
+ /**
+ * Returns a nominal descriptor for a dynamic constant.
+ *
+ * @param <T> the type of the dynamic constant
+ * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
+ * bootstrap method for the constant
+ * @param constantName The unqualified name that would appear in the {@code NameAndType}
+ * operand of the {@code LDC} for this constant
+ * @param constantType a {@link ClassDesc} describing the type
+ * that would appear in the {@code NameAndType} operand
+ * of the {@code LDC} for this constant
+ * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
+ * to the bootstrap, that would appear in the
+ * {@code BootstrapMethods} attribute
+ * @return the nominal descriptor
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if the {@code name} has the incorrect
+ * format
+ * @jvms 4.2.2 Unqualified Names
+ */
+
+ public static<T> DynamicConstantDesc<T> ofNamed(DirectMethodHandleDesc bootstrapMethod,
+ String constantName,
+ ClassDesc constantType,
+ ConstantDesc... bootstrapArgs) {
+ return new AnonymousDynamicConstantDesc<>(bootstrapMethod, constantName, constantType, bootstrapArgs);
+ }
+
+ /**
+ * Returns a nominal descriptor for a dynamic constant whose name parameter
+ * is {@link ConstantDescs#DEFAULT_NAME}, and whose type parameter is always
+ * the same as the bootstrap method return type.
+ *
+ * @param <T> the type of the dynamic constant
+ * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
+ * bootstrap method for the constant
+ * @param bootstrapArgs {@link ConstantDesc}s describing the static arguments
+ * to the bootstrap, that would appear in the
+ * {@code BootstrapMethods} attribute
+ * @return the nominal descriptor
+ * @throws NullPointerException if any argument is null
+ * @jvms 4.2.2 Unqualified Names
+ */
+ public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod,
+ ConstantDesc... bootstrapArgs) {
+ return ofNamed(bootstrapMethod, DEFAULT_NAME, bootstrapMethod.invocationType().returnType(), bootstrapArgs);
+ }
+
+ /**
+ * Returns a nominal descriptor for a dynamic constant whose bootstrap has
+ * no static arguments, whose name parameter is {@link ConstantDescs#DEFAULT_NAME},
+ * and whose type parameter is always the same as the bootstrap method return type.
+ *
+ * @param <T> the type of the dynamic constant
+ * @param bootstrapMethod a {@link DirectMethodHandleDesc} describing the
+ * bootstrap method for the constant
+ * @return the nominal descriptor
+ * @throws NullPointerException if any argument is null
+ */
+ public static<T> DynamicConstantDesc<T> of(DirectMethodHandleDesc bootstrapMethod) {
+ return of(bootstrapMethod, EMPTY_CONSTANTDESC);
+ }
+
+ /**
+ * Returns the name that would appear in the {@code NameAndType} operand
+ * of the {@code LDC} for this constant.
+ *
+ * @return the constant name
+ */
+ public String constantName() {
+ return constantName;
+ }
+
+ /**
+ * Returns a {@link ClassDesc} describing the type that would appear in the
+ * {@code NameAndType} operand of the {@code LDC} for this constant.
+ *
+ * @return the constant type
+ */
+ public ClassDesc constantType() {
+ return constantType;
+ }
+
+ /**
+ * Returns a {@link MethodHandleDesc} describing the bootstrap method for
+ * this constant.
+ *
+ * @return the bootstrap method
+ */
+ public DirectMethodHandleDesc bootstrapMethod() {
+ return bootstrapMethod;
+ }
+
+ /**
+ * Returns the bootstrap arguments for this constant.
+ *
+ * @return the bootstrap arguments
+ */
+ public ConstantDesc[] bootstrapArgs() {
+ return bootstrapArgs.clone();
+ }
+
+ /**
+ * Returns the bootstrap arguments for this constant as an immutable {@link List}.
+ *
+ * @return a {@link List} of the bootstrap arguments
+ */
+ public List<ConstantDesc> bootstrapArgsList() {
+ return List.of(bootstrapArgs);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+ try {
+ MethodHandle bsm = (MethodHandle) bootstrapMethod.resolveConstantDesc(lookup);
+ if (bsm.type().parameterCount() < 2 ||
+ !MethodHandles.Lookup.class.isAssignableFrom(bsm.type().parameterType(0))) {
+ throw new BootstrapMethodError(
+ "Invalid bootstrap method declared for resolving a dynamic constant: " + bootstrapMethod);
+ }
+ Object[] bsmArgs = new Object[3 + bootstrapArgs.length];
+ bsmArgs[0] = lookup;
+ bsmArgs[1] = constantName;
+ bsmArgs[2] = constantType.resolveConstantDesc(lookup);
+ for (int i = 0; i < bootstrapArgs.length; i++)
+ bsmArgs[3 + i] = bootstrapArgs[i].resolveConstantDesc(lookup);
+
+ return (T) bsm.invokeWithArguments(bsmArgs);
+ } catch (Error e) {
+ throw e;
+ } catch (Throwable t) {
+ throw new BootstrapMethodError(t);
+ }
+ }
+
+ private ConstantDesc tryCanonicalize() {
+ Function<DynamicConstantDesc<?>, ConstantDesc> f = canonicalMap.get(bootstrapMethod);
+ if (f != null) {
+ try {
+ return f.apply(this);
+ }
+ catch (Throwable t) {
+ return this;
+ }
+ }
+ return this;
+ }
+
+ private static ConstantDesc canonicalizeNull(DynamicConstantDesc<?> desc) {
+ if (desc.bootstrapArgs.length != 0)
+ return desc;
+ return ConstantDescs.NULL;
+ }
+
+ private static ConstantDesc canonicalizeEnum(DynamicConstantDesc<?> desc) {
+ if (desc.bootstrapArgs.length != 0
+ || desc.constantName == null)
+ return desc;
+ return EnumDesc.of(desc.constantType, desc.constantName);
+ }
+
+ private static ConstantDesc canonicalizePrimitiveClass(DynamicConstantDesc<?> desc) {
+ if (desc.bootstrapArgs.length != 0
+ || !desc.constantType().equals(CD_Class)
+ || desc.constantName == null)
+ return desc;
+ return ClassDesc.ofDescriptor(desc.constantName);
+ }
+
+ private static ConstantDesc canonicalizeStaticFieldVarHandle(DynamicConstantDesc<?> desc) {
+ if (desc.bootstrapArgs.length != 2
+ || !desc.constantType().equals(CD_VarHandle))
+ return desc;
+ return VarHandleDesc.ofStaticField((ClassDesc) desc.bootstrapArgs[0],
+ desc.constantName,
+ (ClassDesc) desc.bootstrapArgs[1]);
+ }
+
+ private static ConstantDesc canonicalizeFieldVarHandle(DynamicConstantDesc<?> desc) {
+ if (desc.bootstrapArgs.length != 2
+ || !desc.constantType().equals(CD_VarHandle))
+ return desc;
+ return VarHandleDesc.ofField((ClassDesc) desc.bootstrapArgs[0],
+ desc.constantName,
+ (ClassDesc) desc.bootstrapArgs[1]);
+ }
+
+ private static ConstantDesc canonicalizeArrayVarHandle(DynamicConstantDesc<?> desc) {
+ if (desc.bootstrapArgs.length != 1
+ || !desc.constantType().equals(CD_VarHandle))
+ return desc;
+ return VarHandleDesc.ofArray((ClassDesc) desc.bootstrapArgs[0]);
+ }
+
+ // @@@ To eventually support in canonicalization: DCR with BSM=MHR_METHODHANDLEDESC_ASTYPE becomes AsTypeMHDesc
+
+ /**
+ * Compares the specified object with this descriptor for equality. Returns
+ * {@code true} if and only if the specified object is also a
+ * {@linkplain DynamicConstantDesc}, and both descriptors have equal
+ * bootstrap methods, bootstrap argument lists, constant name, and
+ * constant type.
+ *
+ * @param o the {@code DynamicConstantDesc} to compare to this
+ * {@code DynamicConstantDesc}
+ * @return {@code true} if the specified {@code DynamicConstantDesc} is
+ * equals to this {@code DynamicConstantDesc}.
+ *
+ */
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DynamicConstantDesc)) return false;
+ DynamicConstantDesc<?> desc = (DynamicConstantDesc<?>) o;
+ return Objects.equals(bootstrapMethod, desc.bootstrapMethod) &&
+ Arrays.equals(bootstrapArgs, desc.bootstrapArgs) &&
+ Objects.equals(constantName, desc.constantName) &&
+ Objects.equals(constantType, desc.constantType);
+ }
+
+ @Override
+ public final int hashCode() {
+ int result = Objects.hash(bootstrapMethod, constantName, constantType);
+ result = 31 * result + Arrays.hashCode(bootstrapArgs);
+ return result;
+ }
+
+ /**
+ * Returns a compact textual description of this constant description,
+ * including the bootstrap method, the constant name and type, and
+ * the static bootstrap arguments.
+ *
+ * @return A compact textual description of this call site descriptor
+ */
+ @Override
+ public String toString() {
+ return String.format("DynamicConstantDesc[%s::%s(%s%s)%s]",
+ bootstrapMethod.owner().displayName(),
+ bootstrapMethod.methodName(),
+ constantName.equals(ConstantDescs.DEFAULT_NAME) ? "" : constantName + "/",
+ Stream.of(bootstrapArgs).map(Object::toString).collect(joining(",")),
+ constantType.displayName());
+ }
+
+ private static class AnonymousDynamicConstantDesc<T> extends DynamicConstantDesc<T> {
+ AnonymousDynamicConstantDesc(DirectMethodHandleDesc bootstrapMethod, String constantName, ClassDesc constantType, ConstantDesc... bootstrapArgs) {
+ super(bootstrapMethod, constantName, constantType, bootstrapArgs);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/MethodHandleDesc.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import static java.lang.constant.ConstantDescs.CD_void;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.CONSTRUCTOR;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
+ * {@link MethodHandle} constant.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain MethodHandleDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except
+ * by explicitly permitted types. Non-platform classes should not implement
+ * {@linkplain MethodHandleDesc} directly.
+ *
+ * @since 12
+ */
+public interface MethodHandleDesc
+ extends ConstantDesc {
+
+ /**
+ * Creates a {@linkplain MethodHandleDesc} corresponding to an invocation of a
+ * declared method, invocation of a constructor, or access to a field.
+ *
+ * <p>The lookup descriptor string has the same format as for the various
+ * variants of {@code CONSTANT_MethodHandle_info} and for the lookup
+ * methods on {@link MethodHandles.Lookup}. For a method or constructor
+ * invocation, it is interpreted as a method type descriptor; for field
+ * access, it is interpreted as a field descriptor. If {@code kind} is
+ * {@code CONSTRUCTOR}, the {@code name} parameter is ignored and the return
+ * type of the lookup descriptor must be {@code void}. If {@code kind}
+ * corresponds to a virtual method invocation, the lookup type includes the
+ * method parameters but not the receiver type.
+ *
+ * @param kind The kind of method handle to be described
+ * @param owner a {@link ClassDesc} describing the class containing the
+ * method, constructor, or field
+ * @param name the unqualified name of the method or field (ignored if
+ * {@code kind} is {@code CONSTRUCTOR})
+ * @param lookupDescriptor a method descriptor string the lookup type,
+ * if the request is for a method invocation, or
+ * describing the invocation type, if the request is
+ * for a field or constructor
+ * @return the {@linkplain MethodHandleDesc}
+ * @throws NullPointerException if any of the non-ignored arguments are null
+ * @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure
+ * @jvms 4.2.2 Unqualified Names
+ * @jvms 4.3.2 Field Descriptors
+ * @jvms 4.3.3 Method Descriptors
+ */
+ static DirectMethodHandleDesc of(DirectMethodHandleDesc.Kind kind,
+ ClassDesc owner,
+ String name,
+ String lookupDescriptor) {
+ switch (kind) {
+ case GETTER:
+ case SETTER:
+ case STATIC_GETTER:
+ case STATIC_SETTER:
+ return ofField(kind, owner, name, ClassDesc.ofDescriptor(lookupDescriptor));
+ default:
+ return new DirectMethodHandleDescImpl(kind, owner, name, MethodTypeDesc.ofDescriptor(lookupDescriptor));
+ }
+ }
+
+ /**
+ * Creates a {@linkplain MethodHandleDesc} corresponding to an invocation of a
+ * declared method or constructor.
+ *
+ * <p>The lookup descriptor string has the same format as for the lookup
+ * methods on {@link MethodHandles.Lookup}. If {@code kind} is
+ * {@code CONSTRUCTOR}, the name is ignored and the return type of the lookup
+ * type must be {@code void}. If {@code kind} corresponds to a virtual method
+ * invocation, the lookup type includes the method parameters but not the
+ * receiver type.
+ *
+ * @param kind The kind of method handle to be described; must be one of
+ * {@code SPECIAL, VIRTUAL, STATIC, INTERFACE_SPECIAL,
+ * INTERFACE_VIRTUAL, INTERFACE_STATIC, CONSTRUCTOR}
+ * @param owner a {@link ClassDesc} describing the class containing the
+ * method or constructor
+ * @param name the unqualified name of the method (ignored if {@code kind}
+ * is {@code CONSTRUCTOR})
+ * @param lookupMethodType a {@link MethodTypeDesc} describing the lookup type
+ * @return the {@linkplain MethodHandleDesc}
+ * @throws NullPointerException if any non-ignored arguments are null
+ * @throws IllegalArgumentException if the {@code name} has the incorrect
+ * format, or the kind is invalid
+ * @jvms 4.2.2 Unqualified Names
+ */
+ static DirectMethodHandleDesc ofMethod(DirectMethodHandleDesc.Kind kind,
+ ClassDesc owner,
+ String name,
+ MethodTypeDesc lookupMethodType) {
+ switch (kind) {
+ case GETTER:
+ case SETTER:
+ case STATIC_GETTER:
+ case STATIC_SETTER:
+ throw new IllegalArgumentException(kind.toString());
+ case VIRTUAL:
+ case SPECIAL:
+ case INTERFACE_VIRTUAL:
+ case INTERFACE_SPECIAL:
+ case INTERFACE_STATIC:
+ case STATIC:
+ case CONSTRUCTOR:
+ return new DirectMethodHandleDescImpl(kind, owner, name, lookupMethodType);
+ default:
+ throw new IllegalArgumentException(kind.toString());
+ }
+ }
+
+ /**
+ * Creates a {@linkplain MethodHandleDesc} corresponding to a method handle
+ * that accesses a field.
+ *
+ * @param kind the kind of the method handle to be described; must be one of {@code GETTER},
+ * {@code SETTER}, {@code STATIC_GETTER}, or {@code STATIC_SETTER}
+ * @param owner a {@link ClassDesc} describing the class containing the field
+ * @param fieldName the unqualified name of the field
+ * @param fieldType a {@link ClassDesc} describing the type of the field
+ * @return the {@linkplain MethodHandleDesc}
+ * @throws NullPointerException if any of the arguments are null
+ * @throws IllegalArgumentException if the {@code kind} is not one of the
+ * valid values or if the field name is not valid
+ * @jvms 4.2.2 Unqualified Names
+ */
+ static DirectMethodHandleDesc ofField(DirectMethodHandleDesc.Kind kind,
+ ClassDesc owner,
+ String fieldName,
+ ClassDesc fieldType) {
+ MethodTypeDesc mtr;
+ switch (kind) {
+ case GETTER: mtr = MethodTypeDesc.of(fieldType, owner); break;
+ case SETTER: mtr = MethodTypeDesc.of(CD_void, owner, fieldType); break;
+ case STATIC_GETTER: mtr = MethodTypeDesc.of(fieldType); break;
+ case STATIC_SETTER: mtr = MethodTypeDesc.of(CD_void, fieldType); break;
+ default:
+ throw new IllegalArgumentException(kind.toString());
+ }
+ return new DirectMethodHandleDescImpl(kind, owner, fieldName, mtr);
+ }
+
+ /**
+ * Returns a {@linkplain MethodHandleDesc} corresponding to invocation of a constructor
+ *
+ * @param owner a {@link ClassDesc} describing the class containing the
+ * constructor
+ * @param paramTypes {@link ClassDesc}s describing the parameter types of
+ * the constructor
+ * @return the {@linkplain MethodHandleDesc}
+ * @throws NullPointerException if any of the arguments are null
+ */
+ static DirectMethodHandleDesc ofConstructor(ClassDesc owner,
+ ClassDesc... paramTypes) {
+ return MethodHandleDesc.ofMethod(CONSTRUCTOR, owner, ConstantDescs.DEFAULT_NAME,
+ MethodTypeDesc.of(CD_void, paramTypes));
+ }
+
+ /**
+ * Returns a {@linkplain MethodHandleDesc} that describes this method handle
+ * adapted to a different type, as if by {@link MethodHandle#asType(MethodType)}.
+ *
+ * @param type a {@link MethodHandleDesc} describing the new method type
+ * @return a {@linkplain MethodHandleDesc} for the adapted method handle
+ */
+ default MethodHandleDesc asType(MethodTypeDesc type) {
+ return (invocationType().equals(type)) ? this : new AsTypeMethodHandleDesc(this, type);
+ }
+
+ /**
+ * Returns a {@link MethodTypeDesc} describing the invocation type of the
+ * method handle described by this nominal descriptor. The invocation type
+ * describes the full set of stack values that are consumed by the invocation
+ * (including the receiver, if any).
+ *
+ * @return a {@linkplain MethodHandleDesc} describing the method handle type
+ */
+ MethodTypeDesc invocationType();
+
+ /**
+ * Compares the specified object with this descriptor for equality. Returns
+ * {@code true} if and only if the specified object is also a
+ * {@linkplain MethodHandleDesc}, and both encode the same nominal description
+ * of a method handle.
+ *
+ * @param o the other object
+ * @return whether this descriptor is equal to the other object
+ */
+ boolean equals(Object o);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodType;
+import java.lang.invoke.TypeDescriptor;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
+ * {@linkplain MethodType} constant.
+ *
+ * @apiNote In the future, if the Java language permits, {@linkplain MethodTypeDesc}
+ * may become a {@code sealed} interface, which would prohibit subclassing except
+ * by explicitly permitted types. Non-platform classes should not implement
+ * {@linkplain MethodTypeDesc} directly.
+ *
+ * @since 12
+ */
+public interface MethodTypeDesc
+ extends ConstantDesc,
+ TypeDescriptor.OfMethod<ClassDesc, MethodTypeDesc> {
+ /**
+ * Creates a {@linkplain MethodTypeDesc} given a method descriptor string.
+ *
+ * @param descriptor a method descriptor string
+ * @return a {@linkplain MethodTypeDesc} describing the desired method type
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IllegalArgumentException if the descriptor string is not a valid
+ * method descriptor
+ * @jvms 4.3.3 Method Descriptors
+ */
+ static MethodTypeDesc ofDescriptor(String descriptor) {
+ return MethodTypeDescImpl.ofDescriptor(descriptor);
+ }
+
+ /**
+ * Returns a {@linkplain MethodTypeDesc} given the return type and parameter
+ * types.
+ *
+ * @param returnDesc a {@linkplain ClassDesc} describing the return type
+ * @param paramDescs {@linkplain ClassDesc}s describing the argument types
+ * @return a {@linkplain MethodTypeDesc} describing the desired method type
+ * @throws NullPointerException if any argument is {@code null}
+ */
+ static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) {
+ return new MethodTypeDescImpl(returnDesc, paramDescs);
+ }
+
+ /**
+ * Gets the return type of the method type described by this {@linkplain MethodTypeDesc}.
+ *
+ * @return a {@link ClassDesc} describing the return type of the method type
+ */
+ ClassDesc returnType();
+
+ /**
+ * Returns the number of parameters of the method type described by
+ * this {@linkplain MethodTypeDesc}.
+ * @return the number of parameters
+ */
+ int parameterCount();
+
+ /**
+ * Returns the parameter type of the {@code index}'th parameter of the method type
+ * described by this {@linkplain MethodTypeDesc}.
+ *
+ * @param index the index of the parameter to retrieve
+ * @return a {@link ClassDesc} describing the desired parameter type
+ * @throws IndexOutOfBoundsException if the index is outside the half-open
+ * range {[0, parameterCount())}
+ */
+ ClassDesc parameterType(int index);
+
+ /**
+ * Returns the parameter types as an immutable {@link List}.
+ *
+ * @return a {@link List} of {@link ClassDesc} describing the parameter types
+ */
+ List<ClassDesc> parameterList();
+
+ /**
+ * Returns the parameter types as an array.
+ *
+ * @return an array of {@link ClassDesc} describing the parameter types
+ */
+ ClassDesc[] parameterArray();
+
+ /**
+ * Returns a {@linkplain MethodTypeDesc} that is identical to
+ * this one, except with the specified return type.
+ *
+ * @param returnType a {@link ClassDesc} describing the new return type
+ * @return a {@linkplain MethodTypeDesc} describing the desired method type
+ * @throws NullPointerException if any argument is {@code null}
+ */
+ MethodTypeDesc changeReturnType(ClassDesc returnType);
+
+ /**
+ * Returns a {@linkplain MethodTypeDesc} that is identical to this one,
+ * except that a single parameter type has been changed to the specified type.
+ *
+ * @param index the index of the parameter to change
+ * @param paramType a {@link ClassDesc} describing the new parameter type
+ * @return a {@linkplain MethodTypeDesc} describing the desired method type
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IndexOutOfBoundsException if the index is outside the half-open
+ * range {[0, parameterCount)}
+ */
+ MethodTypeDesc changeParameterType(int index, ClassDesc paramType);
+
+ /**
+ * Returns a {@linkplain MethodTypeDesc} that is identical to this one,
+ * except that a range of parameter types have been removed.
+ *
+ * @param start the index of the first parameter to remove
+ * @param end the index after the last parameter to remove
+ * @return a {@linkplain MethodTypeDesc} describing the desired method type
+ * @throws IndexOutOfBoundsException if {@code start} is outside the half-open
+ * range {[0, parameterCount)}, or {@code end} is outside the closed range
+ * {@code [0, parameterCount]}
+ */
+ MethodTypeDesc dropParameterTypes(int start, int end);
+
+ /**
+ * Returns a {@linkplain MethodTypeDesc} that is identical to this one,
+ * except that a range of additional parameter types have been inserted.
+ *
+ * @param pos the index at which to insert the first inserted parameter
+ * @param paramTypes {@link ClassDesc}s describing the new parameter types
+ * to insert
+ * @return a {@linkplain MethodTypeDesc} describing the desired method type
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IndexOutOfBoundsException if {@code pos} is outside the closed
+ * range {[0, parameterCount]}
+ */
+ MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes);
+
+ /**
+ * Returns the method type descriptor string.
+ *
+ * @return the method type descriptor string
+ * @jvms 4.3.3 Method Descriptors
+ */
+ default String descriptorString() {
+ return String.format("(%s)%s",
+ Stream.of(parameterArray())
+ .map(ClassDesc::descriptorString)
+ .collect(Collectors.joining()),
+ returnType().descriptorString());
+ }
+
+ /**
+ * Returns a human-readable descriptor for this method type, using the
+ * canonical names for parameter and return types.
+ *
+ * @return the human-readable descriptor for this method type
+ */
+ default String displayDescriptor() {
+ return String.format("(%s)%s",
+ Stream.of(parameterArray())
+ .map(ClassDesc::displayName)
+ .collect(Collectors.joining(",")),
+ returnType().displayName());
+ }
+
+ /**
+ * Compares the specified object with this descriptor for equality. Returns
+ * {@code true} if and only if the specified object is also a
+ * {@linkplain MethodTypeDesc} both have the same arity, their return types
+ * are equal, and each pair of corresponding parameter types are equal.
+ *
+ * @param o the other object
+ * @return whether this descriptor is equal to the other object
+ */
+ boolean equals(Object o);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import java.util.List;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
+ * {@link MethodType}. A {@linkplain MethodTypeDescImpl} corresponds to a
+ * {@code Constant_MethodType_info} entry in the constant pool of a classfile.
+ */
+final class MethodTypeDescImpl implements MethodTypeDesc {
+ private final ClassDesc returnType;
+ private final ClassDesc[] argTypes;
+
+ /**
+ * Constructs a {@linkplain MethodTypeDesc} with the specified return type
+ * and parameter types
+ *
+ * @param returnType a {@link ClassDesc} describing the return type
+ * @param argTypes {@link ClassDesc}s describing the parameter types
+ */
+ MethodTypeDescImpl(ClassDesc returnType, ClassDesc[] argTypes) {
+ this.returnType = requireNonNull(returnType);
+ this.argTypes = requireNonNull(argTypes);
+
+ for (ClassDesc cr : argTypes)
+ if (cr.isPrimitive() && cr.descriptorString().equals("V"))
+ throw new IllegalArgumentException("Void parameters not permitted");
+ }
+
+ /**
+ * Creates a {@linkplain MethodTypeDescImpl} given a method descriptor string.
+ *
+ * @param descriptor the method descriptor string
+ * @return a {@linkplain MethodTypeDescImpl} describing the desired method type
+ * @throws IllegalArgumentException if the descriptor string is not a valid
+ * method descriptor
+ * @jvms 4.3.3 Method Descriptors
+ */
+ static MethodTypeDescImpl ofDescriptor(String descriptor) {
+ requireNonNull(descriptor);
+ List<String> types = ConstantUtils.parseMethodDescriptor(descriptor);
+ ClassDesc[] paramTypes = types.stream().skip(1).map(ClassDesc::ofDescriptor).toArray(ClassDesc[]::new);
+ return new MethodTypeDescImpl(ClassDesc.ofDescriptor(types.get(0)), paramTypes);
+ }
+
+ @Override
+ public ClassDesc returnType() {
+ return returnType;
+ }
+
+ @Override
+ public int parameterCount() {
+ return argTypes.length;
+ }
+
+ @Override
+ public ClassDesc parameterType(int index) {
+ return argTypes[index];
+ }
+
+ @Override
+ public List<ClassDesc> parameterList() {
+ return List.of(argTypes);
+ }
+
+ @Override
+ public ClassDesc[] parameterArray() {
+ return argTypes.clone();
+ }
+
+ @Override
+ public MethodTypeDesc changeReturnType(ClassDesc returnType) {
+ return MethodTypeDesc.of(returnType, argTypes);
+ }
+
+ @Override
+ public MethodTypeDesc changeParameterType(int index, ClassDesc paramType) {
+ ClassDesc[] newArgs = argTypes.clone();
+ newArgs[index] = paramType;
+ return MethodTypeDesc.of(returnType, newArgs);
+ }
+
+ @Override
+ public MethodTypeDesc dropParameterTypes(int start, int end) {
+ if (start < 0 || start >= argTypes.length || end < 0 || end > argTypes.length)
+ throw new IndexOutOfBoundsException();
+ else if (start > end)
+ throw new IllegalArgumentException(String.format("Range (%d, %d) not valid for size %d", start, end, argTypes.length));
+ ClassDesc[] newArgs = new ClassDesc[argTypes.length - (end - start)];
+ System.arraycopy(argTypes, 0, newArgs, 0, start);
+ System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
+ return MethodTypeDesc.of(returnType, newArgs);
+ }
+
+ @Override
+ public MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes) {
+ if (pos < 0 || pos > argTypes.length)
+ throw new IndexOutOfBoundsException(pos);
+ ClassDesc[] newArgs = new ClassDesc[argTypes.length + paramTypes.length];
+ System.arraycopy(argTypes, 0, newArgs, 0, pos);
+ System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length);
+ System.arraycopy(argTypes, pos, newArgs, pos+paramTypes.length, argTypes.length - pos);
+ return MethodTypeDesc.of(returnType, newArgs);
+ }
+
+ @Override
+ public MethodType resolveConstantDesc(MethodHandles.Lookup lookup) {
+ return MethodType.fromMethodDescriptorString(descriptorString(), lookup.lookupClass().getClassLoader());
+ }
+
+ /**
+ * Returns {@code true} if this {@linkplain MethodTypeDescImpl} is
+ * equal to another {@linkplain MethodTypeDescImpl}. Equality is
+ * determined by the two descriptors having equal return types and argument
+ * types.
+ *
+ * @param o the {@code MethodTypeDescImpl} to compare to this
+ * {@code MethodTypeDescImpl}
+ * @return {@code true} if the specified {@code MethodTypeDescImpl} is
+ * equals to this {@code MethodTypeDescImpl}.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MethodTypeDescImpl constant = (MethodTypeDescImpl) o;
+
+ return returnType.equals(constant.returnType)
+ && Arrays.equals(argTypes, constant.argTypes);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = returnType.hashCode();
+ result = 31 * result + Arrays.hashCode(argTypes);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("MethodTypeDesc[%s]", displayDescriptor());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/PrimitiveClassDescImpl.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodHandles;
+
+import sun.invoke.util.Wrapper;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for the class
+ * constant corresponding to a primitive type (e.g., {@code int.class}).
+ */
+final class PrimitiveClassDescImpl
+ extends DynamicConstantDesc<Class<?>> implements ClassDesc {
+
+ private final String descriptor;
+
+ /**
+ * Creates a {@linkplain ClassDesc} given a descriptor string for a primitive
+ * type.
+ *
+ * @param descriptor the descriptor string, which must be a one-character
+ * string corresponding to one of the nine base types
+ * @throws IllegalArgumentException if the descriptor string does not
+ * describe a valid primitive type
+ * @jvms 4.3 Descriptors
+ */
+ PrimitiveClassDescImpl(String descriptor) {
+ super(ConstantDescs.BSM_PRIMITIVE_CLASS, requireNonNull(descriptor), ConstantDescs.CD_Class);
+ if (descriptor.length() != 1
+ || "VIJCSBFDZ".indexOf(descriptor.charAt(0)) < 0)
+ throw new IllegalArgumentException(String.format("not a valid primitive type descriptor: %s", descriptor));
+ this.descriptor = descriptor;
+ }
+
+ @Override
+ public String descriptorString() {
+ return descriptor;
+ }
+
+ @Override
+ public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup) {
+ return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveType();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("PrimitiveClassDesc[%s]", displayName());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/ReferenceClassDescImpl.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.constant;
+
+import java.lang.invoke.MethodHandles;
+
+import static java.lang.constant.ConstantUtils.dropFirstAndLastChar;
+import static java.lang.constant.ConstantUtils.internalToBinary;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a class,
+ * interface, or array type. A {@linkplain ReferenceClassDescImpl} corresponds to a
+ * {@code Constant_Class_info} entry in the constant pool of a classfile.
+ */
+final class ReferenceClassDescImpl implements ClassDesc {
+ private final String descriptor;
+
+ /**
+ * Creates a {@linkplain ClassDesc} from a descriptor string for a class or
+ * interface type
+ *
+ * @param descriptor a field descriptor string for a class or interface type
+ * @throws IllegalArgumentException if the descriptor string is not a valid
+ * field descriptor string, or does not describe a class or interface type
+ * @jvms 4.3.2 Field Descriptors
+ */
+ ReferenceClassDescImpl(String descriptor) {
+ requireNonNull(descriptor);
+ int len = ConstantUtils.matchSig(descriptor, 0, descriptor.length());
+ if (len == 0 || len == 1
+ || len != descriptor.length())
+ throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
+ this.descriptor = descriptor;
+ }
+
+ @Override
+ public String descriptorString() {
+ return descriptor;
+ }
+
+ @Override
+ public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
+ throws ReflectiveOperationException {
+ ClassDesc c = this;
+ int depth = ConstantUtils.arrayDepth(descriptorString());
+ for (int i=0; i<depth; i++)
+ c = c.componentType();
+
+ if (c.isPrimitive())
+ return lookup.findClass(descriptorString());
+ else {
+ Class<?> clazz = lookup.findClass(internalToBinary(dropFirstAndLastChar(c.descriptorString())));
+ for (int i = 0; i < depth; i++)
+ clazz = clazz.arrayType();
+ return clazz;
+ }
+ }
+
+ /**
+ * Returns {@code true} if this {@linkplain ReferenceClassDescImpl} is
+ * equal to another {@linkplain ReferenceClassDescImpl}. Equality is
+ * determined by the two class descriptors having equal class descriptor
+ * strings.
+ *
+ * @param o the {@code ClassDesc} to compare to this
+ * {@code ClassDesc}
+ * @return {@code true} if the specified {@code ClassDesc} is
+ * equals to this {@code ClassDesc}.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ClassDesc constant = (ClassDesc) o;
+ return descriptor.equals(constant.descriptorString());
+ }
+
+ @Override
+ public int hashCode() {
+ return descriptor.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ClassDesc[%s]", displayName());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/constant/package-info.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Classes and interfaces to represent <em>nominal descriptors</em> for run-time
+ * entities such as classes or method handles, and classfile entities such as
+ * constant pool entries or {@code invokedynamic} call sites. These classes
+ * are suitable for use in bytecode reading and writing APIs, {@code invokedynamic}
+ * bootstraps, bytecode intrinsic APIs, and compile-time or link-time program
+ * analysis tools.
+ *
+ * <p>Every API that reads and writes bytecode instructions needs to model the
+ * operands to these instructions and other classfile structures (such as entries
+ * in the bootstrap methods table or stack maps, which frequently reference
+ * entries in the classfile constant pool.) Such entries can denote values of
+ * fundamental types, such as strings or integers; parts of a program, such as
+ * classes or method handles; or values of arbitrary user-defined types. The
+ * {@link java.lang.constant.ConstantDesc} hierarchy provides a representation of
+ * constant pool entries in nominal form that is convenient for APIs to model
+ * operands of bytecode instructions.
+ *
+ * <h2><a id="nominal"></a>Nominal Descriptors</h2>
+ *
+ * <p>A {@link java.lang.constant.ConstantDesc} is a description of a constant
+ * value. Such a description is the <em>nominal form</em> of the constant value;
+ * it is not the value itself, but rather a "recipe" for describing the value,
+ * storing the value in a constant pool entry, or reconstituting the value given
+ * a class loading context. Every {@link java.lang.constant.ConstantDesc}
+ * knows how to <em>resolve</em> itself -- compute the value that it describes --
+ * via {@link java.lang.constant.ConstantDesc#resolveConstantDesc(java.lang.invoke.MethodHandles.Lookup)}.
+ * This allows an API which accepts {@link java.lang.constant.ConstantDesc}
+ * objects to evaluate them reflectively, provided that the classes and methods
+ * referenced in their nominal description are present and accessible.
+ *
+ * <p>The subtypes of {@link java.lang.constant.ConstantDesc} describe various kinds
+ * of constant values. For each type of loadable constant pool entry defined in JVMS 4.4,
+ * there is a corresponding subtype of {@link java.lang.constant.ConstantDesc}:
+ * {@link java.lang.constant.ClassDesc}, {@link java.lang.constant.MethodTypeDesc},
+ * {@link java.lang.constant.DirectMethodHandleDesc}, {@link java.lang.String},
+ * {@link java.lang.Integer}, {@link java.lang.Long}, {@link java.lang.Float},
+ * {@link java.lang.Double}, and {@link java.lang.constant.DynamicConstantDesc}. These classes
+ * provide type-specific accessor methods to extract the nominal information for
+ * that kind of constant. When a bytecode-writing API encounters a {@link java.lang.constant.ConstantDesc},
+ * it should examine it to see which of these types it is, cast it, extract
+ * its nominal information, and generate the corresponding entry to the constant pool.
+ * When a bytecode-reading API encounters a constant pool entry, it can
+ * convert it to the appropriate type of nominal descriptor. For dynamic
+ * constants, bytecode-reading APIs may wish to use the factory
+ * {@link java.lang.constant.DynamicConstantDesc#ofCanonical(DirectMethodHandleDesc, java.lang.String, ClassDesc, ConstantDesc[])},
+ * which will inspect the bootstrap and, for well-known bootstraps, return
+ * a more specific subtype of {@link java.lang.constant.DynamicConstantDesc}, such as
+ * {@link java.lang.Enum.EnumDesc}.
+ *
+ * <p>Another way to obtain the nominal description of a value is to ask the value
+ * itself. A {@link java.lang.constant.Constable} is a type whose values
+ * can describe themselves in nominal form as a {@link java.lang.constant.ConstantDesc}.
+ * Fundamental types such as {@link java.lang.String} and {@link java.lang.Class}
+ * implement {@link java.lang.constant.Constable}, as can user-defined
+ * classes. Entities that generate classfiles (such as compilers) can introspect
+ * over constable objects to obtain a more efficient way to represent their values
+ * in classfiles.
+ *
+ * <p>This package also includes {@link java.lang.constant.DynamicCallSiteDesc},
+ * which represents a (non-loadable) {@code Constant_InvokeDynamic_info} constant
+ * pool entry. It describes the bootstrap method, invocation name and type,
+ * and bootstrap arguments associated with an {@code invokedynamic} instruction.
+ * It is also suitable for describing {@code invokedynamic} call sites in bytecode
+ * reading and writing APIs.
+ *
+ * @jvms 4.4 The Constant Pool
+ *
+ * @since 12
+ */
+package java.lang.constant;
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Sun Dec 09 12:36:24 2018 -0500
@@ -28,10 +28,19 @@
import jdk.internal.HotSpotIntrinsicCandidate;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
+import java.lang.constant.DirectMethodHandleDesc;
+import java.lang.constant.MethodHandleDesc;
+import java.lang.constant.MethodTypeDesc;
import java.util.Arrays;
import java.util.Objects;
+import java.util.Optional;
+import static java.lang.invoke.MethodHandleInfo.*;
import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* A method handle is a typed, directly executable reference to an underlying method,
@@ -428,7 +437,7 @@
* @author John Rose, JSR 292 EG
* @since 1.7
*/
-public abstract class MethodHandle {
+public abstract class MethodHandle implements Constable {
/**
* Internal marker interface which distinguishes (to the Java compiler)
@@ -1512,6 +1521,60 @@
}
/**
+ * Return a nominal descriptor for this instance, if one can be
+ * constructed, or an empty {@link Optional} if one cannot be.
+ *
+ * @return An {@link Optional} containing the resulting nominal descriptor,
+ * or an empty {@link Optional} if one cannot be constructed.
+ * @since 12
+ */
+ @Override
+ public Optional<MethodHandleDesc> describeConstable() {
+ MethodHandleInfo info;
+ ClassDesc owner;
+ String name;
+ MethodTypeDesc type;
+ boolean isInterface;
+ try {
+ info = IMPL_LOOKUP.revealDirect(this);
+ isInterface = info.getDeclaringClass().isInterface();
+ owner = info.getDeclaringClass().describeConstable().orElseThrow();
+ type = info.getMethodType().describeConstable().orElseThrow();
+ name = info.getName();
+ }
+ catch (Exception e) {
+ return Optional.empty();
+ }
+
+ switch (info.getReferenceKind()) {
+ case REF_getField:
+ return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.GETTER, owner, name, type.returnType()));
+ case REF_putField:
+ return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.SETTER, owner, name, type.parameterType(0)));
+ case REF_getStatic:
+ return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.STATIC_GETTER, owner, name, type.returnType()));
+ case REF_putStatic:
+ return Optional.of(MethodHandleDesc.ofField(DirectMethodHandleDesc.Kind.STATIC_SETTER, owner, name, type.parameterType(0)));
+ case REF_invokeVirtual:
+ return Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.VIRTUAL, owner, name, type));
+ case REF_invokeStatic:
+ return isInterface ?
+ Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_STATIC, owner, name, type)) :
+ Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, owner, name, type));
+ case REF_invokeSpecial:
+ return isInterface ?
+ Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_SPECIAL, owner, name, type)) :
+ Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.SPECIAL, owner, name, type));
+ case REF_invokeInterface:
+ return Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.INTERFACE_VIRTUAL, owner, name, type));
+ case REF_newInvokeSpecial:
+ return Optional.of(MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.CONSTRUCTOR, owner, name, type));
+ default:
+ return Optional.empty();
+ }
+ }
+
+ /**
* Returns a string representation of the method handle,
* starting with the string {@code "MethodHandle"} and
* ending with the string representation of the method handle's type.
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -25,21 +25,30 @@
package java.lang.invoke;
-import jdk.internal.vm.annotation.Stable;
-import sun.invoke.util.Wrapper;
-import java.lang.ref.WeakReference;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.Constable;
+import java.lang.constant.MethodTypeDesc;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.NoSuchElementException;
import java.util.Objects;
+import java.util.Optional;
import java.util.StringJoiner;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Stream;
+
+import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.BytecodeDescriptor;
-import static java.lang.invoke.MethodHandleStatics.*;
import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
/**
* A method type represents the arguments and return type accepted and
@@ -91,7 +100,10 @@
* @since 1.7
*/
public final
-class MethodType implements java.io.Serializable {
+class MethodType
+ implements Constable,
+ TypeDescriptor.OfMethod<Class<?>, MethodType>,
+ java.io.Serializable {
private static final long serialVersionUID = 292L; // {rtype, {ptype...}}
// The rtype and ptypes fields define the structural identity of the method type:
@@ -1175,10 +1187,43 @@
return desc;
}
+ /**
+ * Return a field type descriptor string for this type
+ *
+ * @return the descriptor string
+ * @jvms 4.3.2 Field Descriptors
+ * @since 12
+ */
+ @Override
+ public String descriptorString() {
+ return toMethodDescriptorString();
+ }
+
/*non-public*/ static String toFieldDescriptorString(Class<?> cls) {
return BytecodeDescriptor.unparse(cls);
}
+ /**
+ * Return a nominal descriptor for this instance, if one can be
+ * constructed, or an empty {@link Optional} if one cannot be.
+ *
+ * @return An {@link Optional} containing the resulting nominal descriptor,
+ * or an empty {@link Optional} if one cannot be constructed.
+ * @since 12
+ */
+ @Override
+ public Optional<MethodTypeDesc> describeConstable() {
+ try {
+ return Optional.of(MethodTypeDesc.of(returnType().describeConstable().orElseThrow(),
+ Stream.of(parameterArray())
+ .map(p -> p.describeConstable().orElseThrow())
+ .toArray(ClassDesc[]::new)));
+ }
+ catch (NoSuchElementException e) {
+ return Optional.empty();
+ }
+ }
+
/// Serialization.
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/TypeDescriptor.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import java.util.List;
+
+/**
+ * An entity that has a field or method type descriptor
+ *
+ * @jvms 4.3.2 Field Descriptors
+ * @jvms 4.3.3 Method Descriptors
+ *
+ * @since 12
+ */
+public interface TypeDescriptor {
+ /**
+ * Return the type descriptor string for this instance, which must be either
+ * a field type descriptor (JVMS 4.3.2) or method type descriptor (JVMS 4.3.3).
+ *
+ * @return the type descriptor
+ * @jvms 4.3.2 Field Descriptors
+ * @jvms 4.3.3 Method Descriptors
+ */
+ String descriptorString();
+
+
+ /**
+ * An entity that has a field type descriptor
+ *
+ * @param <F> the class implementing {@linkplain TypeDescriptor.OfField}
+ * @jvms 4.3.2 Field Descriptors
+ * @since 12
+ */
+ interface OfField<F extends TypeDescriptor.OfField<F>> extends TypeDescriptor {
+ /**
+ * Does this field descriptor describe an array type?
+ * @return whether this field descriptor describes an array type
+ */
+ boolean isArray();
+
+ /**
+ * Does this field descriptor describe a primitive type?
+ * @return whether this field descriptor describes a primitive type
+ */
+ boolean isPrimitive();
+
+ /**
+ * If this field descriptor describes an array type, return
+ * a descriptor for its component type, otherwise return {@code null}.
+ * @return the component type, or {@code null} if this field descriptor does
+ * not describe an array type
+ */
+ F componentType();
+
+ /**
+ * Return a descriptor for the array type whose component type is described by this
+ * descriptor
+ * @return the descriptor for the array type
+ */
+ F arrayType();
+ }
+
+
+ /**
+ * An entity that has a method type descriptor
+ *
+ * @param <F> the type representing field type descriptors
+ * @param <M> the class implementing {@linkplain TypeDescriptor.OfMethod}
+ * @jvms 4.3.2 Field Descriptors
+ * @jvms 4.3.3 Method Descriptors
+ * @since 12
+ */
+ interface OfMethod<F extends TypeDescriptor.OfField<F>, M extends TypeDescriptor.OfMethod<F, M>>
+ extends TypeDescriptor {
+
+ /**
+ * Return the number of parameters in the method type
+ * @return the number of parameters
+ */
+ int parameterCount();
+
+ /**
+ * Return a field descriptor describing the requested parameter of the method type
+ * described by this descriptor
+ * @param i the index of the parameter
+ * @return a field descriptor for the requested parameter type
+ * @throws IndexOutOfBoundsException if the index is outside the half-open
+ * range {[0, parameterCount)}
+ */
+ F parameterType(int i);
+
+ /**
+ * Return a field descriptor describing the return type of the method type described
+ * by this descriptor
+ * @return a field descriptor for the return type
+ */
+ F returnType();
+
+ /**
+ * Return an array of field descriptors for the parameter types of the method type
+ * described by this descriptor
+ * @return field descriptors for the parameter types
+ */
+ F[] parameterArray();
+
+ /**
+ * Return an immutable list of field descriptors for the parameter types of the method type
+ * described by this descriptor
+ * @return field descriptors for the parameter types
+ */
+ List<F> parameterList();
+
+ /**
+ * Return a method descriptor that is identical to this one, except that the return
+ * type has been changed to the specified type
+ *
+ * @param newReturn a field descriptor for the new return type
+ * @throws NullPointerException if any argument is {@code null}
+ * @return the new method descriptor
+ */
+ M changeReturnType(F newReturn);
+
+ /**
+ * Return a method descriptor that is identical to this one,
+ * except that a single parameter type has been changed to the specified type.
+ *
+ * @param index the index of the parameter to change
+ * @param paramType a field descriptor describing the new parameter type
+ * @return the new method descriptor
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IndexOutOfBoundsException if the index is outside the half-open
+ * range {[0, parameterCount)}
+ */
+ M changeParameterType(int index, F paramType);
+
+ /**
+ * Return a method descriptor that is identical to this one,
+ * except that a range of parameter types have been removed.
+ *
+ * @param start the index of the first parameter to remove
+ * @param end the index after the last parameter to remove
+ * @return the new method descriptor
+ *
+ * @throws IndexOutOfBoundsException if {@code start} is outside the half-open
+ * range {@code [0, parameterCount)}, or {@code end} is outside the closed range
+ * {@code [0, parameterCount]}, or if {@code start > end}
+ */
+ M dropParameterTypes(int start, int end);
+
+ /**
+ * Return a method descriptor that is identical to this one,
+ * except that a range of additional parameter types have been inserted.
+ *
+ * @param pos the index at which to insert the first inserted parameter
+ * @param paramTypes field descriptors describing the new parameter types
+ * to insert
+ * @return the new method descriptor
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IndexOutOfBoundsException if {@code pos} is outside the closed
+ * range {[0, parameterCount]}
+ */
+ @SuppressWarnings("unchecked")
+ M insertParameterTypes(int pos, F... paramTypes);
+ }
+}
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java Sun Dec 09 12:36:24 2018 -0500
@@ -25,19 +25,26 @@
package java.lang.invoke;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
+import java.lang.constant.ConstantDescs;
+import java.lang.constant.DirectMethodHandleDesc;
+import java.lang.constant.DynamicConstantDesc;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Stable;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
-import static java.lang.invoke.MethodHandleStatics.newInternalError;
/**
* A VarHandle is a dynamically strongly typed reference to a variable, or to a
@@ -437,7 +444,7 @@
* @see MethodType
* @since 9
*/
-public abstract class VarHandle {
+public abstract class VarHandle implements Constable {
final VarForm vform;
VarHandle(VarForm vform) {
@@ -1857,6 +1864,32 @@
}
}
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ VarHandle that = (VarHandle) o;
+ return accessModeType(AccessMode.GET).equals(that.accessModeType(AccessMode.GET)) &&
+ internalEquals(that);
+ }
+
+ abstract boolean internalEquals(VarHandle vh);
+
+ @Override
+ public final int hashCode() {
+ return 31 * accessModeType(AccessMode.GET).hashCode() + internalHashCode();
+ }
+
+ abstract int internalHashCode();
+
+ @Override
+ public final String toString() {
+ return String.format("VarHandle[varType=%s, coord=%s]",
+ varType().getName(),
+ coordinateTypes());
+ }
+
/**
* Returns the variable type of variables referenced by this VarHandle.
*
@@ -1951,6 +1984,20 @@
}
}
+ /**
+ * Return a nominal descriptor for this instance, if one can be
+ * constructed, or an empty {@link Optional} if one cannot be.
+ *
+ * @return An {@link Optional} containing the resulting nominal descriptor,
+ * or an empty {@link Optional} if one cannot be constructed.
+ * @since 12
+ */
+ @Override
+ public Optional<VarHandleDesc> describeConstable() {
+ // partial function for field and array only
+ return Optional.empty();
+ }
+
@Stable
TypesAndInvokers typesAndInvokers;
@@ -2082,4 +2129,163 @@
public static void storeStoreFence() {
UNSAFE.storeStoreFence();
}
+
+ /**
+ * A <a href="package-summary.html#nominal">nominal descriptor</a> for a
+ * {@link VarHandle} constant.
+ *
+ * @since 12
+ */
+ public static final class VarHandleDesc extends DynamicConstantDesc<VarHandle> {
+
+ /**
+ * Kinds of variable handle descs
+ */
+ private enum Kind {
+ FIELD(ConstantDescs.BSM_VARHANDLE_FIELD),
+ STATIC_FIELD(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD),
+ ARRAY(ConstantDescs.BSM_VARHANDLE_ARRAY);
+
+ final DirectMethodHandleDesc bootstrapMethod;
+
+ Kind(DirectMethodHandleDesc bootstrapMethod) {
+ this.bootstrapMethod = bootstrapMethod;
+ }
+
+ ConstantDesc[] toBSMArgs(ClassDesc declaringClass, ClassDesc varType) {
+ switch (this) {
+ case FIELD:
+ case STATIC_FIELD:
+ return new ConstantDesc[] {declaringClass, varType };
+ case ARRAY:
+ return new ConstantDesc[] {declaringClass };
+ default:
+ throw new InternalError("Cannot reach here");
+ }
+ }
+ }
+
+ private final Kind kind;
+ private final ClassDesc declaringClass;
+ private final ClassDesc varType;
+
+ /**
+ * Construct a {@linkplain VarHandleDesc} given a kind, name, and declaring
+ * class.
+ *
+ * @param kind the kind of of the var handle
+ * @param name the unqualified name of the field, for field var handles; otherwise ignored
+ * @param declaringClass a {@link ClassDesc} describing the declaring class,
+ * for field var handles
+ * @param varType a {@link ClassDesc} describing the type of the variable
+ * @throws NullPointerException if any required argument is null
+ * @jvms 4.2.2 Unqualified Names
+ */
+ private VarHandleDesc(Kind kind, String name, ClassDesc declaringClass, ClassDesc varType) {
+ super(kind.bootstrapMethod, name,
+ ConstantDescs.CD_VarHandle,
+ kind.toBSMArgs(declaringClass, varType));
+ this.kind = kind;
+ this.declaringClass = declaringClass;
+ this.varType = varType;
+ }
+
+ /**
+ * Returns a {@linkplain VarHandleDesc} corresponding to a {@link VarHandle}
+ * for an instance field.
+ *
+ * @param name the unqualifed name of the field
+ * @param declaringClass a {@link ClassDesc} describing the declaring class,
+ * for field var handles
+ * @param fieldType a {@link ClassDesc} describing the type of the field
+ * @return the {@linkplain VarHandleDesc}
+ * @throws NullPointerException if any of the arguments are null
+ * @jvms 4.2.2 Unqualified Names
+ */
+ public static VarHandleDesc ofField(ClassDesc declaringClass, String name, ClassDesc fieldType) {
+ Objects.requireNonNull(declaringClass);
+ Objects.requireNonNull(name);
+ Objects.requireNonNull(fieldType);
+ return new VarHandleDesc(Kind.FIELD, name, declaringClass, fieldType);
+ }
+
+ /**
+ * Returns a {@linkplain VarHandleDesc} corresponding to a {@link VarHandle}
+ * for a static field.
+ *
+ * @param name the unqualified name of the field
+ * @param declaringClass a {@link ClassDesc} describing the declaring class,
+ * for field var handles
+ * @param fieldType a {@link ClassDesc} describing the type of the field
+ * @return the {@linkplain VarHandleDesc}
+ * @throws NullPointerException if any of the arguments are null
+ * @jvms 4.2.2 Unqualified Names
+ */
+ public static VarHandleDesc ofStaticField(ClassDesc declaringClass, String name, ClassDesc fieldType) {
+ Objects.requireNonNull(declaringClass);
+ Objects.requireNonNull(name);
+ Objects.requireNonNull(fieldType);
+ return new VarHandleDesc(Kind.STATIC_FIELD, name, declaringClass, fieldType);
+ }
+
+ /**
+ * Returns a {@linkplain VarHandleDesc} corresponding to a {@link VarHandle}
+ * for for an array type.
+ *
+ * @param arrayClass a {@link ClassDesc} describing the type of the array
+ * @return the {@linkplain VarHandleDesc}
+ * @throws NullPointerException if any of the arguments are null
+ */
+ public static VarHandleDesc ofArray(ClassDesc arrayClass) {
+ Objects.requireNonNull(arrayClass);
+ if (!arrayClass.isArray())
+ throw new IllegalArgumentException("Array class argument not an array: " + arrayClass);
+ return new VarHandleDesc(Kind.ARRAY, ConstantDescs.DEFAULT_NAME, arrayClass, arrayClass.componentType());
+ }
+
+ /**
+ * Returns a {@link ClassDesc} describing the type of the variable described
+ * by this descriptor.
+ *
+ * @return the variable type
+ */
+ public ClassDesc varType() {
+ return varType;
+ }
+
+ @Override
+ public VarHandle resolveConstantDesc(MethodHandles.Lookup lookup)
+ throws ReflectiveOperationException {
+ switch (kind) {
+ case FIELD:
+ return lookup.findVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup),
+ constantName(),
+ (Class<?>) varType.resolveConstantDesc(lookup));
+ case STATIC_FIELD:
+ return lookup.findStaticVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup),
+ constantName(),
+ (Class<?>) varType.resolveConstantDesc(lookup));
+ case ARRAY:
+ return MethodHandles.arrayElementVarHandle((Class<?>) declaringClass.resolveConstantDesc(lookup));
+ default:
+ throw new InternalError("Cannot reach here");
+ }
+ }
+
+ @Override
+ public String toString() {
+ switch (kind) {
+ case FIELD:
+ case STATIC_FIELD:
+ return String.format("VarHandleDesc[%s%s.%s:%s]",
+ (kind == Kind.STATIC_FIELD) ? "static " : "",
+ declaringClass.displayName(), constantName(), varType.displayName());
+ case ARRAY:
+ return String.format("VarHandleDesc[%s[]]", declaringClass.displayName());
+ default:
+ throw new InternalError("Cannot reach here");
+ }
+ }
+ }
+
}
--- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -25,6 +25,9 @@
package java.lang.invoke;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
final class VarHandles {
@@ -144,6 +147,38 @@
}
}
+ // Required by instance field handles
+ static Field getFieldFromReceiverAndOffset(Class<?> receiverType,
+ long offset,
+ Class<?> fieldType) {
+ for (Field f : receiverType.getDeclaredFields()) {
+ if (Modifier.isStatic(f.getModifiers())) continue;
+
+ if (offset == UNSAFE.objectFieldOffset(f)) {
+ assert f.getType() == fieldType;
+ return f;
+ }
+ }
+ throw new InternalError("Field not found at offset");
+ }
+
+ // Required by instance static field handles
+ static Field getStaticFieldFromBaseAndOffset(Object base,
+ long offset,
+ Class<?> fieldType) {
+ // @@@ This is a little fragile assuming the base is the class
+ Class<?> receiverType = (Class<?>) base;
+ for (Field f : receiverType.getDeclaredFields()) {
+ if (!Modifier.isStatic(f.getModifiers())) continue;
+
+ if (offset == UNSAFE.staticFieldOffset(f)) {
+ assert f.getType() == fieldType;
+ return f;
+ }
+ }
+ throw new InternalError("Static field not found at offset");
+ }
+
static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
if (!arrayClass.isArray())
throw new IllegalArgumentException("not an array: " + arrayClass);
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -27,7 +27,9 @@
import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.ForceInline;
+import java.lang.invoke.VarHandle.VarHandleDesc;
import java.util.Objects;
+import java.util.Optional;
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
@@ -61,6 +63,30 @@
return accessMode.at.accessModeType(receiverType, {#if[Object]?fieldType:$type$.class});
}
+ @Override
+ final boolean internalEquals(VarHandle vh) {
+ FieldInstanceReadOnly that = (FieldInstanceReadOnly) vh;
+ return fieldOffset == that.fieldOffset;
+ }
+
+ @Override
+ final int internalHashCode() {
+ return Long.hashCode(fieldOffset);
+ }
+
+ @Override
+ public Optional<VarHandleDesc> describeConstable() {
+ var receiverTypeRef = receiverType.describeConstable();
+ var fieldTypeRef = {#if[Object]?fieldType:$type$.class}.describeConstable();
+ if (!receiverTypeRef.isPresent() || !fieldTypeRef.isPresent())
+ return Optional.empty();
+
+ // Reflect on this VarHandle to extract the field name
+ String name = VarHandles.getFieldFromReceiverAndOffset(
+ receiverType, fieldOffset, {#if[Object]?fieldType:$type$.class}).getName();
+ return Optional.of(VarHandleDesc.ofField(receiverTypeRef.get(), name, fieldTypeRef.get()));
+ }
+
@ForceInline
static $type$ get(FieldInstanceReadOnly handle, Object holder) {
return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
@@ -324,6 +350,32 @@
}
@Override
+ final boolean internalEquals(VarHandle vh) {
+ FieldStaticReadOnly that = (FieldStaticReadOnly) vh;
+ return base == that.base && fieldOffset == that.fieldOffset;
+ }
+
+ @Override
+ final int internalHashCode() {
+ return 31 * Long.hashCode(fieldOffset) + base.hashCode();
+ }
+
+ @Override
+ public Optional<VarHandleDesc> describeConstable() {
+ var fieldTypeRef = {#if[Object]?fieldType:$type$.class}.describeConstable();
+ if (!fieldTypeRef.isPresent())
+ return Optional.empty();
+
+ // Reflect on this VarHandle to extract the field name
+ var staticField = VarHandles.getStaticFieldFromBaseAndOffset(
+ base, fieldOffset, {#if[Object]?fieldType:$type$.class});
+ var receiverTypeRef = staticField.getDeclaringClass().describeConstable();
+ if (!receiverTypeRef.isPresent())
+ return Optional.empty();
+ return Optional.of(VarHandleDesc.ofStaticField(receiverTypeRef.get(), staticField.getName(), fieldTypeRef.get()));
+ }
+
+ @Override
final MethodType accessModeTypeUncached(AccessMode accessMode) {
return accessMode.at.accessModeType(null, {#if[Object]?fieldType:$type$.class});
}
@@ -588,6 +640,29 @@
}
@Override
+ final boolean internalEquals(VarHandle vh) {
+ // Equality of access mode types of AccessMode.GET is sufficient for
+ // equality checks
+ return true;
+ }
+
+ @Override
+ final int internalHashCode() {
+ // The hash code of the access mode types of AccessMode.GET is
+ // sufficient for hash code generation
+ return 0;
+ }
+
+ @Override
+ public Optional<VarHandleDesc> describeConstable() {
+ var arrayTypeRef = {#if[Object]?arrayType:$type$[].class}.describeConstable();
+ if (!arrayTypeRef.isPresent())
+ return Optional.empty();
+
+ return Optional.of(VarHandleDesc.ofArray(arrayTypeRef.get()));
+ }
+
+ @Override
final MethodType accessModeTypeUncached(AccessMode accessMode) {
return accessMode.at.accessModeType({#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
}
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template Sun Dec 09 12:36:24 2018 -0500
@@ -67,6 +67,17 @@
super(form);
this.be = be;
}
+
+ @Override
+ final boolean internalEquals(VarHandle vh) {
+ ByteArrayViewVarHandle that = (ByteArrayViewVarHandle) vh;
+ return be == that.be;
+ }
+
+ @Override
+ final int internalHashCode() {
+ return Boolean.hashCode(be);
+ }
}
static final class ArrayHandle extends ByteArrayViewVarHandle {
--- a/src/java.base/share/classes/module-info.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/module-info.java Sun Dec 09 12:36:24 2018 -0500
@@ -79,6 +79,7 @@
exports java.io;
exports java.lang;
exports java.lang.annotation;
+ exports java.lang.constant;
exports java.lang.invoke;
exports java.lang.module;
exports java.lang.ref;
--- a/src/java.base/share/classes/sun/invoke/util/Wrapper.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/java.base/share/classes/sun/invoke/util/Wrapper.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -47,6 +47,7 @@
private final Class<?> wrapperType;
private final Class<?> primitiveType;
private final char basicTypeChar;
+ private final String basicTypeString;
private final Object emptyArray;
private final int format;
private final String wrapperSimpleName;
@@ -56,6 +57,7 @@
this.wrapperType = wtype;
this.primitiveType = ptype;
this.basicTypeChar = tchar;
+ this.basicTypeString = new String(new char[] {this.basicTypeChar});
this.emptyArray = emptyArray;
this.format = format;
this.wrapperSimpleName = wtypeName;
@@ -459,6 +461,11 @@
*/
public char basicTypeChar() { return basicTypeChar; }
+ /** What is the bytecode signature string for this wrapper's
+ * primitive type?
+ */
+ public String basicTypeString() { return basicTypeString; }
+
/** What is the simple name of the wrapper type?
*/
public String wrapperSimpleName() { return wrapperSimpleName; }
@@ -581,9 +588,8 @@
* Returns null for {@code VOID}.
*/
public Object wrap(int x) {
- if (basicTypeChar == 'L') return (Integer)x;
switch (basicTypeChar) {
- case 'L': throw newIllegalArgumentException("cannot wrap to object type");
+ case 'L': return (Integer)x;
case 'V': return null;
case 'I': return Integer.valueOf(x);
case 'J': return Long.valueOf(x);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Sat Dec 08 18:52:57 2018 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Sun Dec 09 12:36:24 2018 -0500
@@ -71,6 +71,16 @@
*/
public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter {
+ private static final Set<String> suppressSubtypesSet
+ = Set.of("java.lang.Object",
+ "org.omg.CORBA.Object");
+
+ private static final Set<String> suppressImplementingSet
+ = Set.of( "java.lang.Cloneable",
+ "java.lang.constant.Constable",
+ "java.lang.constant.ConstantDesc",
+ "java.io.Serializable");
+
protected final TypeElement typeElement;
protected final ClassTree classtree;
@@ -370,9 +380,10 @@
@Override
public void addSubClassInfo(Content classInfoTree) {
if (utils.isClass(typeElement)) {
- if (typeElement.getQualifiedName().contentEquals("java.lang.Object") ||
- typeElement.getQualifiedName().contentEquals("org.omg.CORBA.Object")) {
- return; // Don't generate the list, too huge
+ for (String s : suppressSubtypesSet) {
+ if (typeElement.getQualifiedName().contentEquals(s)) {
+ return; // Don't generate the list, too huge
+ }
}
Set<TypeElement> subclasses = classtree.directSubClasses(typeElement, false);
if (!subclasses.isEmpty()) {
@@ -412,9 +423,10 @@
if (!utils.isInterface(typeElement)) {
return;
}
- if (typeElement.getQualifiedName().contentEquals("java.lang.Cloneable") ||
- typeElement.getQualifiedName().contentEquals("java.io.Serializable")) {
- return; // Don't generate the list, too big
+ for (String s : suppressImplementingSet) {
+ if (typeElement.getQualifiedName().contentEquals(s)) {
+ return; // Don't generate the list, too huge
+ }
}
Set<TypeElement> implcl = classtree.implementingClasses(typeElement);
if (!implcl.isEmpty()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/ClassDescTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.lang.invoke.MethodHandles;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.ConstantDescs;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * @test
+ * @compile ClassDescTest.java
+ * @run testng ClassDescTest
+ * @summary unit tests for java.lang.constant.ClassDesc
+ */
+@Test
+public class ClassDescTest extends SymbolicDescTest {
+
+ private void testClassDesc(ClassDesc r) throws ReflectiveOperationException {
+ testSymbolicDesc(r);
+
+ // Test descriptor accessor, factory, equals
+ assertEquals(r, ClassDesc.ofDescriptor(r.descriptorString()));
+
+ if (!r.descriptorString().equals("V")) {
+ assertEquals(r, r.arrayType().componentType());
+ // Commutativity: array -> resolve -> componentType -> toSymbolic
+ assertEquals(r, ((Class<?>) r.arrayType().resolveConstantDesc(LOOKUP)).getComponentType().describeConstable().orElseThrow());
+ // Commutativity: resolve -> array -> toSymbolic -> component type
+ assertEquals(r, Array.newInstance(((Class<?>) r.resolveConstantDesc(LOOKUP)), 0).getClass().describeConstable().orElseThrow().componentType());
+ }
+
+ if (r.isArray()) {
+ assertEquals(r, r.componentType().arrayType());
+ assertEquals(r, ((Class<?>) r.resolveConstantDesc(LOOKUP)).getComponentType().describeConstable().orElseThrow().arrayType());
+ assertEquals(r, Array.newInstance(((Class<?>) r.componentType().resolveConstantDesc(LOOKUP)), 0).getClass().describeConstable().orElseThrow());
+ }
+ }
+
+ private void testClassDesc(ClassDesc r, Class<?> c) throws ReflectiveOperationException {
+ testClassDesc(r);
+
+ assertEquals(r.resolveConstantDesc(LOOKUP), c);
+ assertEquals(c.describeConstable().orElseThrow(), r);
+ assertEquals(ClassDesc.ofDescriptor(c.descriptorString()), r);
+ }
+
+ public void testSymbolicDescsConstants() throws ReflectiveOperationException {
+ int tested = 0;
+ Field[] fields = ConstantDescs.class.getDeclaredFields();
+ for (Field f : fields) {
+ try {
+ if (f.getType().equals(ClassDesc.class)
+ && ((f.getModifiers() & Modifier.STATIC) != 0)
+ && ((f.getModifiers() & Modifier.PUBLIC) != 0)) {
+ ClassDesc cr = (ClassDesc) f.get(null);
+ Class c = (Class)cr.resolveConstantDesc(MethodHandles.lookup());
+ testClassDesc(cr, c);
+ ++tested;
+ }
+ }
+ catch (Throwable e) {
+ System.out.println(e.getMessage());
+ fail("Error testing field " + f.getName(), e);
+ }
+ }
+
+ assertTrue(tested > 0);
+ }
+
+ public void testPrimitiveClassDesc() throws ReflectiveOperationException {
+ for (Primitives p : Primitives.values()) {
+ List<ClassDesc> descs = List.of(ClassDesc.ofDescriptor(p.descriptor),
+ p.classDesc,
+ (ClassDesc) p.clazz.describeConstable().orElseThrow());
+ for (ClassDesc c : descs) {
+ testClassDesc(c, p.clazz);
+ assertTrue(c.isPrimitive());
+ assertEquals(p.descriptor, c.descriptorString());
+ assertEquals(p.name, c.displayName());
+ descs.forEach(cc -> assertEquals(c, cc));
+ if (p != Primitives.VOID) {
+ testClassDesc(c.arrayType(), p.arrayClass);
+ assertEquals(c, ((ClassDesc) p.arrayClass.describeConstable().orElseThrow()).componentType());
+ assertEquals(c, p.classDesc.arrayType().componentType());
+ }
+ }
+
+ for (Primitives other : Primitives.values()) {
+ ClassDesc otherDescr = ClassDesc.ofDescriptor(other.descriptor);
+ if (p != other)
+ descs.forEach(c -> assertNotEquals(c, otherDescr));
+ else
+ descs.forEach(c -> assertEquals(c, otherDescr));
+ }
+ }
+ }
+
+ public void testSimpleClassDesc() throws ReflectiveOperationException {
+
+ List<ClassDesc> stringClassDescs = Arrays.asList(ClassDesc.ofDescriptor("Ljava/lang/String;"),
+ ClassDesc.of("java.lang", "String"),
+ ClassDesc.of("java.lang.String"),
+ ClassDesc.of("java.lang.String").arrayType().componentType(),
+ String.class.describeConstable().orElseThrow());
+ for (ClassDesc r : stringClassDescs) {
+ testClassDesc(r, String.class);
+ assertFalse(r.isPrimitive());
+ assertEquals("Ljava/lang/String;", r.descriptorString());
+ assertEquals("String", r.displayName());
+ assertEquals(r.arrayType().resolveConstantDesc(LOOKUP), String[].class);
+ stringClassDescs.forEach(rr -> assertEquals(r, rr));
+ }
+
+ testClassDesc(ClassDesc.of("java.lang.String").arrayType(), String[].class);
+ testClassDesc(ClassDesc.of("java.util.Map").nested("Entry"), Map.Entry.class);
+
+ ClassDesc thisClassDesc = ClassDesc.ofDescriptor("LClassDescTest;");
+ assertEquals(thisClassDesc, ClassDesc.of("", "ClassDescTest"));
+ assertEquals(thisClassDesc, ClassDesc.of("ClassDescTest"));
+ assertEquals(thisClassDesc.displayName(), "ClassDescTest");
+ testClassDesc(thisClassDesc, ClassDescTest.class);
+ }
+
+ public void testPackageName() {
+ assertEquals("com.foo", ClassDesc.of("com.foo.Bar").packageName());
+ assertEquals("com.foo", ClassDesc.of("com.foo.Bar").nested("Baz").packageName());
+ assertEquals("", ClassDesc.of("Bar").packageName());
+ assertEquals("", ClassDesc.of("Bar").nested("Baz").packageName());
+ assertEquals("", ClassDesc.of("Bar").nested("Baz", "Foo").packageName());
+
+ assertEquals("", ConstantDescs.CD_int.packageName());
+ assertEquals("", ConstantDescs.CD_int.arrayType().packageName());
+ assertEquals("", ConstantDescs.CD_String.arrayType().packageName());
+ assertEquals("", ClassDesc.of("Bar").arrayType().packageName());
+ }
+
+ private void testBadArrayRank(ClassDesc cr) {
+ try {
+ cr.arrayType(-1);
+ fail("");
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+
+ public void testArrayClassDesc() throws ReflectiveOperationException {
+ for (String d : basicDescs) {
+ ClassDesc a0 = ClassDesc.ofDescriptor(d);
+ ClassDesc a1 = a0.arrayType();
+ ClassDesc a2 = a1.arrayType();
+
+ testClassDesc(a0);
+ testClassDesc(a1);
+ testClassDesc(a2);
+ assertFalse(a0.isArray());
+ assertTrue(a1.isArray());
+ assertTrue(a2.isArray());
+ assertFalse(a1.isPrimitive());
+ assertFalse(a2.isPrimitive());
+ assertEquals(a0.descriptorString(), d);
+ assertEquals(a1.descriptorString(), "[" + a0.descriptorString());
+ assertEquals(a2.descriptorString(), "[[" + a0.descriptorString());
+
+ assertNull(a0.componentType());
+ assertEquals(a0, a1.componentType());
+ assertEquals(a1, a2.componentType());
+
+ assertNotEquals(a0, a1);
+ assertNotEquals(a1, a2);
+
+ assertEquals(a1, ClassDesc.ofDescriptor("[" + d));
+ assertEquals(a2, ClassDesc.ofDescriptor("[[" + d));
+ assertEquals(classToDescriptor((Class<?>) a0.resolveConstantDesc(LOOKUP)), a0.descriptorString());
+ assertEquals(classToDescriptor((Class<?>) a1.resolveConstantDesc(LOOKUP)), a1.descriptorString());
+ assertEquals(classToDescriptor((Class<?>) a2.resolveConstantDesc(LOOKUP)), a2.descriptorString());
+
+ testBadArrayRank(ConstantDescs.CD_int);
+ testBadArrayRank(ConstantDescs.CD_String);
+ testBadArrayRank(ClassDesc.of("Bar"));
+ }
+ }
+
+ public void testBadClassDescs() {
+ List<String> badDescriptors = List.of("II", "I;", "Q", "L",
+ "java.lang.String", "[]", "Ljava/lang/String",
+ "Ljava.lang.String;", "java/lang/String");
+
+ for (String d : badDescriptors) {
+ try {
+ ClassDesc constant = ClassDesc.ofDescriptor(d);
+ fail(d);
+ }
+ catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+
+ List<String> badBinaryNames = List.of("I;", "[]", "Ljava/lang/String",
+ "Ljava.lang.String;", "java/lang/String");
+ for (String d : badBinaryNames) {
+ try {
+ ClassDesc constant = ClassDesc.of(d);
+ fail(d);
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+
+ for (Primitives p : Primitives.values()) {
+ testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any");
+ testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any", "other");
+ }
+ }
+
+ private void testBadNestedClasses(ClassDesc cr, String firstNestedName, String... moreNestedNames) {
+ try {
+ cr.nested(firstNestedName, moreNestedNames);
+ fail("");
+ } catch (IllegalStateException e) {
+ // good
+ }
+ }
+
+ public void testLangClasses() {
+ Double d = 1.0;
+ assertEquals(d.resolveConstantDesc(LOOKUP), d);
+ assertEquals(d.describeConstable().get(), d);
+
+ Integer i = 1;
+ assertEquals(i.resolveConstantDesc(LOOKUP), i);
+ assertEquals(i.describeConstable().get(), i);
+
+ Float f = 1.0f;
+ assertEquals(f.resolveConstantDesc(LOOKUP), f);
+ assertEquals(f.describeConstable().get(), f);
+
+ Long l = 1L;
+ assertEquals(l.resolveConstantDesc(LOOKUP), l);
+ assertEquals(l.describeConstable().get(), l);
+
+ String s = "";
+ assertEquals(s.resolveConstantDesc(LOOKUP), s);
+ assertEquals(s.describeConstable().get(), s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/CondyDescTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.lang.Enum.EnumDesc;
+import java.lang.constant.MethodTypeDesc;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.VarHandle.VarHandleDesc;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.ConstantDesc;
+import java.lang.constant.ConstantDescs;
+import java.lang.constant.DirectMethodHandleDesc;
+import java.lang.constant.DynamicConstantDesc;
+import java.lang.constant.MethodHandleDesc;
+
+import org.testng.annotations.Test;
+
+import static java.lang.constant.ConstantDescs.CD_MethodHandle;
+import static java.lang.constant.ConstantDescs.CD_Object;
+import static java.lang.constant.ConstantDescs.CD_String;
+import static java.lang.constant.ConstantDescs.CD_VarHandle;
+import static java.lang.constant.ConstantDescs.CD_int;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @test
+ * @compile CondyDescTest.java
+ * @run testng CondyDescTest
+ * @summary unit tests for java.lang.constant.CondyDescTest
+ */
+@Test
+public class CondyDescTest extends SymbolicDescTest {
+ private final static ConstantDesc[] EMPTY_ARGS = new ConstantDesc[0];
+ private final static ClassDesc CD_ConstantBootstraps = ClassDesc.of("java.lang.invoke.ConstantBootstraps");
+
+ private static<T> void testDCR(DynamicConstantDesc<T> r, T c) throws ReflectiveOperationException {
+ assertEquals(r, DynamicConstantDesc.ofNamed(r.bootstrapMethod(), r.constantName(), r.constantType(), r.bootstrapArgs()));
+ assertEquals(r.resolveConstantDesc(LOOKUP), c);
+ }
+
+ private void testVarHandleDesc(DynamicConstantDesc<VarHandle> r, VarHandle vh) throws ReflectiveOperationException {
+ testSymbolicDesc(r);
+ assertEquals(r.resolveConstantDesc(LOOKUP), vh);
+ assertEquals(vh.describeConstable().orElseThrow(), r);
+ }
+
+ private static<E extends Enum<E>> void testEnumDesc(EnumDesc<E> r, E e) throws ReflectiveOperationException {
+ testSymbolicDesc(r);
+
+ assertEquals(r, EnumDesc.of(r.constantType(), r.constantName()));
+ assertEquals(r.resolveConstantDesc(LOOKUP), e);
+ }
+
+ public void testNullConstant() throws ReflectiveOperationException {
+ DynamicConstantDesc<?> r = (DynamicConstantDesc<?>) ConstantDescs.NULL;
+ assertEquals(r, DynamicConstantDesc.ofNamed(r.bootstrapMethod(), r.constantName(), r.constantType(), r.bootstrapArgs()));
+ assertNull(r.resolveConstantDesc(LOOKUP));
+ }
+
+ static String concatBSM(MethodHandles.Lookup lookup, String name, Class<?> type, String a, String b) {
+ return a + b;
+ }
+
+ public void testDynamicConstant() throws ReflectiveOperationException {
+ DirectMethodHandleDesc bsmDesc = ConstantDescs.ofConstantBootstrap(ClassDesc.of("CondyDescTest"), "concatBSM",
+ CD_String, CD_String, CD_String);
+ DynamicConstantDesc<String> r = DynamicConstantDesc.of(bsmDesc, "foo", "bar");
+ testDCR(r, "foobar");
+ }
+
+ public void testNested() throws Throwable {
+ DirectMethodHandleDesc invoker = ConstantDescs.ofConstantBootstrap(CD_ConstantBootstraps, "invoke", CD_Object, CD_MethodHandle, CD_Object.arrayType());
+ DirectMethodHandleDesc format = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, CD_String, "format",
+ MethodTypeDesc.of(CD_String, CD_String, CD_Object.arrayType()));
+
+ String s = (String) ((MethodHandle) invoker.resolveConstantDesc(LOOKUP))
+ .invoke(LOOKUP, "", String.class,
+ format.resolveConstantDesc(LOOKUP), "%s%s", "moo", "cow");
+ assertEquals(s, "moocow");
+
+ DynamicConstantDesc<String> desc = DynamicConstantDesc.of(invoker, format, "%s%s", "moo", "cow");
+ testDCR(desc, "moocow");
+
+ DynamicConstantDesc<String> desc2 = DynamicConstantDesc.of(invoker, format, "%s%s", desc, "cow");
+ testDCR(desc2, "moocowcow");
+ }
+
+ enum MyEnum { A, B, C }
+
+ public void testEnumDesc() throws ReflectiveOperationException {
+ ClassDesc enumClass = ClassDesc.of("CondyDescTest").nested("MyEnum");
+
+ testEnumDesc(EnumDesc.of(enumClass, "A"), MyEnum.A);
+ testEnumDesc(EnumDesc.of(enumClass, "B"), MyEnum.B);
+ testEnumDesc(EnumDesc.of(enumClass, "C"), MyEnum.C);
+
+ DynamicConstantDesc<MyEnum> denum = DynamicConstantDesc.ofNamed(ConstantDescs.BSM_ENUM_CONSTANT, "A", enumClass, EMPTY_ARGS);
+ assertEquals(MyEnum.A, denum.resolveConstantDesc(LOOKUP));
+
+ EnumDesc<MyEnum> enumDesc = (EnumDesc<MyEnum>)DynamicConstantDesc.<MyEnum>ofCanonical(ConstantDescs.BSM_ENUM_CONSTANT, "A", enumClass, EMPTY_ARGS);
+ assertEquals(MyEnum.A, enumDesc.resolveConstantDesc(LOOKUP));
+ }
+
+ static class MyClass {
+ static int sf;
+ int f;
+ }
+
+ public void testVarHandles() throws ReflectiveOperationException {
+ ClassDesc testClass = ClassDesc.of("CondyDescTest").nested("MyClass");
+ MyClass instance = new MyClass();
+
+ // static varHandle
+ VarHandleDesc vhc = VarHandleDesc.ofStaticField(testClass, "sf", CD_int);
+ VarHandle varHandle = LOOKUP.findStaticVarHandle(MyClass.class, "sf", int.class);
+ testVarHandleDesc(vhc, varHandle);
+
+ assertEquals(varHandle.varType(), int.class);
+ varHandle.set(8);
+ assertEquals(8, (int) varHandle.get());
+ assertEquals(MyClass.sf, 8);
+
+ // static varHandle
+ vhc = VarHandleDesc.ofField(testClass, "f", CD_int);
+ varHandle = LOOKUP.findVarHandle(MyClass.class, "f", int.class);
+ testVarHandleDesc(vhc, varHandle);
+
+ assertEquals(varHandle.varType(), int.class);
+ varHandle.set(instance, 9);
+ assertEquals(9, (int) varHandle.get(instance));
+ assertEquals(instance.f, 9);
+
+ vhc = VarHandleDesc.ofArray(CD_int.arrayType());
+ varHandle = MethodHandles.arrayElementVarHandle(int[].class);
+ testVarHandleDesc(vhc, varHandle);
+
+ int[] ints = new int[3];
+ varHandle.set(ints, 0, 1);
+ varHandle.set(ints, 1, 2);
+ varHandle.set(ints, 2, 3);
+
+ assertEquals(1, varHandle.get(ints, 0));
+ assertEquals(2, varHandle.get(ints, 1));
+ assertEquals(3, varHandle.get(ints, 2));
+ assertEquals(1, ints[0]);
+ assertEquals(2, ints[1]);
+ assertEquals(3, ints[2]);
+
+ // static var handle obtained using the DynamicConstantDesc
+ DynamicConstantDesc<VarHandle> dcd = DynamicConstantDesc.ofNamed(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, "sf", CD_VarHandle, new ConstantDesc[] {testClass, CD_int });
+ VarHandle vh = dcd.resolveConstantDesc(LOOKUP);
+ testVarHandleDesc(dcd, vh);
+
+ VarHandleDesc vhd = (VarHandleDesc) DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, "sf", CD_VarHandle, new ConstantDesc[] {testClass, CD_int });
+ vh = vhd.resolveConstantDesc(LOOKUP);
+ testVarHandleDesc(vhd, vh);
+
+ dcd = DynamicConstantDesc.ofNamed(ConstantDescs.BSM_VARHANDLE_FIELD, "f", CD_VarHandle, new ConstantDesc[] {testClass, CD_int });
+ vh = dcd.resolveConstantDesc(LOOKUP);
+ testVarHandleDesc(dcd, vh);
+
+ vhd = (VarHandleDesc) DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_FIELD, "f", CD_VarHandle, new ConstantDesc[] {testClass, CD_int });
+ vh = vhd.resolveConstantDesc(LOOKUP);
+ testVarHandleDesc(vhd, vh);
+
+ dcd = DynamicConstantDesc.ofNamed(ConstantDescs.BSM_VARHANDLE_ARRAY, "_", CD_VarHandle, new ConstantDesc[] {CD_int.arrayType() });
+ vh = dcd.resolveConstantDesc(LOOKUP);
+ testVarHandleDesc(dcd, vh);
+
+ vhd = (VarHandleDesc)DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_ARRAY, "_", CD_VarHandle, new ConstantDesc[] {CD_int.arrayType() });
+ vh = vhd.resolveConstantDesc(LOOKUP);
+ testVarHandleDesc(vhd, vh);
+ }
+
+ private<T> void assertLifted(ConstantDesc prototype,
+ DynamicConstantDesc<T> nonCanonical,
+ ConstantDesc canonical) {
+ Class<?> clazz = prototype.getClass();
+
+ assertNotSame(canonical, nonCanonical);
+ assertTrue(clazz.isAssignableFrom(canonical.getClass()));
+ assertFalse(clazz.isAssignableFrom(nonCanonical.getClass()));
+ assertEquals(prototype, canonical);
+ assertEquals(canonical, prototype);
+ if (prototype instanceof DynamicConstantDesc) {
+ assertEquals(canonical, nonCanonical);
+ assertEquals(nonCanonical, canonical);
+ assertEquals(prototype, nonCanonical);
+ assertEquals(nonCanonical, prototype);
+ }
+ }
+
+ public void testLifting() {
+ DynamicConstantDesc<Object> unliftedNull = DynamicConstantDesc.ofNamed(ConstantDescs.BSM_NULL_CONSTANT, "_", CD_Object, EMPTY_ARGS);
+ assertEquals(ConstantDescs.NULL, unliftedNull);
+ assertNotSame(ConstantDescs.NULL, unliftedNull);
+ assertSame(ConstantDescs.NULL, DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_NULL_CONSTANT, "_", CD_Object, EMPTY_ARGS));
+ assertSame(ConstantDescs.NULL, DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_NULL_CONSTANT, "_", CD_String, EMPTY_ARGS));
+ assertSame(ConstantDescs.NULL, DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_NULL_CONSTANT, "wahoo", CD_Object, EMPTY_ARGS));
+
+ assertLifted(CD_int,
+ DynamicConstantDesc.ofNamed(ConstantDescs.BSM_PRIMITIVE_CLASS, "I", ConstantDescs.CD_Class, EMPTY_ARGS),
+ DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_PRIMITIVE_CLASS, "I", ConstantDescs.CD_Class, EMPTY_ARGS));
+
+ ClassDesc enumClass = ClassDesc.of("CondyDescTest").nested("MyEnum");
+ assertLifted(EnumDesc.of(enumClass, "A"),
+ DynamicConstantDesc.ofNamed(ConstantDescs.BSM_ENUM_CONSTANT, "A", enumClass, EMPTY_ARGS),
+ DynamicConstantDesc.<MyEnum>ofCanonical(ConstantDescs.BSM_ENUM_CONSTANT, "A", enumClass, EMPTY_ARGS));
+
+
+ ClassDesc testClass = ClassDesc.of("CondyDescTest").nested("MyClass");
+
+ assertLifted(VarHandleDesc.ofStaticField(testClass, "sf", CD_int),
+ DynamicConstantDesc.ofNamed(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, "sf", CD_VarHandle, new ConstantDesc[] {testClass, CD_int }),
+ DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, "sf", CD_VarHandle, new ConstantDesc[] {testClass, CD_int }));
+ assertLifted(VarHandleDesc.ofField(testClass, "f", CD_int),
+ DynamicConstantDesc.ofNamed(ConstantDescs.BSM_VARHANDLE_FIELD, "f", CD_VarHandle, new ConstantDesc[] {testClass, CD_int }),
+ DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_FIELD, "f", CD_VarHandle, new ConstantDesc[] {testClass, CD_int }));
+
+ assertLifted(VarHandleDesc.ofArray(CD_int.arrayType()),
+ DynamicConstantDesc.ofNamed(ConstantDescs.BSM_VARHANDLE_ARRAY, "_", CD_VarHandle, new ConstantDesc[] {CD_int.arrayType() }),
+ DynamicConstantDesc.ofCanonical(ConstantDescs.BSM_VARHANDLE_ARRAY, "_", CD_VarHandle, new ConstantDesc[] {CD_int.arrayType() }));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/IndyDescTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.DirectMethodHandleDesc;
+import java.lang.constant.DynamicCallSiteDesc;
+import java.lang.constant.MethodHandleDesc;
+import java.lang.constant.MethodTypeDesc;
+
+import org.testng.annotations.Test;
+
+import static java.lang.constant.ConstantDescs.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+
+/**
+ * @test
+ * @compile IndyDescTest.java
+ * @run testng IndyDescTest
+ * @summary unit tests for java.lang.constant.IndyDescTest
+ */
+@Test
+public class IndyDescTest {
+ public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type,
+ Object... args) {
+ if (args.length == 0)
+ return new ConstantCallSite(MethodHandles.constant(String.class, "Foo"));
+ else
+ return new ConstantCallSite(MethodHandles.constant(String.class, (String) args[0]));
+ }
+
+ public void testIndyDesc() throws Throwable {
+ ClassDesc c = ClassDesc.of("IndyDescTest");
+ MethodTypeDesc mt = MethodTypeDesc.of(CD_CallSite, CD_MethodHandles_Lookup, CD_String, CD_MethodType, CD_Object.arrayType());
+ DirectMethodHandleDesc mh = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
+ DynamicCallSiteDesc csd = DynamicCallSiteDesc.of(mh, "wooga", MethodTypeDesc.of(CD_String));
+ CallSite cs = csd.resolveCallSiteDesc(MethodHandles.lookup());
+ MethodHandle target = cs.getTarget();
+ assertEquals("Foo", target.invoke());
+ assertEquals("wooga", csd.invocationName());
+
+ mh = ofCallsiteBootstrap(c, "bootstrap", CD_CallSite, CD_Object.arrayType());
+ csd = DynamicCallSiteDesc.of(mh, "wooga", MethodTypeDesc.of(CD_String));
+ cs = csd.resolveCallSiteDesc(MethodHandles.lookup());
+ target = cs.getTarget();
+ assertEquals("Foo", target.invoke());
+ assertEquals("wooga", csd.invocationName());
+
+ DynamicCallSiteDesc csd2 = DynamicCallSiteDesc.of(mh, "foo", MethodTypeDesc.of(CD_String), "Bar");
+ CallSite cs2 = csd2.resolveCallSiteDesc(MethodHandles.lookup());
+ MethodHandle target2 = cs2.getTarget();
+ assertEquals("Bar", target2.invoke());
+ assertEquals("foo", csd2.invocationName());
+
+ DynamicCallSiteDesc csd3 = DynamicCallSiteDesc.of(mh, MethodTypeDesc.of(CD_String));
+ CallSite cs3 = csd.resolveCallSiteDesc(MethodHandles.lookup());
+ MethodHandle target3 = cs3.getTarget();
+ assertEquals("Foo", target3.invoke());
+ assertEquals("_", csd3.invocationName());
+
+ DynamicCallSiteDesc csd4 = DynamicCallSiteDesc.of(mh, "foo", MethodTypeDesc.of(CD_String)).withArgs("Bar");
+ CallSite cs4 = csd4.resolveCallSiteDesc(MethodHandles.lookup());
+ MethodHandle target4 = cs4.getTarget();
+ assertEquals("Bar", target4.invoke());
+
+ DynamicCallSiteDesc csd5 = DynamicCallSiteDesc.of(mh, MethodTypeDesc.of(CD_String, CD_String))
+ .withNameAndType("foo", MethodTypeDesc.of(CD_String)).withArgs("Bar");
+ CallSite cs5 = csd5.resolveCallSiteDesc(MethodHandles.lookup());
+ MethodHandle target5 = cs5.getTarget();
+ assertEquals("Bar", target5.invoke());
+ assertEquals("foo", csd5.invocationName());
+ }
+
+ public void testEqualsHashToString() throws Throwable {
+ ClassDesc c = ClassDesc.of("IndyDescTest");
+ MethodTypeDesc mt = MethodTypeDesc.of(CD_CallSite, CD_MethodHandles_Lookup, CD_String, CD_MethodType, CD_Object.arrayType());
+ DirectMethodHandleDesc mh = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
+
+ DynamicCallSiteDesc csd1 = DynamicCallSiteDesc.of(mh, "wooga", MethodTypeDesc.of(CD_String));
+ DynamicCallSiteDesc csd2 = DynamicCallSiteDesc.of(mh, "wooga", MethodTypeDesc.of(CD_String));
+ DynamicCallSiteDesc csd3 = DynamicCallSiteDesc.of(mh, "foo", MethodTypeDesc.of(CD_String));
+ assertEquals(csd1, csd2);
+ assertEquals(csd1.hashCode(), csd2.hashCode());
+ assertNotEquals(csd1, csd3);
+ assertNotEquals(csd1.hashCode(), csd3.hashCode());
+
+ assertEquals(csd1.toString(), "DynamicCallSiteDesc[IndyDescTest::bootstrap(wooga/):()String]");
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testEmptyInvocationName() throws Throwable {
+ ClassDesc c = ClassDesc.of("IndyDescTest");
+ MethodTypeDesc mt = MethodTypeDesc.of(CD_CallSite, CD_MethodHandles_Lookup, CD_String, CD_MethodType, CD_Object.arrayType());
+ DirectMethodHandleDesc mh = MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, c, "bootstrap", mt);
+ DynamicCallSiteDesc csd1 = DynamicCallSiteDesc.of(mh, "", MethodTypeDesc.of(CD_String));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/MethodHandleDescTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.ConstantDescs;
+import java.lang.constant.DirectMethodHandleDesc;
+import java.lang.constant.MethodHandleDesc;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.constant.MethodTypeDesc;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+import org.testng.annotations.Test;
+
+import static java.lang.constant.ConstantDescs.CD_Void;
+import static java.lang.constant.ConstantDescs.CD_boolean;
+import static java.lang.constant.DirectMethodHandleDesc.*;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.GETTER;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.SETTER;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC_GETTER;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC_SETTER;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.VIRTUAL;
+import static java.lang.constant.ConstantDescs.CD_Integer;
+import static java.lang.constant.ConstantDescs.CD_List;
+import static java.lang.constant.ConstantDescs.CD_Object;
+import static java.lang.constant.ConstantDescs.CD_String;
+import static java.lang.constant.ConstantDescs.CD_int;
+import static java.lang.constant.ConstantDescs.CD_void;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * @test
+ * @compile MethodHandleDescTest.java
+ * @run testng MethodHandleDescTest
+ * @summary unit tests for java.lang.constant.MethodHandleDesc
+ */
+@Test
+public class MethodHandleDescTest extends SymbolicDescTest {
+ private static ClassDesc helperHolderClass = ClassDesc.of("TestHelpers");
+ private static ClassDesc testClass = helperHolderClass.nested("TestClass");
+ private static ClassDesc testInterface = helperHolderClass.nested("TestInterface");
+ private static ClassDesc testSuperclass = helperHolderClass.nested("TestSuperclass");
+
+
+ private static void assertMHEquals(MethodHandle a, MethodHandle b) {
+ MethodHandleInfo ia = LOOKUP.revealDirect(a);
+ MethodHandleInfo ib = LOOKUP.revealDirect(b);
+ assertEquals(ia.getDeclaringClass(), ib.getDeclaringClass());
+ assertEquals(ia.getName(), ib.getName());
+ assertEquals(ia.getMethodType(), ib.getMethodType());
+ assertEquals(ia.getReferenceKind(), ib.getReferenceKind());
+ }
+
+ private void testMethodHandleDesc(MethodHandleDesc r) throws ReflectiveOperationException {
+ if (r instanceof DirectMethodHandleDesc) {
+ testSymbolicDesc(r);
+
+ DirectMethodHandleDesc rr = (DirectMethodHandleDesc) r;
+ assertEquals(r, MethodHandleDesc.of(rr.kind(), rr.owner(), rr.methodName(), rr.lookupDescriptor()));
+ assertEquals(r.invocationType().resolveConstantDesc(LOOKUP), ((MethodHandle) r.resolveConstantDesc(LOOKUP)).type());
+ }
+ else {
+ testSymbolicDescForwardOnly(r);
+ }
+ }
+
+ private String lookupDescriptor(DirectMethodHandleDesc rr) {
+ switch (rr.kind()) {
+ case VIRTUAL:
+ case SPECIAL:
+ case INTERFACE_VIRTUAL:
+ case INTERFACE_SPECIAL:
+ return rr.invocationType().dropParameterTypes(0, 1).descriptorString();
+ case CONSTRUCTOR:
+ return rr.invocationType().changeReturnType(CD_void).descriptorString();
+ default:
+ return rr.invocationType().descriptorString();
+ }
+ }
+
+ private void testMethodHandleDesc(MethodHandleDesc r, MethodHandle mh) throws ReflectiveOperationException {
+ testMethodHandleDesc(r);
+
+ assertMHEquals(((MethodHandle) r.resolveConstantDesc(LOOKUP)), mh);
+ assertEquals(mh.describeConstable().orElseThrow(), r);
+
+ // compare extractable properties: refKind, owner, name, type
+ MethodHandleInfo mhi = LOOKUP.revealDirect(mh);
+ DirectMethodHandleDesc rr = (DirectMethodHandleDesc) r;
+ assertEquals(mhi.getDeclaringClass().descriptorString(), rr.owner().descriptorString());
+ assertEquals(mhi.getName(), rr.methodName());
+ assertEquals(mhi.getReferenceKind(), rr.kind().refKind);
+ MethodType type = mhi.getMethodType();
+ assertEquals(type.toMethodDescriptorString(), lookupDescriptor(rr));
+ }
+
+ public void testSimpleMHs() throws ReflectiveOperationException {
+ MethodHandle MH_String_isEmpty = LOOKUP.findVirtual(String.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null));
+ testMethodHandleDesc(MethodHandleDesc.of(Kind.VIRTUAL, CD_String, "isEmpty", "()Z"), MH_String_isEmpty);
+ testMethodHandleDesc(MethodHandleDesc.ofMethod(Kind.VIRTUAL, CD_String, "isEmpty", MethodTypeDesc.of(CD_boolean)), MH_String_isEmpty);
+
+ MethodHandle MH_List_isEmpty = LOOKUP.findVirtual(List.class, "isEmpty", MethodType.fromMethodDescriptorString("()Z", null));
+ testMethodHandleDesc(MethodHandleDesc.of(Kind.INTERFACE_VIRTUAL, CD_List, "isEmpty", "()Z"), MH_List_isEmpty);
+ testMethodHandleDesc(MethodHandleDesc.ofMethod(Kind.INTERFACE_VIRTUAL, CD_List, "isEmpty", MethodTypeDesc.of(CD_boolean)), MH_List_isEmpty);
+
+ MethodHandle MH_String_format = LOOKUP.findStatic(String.class, "format", MethodType.methodType(String.class, String.class, Object[].class));
+ testMethodHandleDesc(MethodHandleDesc.of(Kind.STATIC, CD_String, "format", MethodType.methodType(String.class, String.class, Object[].class).descriptorString()),
+ MH_String_format);
+ testMethodHandleDesc(MethodHandleDesc.ofMethod(Kind.STATIC, CD_String, "format", MethodTypeDesc.of(CD_String, CD_String, CD_Object.arrayType())),
+ MH_String_format);
+
+ MethodHandle MH_ArrayList_new = LOOKUP.findConstructor(ArrayList.class, MethodType.methodType(void.class));
+ testMethodHandleDesc(MethodHandleDesc.ofMethod(Kind.CONSTRUCTOR, ClassDesc.of("java.util.ArrayList"), "<init>", MethodTypeDesc.of(CD_void)),
+ MH_ArrayList_new);
+ testMethodHandleDesc(MethodHandleDesc.ofConstructor(ClassDesc.of("java.util.ArrayList")), MH_ArrayList_new);
+
+ // bad constructor non void return type
+ try {
+ MethodHandleDesc.of(Kind.CONSTRUCTOR, ClassDesc.of("java.util.ArrayList"), "<init>", "()I");
+ fail("should have failed: non void return type for constructor");
+ } catch (IllegalArgumentException ex) {
+ // good
+ }
+ }
+
+ public void testAsType() throws Throwable {
+ MethodHandleDesc mhr = MethodHandleDesc.ofMethod(Kind.STATIC, ClassDesc.of("java.lang.Integer"), "valueOf",
+ MethodTypeDesc.of(CD_Integer, CD_int));
+ MethodHandleDesc takesInteger = mhr.asType(MethodTypeDesc.of(CD_Integer, CD_Integer));
+ testMethodHandleDesc(takesInteger);
+ MethodHandle mh1 = (MethodHandle) takesInteger.resolveConstantDesc(LOOKUP);
+ assertEquals((Integer) 3, (Integer) mh1.invokeExact((Integer) 3));
+ assertEquals(takesInteger.toString(), "MethodHandleDesc[STATIC/Integer::valueOf(int)Integer].asType(Integer)Integer");
+
+ try {
+ Integer i = (Integer) mh1.invokeExact(3);
+ fail("Expected WMTE");
+ }
+ catch (WrongMethodTypeException ignored) { }
+
+ MethodHandleDesc takesInt = takesInteger.asType(MethodTypeDesc.of(CD_Integer, CD_int));
+ testMethodHandleDesc(takesInt);
+ MethodHandle mh2 = (MethodHandle) takesInt.resolveConstantDesc(LOOKUP);
+ assertEquals((Integer) 3, (Integer) mh2.invokeExact(3));
+
+ try {
+ Integer i = (Integer) mh2.invokeExact((Integer) 3);
+ fail("Expected WMTE");
+ }
+ catch (WrongMethodTypeException ignored) { }
+
+ // Short circuit optimization
+ MethodHandleDesc same = mhr.asType(mhr.invocationType());
+ assertSame(mhr, same);
+
+ // @@@ Test varargs adaptation
+ // @@@ Test bad adaptations and assert runtime error on resolution
+ // @@@ Test intrinsification of adapted MH
+ }
+
+ public void testMethodHandleDesc() throws Throwable {
+ MethodHandleDesc ctorDesc = MethodHandleDesc.of(Kind.CONSTRUCTOR, testClass, "<ignored!>", "()V");
+ MethodHandleDesc staticMethodDesc = MethodHandleDesc.of(Kind.STATIC, testClass, "sm", "(I)I");
+ MethodHandleDesc staticIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_STATIC, testInterface, "sm", "(I)I");
+ MethodHandleDesc instanceMethodDesc = MethodHandleDesc.of(Kind.VIRTUAL, testClass, "m", "(I)I");
+ MethodHandleDesc instanceIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_VIRTUAL, testInterface, "m", "(I)I");
+ MethodHandleDesc superMethodDesc = MethodHandleDesc.of(Kind.SPECIAL, testSuperclass, "m", "(I)I");
+ MethodHandleDesc superIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_SPECIAL, testInterface, "m", "(I)I");
+ MethodHandleDesc privateMethodDesc = MethodHandleDesc.of(Kind.SPECIAL, testClass, "pm", "(I)I");
+ MethodHandleDesc privateIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_SPECIAL, testInterface, "pm", "(I)I");
+ MethodHandleDesc privateStaticMethodDesc = MethodHandleDesc.of(Kind.STATIC, testClass, "psm", "(I)I");
+ MethodHandleDesc privateStaticIMethodDesc = MethodHandleDesc.of(Kind.INTERFACE_STATIC, testInterface, "psm", "(I)I");
+
+ assertEquals(ctorDesc.invocationType(), MethodTypeDesc.of(testClass));
+ assertEquals(((DirectMethodHandleDesc) ctorDesc).lookupDescriptor(), "()V");
+
+ assertEquals(staticMethodDesc.invocationType().descriptorString(), "(I)I");
+ assertEquals(((DirectMethodHandleDesc) staticMethodDesc).lookupDescriptor(), "(I)I");
+
+ assertEquals(instanceMethodDesc.invocationType().descriptorString(), "(" + testClass.descriptorString() + "I)I");
+ assertEquals(((DirectMethodHandleDesc) instanceMethodDesc).lookupDescriptor(), "(I)I");
+
+ for (MethodHandleDesc r : List.of(ctorDesc, staticMethodDesc, staticIMethodDesc, instanceMethodDesc, instanceIMethodDesc))
+ testMethodHandleDesc(r);
+
+ TestHelpers.TestClass instance = (TestHelpers.TestClass) ((MethodHandle)ctorDesc.resolveConstantDesc(LOOKUP)).invokeExact();
+ TestHelpers.TestClass instance2 = (TestHelpers.TestClass) ((MethodHandle)ctorDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact();
+ TestHelpers.TestInterface instanceI = instance;
+
+ assertNotSame(instance, instance2);
+
+ assertEquals(5, (int) ((MethodHandle)staticMethodDesc.resolveConstantDesc(LOOKUP)).invokeExact(5));
+ assertEquals(5, (int) ((MethodHandle)staticMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(5));
+ assertEquals(0, (int) ((MethodHandle)staticIMethodDesc.resolveConstantDesc(LOOKUP)).invokeExact(5));
+ assertEquals(0, (int) ((MethodHandle)staticIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(5));
+
+ assertEquals(5, (int) ((MethodHandle)instanceMethodDesc.resolveConstantDesc(LOOKUP)).invokeExact(instance, 5));
+ assertEquals(5, (int) ((MethodHandle)instanceMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(instance, 5));
+ assertEquals(5, (int) ((MethodHandle)instanceIMethodDesc.resolveConstantDesc(LOOKUP)).invokeExact(instanceI, 5));
+ assertEquals(5, (int) ((MethodHandle)instanceIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(instanceI, 5));
+
+ try { superMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
+ catch (IllegalAccessException e) { /* expected */ }
+ assertEquals(-1, (int) ((MethodHandle)superMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(instance, 5));
+
+ try { superIMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
+ catch (IllegalAccessException e) { /* expected */ }
+ assertEquals(0, (int) ((MethodHandle)superIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(instance, 5));
+
+ try { privateMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
+ catch (IllegalAccessException e) { /* expected */ }
+ assertEquals(5, (int) ((MethodHandle)privateMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(instance, 5));
+
+ try { privateIMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
+ catch (IllegalAccessException e) { /* expected */ }
+ assertEquals(0, (int) ((MethodHandle)privateIMethodDesc.resolveConstantDesc(TestHelpers.TestInterface.LOOKUP)).invokeExact(instanceI, 5));
+ assertEquals(0, (int) ((MethodHandle)privateIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invoke(instanceI, 5));
+
+ try { privateStaticMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
+ catch (IllegalAccessException e) { /* expected */ }
+ assertEquals(5, (int) ((MethodHandle)privateStaticMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(5));
+
+ try { privateStaticIMethodDesc.resolveConstantDesc(LOOKUP); fail(); }
+ catch (IllegalAccessException e) { /* expected */ }
+ assertEquals(0, (int) ((MethodHandle)privateStaticIMethodDesc.resolveConstantDesc(TestHelpers.TestInterface.LOOKUP)).invokeExact(5));
+ assertEquals(0, (int) ((MethodHandle)privateStaticIMethodDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(5));
+
+ MethodHandleDesc staticSetterDesc = MethodHandleDesc.ofField(STATIC_SETTER, testClass, "sf", CD_int);
+ MethodHandleDesc staticGetterDesc = MethodHandleDesc.ofField(STATIC_GETTER, testClass, "sf", CD_int);
+ MethodHandleDesc staticGetterIDesc = MethodHandleDesc.ofField(STATIC_GETTER, testInterface, "sf", CD_int);
+ MethodHandleDesc setterDesc = MethodHandleDesc.ofField(SETTER, testClass, "f", CD_int);
+ MethodHandleDesc getterDesc = MethodHandleDesc.ofField(GETTER, testClass, "f", CD_int);
+
+ for (MethodHandleDesc r : List.of(staticSetterDesc, staticGetterDesc, staticGetterIDesc, setterDesc, getterDesc))
+ testMethodHandleDesc(r);
+
+ ((MethodHandle)staticSetterDesc.resolveConstantDesc(LOOKUP)).invokeExact(6); assertEquals(TestHelpers.TestClass.sf, 6);
+ assertEquals(6, (int) ((MethodHandle)staticGetterDesc.resolveConstantDesc(LOOKUP)).invokeExact());
+ assertEquals(6, (int) ((MethodHandle)staticGetterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact());
+ ((MethodHandle)staticSetterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(7); assertEquals(TestHelpers.TestClass.sf, 7);
+ assertEquals(7, (int) ((MethodHandle)staticGetterDesc.resolveConstantDesc(LOOKUP)).invokeExact());
+ assertEquals(7, (int) ((MethodHandle)staticGetterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact());
+
+ assertEquals(3, (int) ((MethodHandle)staticGetterIDesc.resolveConstantDesc(LOOKUP)).invokeExact());
+ assertEquals(3, (int) ((MethodHandle)staticGetterIDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact());
+
+ ((MethodHandle)setterDesc.resolveConstantDesc(LOOKUP)).invokeExact(instance, 6); assertEquals(instance.f, 6);
+ assertEquals(6, (int) ((MethodHandle)getterDesc.resolveConstantDesc(LOOKUP)).invokeExact(instance));
+ assertEquals(6, (int) ((MethodHandle)getterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(instance));
+ ((MethodHandle)setterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(instance, 7); assertEquals(instance.f, 7);
+ assertEquals(7, (int) ((MethodHandle)getterDesc.resolveConstantDesc(LOOKUP)).invokeExact(instance));
+ assertEquals(7, (int) ((MethodHandle)getterDesc.resolveConstantDesc(TestHelpers.TestClass.LOOKUP)).invokeExact(instance));
+ }
+
+ private void assertBadArgs(Supplier<MethodHandleDesc> supplier, String s) {
+ try {
+ MethodHandleDesc r = supplier.get();
+ fail("Expected failure for " + s);
+ }
+ catch (IllegalArgumentException e) {
+ // succeed
+ }
+ }
+
+ public void testBadFieldMHs() {
+ List<String> badGetterDescs = List.of("()V", "(Ljava/lang/Object;)V", "(I)I", "(Ljava/lang/Object;I)I");
+ List<String> badStaticGetterDescs = List.of("()V", "(Ljava/lang/Object;)I", "(I)I", "(Ljava/lang/Object;I)I");
+ List<String> badSetterDescs = List.of("()V", "(I)V", "(Ljava/lang/Object;)V", "(Ljava/lang/Object;I)I", "(Ljava/lang/Object;II)V");
+ List<String> badStaticSetterDescs = List.of("()V", "(II)V", "()I");
+
+ badGetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleDesc.of(GETTER, helperHolderClass, "x", s), s));
+ badSetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleDesc.of(SETTER, helperHolderClass, "x", s), s));
+ badStaticGetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleDesc.of(STATIC_GETTER, helperHolderClass, "x", s), s));
+ badStaticSetterDescs.forEach(s -> assertBadArgs(() -> MethodHandleDesc.of(STATIC_SETTER, helperHolderClass, "x", s), s));
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testBadOwners() {
+ MethodHandleDesc.ofMethod(VIRTUAL, ClassDesc.ofDescriptor("I"), "x", MethodTypeDesc.ofDescriptor("()I"));
+ }
+
+ public void testSymbolicDescsConstants() throws ReflectiveOperationException {
+ int tested = 0;
+ Field[] fields = ConstantDescs.class.getDeclaredFields();
+ for (Field f : fields) {
+ try {
+ if (f.getType().equals(DirectMethodHandleDesc.class)
+ && ((f.getModifiers() & Modifier.STATIC) != 0)
+ && ((f.getModifiers() & Modifier.PUBLIC) != 0)) {
+ MethodHandleDesc r = (MethodHandleDesc) f.get(null);
+ MethodHandle m = (MethodHandle)r.resolveConstantDesc(MethodHandles.lookup());
+ testMethodHandleDesc(r, m);
+ ++tested;
+ }
+ }
+ catch (Throwable e) {
+ fail("Error testing field " + f.getName(), e);
+ }
+ }
+
+ assertTrue(tested > 0);
+ }
+
+ public void testKind() {
+ for (Kind k : Kind.values()) {
+ assertEquals(Kind.valueOf(k.refKind, k.isInterface), k);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/MethodTypeDescTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.lang.invoke.MethodType;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.MethodTypeDesc;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.testng.annotations.Test;
+
+import static java.lang.constant.ConstantDescs.CD_int;
+import static java.lang.constant.ConstantDescs.CD_void;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+/**
+ * @test
+ * @compile MethodTypeDescTest.java
+ * @run testng MethodTypeDescTest
+ * @summary unit tests for java.lang.constant.MethodTypeDesc
+ */
+@Test
+public class MethodTypeDescTest extends SymbolicDescTest {
+
+ private void testMethodTypeDesc(MethodTypeDesc r) throws ReflectiveOperationException {
+ testSymbolicDesc(r);
+
+ // Tests accessors (rType, pType, pCount, pList, pArray, descriptorString),
+ // factories (ofDescriptor, of), equals
+ assertEquals(r, MethodTypeDesc.ofDescriptor(r.descriptorString()));
+ assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterArray()));
+ assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList().toArray(new ClassDesc[0])));
+ assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList().stream().toArray(ClassDesc[]::new)));
+ assertEquals(r, MethodTypeDesc.of(r.returnType(), IntStream.range(0, r.parameterCount())
+ .mapToObj(r::parameterType)
+ .toArray(ClassDesc[]::new)));
+ }
+
+ private void testMethodTypeDesc(MethodTypeDesc r, MethodType mt) throws ReflectiveOperationException {
+ testMethodTypeDesc(r);
+
+ assertEquals(r.resolveConstantDesc(LOOKUP), mt);
+ assertEquals(mt.describeConstable().get(), r);
+
+ assertEquals(r.descriptorString(), mt.toMethodDescriptorString());
+ assertEquals(r.parameterCount(), mt.parameterCount());
+ assertEquals(r.parameterList(), mt.parameterList().stream().map(SymbolicDescTest::classToDesc).collect(toList()));
+ assertEquals(r.parameterArray(), Stream.of(mt.parameterArray()).map(SymbolicDescTest::classToDesc).toArray(ClassDesc[]::new));
+ for (int i=0; i<r.parameterCount(); i++)
+ assertEquals(r.parameterType(i), classToDesc(mt.parameterType(i)));
+ assertEquals(r.returnType(), classToDesc(mt.returnType()));
+ }
+
+ private void assertMethodType(ClassDesc returnType,
+ ClassDesc... paramTypes) throws ReflectiveOperationException {
+ String descriptor = Stream.of(paramTypes).map(ClassDesc::descriptorString).collect(joining("", "(", ")"))
+ + returnType.descriptorString();
+ MethodTypeDesc mtDesc = MethodTypeDesc.of(returnType, paramTypes);
+
+ // MTDesc accessors
+ assertEquals(descriptor, mtDesc.descriptorString());
+ assertEquals(returnType, mtDesc.returnType());
+ assertEquals(paramTypes, mtDesc.parameterArray());
+ assertEquals(Arrays.asList(paramTypes), mtDesc.parameterList());
+ assertEquals(paramTypes.length, mtDesc.parameterCount());
+ for (int i=0; i<paramTypes.length; i++)
+ assertEquals(paramTypes[i], mtDesc.parameterType(i));
+
+ // Consistency between MT and MTDesc
+ MethodType mt = MethodType.fromMethodDescriptorString(descriptor, null);
+ testMethodTypeDesc(mtDesc, mt);
+
+ // changeReturnType
+ for (String r : returnDescs) {
+ ClassDesc rc = ClassDesc.ofDescriptor(r);
+ MethodTypeDesc newDesc = mtDesc.changeReturnType(rc);
+ assertEquals(newDesc, MethodTypeDesc.of(rc, paramTypes));
+ testMethodTypeDesc(newDesc, mt.changeReturnType((Class<?>)rc.resolveConstantDesc(LOOKUP)));
+ }
+
+ // changeParamType
+ for (int i=0; i<paramTypes.length; i++) {
+ for (String p : paramDescs) {
+ ClassDesc pc = ClassDesc.ofDescriptor(p);
+ ClassDesc[] ps = paramTypes.clone();
+ ps[i] = pc;
+ MethodTypeDesc newDesc = mtDesc.changeParameterType(i, pc);
+ assertEquals(newDesc, MethodTypeDesc.of(returnType, ps));
+ testMethodTypeDesc(newDesc, mt.changeParameterType(i, (Class<?>)pc.resolveConstantDesc(LOOKUP)));
+ }
+ }
+
+ // dropParamType
+ for (int i=0; i<paramTypes.length; i++) {
+ int k = i;
+ ClassDesc[] ps = IntStream.range(0, paramTypes.length)
+ .filter(j -> j != k)
+ .mapToObj(j -> paramTypes[j])
+ .toArray(ClassDesc[]::new);
+ MethodTypeDesc newDesc = mtDesc.dropParameterTypes(i, i + 1);
+ assertEquals(newDesc, MethodTypeDesc.of(returnType, ps));
+ testMethodTypeDesc(newDesc, mt.dropParameterTypes(i, i+1));
+ }
+
+ badDropParametersTypes(CD_void, paramDescs);
+
+ // addParam
+ for (int i=0; i <= paramTypes.length; i++) {
+ for (ClassDesc p : paramTypes) {
+ int k = i;
+ ClassDesc[] ps = IntStream.range(0, paramTypes.length + 1)
+ .mapToObj(j -> (j < k) ? paramTypes[j] : (j == k) ? p : paramTypes[j-1])
+ .toArray(ClassDesc[]::new);
+ MethodTypeDesc newDesc = mtDesc.insertParameterTypes(i, p);
+ assertEquals(newDesc, MethodTypeDesc.of(returnType, ps));
+ testMethodTypeDesc(newDesc, mt.insertParameterTypes(i, (Class<?>)p.resolveConstantDesc(LOOKUP)));
+ }
+ }
+
+ badInsertParametersTypes(CD_void, paramDescs);
+ }
+
+ private void badInsertParametersTypes(ClassDesc returnType, String... paramDescTypes) {
+ ClassDesc[] paramTypes =
+ IntStream.rangeClosed(0, paramDescTypes.length - 1)
+ .mapToObj(i -> ClassDesc.ofDescriptor(paramDescTypes[i])).toArray(ClassDesc[]::new);
+ MethodTypeDesc mtDesc = MethodTypeDesc.of(returnType, paramTypes);
+ try {
+ MethodTypeDesc newDesc = mtDesc.insertParameterTypes(-1, paramTypes);
+ fail("pos < 0 should have failed");
+ } catch (IndexOutOfBoundsException ex) {
+ // good
+ }
+
+ try {
+ MethodTypeDesc newDesc = mtDesc.insertParameterTypes(paramTypes.length + 1, paramTypes);
+ fail("pos > current arguments length should have failed");
+ } catch (IndexOutOfBoundsException ex) {
+ // good
+ }
+ }
+
+ private void badDropParametersTypes(ClassDesc returnType, String... paramDescTypes) {
+ ClassDesc[] paramTypes =
+ IntStream.rangeClosed(0, paramDescTypes.length - 1)
+ .mapToObj(i -> ClassDesc.ofDescriptor(paramDescTypes[i])).toArray(ClassDesc[]::new);
+ MethodTypeDesc mtDesc = MethodTypeDesc.of(returnType, paramTypes);
+ try {
+ MethodTypeDesc newDesc = mtDesc.dropParameterTypes(-1, 0);
+ fail("start index < 0 should have failed");
+ } catch (IndexOutOfBoundsException ex) {
+ // good
+ }
+
+ try {
+ MethodTypeDesc newDesc = mtDesc.dropParameterTypes(paramTypes.length, 0);
+ fail("start index = arguments.length should have failed");
+ } catch (IndexOutOfBoundsException ex) {
+ // good
+ }
+
+ try {
+ MethodTypeDesc newDesc = mtDesc.dropParameterTypes(paramTypes.length + 1, 0);
+ fail("start index > arguments.length should have failed");
+ } catch (IndexOutOfBoundsException ex) {
+ // good
+ }
+
+ try {
+ MethodTypeDesc newDesc = mtDesc.dropParameterTypes(0, paramTypes.length + 1);
+ fail("end index > arguments.length should have failed");
+ } catch (IndexOutOfBoundsException ex) {
+ // good
+ }
+
+ try {
+ MethodTypeDesc newDesc = mtDesc.dropParameterTypes(1, 0);
+ fail("start index > end index should have failed");
+ } catch (IllegalArgumentException ex) {
+ // good
+ }
+ }
+
+ public void testMethodTypeDesc() throws ReflectiveOperationException {
+ for (String r : returnDescs) {
+ assertMethodType(ClassDesc.ofDescriptor(r));
+ for (String p1 : paramDescs) {
+ assertMethodType(ClassDesc.ofDescriptor(r), ClassDesc.ofDescriptor(p1));
+ for (String p2 : paramDescs) {
+ assertMethodType(ClassDesc.ofDescriptor(r), ClassDesc.ofDescriptor(p1), ClassDesc.ofDescriptor(p2));
+ }
+ }
+ }
+ }
+
+ public void testBadMethodTypeRefs() {
+ List<String> badDescriptors = List.of("()II", "()I;", "(I;)", "(I)", "()L", "(V)V",
+ "(java.lang.String)V", "()[]", "(Ljava/lang/String)V",
+ "(Ljava.lang.String;)V", "(java/lang/String)V");
+
+ for (String d : badDescriptors) {
+ try {
+ MethodTypeDesc r = MethodTypeDesc.ofDescriptor(d);
+ fail(d);
+ }
+ catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+
+ // try with void arguments, this will stress another code path in particular
+ // ConstantMethodTypeDesc::init
+ try {
+ MethodTypeDesc r = MethodTypeDesc.of(CD_int, CD_void);
+ fail("can't reach here");
+ }
+ catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/NameValidationTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018, 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
+ * @compile NameValidationTest.java
+ * @run testng NameValidationTest
+ * @summary unit tests for verifying member names
+ */
+
+import java.lang.constant.*;
+import java.lang.invoke.*;
+
+import org.testng.annotations.Test;
+
+import static java.lang.constant.DirectMethodHandleDesc.*;
+import static java.lang.constant.ConstantDescs.*;
+import static java.lang.constant.DirectMethodHandleDesc.Kind.VIRTUAL;
+
+import static org.testng.Assert.fail;
+
+@Test
+public class NameValidationTest {
+
+ private static final String[] badMemberNames = new String[] {"xx.xx", "zz;zz", "[l", "aa/aa", "<cinit>"};
+ private static final String[] goodMemberNames = new String[] {"<clinit>", "<init>", "3", "~", "$", "qq"};
+
+ private static final String[] badClassNames = new String[] {"zz;zz", "[l", "aa/aa"};
+ private static final String[] goodClassNames = new String[] {"3", "~", "$", "qq", ".", "a.a"};
+
+ public void testMemberNames() {
+ DirectMethodHandleDesc mh = MethodHandleDesc.of(Kind.VIRTUAL, CD_String, "isEmpty", "()Z");
+ for (String badName : badMemberNames) {
+ try {
+ memberNamesHelper(badName, mh, CD_int, null);
+ fail("Expected failure for name " + badName);
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ try {
+ memberNamesHelper(badName, mh, CD_int, new ConstantDesc[0]);
+ fail("Expected failure for name " + badName);
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ for (String badName : goodMemberNames) {
+ memberNamesHelper(badName, mh, CD_int, null);
+ memberNamesHelper(badName, mh, CD_int, new ConstantDesc[0]);
+ }
+ }
+
+ private void memberNamesHelper(String constantName,
+ DirectMethodHandleDesc bootstrapMethod,
+ ClassDesc constantType,
+ ConstantDesc... bootstrapArgs) {
+ if (bootstrapArgs == null) {
+ DynamicConstantDesc.ofNamed(bootstrapMethod, constantName, constantType);
+ } else {
+ DynamicConstantDesc.ofNamed(bootstrapMethod, constantName, constantType, bootstrapArgs);
+ }
+ }
+
+ public void testClassNames() {
+ for (String badName : badClassNames) {
+ try {
+ ClassDesc.of(badName);
+ fail("Expected failure for name " + badName);
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ for (String goodName : goodClassNames) {
+ ClassDesc.of(goodName);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/SymbolicDescTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.lang.Class;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.constant.ClassDesc;
+import java.lang.constant.Constable;
+import java.lang.constant.ConstantDesc;
+import java.lang.constant.ConstantDescs;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Base class for XxxDesc tests
+ */
+public abstract class SymbolicDescTest {
+
+ public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+ static List<String> someDescs = List.of("Ljava/lang/String;", "Ljava/util/List;");
+ static String[] basicDescs = Stream.concat(Stream.of(Primitives.values())
+ .filter(p -> p != Primitives.VOID)
+ .map(p -> p.descriptor),
+ someDescs.stream())
+ .toArray(String[]::new);
+ static String[] paramDescs = Stream.of(basicDescs)
+ .flatMap(d -> Stream.of(d, "[" + d))
+ .toArray(String[]::new);
+ static String[] returnDescs = Stream.concat(Stream.of(paramDescs), Stream.of("V")).toArray(String[]::new);
+
+ enum Primitives {
+ INT("I", "int", int.class, int[].class, ConstantDescs.CD_int),
+ LONG("J", "long", long.class, long[].class, ConstantDescs.CD_long),
+ SHORT("S", "short", short.class, short[].class, ConstantDescs.CD_short),
+ BYTE("B", "byte", byte.class, byte[].class, ConstantDescs.CD_byte),
+ CHAR("C", "char", char.class, char[].class, ConstantDescs.CD_char),
+ FLOAT("F", "float", float.class, float[].class, ConstantDescs.CD_float),
+ DOUBLE("D", "double", double.class, double[].class, ConstantDescs.CD_double),
+ BOOLEAN("Z", "boolean", boolean.class, boolean[].class, ConstantDescs.CD_boolean),
+ VOID("V", "void", void.class, null, ConstantDescs.CD_void);
+
+ public final String descriptor;
+ public final String name;
+ public final Class<?> clazz;
+ public final Class<?> arrayClass;
+ public final ClassDesc classDesc;
+
+ Primitives(String descriptor, String name, Class<?> clazz, Class<?> arrayClass, ClassDesc desc) {
+ this.descriptor = descriptor;
+ this.name = name;
+ this.clazz = clazz;
+ this.arrayClass = arrayClass;
+ classDesc = desc;
+ }
+ }
+
+ static String classToDescriptor(Class<?> clazz) {
+ return MethodType.methodType(clazz).toMethodDescriptorString().substring(2);
+ }
+
+ static ClassDesc classToDesc(Class<?> c) {
+ return ClassDesc.ofDescriptor(c.descriptorString());
+ }
+
+ static<T> void testSymbolicDesc(ConstantDesc desc) throws ReflectiveOperationException {
+ testSymbolicDesc(desc, false);
+ }
+
+ static<T> void testSymbolicDescForwardOnly(ConstantDesc desc) throws ReflectiveOperationException {
+ testSymbolicDesc(desc, true);
+ }
+
+ private static<T> void testSymbolicDesc(ConstantDesc desc, boolean forwardOnly) throws ReflectiveOperationException {
+ // Round trip sym -> resolve -> toSymbolicDesc
+ Constable constable = (Constable) desc.resolveConstantDesc(LOOKUP);
+ Optional<? extends ConstantDesc> described = constable.describeConstable();
+ if (!forwardOnly) {
+ assertEquals(desc, described.orElseThrow());
+ }
+
+ // Round trip sym -> quoted sym -> resolve
+ if (desc instanceof Constable) {
+ Optional<ConstantDesc> opt = (Optional<ConstantDesc>) ((Constable) desc).describeConstable();
+ ConstantDesc sr = (ConstantDesc) opt.orElseThrow().resolveConstantDesc(LOOKUP);
+ assertEquals(sr, desc);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/TestHelpers.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.lang.invoke.MethodHandles;
+
+/**
+ * TestHelpers
+ *
+ * @author Brian Goetz
+ */
+class TestHelpers {
+ interface TestInterface {
+ public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+ public static final int sf = 3;
+
+ static int sm(int x) { return 0; }
+ default int m(int x) { return 0; }
+ private int pm(int x) { return 0; }
+ private static int psm(int x) { return 0; }
+ }
+
+ static class TestSuperclass {
+ public int m(int x) { return -1; }
+ }
+
+ static class TestClass extends TestSuperclass implements TestInterface {
+ public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+ static int sf;
+ int f;
+
+ public TestClass() {}
+
+ public static int sm(int x) { return x; }
+ public int m(int x) { return x; }
+ private static int psm(int x) { return x; }
+ private int pm(int x) { return x; }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/TypeDescriptorTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+import java.lang.invoke.TypeDescriptor;
+import java.lang.constant.ClassDesc;
+
+import org.testng.annotations.Test;
+
+import static java.lang.constant.ConstantDescs.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @test
+ * @compile TypeDescriptorTest.java
+ * @run testng TypeDescriptorTest
+ * @summary unit tests for implementations of java.lang.invoke.TypeDescriptor
+ */
+@Test
+public class TypeDescriptorTest {
+ private<F extends TypeDescriptor.OfField<F>> void testArray(F f, boolean isArray, F component, F array) {
+ if (isArray) {
+ assertTrue(f.isArray());
+ assertEquals(f.arrayType(), array);
+ assertEquals(f.componentType(), component);
+ }
+ else {
+ assertFalse(f.isArray());
+ assertEquals(f.arrayType(), array);
+ assertNull(f.componentType());
+ }
+ }
+
+ public void testClass() {
+ testArray(int.class, false, null, int[].class);
+ testArray(int[].class, true, int.class, int[][].class);
+ testArray(int[][].class, true, int[].class, int[][][].class);
+ testArray(String.class, false, null, String[].class);
+ testArray(String[].class, true, String.class, String[][].class);
+ testArray(String[][].class, true, String[].class, String[][][].class);
+
+ assertTrue(int.class.isPrimitive());
+ assertFalse(int[].class.isPrimitive());
+ assertFalse(String.class.isPrimitive());
+ assertFalse(String[].class.isPrimitive());
+ }
+
+ public void testClassDesc() {
+
+ testArray(CD_int, false, null, CD_int.arrayType());
+ testArray(CD_int.arrayType(), true, CD_int, CD_int.arrayType(2));
+ testArray(CD_int.arrayType(2), true, CD_int.arrayType(), CD_int.arrayType(3));
+ testArray(CD_String, false, null, CD_String.arrayType());
+ testArray(CD_String.arrayType(), true, CD_String, CD_String.arrayType(2));
+ testArray(CD_String.arrayType(2), true, CD_String.arrayType(), CD_String.arrayType(3));
+
+ assertTrue(CD_int.isPrimitive());
+ assertFalse(CD_int.arrayType().isPrimitive());
+ assertFalse(CD_String.isPrimitive());
+ assertFalse(CD_String.arrayType().isPrimitive());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/boottest/TEST.properties Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,4 @@
+# This file identifies root(s) of the test-ng hierarchy.
+
+TestNG.dirs = .
+lib.dirs = /lib/testlibrary/bootlib
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/boottest/java.base/java/lang/constant/ConstantUtilsTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, 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 java.lang.constant;
+
+import java.lang.invoke.*;
+import java.lang.constant.*;
+import java.util.*;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @compile ConstantUtilsTest.java
+ * @run testng ConstantUtilsTest
+ * @summary unit tests for methods of java.lang.constant.ConstantUtils that are not covered by other unit tests
+ */
+@Test
+public class ConstantUtilsTest {
+ private static ClassDesc thisClass = ClassDesc.of("MethodHandleDescTest");
+
+ public void testValidateMemberName() {
+ try {
+ ConstantUtils.validateMemberName(null);
+ fail("");
+ } catch (NullPointerException e) {
+ // good
+ }
+
+ try {
+ ConstantUtils.validateMemberName("");
+ fail("");
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+
+ List<String> badNames = List.of(".", ";", "[", "/", "<", ">");
+ for (String n : badNames) {
+ try {
+ ConstantUtils.validateMemberName(n);
+ fail(n);
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+ }
+}
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -338,10 +338,10 @@
@BeforeClass
public void setup() {
setupByteSources();
- setupVarHandleSources();
+ vhss = setupVarHandleSources(true);
}
- abstract void setupVarHandleSources();
+ abstract List<VarHandleSource> setupVarHandleSources(boolean same);
@DataProvider
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
boolean v;
+ static final boolean static_final_v2 = true;
+
+ static boolean static_v2;
+
+ final boolean final_v2 = true;
+
+ boolean v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -61,6 +69,41 @@
VarHandle vhArray;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessBoolean.class, "final_v" + postfix, boolean.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessBoolean.class, "v" + postfix, boolean.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessBoolean.class, "static_final_v" + postfix, boolean.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessBoolean.class, "static_v" + postfix, boolean.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(boolean[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -89,6 +132,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
byte v;
+ static final byte static_final_v2 = (byte)0x01;
+
+ static byte static_v2;
+
+ final byte final_v2 = (byte)0x01;
+
+ byte v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -61,6 +69,41 @@
VarHandle vhArray;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessByte.class, "final_v" + postfix, byte.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessByte.class, "v" + postfix, byte.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessByte.class, "static_final_v" + postfix, byte.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessByte.class, "static_v" + postfix, byte.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(byte[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -89,6 +132,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
char v;
+ static final char static_final_v2 = '\u0123';
+
+ static char static_v2;
+
+ final char final_v2 = '\u0123';
+
+ char v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -61,6 +69,41 @@
VarHandle vhArray;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessChar.class, "final_v" + postfix, char.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessChar.class, "v" + postfix, char.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessChar.class, "static_final_v" + postfix, char.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessChar.class, "static_v" + postfix, char.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(char[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -89,6 +132,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
double v;
+ static final double static_final_v2 = 1.0d;
+
+ static double static_v2;
+
+ final double final_v2 = 1.0d;
+
+ double v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -61,6 +69,41 @@
VarHandle vhArray;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessDouble.class, "final_v" + postfix, double.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessDouble.class, "v" + postfix, double.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessDouble.class, "static_final_v" + postfix, double.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessDouble.class, "static_v" + postfix, double.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(double[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -89,6 +132,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
float v;
+ static final float static_final_v2 = 1.0f;
+
+ static float static_v2;
+
+ final float final_v2 = 1.0f;
+
+ float v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -61,6 +69,41 @@
VarHandle vhArray;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessFloat.class, "final_v" + postfix, float.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessFloat.class, "v" + postfix, float.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessFloat.class, "static_final_v" + postfix, float.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessFloat.class, "static_v" + postfix, float.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(float[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -89,6 +132,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
int v;
+ static final int static_final_v2 = 0x01234567;
+
+ static int static_v2;
+
+ final int final_v2 = 0x01234567;
+
+ int v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -61,6 +69,41 @@
VarHandle vhArray;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessInt.class, "final_v" + postfix, int.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessInt.class, "v" + postfix, int.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessInt.class, "static_final_v" + postfix, int.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessInt.class, "static_v" + postfix, int.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(int[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -89,6 +132,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
long v;
+ static final long static_final_v2 = 0x0123456789ABCDEFL;
+
+ static long static_v2;
+
+ final long final_v2 = 0x0123456789ABCDEFL;
+
+ long v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -61,6 +69,41 @@
VarHandle vhArray;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessLong.class, "final_v" + postfix, long.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessLong.class, "v" + postfix, long.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessLong.class, "static_final_v" + postfix, long.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessLong.class, "static_v" + postfix, long.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(long[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -89,6 +132,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
short v;
+ static final short static_final_v2 = (short)0x0123;
+
+ static short static_v2;
+
+ final short final_v2 = (short)0x0123;
+
+ short v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -61,6 +69,41 @@
VarHandle vhArray;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessShort.class, "final_v" + postfix, short.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessShort.class, "v" + postfix, short.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessShort.class, "static_final_v" + postfix, short.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessShort.class, "static_v" + postfix, short.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(short[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -89,6 +132,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
String v;
+ static final String static_final_v2 = "foo";
+
+ static String static_v2;
+
+ final String final_v2 = "foo";
+
+ String v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -62,6 +70,41 @@
VarHandle vhArrayObject;
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessString.class, "final_v" + postfix, String.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccessString.class, "v" + postfix, String.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessString.class, "static_final_v" + postfix, String.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccessString.class, "static_v" + postfix, String.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+ }
+ else {
+ vh = MethodHandles.arrayElementVarHandle(int[].class);
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -91,6 +134,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java Sun Dec 09 12:36:24 2018 -0500
@@ -54,25 +54,61 @@
@Override
- public void setupVarHandleSources() {
+ public List<VarHandleSource> setupVarHandleSources(boolean same) {
// Combinations of VarHandle byte[] or ByteBuffer
- vhss = new ArrayList<>();
- for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+ List<VarHandleSource> vhss = new ArrayList<>();
+ for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+
+ Class<?> arrayType;
+ if (same) {
+ arrayType = char[].class;
+ }
+ else {
+ arrayType = int[].class;
+ }
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(char[].class, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(char[].class, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
+ return vhss;
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ VarHandle[] vhs2 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = setupVarHandleSources(false).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java Sun Dec 09 12:36:24 2018 -0500
@@ -54,25 +54,61 @@
@Override
- public void setupVarHandleSources() {
+ public List<VarHandleSource> setupVarHandleSources(boolean same) {
// Combinations of VarHandle byte[] or ByteBuffer
- vhss = new ArrayList<>();
- for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+ List<VarHandleSource> vhss = new ArrayList<>();
+ for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+
+ Class<?> arrayType;
+ if (same) {
+ arrayType = double[].class;
+ }
+ else {
+ arrayType = int[].class;
+ }
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(double[].class, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(double[].class, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
+ return vhss;
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ VarHandle[] vhs2 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = setupVarHandleSources(false).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java Sun Dec 09 12:36:24 2018 -0500
@@ -54,25 +54,61 @@
@Override
- public void setupVarHandleSources() {
+ public List<VarHandleSource> setupVarHandleSources(boolean same) {
// Combinations of VarHandle byte[] or ByteBuffer
- vhss = new ArrayList<>();
- for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+ List<VarHandleSource> vhss = new ArrayList<>();
+ for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+
+ Class<?> arrayType;
+ if (same) {
+ arrayType = float[].class;
+ }
+ else {
+ arrayType = int[].class;
+ }
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(float[].class, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(float[].class, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
+ return vhss;
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ VarHandle[] vhs2 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = setupVarHandleSources(false).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java Sun Dec 09 12:36:24 2018 -0500
@@ -54,25 +54,61 @@
@Override
- public void setupVarHandleSources() {
+ public List<VarHandleSource> setupVarHandleSources(boolean same) {
// Combinations of VarHandle byte[] or ByteBuffer
- vhss = new ArrayList<>();
- for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+ List<VarHandleSource> vhss = new ArrayList<>();
+ for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+
+ Class<?> arrayType;
+ if (same) {
+ arrayType = int[].class;
+ }
+ else {
+ arrayType = long[].class;
+ }
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(int[].class, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(int[].class, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
+ return vhss;
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ VarHandle[] vhs2 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = setupVarHandleSources(false).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java Sun Dec 09 12:36:24 2018 -0500
@@ -54,25 +54,61 @@
@Override
- public void setupVarHandleSources() {
+ public List<VarHandleSource> setupVarHandleSources(boolean same) {
// Combinations of VarHandle byte[] or ByteBuffer
- vhss = new ArrayList<>();
- for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+ List<VarHandleSource> vhss = new ArrayList<>();
+ for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+
+ Class<?> arrayType;
+ if (same) {
+ arrayType = long[].class;
+ }
+ else {
+ arrayType = int[].class;
+ }
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(long[].class, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(long[].class, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
+ return vhss;
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ VarHandle[] vhs2 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = setupVarHandleSources(false).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java Sun Dec 09 12:36:24 2018 -0500
@@ -54,25 +54,61 @@
@Override
- public void setupVarHandleSources() {
+ public List<VarHandleSource> setupVarHandleSources(boolean same) {
// Combinations of VarHandle byte[] or ByteBuffer
- vhss = new ArrayList<>();
- for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+ List<VarHandleSource> vhss = new ArrayList<>();
+ for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+
+ Class<?> arrayType;
+ if (same) {
+ arrayType = short[].class;
+ }
+ else {
+ arrayType = int[].class;
+ }
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(short[].class, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(short[].class, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
+ return vhss;
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ VarHandle[] vhs2 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = setupVarHandleSources(false).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
--- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,6 +50,14 @@
$type$ v;
+ static final $type$ static_final_v2 = $value1$;
+
+ static $type$ static_v2;
+
+ final $type$ final_v2 = $value1$;
+
+ $type$ v2;
+
VarHandle vhFinalField;
VarHandle vhField;
@@ -64,6 +72,45 @@
VarHandle vhArrayObject;
#end[String]
+ VarHandle[] allocate(boolean same) {
+ List<VarHandle> vhs = new ArrayList<>();
+
+ String postfix = same ? "" : "2";
+ VarHandle vh;
+ try {
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccess$Type$.class, "final_v" + postfix, $type$.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findVarHandle(
+ VarHandleTestAccess$Type$.class, "v" + postfix, $type$.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccess$Type$.class, "static_final_v" + postfix, $type$.class);
+ vhs.add(vh);
+
+ vh = MethodHandles.lookup().findStaticVarHandle(
+ VarHandleTestAccess$Type$.class, "static_v" + postfix, $type$.class);
+ vhs.add(vh);
+
+ if (same) {
+ vh = MethodHandles.arrayElementVarHandle($type$[].class);
+ }
+ else {
+#if[String]
+ vh = MethodHandles.arrayElementVarHandle(int[].class);
+#else[String]
+ vh = MethodHandles.arrayElementVarHandle(String[].class);
+#end[String]
+ }
+ vhs.add(vh);
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ return vhs.toArray(new VarHandle[0]);
+ }
+
@BeforeClass
public void setup() throws Exception {
vhFinalField = MethodHandles.lookup().findVarHandle(
@@ -95,6 +142,31 @@
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = allocate(true);
+ VarHandle[] vhs2 = allocate(true);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = allocate(false);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
+
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandle vh) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
--- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template Sat Dec 08 18:52:57 2018 -0500
+++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template Sun Dec 09 12:36:24 2018 -0500
@@ -54,25 +54,65 @@
@Override
- public void setupVarHandleSources() {
+ public List<VarHandleSource> setupVarHandleSources(boolean same) {
// Combinations of VarHandle byte[] or ByteBuffer
- vhss = new ArrayList<>();
- for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+ List<VarHandleSource> vhss = new ArrayList<>();
+ for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+
+ Class<?> arrayType;
+ if (same) {
+ arrayType = $type$[].class;
+ }
+ else {
+#if[int]
+ arrayType = long[].class;
+#else[int]
+ arrayType = int[].class;
+#end[int]
+ }
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle($type$[].class, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle($type$[].class, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo),
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
+ return vhss;
}
+ @Test
+ public void testEqualsAndHashCode() {
+ VarHandle[] vhs1 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ VarHandle[] vhs2 = setupVarHandleSources(true).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+
+ for (int i = 0; i < vhs1.length; i++) {
+ for (int j = 0; j < vhs1.length; j++) {
+ if (i == j) {
+ assertEquals(vhs1[i], vhs1[i]);
+ assertEquals(vhs1[i], vhs2[i]);
+ assertEquals(vhs1[i].hashCode(), vhs2[i].hashCode());
+ }
+ else {
+ assertNotEquals(vhs1[i], vhs1[j]);
+ assertNotEquals(vhs1[i], vhs2[j]);
+ }
+ }
+ }
+
+ VarHandle[] vhs3 = setupVarHandleSources(false).stream().
+ map(vhs -> vhs.s).toArray(VarHandle[]::new);
+ for (int i = 0; i < vhs1.length; i++) {
+ assertNotEquals(vhs1[i], vhs3[i]);
+ }
+ }
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
--- a/test/langtools/jdk/javadoc/doclet/lib/JavadocTester.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/jdk/javadoc/doclet/lib/JavadocTester.java Sun Dec 09 12:36:24 2018 -0500
@@ -522,7 +522,9 @@
+ stringToFind);
} else {
failed(path + ": following text " + (isFound ? "found:" : "not found:") + "\n"
- + stringToFind);
+ + stringToFind + '\n' +
+ "found \n" +
+ fileString);
}
}
}
--- a/test/langtools/jdk/javadoc/doclet/testClassTree/TestClassTree.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testClassTree/TestClassTree.java Sun Dec 09 12:36:24 2018 -0500
@@ -63,8 +63,7 @@
+ "<ul>\n"
+ "<li class=\"circle\">java.lang.Object\n"
+ "<ul>\n"
- + "<li class=\"circle\">java.lang.Enum<E> (implements java.lang."
- + "Comparable<T>, java.io.Serializable)\n"
+ + "<li class=\"circle\">java.lang.Enum<E> (implements java.lang.Comparable<T>, java.lang.constant.Constable, java.io.Serializable)\n"
+ "<ul>\n"
+ "<li class=\"circle\">pkg.<a href=\"Coin.html\" "
+ "title=\"enum in pkg\"><span class=\"typeNameLink\">Coin</span></a></li>\n"
--- a/test/langtools/jdk/jshell/TypeNameTest.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/jdk/jshell/TypeNameTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -192,7 +192,9 @@
assertType("arrayOf(99)[0]", "Integer");
assertEval("<Z> Z choose(Z z1, Z z2) { return z1; }");
- assertType("choose(1, 1L);", "Number&Comparable<? extends Number&Comparable<?>>", "Object");
+ assertType("choose(1, 1L);",
+ "Number&Comparable<? extends Number&Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc",
+ "Object");
}
public void testVariableTypeName() {
--- a/test/langtools/tools/javac/T8187978/FilterOutCandidatesForDiagnosticsTest.out Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/tools/javac/T8187978/FilterOutCandidatesForDiagnosticsTest.out Sun Dec 09 12:36:24 2018 -0500
@@ -1,2 +1,2 @@
-FilterOutCandidatesForDiagnosticsTest.java:12:64: compiler.err.cant.apply.symbols: kindname.method, add, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, java.util.ArrayList, add(compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>,java.lang.Object[],int), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, java.util.ArrayList, add(compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>))),(compiler.misc.inapplicable.method: kindname.method, java.util.ArrayList, add(int,compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>), (compiler.misc.arg.length.mismatch))}
+FilterOutCandidatesForDiagnosticsTest.java:12:64: compiler.err.cant.apply.symbols: kindname.method, add, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, java.util.ArrayList, add(compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc,java.lang.Object[],int), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, java.util.ArrayList, add(compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc))),(compiler.misc.inapplicable.method: kindname.method, java.util.ArrayList, add(int,compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc), (compiler.misc.arg.length.mismatch))}
1 error
--- a/test/langtools/tools/javac/diags/examples/EnumNoSubclassing.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/tools/javac/diags/examples/EnumNoSubclassing.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,5 +22,7 @@
*/
// key: compiler.err.enum.no.subclassing
+// key: compiler.note.unchecked.filename
+// key: compiler.note.unchecked.recompile
class EnumNoSubclassing extends Enum { }
--- a/test/langtools/tools/javac/enum/FauxEnum1.out Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/tools/javac/enum/FauxEnum1.out Sun Dec 09 12:36:24 2018 -0500
@@ -1,2 +1,4 @@
FauxEnum1.java:10:8: compiler.err.enum.no.subclassing
+- compiler.note.unchecked.filename: FauxEnum1.java
+- compiler.note.unchecked.recompile
1 error
--- a/test/langtools/tools/javac/generics/inference/8176534/TestUncheckedCalls.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/tools/javac/generics/inference/8176534/TestUncheckedCalls.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -221,7 +221,7 @@
return Stream.of(decls)
.filter(d -> d.hasKind(DeclKind.NONE))
.flatMap(d -> Stream.of(d.returnKind(), d.argumentsKind(), d.typeVarsKind()))
- .noneMatch(tk -> tk.ordinal() != 0);
+ .noneMatch((Enum<? extends Enum<?>> tk) -> tk.ordinal() != 0);
}
boolean tvarFilter() {
--- a/test/langtools/tools/javac/generics/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/tools/javac/generics/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out Sun Dec 09 12:36:24 2018 -0500
@@ -4,10 +4,10 @@
EagerReturnTypeResolutionTestb.java:45:26: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<?>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
EagerReturnTypeResolutionTestb.java:74:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.I<java.lang.Integer>,EagerReturnTypeResolutionTestb.I<java.lang.String>)
EagerReturnTypeResolutionTestb.java:75:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.I<java.lang.Integer>,EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
-EagerReturnTypeResolutionTestb.java:77:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I<java.lang.String>, EagerReturnTypeResolutionTestb.I<compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object))
+EagerReturnTypeResolutionTestb.java:77:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I<java.lang.String>, EagerReturnTypeResolutionTestb.I<compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object))
EagerReturnTypeResolutionTestb.java:78:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.I<java.lang.Integer>,EagerReturnTypeResolutionTestb.I<java.lang.String>)
EagerReturnTypeResolutionTestb.java:79:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.I<java.lang.Integer>,EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
-EagerReturnTypeResolutionTestb.java:81:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
+EagerReturnTypeResolutionTestb.java:81:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
EagerReturnTypeResolutionTestb.java:82:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.I<java.lang.Integer>,EagerReturnTypeResolutionTestb.I<java.lang.String>)
EagerReturnTypeResolutionTestb.java:83:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.I<java.lang.Integer>,EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
EagerReturnTypeResolutionTestb.java:85:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.I<?>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.I<?>,EagerReturnTypeResolutionTestb.I<java.lang.String>)
@@ -17,10 +17,10 @@
EagerReturnTypeResolutionTestb.java:90:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.I<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.I<?>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.I<?>,EagerReturnTypeResolutionTestb.I<java.lang.String>)
EagerReturnTypeResolutionTestb.java:91:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.J<java.lang.Integer>,EagerReturnTypeResolutionTestb.J<java.lang.String>)
EagerReturnTypeResolutionTestb.java:92:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.J<java.lang.Integer>,EagerReturnTypeResolutionTestb.J<java.lang.String>,java.lang.Object)
-EagerReturnTypeResolutionTestb.java:94:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I<java.lang.String>, EagerReturnTypeResolutionTestb.J<compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object))
+EagerReturnTypeResolutionTestb.java:94:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I<java.lang.String>, EagerReturnTypeResolutionTestb.J<compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object))
EagerReturnTypeResolutionTestb.java:95:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.J<java.lang.Integer>,EagerReturnTypeResolutionTestb.J<java.lang.String>)
EagerReturnTypeResolutionTestb.java:96:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.J<java.lang.Integer>,EagerReturnTypeResolutionTestb.J<java.lang.String>,java.lang.Object)
-EagerReturnTypeResolutionTestb.java:98:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
+EagerReturnTypeResolutionTestb.java:98:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
EagerReturnTypeResolutionTestb.java:99:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.J<java.lang.Integer>,EagerReturnTypeResolutionTestb.J<java.lang.String>)
EagerReturnTypeResolutionTestb.java:100:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.J<java.lang.Integer>,EagerReturnTypeResolutionTestb.J<java.lang.String>,java.lang.Object)
EagerReturnTypeResolutionTestb.java:102:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.K>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J<java.lang.String>)
@@ -28,10 +28,10 @@
EagerReturnTypeResolutionTestb.java:104:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.String>>,java.util.List<EagerReturnTypeResolutionTestb.K>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J<java.lang.String>)
EagerReturnTypeResolutionTestb.java:105:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>,java.util.List<EagerReturnTypeResolutionTestb.K>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J<java.lang.Integer>)
EagerReturnTypeResolutionTestb.java:106:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>,java.util.List<EagerReturnTypeResolutionTestb.K>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J<java.lang.Integer>,java.lang.Object)
-EagerReturnTypeResolutionTestb.java:108:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I<java.lang.String>, EagerReturnTypeResolutionTestb.I<compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object))
+EagerReturnTypeResolutionTestb.java:108:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I<java.lang.String>, EagerReturnTypeResolutionTestb.I<compiler.misc.type.captureof: 1, ? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object))
EagerReturnTypeResolutionTestb.java:109:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>,java.util.List<EagerReturnTypeResolutionTestb.K>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J<java.lang.Integer>)
EagerReturnTypeResolutionTestb.java:110:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>,java.util.List<EagerReturnTypeResolutionTestb.K>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J<java.lang.Integer>,java.lang.Object)
-EagerReturnTypeResolutionTestb.java:112:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
+EagerReturnTypeResolutionTestb.java:112:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>, EagerReturnTypeResolutionTestb.I<java.lang.String>,java.lang.Object)
EagerReturnTypeResolutionTestb.java:113:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List<T>,java.util.List<T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>,java.util.List<EagerReturnTypeResolutionTestb.K>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.eq.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J<java.lang.Integer>)
EagerReturnTypeResolutionTestb.java:114:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List<? super T>,java.util.List<? super T>, java.util.List<EagerReturnTypeResolutionTestb.J<java.lang.Integer>>,java.util.List<EagerReturnTypeResolutionTestb.K>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J<java.lang.Integer>,java.lang.Object)
EagerReturnTypeResolutionTestb.java:174:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Double, java.lang.Long,java.lang.Object))
--- a/test/langtools/tools/javac/lvti/harness/NonDenotableTest.java Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/tools/javac/lvti/harness/NonDenotableTest.java Sun Dec 09 12:36:24 2018 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -123,8 +123,6 @@
@InferredType(SEL_INT_ENUM_SEL)
var c = s;
for (@InferredType(SEL_INT_ENUM_SEL) var s2 = s ; ;) { break; }
- for (@InferredType(SEL_INT_ENUM_SEL) var s2 : arrayOf(s)) { break; }
- for (@InferredType(SEL_INT_ENUM_SEL) var s2 : listOf(s)) { break; }
}
List<? extends String> extString() { return null; }
--- a/test/langtools/tools/javac/varargs/6806876/T6806876.out Sat Dec 08 18:52:57 2018 -0500
+++ b/test/langtools/tools/javac/varargs/6806876/T6806876.out Sun Dec 09 12:36:24 2018 -0500
@@ -1,4 +1,4 @@
-T6806876.java:11:32: compiler.warn.unchecked.generic.array.creation: java.lang.Number&java.lang.Comparable<? extends java.lang.Number&java.lang.Comparable<?>>[]
+T6806876.java:11:32: compiler.warn.unchecked.generic.array.creation: java.lang.Number&java.lang.Comparable<? extends java.lang.Number&java.lang.Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc[]
T6806876.java:14:19: compiler.warn.unchecked.varargs.non.reifiable.type: T
- compiler.err.warnings.and.werror
1 error