Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8260606: Update Valhalla core-libs naming for methods related to prim…
…itive classes

Reviewed-by: mchung
  • Loading branch information
Roger Riggs committed Feb 5, 2021
1 parent ddfba61 commit 5f1e8d9
Show file tree
Hide file tree
Showing 28 changed files with 195 additions and 209 deletions.
Expand Up @@ -1178,7 +1178,7 @@ private void writeObject0(Object obj, boolean unshared)
// remaining cases
if (obj instanceof String) {
writeString((String) obj, unshared);
} else if (cl.isInlineClass()) {
} else if (cl.isPrimitiveClass()) {
throw new NotSerializableException(cl.getName());
} else if (cl.isArray()) {
writeArray(obj, desc, unshared);
Expand Down
6 changes: 3 additions & 3 deletions src/java.base/share/classes/java/io/ObjectStreamClass.java
Expand Up @@ -499,7 +499,7 @@ private ObjectStreamClass(final Class<?> cl) {
name = cl.getName();
isProxy = Proxy.isProxyClass(cl);
isEnum = Enum.class.isAssignableFrom(cl);
boolean isInlineClass = cl.isInlineClass();
boolean isPrimitiveClass = cl.isPrimitiveClass();
isRecord = cl.isRecord();
serializable = Serializable.class.isAssignableFrom(cl);
externalizable = Externalizable.class.isAssignableFrom(cl);
Expand Down Expand Up @@ -571,8 +571,8 @@ public Void run() {
if (deserializeEx == null) {
if (isEnum) {
deserializeEx = new ExceptionInfo(name, "enum type");
} else if (isInlineClass && writeReplaceMethod == null) {
deserializeEx = new ExceptionInfo(name, "inline class");
} else if (isPrimitiveClass && writeReplaceMethod == null) {
deserializeEx = new ExceptionInfo(name, "primitive class");
} else if (cons == null && !isRecord) {
deserializeEx = new ExceptionInfo(name, "no valid constructor");
}
Expand Down
147 changes: 69 additions & 78 deletions src/java.base/share/classes/java/lang/Class.java
Expand Up @@ -201,7 +201,7 @@ public final class Class<T> implements java.io.Serializable,
private static final int ANNOTATION = 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000;
private static final int INLINE = 0x00000100;
private static final int PRIMITIVE_CLASS = 0x00000100;

private static native void registerNatives();
static {
Expand Down Expand Up @@ -233,7 +233,7 @@ private Class(ClassLoader loader, Class<?> arrayComponentType) {
* @return a string representation of this {@code Class} object.
*/
public String toString() {
return (isInlineClass() ? "inline " : "")
return (isPrimitiveClass() ? "primitive " : "")
+ (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
+ getName();
}
Expand Down Expand Up @@ -296,9 +296,8 @@ public String toGenericString() {
if (isAnnotation()) {
sb.append('@');
}
if (isInlineClass()) {
sb.append("inline");
sb.append(' ');
if (isPrimitiveClass()) {
sb.append("primitive ");
}
if (isInterface()) { // Note: all annotation interfaces are interfaces
sb.append("interface");
Expand Down Expand Up @@ -553,137 +552,129 @@ public static Class<?> forName(Module module, String name) {
}

/**
* Returns {@code true} if this class is an inline class.
* Returns {@code true} if this class is a primitive class.
*
* @return {@code true} if this class is an inline class
* @return {@code true} if this class is a primitive class, otherwise {@code false}
* @since Valhalla
*/
public boolean isInlineClass() {
return (this.getModifiers() & INLINE) != 0;
public boolean isPrimitiveClass() {
return (this.getModifiers() & PRIMITIVE_CLASS) != 0;
}

/**
* Returns a {@code Class} object representing the <em>value projection</em>
* type of this class if this {@code Class} represents the reference projection
* type of an {@linkplain #isInlineClass() inline class}.
* If this {@code Class} represents the value projection type
* of an inline class, then this method returns this class.
* Returns an {@code Optional<Class>} object representing the <em>primitive value type</em>
* of this class if this {@code Class} represents the <em>reference type</em>
* of a {@linkplain #isPrimitiveClass() primitive class}.
* If this {@code Class} represents the value type of a primitive class,
* then this method returns this class.
* Otherwise an empty {@link Optional} is returned.
*
* @return the {@code Class} object representing the value projection type of
* this class if this class is the value projection type
* or the reference projection type of an inline class;
* @return the {@code Optional<Class>} representing the primitive value type of
* this class if this class is either the value type
* or the reference type of a primitive class;
* an empty {@link Optional} otherwise
* @since Valhalla
*/
public Optional<Class<?>> valueType() {
if (isPrimitive() || isInterface() || isArray())
return Optional.empty();

Class<?>[] valRefTypes = getProjectionTypes();
Class<?>[] valRefTypes = getPrimitiveTypes();
return valRefTypes.length > 0 ? Optional.of(valRefTypes[0]) : Optional.empty();
}

/**
* Returns a {@code Class} object representing the reference type
* of this class.
* <p>
* If this {@code Class} represents an {@linkplain #isInlineClass()
* inline class} with a reference projection type, then this method
* returns the <em>reference projection</em> type of this inline class.
* <p>
* If this {@code Class} represents the reference projection type
* of an inline class, then this method returns this class.
* If this {@code Class} represents a {@linkplain #isPrimitiveClass()
* primitive reference type}, then this method
* returns the <em>primitive reference type</em> type of this primitive class.
* <p>
* If this class is an {@linkplain #isInlineClass() inline class}
* without a reference projection, then this method returns an empty
* {@code Optional}.
* If this {@code Class} represents the reference type
* of a primitive class, then this method returns this class.
* <p>
* If this class is an identity class, then this method returns this
* class.
* If this class is an identity class, then this method returns this class.
* <p>
* Otherwise this method returns an empty {@code Optional}.
*
* @return the {@code Class} object representing a reference type for
* this class if present; an empty {@link Optional} otherwise.
* @return the {@code Optional<Class>} object representing the reference type for
* this class, if present; an empty {@link Optional} otherwise.
* @since Valhalla
*/
public Optional<Class<?>> referenceType() {
if (isPrimitive()) return Optional.empty();
if (isInterface() || isArray()) return Optional.of(this);

Class<?>[] valRefTypes = getProjectionTypes();
Class<?>[] valRefTypes = getPrimitiveTypes();
return valRefTypes.length == 2 ? Optional.of(valRefTypes[1]) : Optional.empty();
}

/*
* Returns true if this Class object represents a reference projection
* type for an inline class.
* Returns true if this Class object represents a primitive reference
* type for a primitive class.
*
* A reference projection type must be a sealed abstract class that
* permits the inline projection type to extend. The inline projection
* type and reference projection type for an inline type must be of
* the same package.
* A primitive reference type must be a sealed abstract class that
* permits the primitive value type to extend. The primitive value type
* and primitive reference type for a primitive type must be of the same package.
*/
private boolean isReferenceProjectionType() {
if (isPrimitive() || isArray() || isInterface() || isInlineClass())
private boolean isPrimitiveReferenceType() {
if (isPrimitive() || isArray() || isInterface() || isPrimitiveClass())
return false;

int mods = getModifiers();
if (!Modifier.isAbstract(mods)) {
return false;
}

Class<?>[] valRefTypes = getProjectionTypes();
Class<?>[] valRefTypes = getPrimitiveTypes();
return valRefTypes.length == 2 && valRefTypes[1] == this;
}

private transient Class<?>[] projectionTypes;
private Class<?>[] getProjectionTypes() {
private transient Class<?>[] primitiveTypes;
private Class<?>[] getPrimitiveTypes() {
if (isPrimitive() || isArray() || isInterface())
return null;

Class<?>[] valRefTypes = projectionTypes;
Class<?>[] valRefTypes = primitiveTypes;
if (valRefTypes == null) {
// C.ensureProjectionTypesInited calls initProjectionTypes that may
// call D.ensureProjectionTypesInited where D is its superclass.
// So initProjectionTypes is called without holding any lock to
// So newPrimitiveTypeArray is called without holding any lock to
// avoid potential deadlock when multiple threads attempt to
// initialize the projection types for C and E where D is
// initialize the primitive types for C and E where D is
// the superclass of both C and E (which is an error case)
valRefTypes = newProjectionTypeArray();
valRefTypes = newTypeArrayForPrimitiveClass();
}
synchronized (this) {
// set the projection types if not set
if (projectionTypes == null) {
projectionTypes = valRefTypes;
// set the value and reference types if not set
if (primitiveTypes == null) {
primitiveTypes = valRefTypes;
}
}
return projectionTypes;
return primitiveTypes;
}

/*
* Returns an array of Class object whose element at index 0 represents the
* value projection type and element at index 1 represents the reference
* projection type if present.
* Returns an array of Class objects whose element at index 0 represents the
* primitive value type and element at index 1 represents the
* primitive reference type, if present.
*
* If this Class object is neither a value projection type nor
* a reference projection type for an inline class, then an empty array
* If this Class object is neither a primitive value type nor
* a primitive reference type for a primitive class, then an empty array
* is returned.
*/
private Class<?>[] newProjectionTypeArray() {
private Class<?>[] newTypeArrayForPrimitiveClass() {
if (isPrimitive() || isArray() || isInterface())
return null;

if (isInlineClass()) {
if (isPrimitiveClass()) {
Class<?> superClass = getSuperclass();
if (superClass != Object.class && superClass.isReferenceProjectionType()) {
if (superClass != Object.class && superClass.isPrimitiveReferenceType()) {
return new Class<?>[] { this, superClass };
} else {
return new Class<?>[] { this };
}
} else {
Class<?> valType = valueProjectionType();
Class<?> valType = primitiveValueType();
if (valType != null) {
return new Class<?>[] { valType, this};
} else {
Expand All @@ -693,30 +684,30 @@ private Class<?>[] newProjectionTypeArray() {
}

/*
* Returns the value projection type if this Class represents
* a reference projection type. If this class is an inline class
* Returns the primitive value type if this Class represents
* a primitive reference type. If this class is a primitive class
* then this method returns this class. Otherwise, returns null.
*/
private Class<?> valueProjectionType() {
private Class<?> primitiveValueType() {
if (isPrimitive() || isArray() || isInterface())
return null;

if (isInlineClass())
if (isPrimitiveClass())
return this;

int mods = getModifiers();
if (!Modifier.isAbstract(mods)) {
return null;
}

// A reference projection type must be a sealed abstract class
// that permits the inline projection type to extend.
// The inline projection type and reference projection type for
// an inline type must be of the same package.
// A primitive reference type must be a sealed abstract class
// that permits the primitive class type to extend.
// The primitive class project type and primitive reference type for
// a primitive class type must be of the same package.
Class<?>[] subclasses = getPermittedSubclasses0();
if ((subclasses.length == 1) &&
(subclasses[0].isInlineClass()) &&
(getPackageName().equals(subclasses[0].getPackageName()))) {
(subclasses[0].isPrimitiveClass()) &&
(getPackageName().equals(subclasses[0].getPackageName()))) {
return subclasses[0];
}
return null;
Expand Down Expand Up @@ -1001,7 +992,7 @@ public boolean isSynthetic() {
* <tr><th scope="row"> {@code char} <td style="text-align:center"> {@code C}
* <tr><th scope="row"> class or interface with <a href="ClassLoader.html#binary-name">binary name</a> <i>N</i>
* <td style="text-align:center"> {@code L}<em>N</em>{@code ;}
* <tr><th scope="row"> {@linkplain #isInlineClass() inline class} with <a href="ClassLoader.html#binary-name">binary name</a> <i>N</i>
* <tr><th scope="row"> {@linkplain #isPrimitiveClass() primitive class} with <a href="ClassLoader.html#binary-name">binary name</a> <i>N</i>
* <td style="text-align:center"> {@code Q}<em>N</em>{@code ;}
* <tr><th scope="row"> {@code double} <td style="text-align:center"> {@code D}
* <tr><th scope="row"> {@code float} <td style="text-align:center"> {@code F}
Expand Down Expand Up @@ -3990,16 +3981,16 @@ Map<String, T> enumConstantDirectory() {
*
* @throws ClassCastException if the object is not
* {@code null} and is not assignable to the type T.
* @throws NullPointerException if this is an {@linkplain #isInlineClass()
* inline type} and the object is {@code null}
* @throws NullPointerException if this is an {@linkplain #isPrimitiveClass()
* primitive class} and the object is {@code null}
*
* @since 1.5
*/
@SuppressWarnings("unchecked")
@IntrinsicCandidate
public T cast(Object obj) {
if (isInlineClass() && obj == null)
throw new NullPointerException(getName() + " is an inline class");
if (isPrimitiveClass() && obj == null)
throw new NullPointerException(getName() + " is a primitive class");

if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
Expand Down Expand Up @@ -4510,7 +4501,7 @@ public String descriptorString() {
if (isArray()) {
return "[" + componentType.descriptorString();
}
String typeDesc = isInlineClass() ? "Q" : "L";
String typeDesc = isPrimitiveClass() ? "Q" : "L";
if (isHidden()) {
String name = getName();
int index = name.indexOf('/');
Expand Down
10 changes: 5 additions & 5 deletions src/java.base/share/classes/java/lang/NonTearable.java
Expand Up @@ -26,7 +26,7 @@
package java.lang;

/**
* An inline class implements the {@code NonTearable} interface to
* A primitive class implements the {@code NonTearable} interface to
* request that the JVM take extra care to avoid structure tearing
* when loading or storing any value of the class to a field or array
* element. Normally, only fields declared {@code volatile} are
Expand All @@ -35,7 +35,7 @@
* they are stored in array elements or in non-{@code volatile}
* fields, and even when multiple threads perform racing writes.
*
* <p> An inline instance of multiple components is said to be "torn"
* <p> An primitive instance of multiple components is said to be "torn"
* when two racing threads compete to write those components, and one
* thread writes some components while another thread writes other
* components, so a subsequent observer will read a hybrid composed,
Expand All @@ -45,7 +45,7 @@
* requires a read and two writes (initialization counting as a write)
* of a multi-component value, with a race between any two of the
* accesses. The effect can also be described as if the Java memory
* model break up inline instance reads and writes into reads and
* model break up primitive classinstance reads and writes into reads and
* writes of their various fields, as it does with longs and doubles
* (JLS 17.7).
*
Expand All @@ -59,7 +59,7 @@
*/
public interface NonTearable {
// TO DO: Finalize name.
// TO DO: Decide whether and how to restrict this type to to
// inline classes only, or if not, whether to document its
// TO DO: Decide whether and how to restrict this type to
// primitive classes only, or if not, whether to document its
// non-effect on identity classes.
}
7 changes: 3 additions & 4 deletions src/java.base/share/classes/java/lang/Object.java
Expand Up @@ -28,7 +28,6 @@
import jdk.internal.vm.annotation.IntrinsicCandidate;
import jdk.internal.access.SharedSecrets;

import java.lang.invoke.ValueBootstrapMethods;
import java.util.Objects;

/**
Expand Down Expand Up @@ -239,16 +238,16 @@ public boolean equals(Object obj) {
* getClass().getName() + '@' + Integer.toHexString(hashCode())
* </pre></blockquote>
* <p>
* If this object is an instance of an inline class, then
* If this object is an instance of a primitive class, then
* the {@code toString} method returns a string which contains
* the name of the inline class, and string representations of
* the name of the primitive class, and string representations of
* all its fields. The precise format produced by this method
* is unspecified and subject to change.
*
* @return a string representation of the object.
*/
public String toString() {
if (getClass().isInlineClass()) {
if (getClass().isPrimitiveClass()) {
return SharedSecrets.getJavaLangInvokeAccess().inlineObjectToString(this);
} else {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
Expand Down

0 comments on commit 5f1e8d9

Please sign in to comment.