8241100: Make Boolean, Character, Byte, and Short implement Constable

Reviewed-by: jrose, briangoetz, psandoz
This commit is contained in:
Jorn Vernee 2020-05-04 09:41:01 -07:00
parent 2d8bea8c1d
commit 31041d406a
8 changed files with 330 additions and 14 deletions

View file

@ -27,6 +27,15 @@ package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
import java.lang.constant.Constable;
import java.lang.constant.ConstantDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.DynamicConstantDesc;
import java.util.Optional;
import static java.lang.constant.ConstantDescs.BSM_GET_STATIC_FINAL;
import static java.lang.constant.ConstantDescs.CD_Boolean;
/**
* The Boolean class wraps a value of the primitive type
* {@code boolean} in an object. An object of type
@ -43,7 +52,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
* @since 1.0
*/
public final class Boolean implements java.io.Serializable,
Comparable<Boolean>
Comparable<Boolean>, Constable
{
/**
* The {@code Boolean} object corresponding to the primitive
@ -344,4 +353,16 @@ public final class Boolean implements java.io.Serializable,
public static boolean logicalXor(boolean a, boolean b) {
return a ^ b;
}
/**
* Returns an {@link Optional} containing the nominal descriptor for this
* instance.
*
* @return an {@link Optional} describing the {@linkplain Boolean} instance
* @since 15
*/
@Override
public Optional<DynamicConstantDesc<Boolean>> describeConstable() {
return Optional.of(value ? ConstantDescs.TRUE : ConstantDescs.FALSE);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, 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
@ -28,6 +28,15 @@ package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.VM;
import java.lang.constant.Constable;
import java.lang.constant.DynamicConstantDesc;
import java.util.Optional;
import static java.lang.constant.ConstantDescs.BSM_EXPLICIT_CAST;
import static java.lang.constant.ConstantDescs.CD_byte;
import static java.lang.constant.ConstantDescs.CD_int;
import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
/**
*
* The {@code Byte} class wraps a value of primitive type {@code byte}
@ -44,7 +53,7 @@ import jdk.internal.misc.VM;
* @see java.lang.Number
* @since 1.1
*/
public final class Byte extends Number implements Comparable<Byte> {
public final class Byte extends Number implements Comparable<Byte>, Constable {
/**
* A constant holding the minimum value a {@code byte} can
@ -77,6 +86,18 @@ public final class Byte extends Number implements Comparable<Byte> {
return Integer.toString((int)b, 10);
}
/**
* Returns an {@link Optional} containing the nominal descriptor for this
* instance.
*
* @return an {@link Optional} describing the {@linkplain Byte} instance
* @since 15
*/
@Override
public Optional<DynamicConstantDesc<Byte>> describeConstable() {
return Optional.of(DynamicConstantDesc.ofNamed(BSM_EXPLICIT_CAST, DEFAULT_NAME, CD_byte, intValue()));
}
private static class ByteCache {
private ByteCache() {}

View file

@ -25,14 +25,22 @@
package java.lang;
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.Locale;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.VM;
import java.lang.constant.Constable;
import java.lang.constant.DynamicConstantDesc;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import static java.lang.constant.ConstantDescs.BSM_EXPLICIT_CAST;
import static java.lang.constant.ConstantDescs.CD_char;
import static java.lang.constant.ConstantDescs.CD_int;
import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
/**
* The {@code Character} class wraps a value of the primitive
* type {@code char} in an object. An object of class
@ -122,7 +130,7 @@ import jdk.internal.misc.VM;
* @since 1.0
*/
public final
class Character implements java.io.Serializable, Comparable<Character> {
class Character implements java.io.Serializable, Comparable<Character>, Constable {
/**
* The minimum radix available for conversion to and from strings.
* The constant value of this field is the smallest value permitted
@ -602,6 +610,17 @@ class Character implements java.io.Serializable, Comparable<Character> {
*/
public static final int MAX_CODE_POINT = 0X10FFFF;
/**
* Returns an {@link Optional} containing the nominal descriptor for this
* instance.
*
* @return an {@link Optional} describing the {@linkplain Character} instance
* @since 15
*/
@Override
public Optional<DynamicConstantDesc<Character>> describeConstable() {
return Optional.of(DynamicConstantDesc.ofNamed(BSM_EXPLICIT_CAST, DEFAULT_NAME, CD_char, (int) value));
}
/**
* Instances of this class represent particular subsets of the Unicode

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, 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
@ -28,6 +28,15 @@ package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.VM;
import java.lang.constant.Constable;
import java.lang.constant.DynamicConstantDesc;
import java.util.Optional;
import static java.lang.constant.ConstantDescs.BSM_EXPLICIT_CAST;
import static java.lang.constant.ConstantDescs.CD_int;
import static java.lang.constant.ConstantDescs.CD_short;
import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
/**
* The {@code Short} class wraps a value of primitive type {@code
* short} in an object. An object of type {@code Short} contains a
@ -43,7 +52,7 @@ import jdk.internal.misc.VM;
* @see java.lang.Number
* @since 1.1
*/
public final class Short extends Number implements Comparable<Short> {
public final class Short extends Number implements Comparable<Short>, Constable {
/**
* A constant holding the minimum value a {@code short} can
@ -203,6 +212,18 @@ public final class Short extends Number implements Comparable<Short> {
return valueOf(s, 10);
}
/**
* Returns an {@link Optional} containing the nominal descriptor for this
* instance.
*
* @return an {@link Optional} describing the {@linkplain Short} instance
* @since 15
*/
@Override
public Optional<DynamicConstantDesc<Short>> describeConstable() {
return Optional.of(DynamicConstantDesc.ofNamed(BSM_EXPLICIT_CAST, DEFAULT_NAME, CD_short, intValue()));
}
private static class ShortCache {
private ShortCache() {}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, 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
@ -194,10 +194,18 @@ public final class ConstantDescs {
= ofConstantBootstrap(CD_ConstantBootstraps, "enumConstant",
CD_Enum);
/**
* {@link MethodHandleDesc} representing {@link ConstantBootstraps#getStaticFinal(Lookup, String, Class, Class) ConstantBootstraps.getStaticFinal}
* @since 15
*/
public static final DirectMethodHandleDesc BSM_GET_STATIC_FINAL
= ofConstantBootstrap(CD_ConstantBootstraps, "getStaticFinal",
CD_Object, CD_Class);
/** {@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);
CD_Object);
/** {@link MethodHandleDesc} representing {@link ConstantBootstraps#fieldVarHandle(Lookup, String, Class, Class, Class) ConstantBootstraps.fieldVarHandle} */
public static final DirectMethodHandleDesc BSM_VARHANDLE_FIELD
@ -219,6 +227,14 @@ public final class ConstantDescs {
= ofConstantBootstrap(CD_ConstantBootstraps, "invoke",
CD_Object, CD_MethodHandle, CD_Object.arrayType());
/**
* {@link MethodHandleDesc} representing {@link ConstantBootstraps#explicitCast(Lookup, String, Class, Object)} ConstantBootstraps.explicitCast}
* @since 15
*/
public static final DirectMethodHandleDesc BSM_EXPLICIT_CAST
= ofConstantBootstrap(CD_ConstantBootstraps, "explicitCast",
CD_Object, CD_Object);
/** {@link ClassDesc} representing the primitive type {@code int} */
public static final ClassDesc CD_int = ClassDesc.ofDescriptor("I");
@ -251,6 +267,22 @@ public final class ConstantDescs {
= DynamicConstantDesc.ofNamed(ConstantDescs.BSM_NULL_CONSTANT,
DEFAULT_NAME, ConstantDescs.CD_Object);
/**
* Nominal descriptor representing the constant {@linkplain Boolean#TRUE}
* @since 15
*/
public static final DynamicConstantDesc<Boolean> TRUE
= DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL,
"TRUE", CD_Boolean, CD_Boolean);
/**
* Nominal descriptor representing the constant {@linkplain Boolean#TRUE}
* @since 15
*/
public static final DynamicConstantDesc<Boolean> FALSE
= DynamicConstantDesc.ofNamed(BSM_GET_STATIC_FINAL,
"FALSE", CD_Boolean, CD_Boolean);
static final DirectMethodHandleDesc MHD_METHODHANDLE_ASTYPE
= MethodHandleDesc.ofMethod(Kind.VIRTUAL, CD_MethodHandle, "asType",
MethodTypeDesc.of(CD_MethodHandle, CD_MethodType));

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020, 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
@ -355,6 +355,71 @@ public final class ConstantBootstraps {
return MethodHandles.arrayElementVarHandle(validateClassAccess(lookup, arrayClass));
}
/**
* Applies a conversion from a source type to a destination type.
* <p>
* Given a destination type {@code dstType} and an input
* value {@code value}, one of the following will happen:
* <ul>
* <li>If {@code dstType} is {@code void.class},
* a {@link ClassCastException} is thrown.
* <li>If {@code dstType} is {@code Object.class}, {@code value} is returned as is.
* </ul>
* <p>
* Otherwise one of the following conversions is applied to {@code value}:
* <ol>
* <li>If {@code dstType} is a reference type, a reference cast
* is applied to {@code value} as if by calling {@code dstType.cast(value)}.
* <li>If {@code dstType} is a primitive type, then, if the runtime type
* of {@code value} is a primitive wrapper type (such as {@link Integer}),
* a Java unboxing conversion is applied {@jls 5.1.8} followed by a
* Java casting conversion {@jls 5.5} converting either directly to
* {@code dstType}, or, if {@code dstType} is {@code boolean},
* to {@code int}, which is then converted to either {@code true}
* or {@code false} depending on whether the least-significant-bit
* is 1 or 0 respectively. If the runtime type of {@code value} is
* not a primitive wrapper type a {@link ClassCastException} is thrown.
* </ol>
* <p>
* The result is the same as when using the following code:
* <blockquote><pre>{@code
* MethodHandle id = MethodHandles.identity(dstType);
* MethodType mt = MethodType.methodType(dstType, Object.class);
* MethodHandle conv = MethodHandles.explicitCastArguments(id, mt);
* return conv.invoke(value);
* }</pre></blockquote>
*
* @param lookup unused
* @param name unused
* @param dstType the destination type of the conversion
* @param value the value to be converted
* @return the converted value
* @throws ClassCastException when {@code dstType} is {@code void},
* when a cast per (1) fails, or when {@code dstType} is a primitive type
* and the runtime type of {@code value} is not a primitive wrapper type
* (such as {@link Integer})
*
* @since 15
*/
public static Object explicitCast(MethodHandles.Lookup lookup, String name, Class<?> dstType, Object value)
throws ClassCastException {
if (dstType == void.class)
throw new ClassCastException("Can not convert to void");
if (dstType == Object.class)
return value;
MethodHandle id = MethodHandles.identity(dstType);
MethodType mt = MethodType.methodType(dstType, Object.class);
MethodHandle conv = MethodHandles.explicitCastArguments(id, mt);
try {
return conv.invoke(value);
} catch (ClassCastException e) {
throw e; // specified, let CCE through
} catch (Throwable throwable) {
throw new InternalError(throwable); // Not specified, throw InternalError
}
}
private static <T> Class<T> validateClassAccess(MethodHandles.Lookup lookup, Class<T> type) {
try {
lookup.accessClass(type);