8333749: Consolidate ConstantDesc conversion in java.base
Co-authored-by: Claes Redestad <redestad@openjdk.org> Reviewed-by: redestad, jvernee
This commit is contained in:
parent
a6fc2f839a
commit
8d2f9e57c3
@ -70,6 +70,7 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
import jdk.internal.loader.BootLoader;
|
||||
import jdk.internal.loader.BuiltinClassLoader;
|
||||
@ -4709,7 +4710,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
public Optional<ClassDesc> describeConstable() {
|
||||
Class<?> c = isArray() ? elementType() : this;
|
||||
return c.isHidden() ? Optional.empty()
|
||||
: Optional.of(ClassDesc.ofDescriptor(descriptorString()));
|
||||
: Optional.of(ConstantUtils.classDesc(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,6 +45,7 @@ import java.lang.classfile.attribute.LocalVariableTypeInfo;
|
||||
import java.lang.classfile.instruction.ExceptionCatch;
|
||||
import java.util.List;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static jdk.internal.constant.ConstantUtils.CD_module_info;
|
||||
import jdk.internal.javac.PreviewFeature;
|
||||
|
||||
/**
|
||||
@ -392,7 +393,7 @@ public sealed interface ClassFile
|
||||
*/
|
||||
default byte[] buildModule(ModuleAttribute moduleAttribute,
|
||||
Consumer<? super ClassBuilder> handler) {
|
||||
return build(ClassDesc.of("module-info"), clb -> {
|
||||
return build(CD_module_info, clb -> {
|
||||
clb.withFlags(AccessFlag.MODULE);
|
||||
clb.with(moduleAttribute);
|
||||
handler.accept(clb);
|
||||
|
@ -36,7 +36,6 @@ import static java.util.stream.Collectors.joining;
|
||||
import static jdk.internal.constant.ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS;
|
||||
import static jdk.internal.constant.ConstantUtils.arrayDepth;
|
||||
import static jdk.internal.constant.ConstantUtils.binaryToInternal;
|
||||
import static jdk.internal.constant.ConstantUtils.dropFirstAndLastChar;
|
||||
import static jdk.internal.constant.ConstantUtils.internalToBinary;
|
||||
import static jdk.internal.constant.ConstantUtils.validateBinaryClassName;
|
||||
import static jdk.internal.constant.ConstantUtils.validateInternalClassName;
|
||||
@ -165,7 +164,7 @@ public sealed interface ClassDesc
|
||||
static ClassDesc ofDescriptor(String descriptor) {
|
||||
// implicit null-check
|
||||
return (descriptor.length() == 1)
|
||||
? Wrapper.forPrimitiveType(descriptor.charAt(0)).classDescriptor()
|
||||
? Wrapper.forPrimitiveType(descriptor.charAt(0)).basicClassDescriptor()
|
||||
// will throw IAE on descriptor.length == 0 or if array dimensions too long
|
||||
: ReferenceClassDescImpl.of(descriptor);
|
||||
}
|
||||
@ -315,7 +314,7 @@ public sealed interface ClassDesc
|
||||
if (isArray()) {
|
||||
String desc = descriptorString();
|
||||
if (desc.length() == 2) {
|
||||
return Wrapper.forBasicType(desc.charAt(1)).classDescriptor();
|
||||
return Wrapper.forBasicType(desc.charAt(1)).basicClassDescriptor();
|
||||
} else {
|
||||
return ReferenceClassDescImpl.ofValidated(desc.substring(1));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2024, 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
|
||||
@ -52,6 +52,8 @@ import java.lang.classfile.ClassHierarchyResolver;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.TypeKind;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.module.Modules;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
import jdk.internal.reflect.Reflection;
|
||||
@ -63,6 +65,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodType.methodType;
|
||||
import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC;
|
||||
import static java.lang.classfile.ClassFile.*;
|
||||
import static jdk.internal.constant.ConstantUtils.*;
|
||||
|
||||
/**
|
||||
* This class consists exclusively of static methods that help adapt
|
||||
@ -249,14 +252,14 @@ public class MethodHandleProxies {
|
||||
|
||||
// the field name holding the method handle for this method
|
||||
String fieldName = "m" + count++;
|
||||
var mt = methodType(m.getReturnType(), JLRA.getExecutableSharedParameterTypes(m), true);
|
||||
var md = methodTypeDesc(m.getReturnType(), JLRA.getExecutableSharedParameterTypes(m));
|
||||
var thrown = JLRA.getExecutableSharedExceptionTypes(m);
|
||||
var exceptionTypeDescs =
|
||||
thrown.length == 0 ? DEFAULT_RETHROWS
|
||||
: Stream.concat(DEFAULT_RETHROWS.stream(),
|
||||
Arrays.stream(thrown).map(MethodHandleProxies::desc))
|
||||
Arrays.stream(thrown).map(ConstantUtils::referenceClassDesc))
|
||||
.distinct().toList();
|
||||
methods.add(new MethodInfo(desc(mt), exceptionTypeDescs, fieldName));
|
||||
methods.add(new MethodInfo(md, exceptionTypeDescs, fieldName));
|
||||
|
||||
// find the types referenced by this method
|
||||
addElementType(referencedTypes, m.getReturnType());
|
||||
@ -279,7 +282,8 @@ public class MethodHandleProxies {
|
||||
int i = intfcName.lastIndexOf('.');
|
||||
// jdk.MHProxy#.Interface
|
||||
String className = packageName + "." + (i > 0 ? intfcName.substring(i + 1) : intfcName);
|
||||
byte[] template = createTemplate(loader, ClassDesc.of(className), desc(intfc), uniqueName, methods);
|
||||
byte[] template = createTemplate(loader, binaryNameToDesc(className),
|
||||
referenceClassDesc(intfc), uniqueName, methods);
|
||||
// define the dynamic module to the class loader of the interface
|
||||
var definer = new Lookup(intfc).makeHiddenClassDefiner(className, template, Set.of(), DUMPER);
|
||||
|
||||
@ -335,17 +339,17 @@ public class MethodHandleProxies {
|
||||
}
|
||||
}
|
||||
|
||||
private static final List<ClassDesc> DEFAULT_RETHROWS = List.of(desc(RuntimeException.class), desc(Error.class));
|
||||
private static final ClassDesc CD_UndeclaredThrowableException = desc(UndeclaredThrowableException.class);
|
||||
private static final ClassDesc CD_IllegalAccessException = desc(IllegalAccessException.class);
|
||||
private static final List<ClassDesc> DEFAULT_RETHROWS = List.of(referenceClassDesc(RuntimeException.class), referenceClassDesc(Error.class));
|
||||
private static final ClassDesc CD_UndeclaredThrowableException = referenceClassDesc(UndeclaredThrowableException.class);
|
||||
private static final ClassDesc CD_IllegalAccessException = referenceClassDesc(IllegalAccessException.class);
|
||||
private static final MethodTypeDesc MTD_void_Throwable = MethodTypeDesc.of(CD_void, CD_Throwable);
|
||||
private static final MethodType MT_void_Lookup_MethodHandle_MethodHandle =
|
||||
methodType(void.class, Lookup.class, MethodHandle.class, MethodHandle.class);
|
||||
private static final MethodType MT_Object_Lookup_MethodHandle_MethodHandle =
|
||||
MT_void_Lookup_MethodHandle_MethodHandle.changeReturnType(Object.class);
|
||||
private static final MethodType MT_MethodHandle_Object = methodType(MethodHandle.class, Object.class);
|
||||
private static final MethodTypeDesc MTD_void_Lookup_MethodHandle_MethodHandle =
|
||||
desc(MT_void_Lookup_MethodHandle_MethodHandle);
|
||||
private static final MethodTypeDesc MTD_void_Lookup_MethodHandle_MethodHandle
|
||||
= methodTypeDesc(MT_void_Lookup_MethodHandle_MethodHandle);
|
||||
private static final MethodTypeDesc MTD_void_Lookup = MethodTypeDesc.of(CD_void, CD_MethodHandles_Lookup);
|
||||
private static final MethodTypeDesc MTD_MethodHandle_MethodType = MethodTypeDesc.of(CD_MethodHandle, CD_MethodType);
|
||||
private static final MethodTypeDesc MTD_Class = MethodTypeDesc.of(CD_Class);
|
||||
@ -531,16 +535,6 @@ public class MethodHandleProxies {
|
||||
}
|
||||
}
|
||||
|
||||
private static ClassDesc desc(Class<?> cl) {
|
||||
return cl.describeConstable().orElseThrow(() -> newInternalError("Cannot convert class "
|
||||
+ cl.getName() + " to a constant"));
|
||||
}
|
||||
|
||||
private static MethodTypeDesc desc(MethodType mt) {
|
||||
return mt.describeConstable().orElseThrow(() -> newInternalError("Cannot convert method type "
|
||||
+ mt + " to a constant"));
|
||||
}
|
||||
|
||||
private static final JavaLangReflectAccess JLRA = SharedSecrets.getJavaLangReflectAccess();
|
||||
private static final AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
|
@ -27,6 +27,7 @@ package java.lang.invoke;
|
||||
|
||||
import jdk.internal.access.JavaLangAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.util.ClassFileDumper;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
@ -1090,13 +1091,13 @@ public final class StringConcatFactory {
|
||||
private static MethodHandle generate(Lookup lookup, MethodType args, String[] constants) throws Exception {
|
||||
String className = getClassName(lookup.lookupClass());
|
||||
|
||||
byte[] classBytes = ClassFile.of().build(ClassDesc.of(className),
|
||||
byte[] classBytes = ClassFile.of().build(ConstantUtils.binaryNameToDesc(className),
|
||||
new Consumer<ClassBuilder>() {
|
||||
@Override
|
||||
public void accept(ClassBuilder clb) {
|
||||
clb.withFlags(AccessFlag.FINAL, AccessFlag.SUPER, AccessFlag.SYNTHETIC)
|
||||
.withMethodBody(METHOD_NAME,
|
||||
MethodTypeDesc.ofDescriptor(args.toMethodDescriptorString()),
|
||||
ConstantUtils.methodTypeDesc(args),
|
||||
ClassFile.ACC_FINAL | ClassFile.ACC_PRIVATE | ClassFile.ACC_STATIC,
|
||||
generateMethod(constants, args));
|
||||
}});
|
||||
|
@ -49,6 +49,8 @@ import java.lang.classfile.attribute.StackMapFrameInfo;
|
||||
import java.lang.classfile.attribute.StackMapTableAttribute;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
import static jdk.internal.constant.ConstantUtils.*;
|
||||
|
||||
import java.lang.constant.DirectMethodHandleDesc;
|
||||
import java.lang.constant.DynamicConstantDesc;
|
||||
|
||||
@ -134,7 +136,7 @@ final class ProxyGenerator {
|
||||
/**
|
||||
* Name of proxy class
|
||||
*/
|
||||
private ClassEntry classEntry;
|
||||
private final ClassEntry classEntry;
|
||||
|
||||
/**
|
||||
* Proxy interfaces
|
||||
@ -160,10 +162,10 @@ final class ProxyGenerator {
|
||||
* A ProxyGenerator object contains the state for the ongoing
|
||||
* generation of a particular proxy class.
|
||||
*/
|
||||
private ProxyGenerator(ClassLoader loader, String className, List<Class<?>> interfaces,
|
||||
private ProxyGenerator(String className, List<Class<?>> interfaces,
|
||||
int accessFlags) {
|
||||
this.cp = ConstantPoolBuilder.of();
|
||||
this.classEntry = cp.classEntry(ReferenceClassDescImpl.ofValidatedBinaryName(className));
|
||||
this.classEntry = cp.classEntry(ConstantUtils.binaryNameToDesc(className));
|
||||
this.interfaces = interfaces;
|
||||
this.accessFlags = accessFlags;
|
||||
this.throwableStack = List.of(StackMapFrameInfo.ObjectVerificationTypeInfo.of(cp.classEntry(CD_Throwable)));
|
||||
@ -190,7 +192,7 @@ final class ProxyGenerator {
|
||||
List<Class<?>> interfaces,
|
||||
int accessFlags) {
|
||||
Objects.requireNonNull(interfaces);
|
||||
ProxyGenerator gen = new ProxyGenerator(loader, name, interfaces, accessFlags);
|
||||
ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
|
||||
final byte[] classFile = gen.generateClassFile();
|
||||
|
||||
if (SAVE_GENERATED_FILES) {
|
||||
@ -227,18 +229,10 @@ final class ProxyGenerator {
|
||||
private static List<ClassEntry> toClassEntries(ConstantPoolBuilder cp, List<Class<?>> types) {
|
||||
var ces = new ArrayList<ClassEntry>(types.size());
|
||||
for (var t : types)
|
||||
ces.add(cp.classEntry(ReferenceClassDescImpl.ofValidatedBinaryName(t.getName())));
|
||||
ces.add(cp.classEntry(ConstantUtils.binaryNameToDesc(t.getName())));
|
||||
return ces;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the {@code ClassDesc} of the given type}
|
||||
* @param type the {@code Class} object
|
||||
*/
|
||||
private static ClassDesc toClassDesc(Class<?> type) {
|
||||
return ClassDesc.ofDescriptor(type.descriptorString());
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given set of proxy methods with the same signature, check
|
||||
* that their return types are compatible according to the Proxy
|
||||
@ -325,7 +319,7 @@ final class ProxyGenerator {
|
||||
* not assignable from any of the others.
|
||||
*/
|
||||
if (uncoveredReturnTypes.size() > 1) {
|
||||
ProxyMethod pm = methods.get(0);
|
||||
ProxyMethod pm = methods.getFirst();
|
||||
throw new IllegalArgumentException(
|
||||
"methods with same signature " +
|
||||
pm.shortSignature +
|
||||
@ -501,7 +495,7 @@ final class ProxyGenerator {
|
||||
|
||||
String sig = m.toShortSignature();
|
||||
List<ProxyMethod> sigmethods = proxyMethods.computeIfAbsent(sig,
|
||||
(f) -> new ArrayList<>(3));
|
||||
_ -> new ArrayList<>(3));
|
||||
for (ProxyMethod pm : sigmethods) {
|
||||
if (returnType == pm.returnType) {
|
||||
/*
|
||||
@ -531,7 +525,7 @@ final class ProxyGenerator {
|
||||
private void addProxyMethod(ProxyMethod pm) {
|
||||
String sig = pm.shortSignature;
|
||||
List<ProxyMethod> sigmethods = proxyMethods.computeIfAbsent(sig,
|
||||
(f) -> new ArrayList<>(3));
|
||||
_ -> new ArrayList<>(3));
|
||||
sigmethods.add(pm);
|
||||
}
|
||||
|
||||
@ -637,7 +631,6 @@ final class ProxyGenerator {
|
||||
* Create a new specific ProxyMethod with a specific field name
|
||||
*
|
||||
* @param method The method for which to create a proxy
|
||||
* @param methodFieldName the fieldName to generate
|
||||
*/
|
||||
private ProxyMethod(Method method) {
|
||||
this(method, method.toShortSignature(),
|
||||
@ -650,11 +643,7 @@ final class ProxyGenerator {
|
||||
*/
|
||||
private void generateMethod(ProxyGenerator pg, ClassBuilder clb) {
|
||||
var cp = pg.cp;
|
||||
var pTypes = new ClassDesc[parameterTypes.length];
|
||||
for (int i = 0; i < pTypes.length; i++) {
|
||||
pTypes[i] = toClassDesc(parameterTypes[i]);
|
||||
}
|
||||
MethodTypeDesc desc = MethodTypeDescImpl.ofTrusted(toClassDesc(returnType), pTypes);
|
||||
var desc = methodTypeDesc(returnType, parameterTypes);
|
||||
int accessFlags = (method.isVarArgs()) ? ACC_VARARGS | ACC_PUBLIC | ACC_FINAL
|
||||
: ACC_PUBLIC | ACC_FINAL;
|
||||
var catchList = computeUniqueCatchList(exceptionTypes);
|
||||
@ -665,7 +654,7 @@ final class ProxyGenerator {
|
||||
.getfield(pg.handlerField)
|
||||
.aload(0)
|
||||
.ldc(DynamicConstantDesc.of(pg.bsm,
|
||||
toClassDesc(fromClass),
|
||||
referenceClassDesc(fromClass),
|
||||
method.getName(),
|
||||
desc));
|
||||
if (parameterTypes.length > 0) {
|
||||
@ -693,7 +682,7 @@ final class ProxyGenerator {
|
||||
if (!catchList.isEmpty()) {
|
||||
var c1 = cob.newBoundLabel();
|
||||
for (var exc : catchList) {
|
||||
cob.exceptionCatch(cob.startLabel(), c1, c1, toClassDesc(exc));
|
||||
cob.exceptionCatch(cob.startLabel(), c1, c1, referenceClassDesc(exc));
|
||||
}
|
||||
cob.athrow(); // just rethrow the exception
|
||||
var c2 = cob.newBoundLabel();
|
||||
@ -739,7 +728,7 @@ final class ProxyGenerator {
|
||||
.invokevirtual(prim.unwrapMethodRef(cob.constantPool()))
|
||||
.return_(TypeKind.from(type).asLoadable());
|
||||
} else {
|
||||
cob.checkcast(toClassDesc(type))
|
||||
cob.checkcast(referenceClassDesc(type))
|
||||
.areturn();
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
package java.lang.runtime;
|
||||
|
||||
import java.lang.Enum.EnumDesc;
|
||||
import java.lang.classfile.ClassBuilder;
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.ConstantDesc;
|
||||
@ -50,6 +49,7 @@ import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.instruction.SwitchCase;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import jdk.internal.misc.PreviewFeatures;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
@ -59,6 +59,9 @@ import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static jdk.internal.constant.ConstantUtils.classDesc;
|
||||
import static jdk.internal.constant.ConstantUtils.referenceClassDesc;
|
||||
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
/**
|
||||
@ -321,7 +324,7 @@ public class SwitchBootstraps {
|
||||
}
|
||||
return label;
|
||||
} else if (labelClass == String.class) {
|
||||
return EnumDesc.of(enumClassTemplate.describeConstable().orElseThrow(), (String) label);
|
||||
return EnumDesc.of(referenceClassDesc(enumClassTemplate), (String) label);
|
||||
} else {
|
||||
throw new IllegalArgumentException("label with illegal type found: " + labelClass +
|
||||
", expected label of type either String or Class");
|
||||
@ -464,10 +467,7 @@ public class SwitchBootstraps {
|
||||
// Object o = ...
|
||||
// o instanceof Wrapped(float)
|
||||
cb.aload(SELECTOR_OBJ);
|
||||
cb.instanceOf(Wrapper.forBasicType(classLabel)
|
||||
.wrapperType()
|
||||
.describeConstable()
|
||||
.orElseThrow());
|
||||
cb.instanceOf(Wrapper.forBasicType(classLabel).wrapperClassDescriptor());
|
||||
cb.ifeq(next);
|
||||
} else if (!unconditionalExactnessCheck(Wrapper.asPrimitiveType(selectorType), classLabel)) {
|
||||
// Integer i = ... or int i = ...
|
||||
@ -515,9 +515,9 @@ public class SwitchBootstraps {
|
||||
|
||||
TypePairs typePair = TypePairs.of(Wrapper.asPrimitiveType(selectorType), classLabel);
|
||||
String methodName = TypePairs.typePairToName.get(typePair);
|
||||
cb.invokestatic(ExactConversionsSupport.class.describeConstable().orElseThrow(),
|
||||
cb.invokestatic(referenceClassDesc(ExactConversionsSupport.class),
|
||||
methodName,
|
||||
MethodTypeDesc.of(ConstantDescs.CD_boolean, typePair.from.describeConstable().orElseThrow()));
|
||||
MethodTypeDesc.of(ConstantDescs.CD_boolean, classDesc(typePair.from)));
|
||||
cb.ifeq(next);
|
||||
}
|
||||
} else {
|
||||
@ -553,7 +553,7 @@ public class SwitchBootstraps {
|
||||
MethodTypeDesc.of(ConstantDescs.CD_Integer,
|
||||
ConstantDescs.CD_int));
|
||||
cb.aload(SELECTOR_OBJ);
|
||||
cb.invokeinterface(BiPredicate.class.describeConstable().orElseThrow(),
|
||||
cb.invokeinterface(referenceClassDesc(BiPredicate.class),
|
||||
"test",
|
||||
MethodTypeDesc.of(ConstantDescs.CD_boolean,
|
||||
ConstantDescs.CD_Object,
|
||||
@ -601,10 +601,11 @@ public class SwitchBootstraps {
|
||||
} else {
|
||||
cb.loadConstant((ConstantDesc) element.caseLabel());
|
||||
}
|
||||
cb.invokestatic(element.caseLabel().getClass().describeConstable().orElseThrow(),
|
||||
var caseLabelWrapper = Wrapper.forWrapperType(element.caseLabel().getClass());
|
||||
cb.invokestatic(caseLabelWrapper.wrapperClassDescriptor(),
|
||||
"valueOf",
|
||||
MethodTypeDesc.of(element.caseLabel().getClass().describeConstable().orElseThrow(),
|
||||
Wrapper.asPrimitiveType(element.caseLabel().getClass()).describeConstable().orElseThrow()));
|
||||
MethodTypeDesc.of(caseLabelWrapper.wrapperClassDescriptor(),
|
||||
caseLabelWrapper.basicClassDescriptor()));
|
||||
cb.aload(SELECTOR_OBJ);
|
||||
cb.invokevirtual(ConstantDescs.CD_Object,
|
||||
"equals",
|
||||
@ -631,7 +632,7 @@ public class SwitchBootstraps {
|
||||
List<EnumDesc<?>> enumDescs = new ArrayList<>();
|
||||
List<Class<?>> extraClassLabels = new ArrayList<>();
|
||||
|
||||
byte[] classBytes = ClassFile.of().build(ReferenceClassDescImpl.ofValidatedBinaryName(typeSwitchClassName(caller.lookupClass())),
|
||||
byte[] classBytes = ClassFile.of().build(ConstantUtils.binaryNameToDesc(typeSwitchClassName(caller.lookupClass())),
|
||||
clb -> {
|
||||
clb.withFlags(AccessFlag.FINAL, AccessFlag.SUPER, AccessFlag.SYNTHETIC)
|
||||
.withMethodBody("typeSwitch",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2024, 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
|
||||
@ -41,6 +41,7 @@ import java.lang.classfile.ClassHierarchyResolver;
|
||||
import static java.lang.constant.ConstantDescs.CD_Object;
|
||||
import static java.lang.classfile.ClassFile.*;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static jdk.internal.constant.ConstantUtils.referenceClassDesc;
|
||||
|
||||
/**
|
||||
* Class hierarchy resolution framework is answering questions about classes assignability, common classes ancestor and whether the class represents an interface.
|
||||
@ -245,7 +246,7 @@ public final class ClassHierarchyImpl {
|
||||
}
|
||||
|
||||
return cl.isInterface() ? ClassHierarchyInfo.ofInterface()
|
||||
: ClassHierarchyInfo.ofClass(cl.getSuperclass().describeConstable().orElseThrow());
|
||||
: ClassHierarchyInfo.ofClass(referenceClassDesc(cl.getSuperclass()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,14 +26,12 @@
|
||||
package jdk.internal.classfile.impl;
|
||||
|
||||
import java.lang.classfile.constantpool.InvokeDynamicEntry;
|
||||
import java.lang.classfile.constantpool.NameAndTypeEntry;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.constantpool.ClassEntry;
|
||||
import java.lang.classfile.constantpool.ConstantDynamicEntry;
|
||||
import java.lang.classfile.constantpool.DynamicConstantPoolEntry;
|
||||
import java.lang.classfile.constantpool.MemberRefEntry;
|
||||
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -46,6 +44,8 @@ import java.util.stream.Collectors;
|
||||
import java.lang.classfile.Attribute;
|
||||
|
||||
import static java.lang.classfile.ClassFile.*;
|
||||
import static jdk.internal.constant.ConstantUtils.binaryNameToDesc;
|
||||
|
||||
import java.lang.classfile.BufWriter;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.attribute.StackMapTableAttribute;
|
||||
@ -1321,8 +1321,8 @@ public final class StackMapGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private static final ClassDesc CD_Cloneable = ClassDesc.of("java.lang.Cloneable");
|
||||
private static final ClassDesc CD_Serializable = ClassDesc.of("java.io.Serializable");
|
||||
private static final ClassDesc CD_Cloneable = binaryNameToDesc("java.lang.Cloneable");
|
||||
private static final ClassDesc CD_Serializable = binaryNameToDesc("java.io.Serializable");
|
||||
|
||||
private Type mergeReferenceFrom(Type from, ClassHierarchyImpl context) {
|
||||
if (from == NULL_TYPE) {
|
||||
|
@ -29,6 +29,8 @@ import sun.invoke.util.Wrapper;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.ConstantDesc;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -41,12 +43,85 @@ public final class ConstantUtils {
|
||||
public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0];
|
||||
public static final ClassDesc[] EMPTY_CLASSDESC = new ClassDesc[0];
|
||||
public static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255;
|
||||
public static final ClassDesc CD_module_info = binaryNameToDesc("module-info");
|
||||
|
||||
private static final Set<String> pointyNames = Set.of(ConstantDescs.INIT_NAME, ConstantDescs.CLASS_INIT_NAME);
|
||||
|
||||
/** No instantiation */
|
||||
private ConstantUtils() {}
|
||||
|
||||
// Note:
|
||||
// Non-JDK users should create their own utilities that wrap
|
||||
// {@code .describeConstable().orElseThrow()} calls;
|
||||
// these xxDesc methods has undefined and unsafe exceptional
|
||||
// behavior, so they are not suitable as public APIs.
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassDesc} from a pre-validated binary name
|
||||
* for a class or interface type. Validated version of {@link
|
||||
* ClassDesc#of(String)}.
|
||||
*
|
||||
* @param binaryName a binary name
|
||||
*/
|
||||
public static ClassDesc binaryNameToDesc(String binaryName) {
|
||||
return ReferenceClassDescImpl.ofValidated("L" + binaryToInternal(binaryName) + ";");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ClassDesc from a Class object, requires that this class
|
||||
* can always be described nominally, i.e. this class is not a
|
||||
* hidden class or interface or an array with a hidden component
|
||||
* type.
|
||||
*/
|
||||
public static ClassDesc classDesc(Class<?> type) {
|
||||
if (type.isPrimitive()) {
|
||||
return Wrapper.forPrimitiveType(type).basicClassDescriptor();
|
||||
}
|
||||
return referenceClassDesc(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ClassDesc from a Class object representing a non-hidden
|
||||
* class or interface or an array type with a non-hidden component type.
|
||||
*/
|
||||
public static ClassDesc referenceClassDesc(Class<?> type) {
|
||||
return ReferenceClassDescImpl.ofValidated(type.descriptorString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MethodTypeDesc from a MethodType object, requires that
|
||||
* the type can be described nominally, i.e. all of its return
|
||||
* type and parameter types can be described nominally.
|
||||
*/
|
||||
public static MethodTypeDesc methodTypeDesc(MethodType type) {
|
||||
var returnDesc = classDesc(type.returnType());
|
||||
if (type.parameterCount() == 0) {
|
||||
return MethodTypeDescImpl.ofValidated(returnDesc, EMPTY_CLASSDESC);
|
||||
}
|
||||
var paramDescs = new ClassDesc[type.parameterCount()];
|
||||
for (int i = 0; i < type.parameterCount(); i++) {
|
||||
paramDescs[i] = classDesc(type.parameterType(i));
|
||||
}
|
||||
return MethodTypeDescImpl.ofValidated(returnDesc, paramDescs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MethodTypeDesc from return class and parameter
|
||||
* class objects, requires that all of them can be described nominally.
|
||||
* This version is mainly useful for working with Method objects.
|
||||
*/
|
||||
public static MethodTypeDesc methodTypeDesc(Class<?> returnType, Class<?>[] parameterTypes) {
|
||||
var returnDesc = classDesc(returnType);
|
||||
if (parameterTypes.length == 0) {
|
||||
return MethodTypeDescImpl.ofValidated(returnDesc, EMPTY_CLASSDESC);
|
||||
}
|
||||
var paramDescs = new ClassDesc[parameterTypes.length];
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
paramDescs[i] = classDesc(parameterTypes[i]);
|
||||
}
|
||||
return MethodTypeDescImpl.ofValidated(returnDesc, paramDescs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the correctness of a binary class name. In particular checks for the presence of
|
||||
* invalid characters in the name.
|
||||
@ -231,7 +306,7 @@ public final class ConstantUtils {
|
||||
|
||||
private static ClassDesc resolveClassDesc(String descriptor, int start, int len) {
|
||||
if (len == 1) {
|
||||
return Wrapper.forPrimitiveType(descriptor.charAt(start)).classDescriptor();
|
||||
return Wrapper.forPrimitiveType(descriptor.charAt(start)).basicClassDescriptor();
|
||||
}
|
||||
// Pre-verified in parseMethodDescriptor; avoid redundant verification
|
||||
return ReferenceClassDescImpl.ofValidated(descriptor.substring(start, start + len));
|
||||
|
@ -66,20 +66,11 @@ public final class ReferenceClassDescImpl implements ClassDesc {
|
||||
* @jvms 4.3.2 Field Descriptors
|
||||
*/
|
||||
public static ReferenceClassDescImpl ofValidated(String descriptor) {
|
||||
assert ConstantUtils.skipOverFieldSignature(descriptor, 0, descriptor.length(), false)
|
||||
== descriptor.length() : descriptor;
|
||||
return new ReferenceClassDescImpl(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassDesc} from a pre-validated descriptor string
|
||||
* for a class or interface type or an array type.
|
||||
*
|
||||
* @param descriptor a field descriptor string for a class or interface type
|
||||
* @jvms 4.3.2 Field Descriptors
|
||||
*/
|
||||
public static ClassDesc ofValidatedBinaryName(String typeSwitchClassName) {
|
||||
return ofValidated("L" + binaryToInternal(typeSwitchClassName) + ";");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String descriptorString() {
|
||||
return descriptor;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2024, 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
|
||||
@ -29,6 +29,7 @@ import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.TypeKind;
|
||||
|
||||
import jdk.internal.foreign.AbstractMemorySegmentImpl;
|
||||
import jdk.internal.foreign.MemorySessionImpl;
|
||||
import jdk.internal.foreign.Utils;
|
||||
@ -50,7 +51,6 @@ import sun.security.action.GetPropertyAction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.Constable;
|
||||
import java.lang.constant.ConstantDesc;
|
||||
import java.lang.constant.DynamicConstantDesc;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
@ -70,6 +70,7 @@ import java.util.List;
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
import static java.lang.classfile.ClassFile.*;
|
||||
import static java.lang.classfile.TypeKind.*;
|
||||
import static jdk.internal.constant.ConstantUtils.*;
|
||||
|
||||
public class BindingSpecializer {
|
||||
private static final String DUMP_CLASSES_DIR
|
||||
@ -80,24 +81,24 @@ public class BindingSpecializer {
|
||||
// Bunch of helper constants
|
||||
private static final int CLASSFILE_VERSION = ClassFileFormatVersion.latest().major();
|
||||
|
||||
private static final ClassDesc CD_Arena = desc(Arena.class);
|
||||
private static final ClassDesc CD_MemorySegment = desc(MemorySegment.class);
|
||||
private static final ClassDesc CD_MemorySegment_Scope = desc(MemorySegment.Scope.class);
|
||||
private static final ClassDesc CD_SharedUtils = desc(SharedUtils.class);
|
||||
private static final ClassDesc CD_AbstractMemorySegmentImpl = desc(AbstractMemorySegmentImpl.class);
|
||||
private static final ClassDesc CD_MemorySessionImpl = desc(MemorySessionImpl.class);
|
||||
private static final ClassDesc CD_Utils = desc(Utils.class);
|
||||
private static final ClassDesc CD_SegmentAllocator = desc(SegmentAllocator.class);
|
||||
private static final ClassDesc CD_ValueLayout = desc(ValueLayout.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfBoolean = desc(ValueLayout.OfBoolean.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfByte = desc(ValueLayout.OfByte.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfShort = desc(ValueLayout.OfShort.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfChar = desc(ValueLayout.OfChar.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfInt = desc(ValueLayout.OfInt.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfLong = desc(ValueLayout.OfLong.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfFloat = desc(ValueLayout.OfFloat.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfDouble = desc(ValueLayout.OfDouble.class);
|
||||
private static final ClassDesc CD_AddressLayout = desc(AddressLayout.class);
|
||||
private static final ClassDesc CD_Arena = referenceClassDesc(Arena.class);
|
||||
private static final ClassDesc CD_MemorySegment = referenceClassDesc(MemorySegment.class);
|
||||
private static final ClassDesc CD_MemorySegment_Scope = referenceClassDesc(MemorySegment.Scope.class);
|
||||
private static final ClassDesc CD_SharedUtils = referenceClassDesc(SharedUtils.class);
|
||||
private static final ClassDesc CD_AbstractMemorySegmentImpl = referenceClassDesc(AbstractMemorySegmentImpl.class);
|
||||
private static final ClassDesc CD_MemorySessionImpl = referenceClassDesc(MemorySessionImpl.class);
|
||||
private static final ClassDesc CD_Utils = referenceClassDesc(Utils.class);
|
||||
private static final ClassDesc CD_SegmentAllocator = referenceClassDesc(SegmentAllocator.class);
|
||||
private static final ClassDesc CD_ValueLayout = referenceClassDesc(ValueLayout.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfBoolean = referenceClassDesc(ValueLayout.OfBoolean.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfByte = referenceClassDesc(ValueLayout.OfByte.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfShort = referenceClassDesc(ValueLayout.OfShort.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfChar = referenceClassDesc(ValueLayout.OfChar.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfInt = referenceClassDesc(ValueLayout.OfInt.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfLong = referenceClassDesc(ValueLayout.OfLong.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfFloat = referenceClassDesc(ValueLayout.OfFloat.class);
|
||||
private static final ClassDesc CD_ValueLayout_OfDouble = referenceClassDesc(ValueLayout.OfDouble.class);
|
||||
private static final ClassDesc CD_AddressLayout = referenceClassDesc(AddressLayout.class);
|
||||
|
||||
private static final MethodTypeDesc MTD_NEW_BOUNDED_ARENA = MethodTypeDesc.of(CD_Arena, CD_long);
|
||||
private static final MethodTypeDesc MTD_NEW_EMPTY_ARENA = MethodTypeDesc.of(CD_Arena);
|
||||
@ -196,7 +197,7 @@ public class BindingSpecializer {
|
||||
clb.withSuperclass(CD_Object);
|
||||
clb.withVersion(CLASSFILE_VERSION, 0);
|
||||
|
||||
clb.withMethodBody(METHOD_NAME, desc(callerMethodType), ACC_PUBLIC | ACC_STATIC,
|
||||
clb.withMethodBody(METHOD_NAME, methodTypeDesc(callerMethodType), ACC_PUBLIC | ACC_STATIC,
|
||||
cb -> new BindingSpecializer(cb, callerMethodType, callingSequence, abi, leafType).specialize());
|
||||
});
|
||||
|
||||
@ -362,7 +363,7 @@ public class BindingSpecializer {
|
||||
cb.loadLocal(TypeKind.from(leafArgTypes.get(i)), leafArgSlots[i]);
|
||||
}
|
||||
// call leaf MH
|
||||
cb.invokevirtual(CD_MethodHandle, "invokeExact", desc(leafType));
|
||||
cb.invokevirtual(CD_MethodHandle, "invokeExact", methodTypeDesc(leafType));
|
||||
|
||||
// for downcalls, store the result of the leaf handle call away, until
|
||||
// it is requested by a VM_LOAD in the return recipe.
|
||||
@ -466,9 +467,9 @@ public class BindingSpecializer {
|
||||
case Copy copy -> emitCopyBuffer(copy);
|
||||
case Allocate allocate -> emitAllocBuffer(allocate);
|
||||
case BoxAddress boxAddress -> emitBoxAddress(boxAddress);
|
||||
case SegmentBase unused -> emitSegmentBase();
|
||||
case SegmentBase _ -> emitSegmentBase();
|
||||
case SegmentOffset segmentOffset -> emitSegmentOffset(segmentOffset);
|
||||
case Dup unused -> emitDupBinding();
|
||||
case Dup _ -> emitDupBinding();
|
||||
case ShiftLeft shiftLeft -> emitShiftLeft(shiftLeft);
|
||||
case ShiftRight shiftRight -> emitShiftRight(shiftRight);
|
||||
case Cast cast -> emitCast(cast);
|
||||
@ -608,7 +609,7 @@ public class BindingSpecializer {
|
||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType);
|
||||
cb.loadConstant(offset);
|
||||
cb.loadLocal(storeTypeKind, valueIdx);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(storeType));
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(storeType));
|
||||
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
|
||||
} else {
|
||||
// long longValue = ((Number) value).longValue();
|
||||
@ -666,7 +667,7 @@ public class BindingSpecializer {
|
||||
long writeOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize);
|
||||
cb.loadConstant(writeOffset);
|
||||
cb.loadLocal(chunkStoreTypeKind, chunkIdx);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(chunkStoreType));
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(chunkStoreType));
|
||||
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
|
||||
|
||||
remaining -= chunkSize;
|
||||
@ -697,7 +698,7 @@ public class BindingSpecializer {
|
||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(storeType);
|
||||
cb.loadConstant(retBufOffset);
|
||||
cb.loadLocal(storeTypeKind, valueIdx);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, desc(storeType));
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(CD_void, valueLayoutType, CD_long, classDesc(storeType));
|
||||
cb.invokeinterface(CD_MemorySegment, "set", descriptor);
|
||||
retBufOffset += abi.arch.typeSize(vmStore.storage().type());
|
||||
}
|
||||
@ -716,7 +717,7 @@ public class BindingSpecializer {
|
||||
cb.loadLocal(ReferenceType, returnBufferIdx);
|
||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType);
|
||||
cb.loadConstant(retBufOffset);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(desc(loadType), valueLayoutType, CD_long);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long);
|
||||
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
|
||||
retBufOffset += abi.arch.typeSize(vmLoad.storage().type());
|
||||
pushType(loadType);
|
||||
@ -809,7 +810,7 @@ public class BindingSpecializer {
|
||||
if (SharedUtils.isPowerOfTwo(byteWidth)) {
|
||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(loadType);
|
||||
cb.loadConstant(offset);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(desc(loadType), valueLayoutType, CD_long);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(loadType), valueLayoutType, CD_long);
|
||||
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
|
||||
} else {
|
||||
// chunked
|
||||
@ -849,7 +850,7 @@ public class BindingSpecializer {
|
||||
// read from segment
|
||||
cb.loadLocal(ReferenceType, readAddrIdx);
|
||||
ClassDesc valueLayoutType = emitLoadLayoutConstant(chunkType);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(desc(chunkType), valueLayoutType, CD_long);
|
||||
MethodTypeDesc descriptor = MethodTypeDesc.of(classDesc(chunkType), valueLayoutType, CD_long);
|
||||
long readOffset = offset + SharedUtils.pickChunkOffset(chunkOffset, byteWidth, chunkSize);
|
||||
cb.loadConstant(readOffset);
|
||||
cb.invokeinterface(CD_MemorySegment, "get", descriptor);
|
||||
@ -988,9 +989,4 @@ public class BindingSpecializer {
|
||||
case ReferenceType -> cb.aconst_null();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T desc(Constable c) {
|
||||
return (T) c.describeConstable().orElseThrow();
|
||||
}
|
||||
}
|
||||
|
@ -32,20 +32,31 @@ import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
|
||||
public enum Wrapper {
|
||||
// wrapperType simple primitiveType simple char emptyArray format numericClass superClass classDescriptor
|
||||
BOOLEAN( Boolean.class, "Boolean", boolean.class, "boolean", 'Z', new boolean[0], Format.unsigned( 1), 0, 0, ConstantDescs.CD_boolean),
|
||||
// wrapperType simple primitiveType simple char emptyArray format numericClass superClass
|
||||
// basicClassDescriptor wrapperClassDescriptor
|
||||
BOOLEAN( Boolean.class, "Boolean", boolean.class, "boolean", 'Z', new boolean[0], Format.unsigned( 1), 0, 0,
|
||||
ConstantDescs.CD_boolean, ConstantDescs.CD_Boolean),
|
||||
// These must be in the order defined for widening primitive conversions in JLS 5.1.2
|
||||
// Avoid boxing integral types here to defer initialization of internal caches
|
||||
BYTE ( Byte.class, "Byte", byte.class, "byte", 'B', new byte[0], Format.signed( 8), BYTE_CLASS, BYTE_SUPERCLASSES, ConstantDescs.CD_byte),
|
||||
SHORT ( Short.class, "Short", short.class, "short", 'S', new short[0], Format.signed( 16), SHORT_CLASS, SHORT_SUPERCLASSES, ConstantDescs.CD_short),
|
||||
CHAR (Character.class, "Character", char.class, "char", 'C', new char[0], Format.unsigned(16), CHAR_CLASS, CHAR_SUPERCLASSES, ConstantDescs.CD_char),
|
||||
INT ( Integer.class, "Integer", int.class, "int", 'I', new int[0], Format.signed( 32), INT_CLASS, INT_SUPERCLASSES, ConstantDescs.CD_int),
|
||||
LONG ( Long.class, "Long", long.class, "long", 'J', new long[0], Format.signed( 64), LONG_CLASS, LONG_SUPERCLASSES, ConstantDescs.CD_long),
|
||||
FLOAT ( Float.class, "Float", float.class, "float", 'F', new float[0], Format.floating(32), FLOAT_CLASS, FLOAT_SUPERCLASSES, ConstantDescs.CD_float),
|
||||
DOUBLE ( Double.class, "Double", double.class, "double", 'D', new double[0], Format.floating(64), DOUBLE_CLASS, DOUBLE_CLASS, ConstantDescs.CD_double),
|
||||
OBJECT ( Object.class, "Object", Object.class, "Object", 'L', new Object[0], Format.other( 1), 0, 0, ConstantDescs.CD_Object),
|
||||
BYTE ( Byte.class, "Byte", byte.class, "byte", 'B', new byte[0], Format.signed( 8), BYTE_CLASS, BYTE_SUPERCLASSES,
|
||||
ConstantDescs.CD_byte, ConstantDescs.CD_Byte),
|
||||
SHORT ( Short.class, "Short", short.class, "short", 'S', new short[0], Format.signed( 16), SHORT_CLASS, SHORT_SUPERCLASSES,
|
||||
ConstantDescs.CD_short, ConstantDescs.CD_Short),
|
||||
CHAR (Character.class, "Character", char.class, "char", 'C', new char[0], Format.unsigned(16), CHAR_CLASS, CHAR_SUPERCLASSES,
|
||||
ConstantDescs.CD_char, ConstantDescs.CD_Character),
|
||||
INT ( Integer.class, "Integer", int.class, "int", 'I', new int[0], Format.signed( 32), INT_CLASS, INT_SUPERCLASSES,
|
||||
ConstantDescs.CD_int, ConstantDescs.CD_Integer),
|
||||
LONG ( Long.class, "Long", long.class, "long", 'J', new long[0], Format.signed( 64), LONG_CLASS, LONG_SUPERCLASSES,
|
||||
ConstantDescs.CD_long, ConstantDescs.CD_Long),
|
||||
FLOAT ( Float.class, "Float", float.class, "float", 'F', new float[0], Format.floating(32), FLOAT_CLASS, FLOAT_SUPERCLASSES,
|
||||
ConstantDescs.CD_float, ConstantDescs.CD_Float),
|
||||
DOUBLE ( Double.class, "Double", double.class, "double", 'D', new double[0], Format.floating(64), DOUBLE_CLASS, DOUBLE_CLASS,
|
||||
ConstantDescs.CD_double, ConstantDescs.CD_Double),
|
||||
OBJECT ( Object.class, "Object", Object.class, "Object", 'L', new Object[0], Format.other( 1), 0, 0,
|
||||
ConstantDescs.CD_Object, ConstantDescs.CD_Object),
|
||||
// VOID must be the last type, since it is "assignable" from any other type:
|
||||
VOID ( Void.class, "Void", void.class, "void", 'V', null, Format.other( 0), 0, 0, ConstantDescs.CD_void),
|
||||
VOID ( Void.class, "Void", void.class, "void", 'V', null, Format.other( 0), 0, 0,
|
||||
ConstantDescs.CD_void, ConstantDescs.CD_Void),
|
||||
;
|
||||
|
||||
public static final int COUNT = 10;
|
||||
@ -60,18 +71,20 @@ public enum Wrapper {
|
||||
private final int superClasses;
|
||||
private final String wrapperSimpleName;
|
||||
private final String primitiveSimpleName;
|
||||
private final ClassDesc classDesc;
|
||||
private final ClassDesc basicClassDesc;
|
||||
private final ClassDesc wrapperClassDesc;
|
||||
|
||||
private Wrapper(Class<?> wtype,
|
||||
String wtypeName,
|
||||
Class<?> ptype,
|
||||
String ptypeName,
|
||||
char tchar,
|
||||
Object emptyArray,
|
||||
int format,
|
||||
int numericClass,
|
||||
int superClasses,
|
||||
ClassDesc classDesc) {
|
||||
Wrapper(Class<?> wtype,
|
||||
String wtypeName,
|
||||
Class<?> ptype,
|
||||
String ptypeName,
|
||||
char tchar,
|
||||
Object emptyArray,
|
||||
int format,
|
||||
int numericClass,
|
||||
int superClasses,
|
||||
ClassDesc basicClassDesc,
|
||||
ClassDesc wrapperClassDesc) {
|
||||
this.wrapperType = wtype;
|
||||
this.primitiveType = ptype;
|
||||
this.basicTypeChar = tchar;
|
||||
@ -82,7 +95,8 @@ public enum Wrapper {
|
||||
this.superClasses = superClasses;
|
||||
this.wrapperSimpleName = wtypeName;
|
||||
this.primitiveSimpleName = ptypeName;
|
||||
this.classDesc = classDesc;
|
||||
this.basicClassDesc = basicClassDesc;
|
||||
this.wrapperClassDesc = wrapperClassDesc;
|
||||
}
|
||||
|
||||
/** For debugging, give the details of this wrapper. */
|
||||
@ -390,7 +404,10 @@ public enum Wrapper {
|
||||
}
|
||||
|
||||
/** A nominal descriptor of the wrapped type */
|
||||
public ClassDesc classDescriptor() { return classDesc; }
|
||||
public ClassDesc basicClassDescriptor() { return basicClassDesc; }
|
||||
|
||||
/** A nominal descriptor of the wrapper type */
|
||||
public ClassDesc wrapperClassDescriptor() { return wrapperClassDesc; }
|
||||
|
||||
/** What is the primitive type wrapped by this wrapper? */
|
||||
public Class<?> primitiveType() { return primitiveType; }
|
||||
|
Loading…
Reference in New Issue
Block a user