Skip to content

Commit

Permalink
8241100: Make Boolean, Character, Byte, and Short implement Constable
Browse files Browse the repository at this point in the history
Reviewed-by: jrose, briangoetz, psandoz
  • Loading branch information
JornVernee committed May 4, 2020
1 parent 2d8bea8 commit 31041d4
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 12 deletions.
23 changes: 22 additions & 1 deletion src/java.base/share/classes/java/lang/Boolean.java
Expand Up @@ -27,6 +27,15 @@

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
Expand All @@ -43,7 +52,7 @@
* @since 1.0
*/
public final class Boolean implements java.io.Serializable,
Comparable<Boolean>
Comparable<Boolean>, Constable
{
/**
* The {@code Boolean} object corresponding to the primitive
Expand Down Expand Up @@ -344,4 +353,16 @@ public static boolean logicalOr(boolean a, boolean b) {
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);
}
}
25 changes: 23 additions & 2 deletions src/java.base/share/classes/java/lang/Byte.java
@@ -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
Expand Down Expand Up @@ -28,6 +28,15 @@
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}
Expand All @@ -44,7 +53,7 @@
* @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
Expand Down Expand Up @@ -77,6 +86,18 @@ public static String toString(byte b) {
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() {}

Expand Down
27 changes: 23 additions & 4 deletions src/java.base/share/classes/java/lang/Character.java
Expand Up @@ -25,13 +25,21 @@

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.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;

import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.VM;
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
Expand Down Expand Up @@ -122,7 +130,7 @@
* @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
Expand Down Expand Up @@ -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
Expand Down
25 changes: 23 additions & 2 deletions src/java.base/share/classes/java/lang/Short.java
@@ -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
Expand Down Expand Up @@ -28,6 +28,15 @@
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
Expand All @@ -43,7 +52,7 @@
* @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
Expand Down Expand Up @@ -203,6 +212,18 @@ public static Short valueOf(String s) throws NumberFormatException {
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() {}

Expand Down
36 changes: 34 additions & 2 deletions src/java.base/share/classes/java/lang/constant/ConstantDescs.java
@@ -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
Expand Down Expand Up @@ -194,10 +194,18 @@ private 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
Expand All @@ -219,6 +227,14 @@ private 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");

Expand Down Expand Up @@ -251,6 +267,22 @@ private 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));
Expand Down
@@ -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
Expand Down Expand Up @@ -355,6 +355,71 @@ public static VarHandle arrayVarHandle(MethodHandles.Lookup lookup, String name,
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);
Expand Down

0 comments on commit 31041d4

Please sign in to comment.