JVM: Optimize isPrimitiveBoxing and isPrimitiveUnboxing

Precompute internal names and method descriptors instead of computing
on every access.
This commit is contained in:
Ilmir Usmanov
2023-08-22 11:57:11 +02:00
committed by Space Team
parent 3246b0a6bd
commit e333716fbe
2 changed files with 16 additions and 14 deletions
@@ -246,11 +246,7 @@ private fun isWrapperClassNameOrNumber(internalClassName: String) =
isWrapperClassName(internalClassName) || internalClassName == Type.getInternalName(Number::class.java) isWrapperClassName(internalClassName) || internalClassName == Type.getInternalName(Number::class.java)
private fun isWrapperClassName(internalClassName: String) = private fun isWrapperClassName(internalClassName: String) =
JvmPrimitiveType.isWrapperClassName(buildFqNameByInternal(internalClassName)) JvmPrimitiveType.isWrapperClassInternalName(internalClassName)
private fun buildFqNameByInternal(internalClassName: String) =
FqName(Type.getObjectType(internalClassName).className)
private fun isUnboxingMethodName(name: String) = private fun isUnboxingMethodName(name: String) =
UNBOXING_METHOD_NAMES.contains(name) UNBOXING_METHOD_NAMES.contains(name)
@@ -275,10 +271,8 @@ fun AbstractInsnNode.isCoroutinePrimitiveBoxing(): Boolean {
} }
} }
private fun MethodInsnNode.isBoxingMethodDescriptor(): Boolean { private fun MethodInsnNode.isBoxingMethodDescriptor() =
val ownerType = Type.getObjectType(owner) JvmPrimitiveType.isBoxingMethodDescriptor(owner, desc)
return desc == Type.getMethodDescriptor(ownerType, AsmUtil.unboxType(ownerType))
}
fun AbstractInsnNode.isJavaLangClassBoxing() = fun AbstractInsnNode.isJavaLangClassBoxing() =
isMethodInsnWith(Opcodes.INVOKESTATIC) { isMethodInsnWith(Opcodes.INVOKESTATIC) {
@@ -34,27 +34,35 @@ public enum JvmPrimitiveType {
DOUBLE(PrimitiveType.DOUBLE, "double", "D", "java.lang.Double"), DOUBLE(PrimitiveType.DOUBLE, "double", "D", "java.lang.Double"),
; ;
private static final Set<FqName> WRAPPERS_CLASS_NAMES;
private static final Map<String, JvmPrimitiveType> TYPE_BY_NAME; private static final Map<String, JvmPrimitiveType> TYPE_BY_NAME;
private static final Map<PrimitiveType, JvmPrimitiveType> TYPE_BY_PRIMITIVE_TYPE; private static final Map<PrimitiveType, JvmPrimitiveType> TYPE_BY_PRIMITIVE_TYPE;
private static final Map<String, JvmPrimitiveType> TYPE_BY_DESC; private static final Map<String, JvmPrimitiveType> TYPE_BY_DESC;
private static final Set<String> WRAPPER_CLASS_INTERNAL_NAMES;
private static final Map<String, String> OWNER_TO_BOXING_METHOD_DESCRIPTOR;
static { static {
WRAPPERS_CLASS_NAMES = new HashSet<FqName>();
TYPE_BY_NAME = new HashMap<String, JvmPrimitiveType>(); TYPE_BY_NAME = new HashMap<String, JvmPrimitiveType>();
TYPE_BY_PRIMITIVE_TYPE = new EnumMap<PrimitiveType, JvmPrimitiveType>(PrimitiveType.class); TYPE_BY_PRIMITIVE_TYPE = new EnumMap<PrimitiveType, JvmPrimitiveType>(PrimitiveType.class);
TYPE_BY_DESC = new HashMap<String, JvmPrimitiveType>(); TYPE_BY_DESC = new HashMap<String, JvmPrimitiveType>();
WRAPPER_CLASS_INTERNAL_NAMES = new HashSet<>();
OWNER_TO_BOXING_METHOD_DESCRIPTOR = new HashMap<>();
for (JvmPrimitiveType type : values()) { for (JvmPrimitiveType type : values()) {
WRAPPERS_CLASS_NAMES.add(type.getWrapperFqName());
TYPE_BY_NAME.put(type.getJavaKeywordName(), type); TYPE_BY_NAME.put(type.getJavaKeywordName(), type);
TYPE_BY_PRIMITIVE_TYPE.put(type.getPrimitiveType(), type); TYPE_BY_PRIMITIVE_TYPE.put(type.getPrimitiveType(), type);
TYPE_BY_DESC.put(type.getDesc(), type); TYPE_BY_DESC.put(type.getDesc(), type);
String internalName = type.wrapperFqName.asString().replace('.', '/');
WRAPPER_CLASS_INTERNAL_NAMES.add(internalName);
OWNER_TO_BOXING_METHOD_DESCRIPTOR.put(internalName, "(" + type.desc + ")L" + internalName + ";");
} }
} }
public static boolean isWrapperClassName(@NotNull FqName className) { public static boolean isWrapperClassInternalName(@NotNull String internalName) {
return WRAPPERS_CLASS_NAMES.contains(className); return WRAPPER_CLASS_INTERNAL_NAMES.contains(internalName);
}
public static boolean isBoxingMethodDescriptor(@NotNull String owner, @NotNull String methodDescriptor) {
return methodDescriptor.equals(OWNER_TO_BOXING_METHOD_DESCRIPTOR.get(owner));
} }
@NotNull @NotNull