Refactor ConstDynamic usage
- Model better ClassDesc, EnumDesc and
getStaticFinal library constDynamic
Change-Id: I89fb0e9fb156da978f93a64200aa30d666855a35
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
index b125b83..9ff552c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
@@ -187,10 +187,7 @@
@Override
void internalRegisterUse(
UseRegistry<?> registry, DexClassAndMethod context, ListIterator<CfInstruction> iterator) {
- registry.registerTypeReference(reference.getType());
- registry.registerMethodHandle(
- reference.getBootstrapMethod(), NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
- assert reference.getBootstrapMethodArguments().isEmpty();
+ registry.registerConstDynamic(reference);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 693ff71..02d0092 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -845,21 +845,12 @@
createStaticallyKnownType("Ljava/lang/invoke/LambdaMetafactory;");
public final DexType constantBootstrapsType =
createStaticallyKnownType("Ljava/lang/invoke/ConstantBootstraps;");
+ public final ConstantBootstrapsMembers constantBootstrapsMembers =
+ new ConstantBootstrapsMembers();
public final DexType switchBootstrapType = createType("Ljava/lang/runtime/SwitchBootstraps;");
public final DexType callSiteType = createStaticallyKnownType("Ljava/lang/invoke/CallSite;");
public final DexType lookupType =
createStaticallyKnownType("Ljava/lang/invoke/MethodHandles$Lookup;");
- public final DexMethod constantDynamicBootstrapMethod =
- createMethod(
- constantBootstrapsType,
- createProto(
- objectType,
- methodHandlesLookupType,
- stringType,
- classType,
- methodHandleType,
- objectArrayType),
- invokeMethodName);
public final DexProto switchBootstrapMethodProto =
createProto(
callSiteType, methodHandlesLookupType, stringType, methodTypeType, objectArrayType);
@@ -1890,6 +1881,25 @@
}
}
+ public class ConstantBootstrapsMembers {
+ public final DexMethod invoke =
+ createMethod(
+ constantBootstrapsType,
+ createProto(
+ objectType,
+ methodHandlesLookupType,
+ stringType,
+ classType,
+ methodHandleType,
+ objectArrayType),
+ invokeMethodName);
+ public final DexMethod getStaticFinal =
+ createMethod(
+ constantBootstrapsType,
+ createProto(objectType, methodHandlesLookupType, stringType, classType),
+ "getStaticFinal");
+ }
+
public class BufferMembers {
public final DexMethod positionArg =
createMethod(bufferType, createProto(bufferType, intType), "position");
diff --git a/src/main/java/com/android/tools/r8/graph/UseRegistry.java b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
index d138d31..28a12da 100644
--- a/src/main/java/com/android/tools/r8/graph/UseRegistry.java
+++ b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
@@ -3,18 +3,20 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import static com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper.isTypeSwitchCallSite;
+import static com.android.tools.r8.graph.UseRegistry.MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
+import static com.android.tools.r8.ir.desugar.constantdynamic.LibraryConstantDynamic.extractClassDescConstantDynamic;
+import static com.android.tools.r8.ir.desugar.constantdynamic.LibraryConstantDynamic.isClassDescConstantDynamic;
import com.android.tools.r8.dex.code.CfOrDexInstanceFieldRead;
import com.android.tools.r8.dex.code.CfOrDexInstruction;
import com.android.tools.r8.dex.code.CfOrDexStaticFieldRead;
-import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeInstructionMetadata;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper;
+import com.android.tools.r8.ir.desugar.constantdynamic.ConstantDynamicReference;
import com.android.tools.r8.utils.TraversalContinuation;
+import java.util.List;
import java.util.ListIterator;
public abstract class UseRegistry<T extends Definition> {
@@ -237,67 +239,70 @@
}
protected void registerCallSiteBootstrapArgs(DexCallSite callSite, int start, int end) {
- boolean isLambdaMetaFactory =
- appView.dexItemFactory().isLambdaMetafactoryMethod(callSite.bootstrapMethod.asMethod());
- // Register bootstrap method arguments.
- // Only Type, MethodHandle, and MethodType need to be registered.
+ MethodHandleUse use =
+ appView.dexItemFactory().isLambdaMetafactoryMethod(callSite.bootstrapMethod.asMethod())
+ ? MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY
+ : MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
+ registerBootstrapArgs(callSite.bootstrapArgs, start, end, use);
+ }
+
+ protected void registerBootstrapArgs(
+ List<DexValue> bootstrapArgs, int start, int end, MethodHandleUse use) {
assert start >= 0;
- assert end <= callSite.bootstrapArgs.size();
+ assert end <= bootstrapArgs.size();
for (int i = start; i < end; i++) {
- DexValue arg = callSite.bootstrapArgs.get(i);
- switch (arg.getValueKind()) {
- case METHOD_HANDLE:
- DexMethodHandle handle = arg.asDexValueMethodHandle().value;
- MethodHandleUse use =
- isLambdaMetaFactory
- ? MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY
- : MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
- registerMethodHandle(handle, use);
- break;
- case METHOD_TYPE:
- registerProto(arg.asDexValueMethodType().value);
- break;
- case TYPE:
- registerTypeReference(arg.asDexValueType().value);
- break;
- case CONST_DYNAMIC:
- if (!isTypeSwitchCallSite(callSite, appView.dexItemFactory())) {
- throw new CompilationError(
- "Unsupported const dynamic in call site " + arg, getContext().getOrigin());
- }
- if (arg.asDexValueConstDynamic()
- .getValue()
- .getType()
- .isIdenticalTo(appView.dexItemFactory().enumDescType)) {
- TypeSwitchDesugaringHelper.dispatchEnumField(
- (type, fieldName) -> {
- registerTypeReference(type);
- },
- arg.asDexValueConstDynamic().getValue(),
- context,
- dexItemFactory());
- }
- break;
- default:
- assert arg.isDexValueInt()
- || arg.isDexValueLong()
- || arg.isDexValueFloat()
- || arg.isDexValueDouble()
- || arg.isDexValueString()
- || arg.isDexValueResourceNumber();
- break;
- }
+ DexValue arg = bootstrapArgs.get(i);
+ registerBoostrapArg(arg, use);
if (continuation.shouldBreak()) {
break;
}
}
}
+ protected void registerBoostrapArg(DexValue arg, MethodHandleUse use) {
+ switch (arg.getValueKind()) {
+ case METHOD_HANDLE:
+ DexMethodHandle handle = arg.asDexValueMethodHandle().value;
+ registerMethodHandle(handle, use);
+ break;
+ case METHOD_TYPE:
+ registerProto(arg.asDexValueMethodType().value);
+ break;
+ case TYPE:
+ registerTypeReference(arg.asDexValueType().value);
+ break;
+ case CONST_DYNAMIC:
+ ConstantDynamicReference constDynamic = arg.asDexValueConstDynamic().getValue();
+ if (isClassDescConstantDynamic(constDynamic, dexItemFactory())) {
+ registerTypeReference(
+ extractClassDescConstantDynamic(constDynamic, dexItemFactory(), context));
+ } else {
+ registerConstDynamic(constDynamic);
+ }
+ break;
+ default:
+ assert arg.isDexValueInt()
+ || arg.isDexValueLong()
+ || arg.isDexValueFloat()
+ || arg.isDexValueDouble()
+ || arg.isDexValueString()
+ || arg.isDexValueResourceNumber();
+ break;
+ }
+ }
+
public void registerCallSite(DexCallSite callSite) {
registerCallSiteExceptBootstrapArgs(callSite);
registerCallSiteBootstrapArgs(callSite, 0, callSite.bootstrapArgs.size());
}
+ public void registerConstDynamic(ConstantDynamicReference reference) {
+ registerTypeReference(reference.getType());
+ registerMethodHandle(reference.getBootstrapMethod(), NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
+ List<DexValue> bootArgs = reference.getBootstrapMethodArguments();
+ registerBootstrapArgs(bootArgs, 0, bootArgs.size(), NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
+ }
+
public void registerProto(DexProto proto) {
registerTypeReference(proto.returnType);
for (DexType type : proto.parameters.values) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/LibraryConstantDynamic.java b/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/LibraryConstantDynamic.java
new file mode 100644
index 0000000..5c36c18
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/LibraryConstantDynamic.java
@@ -0,0 +1,115 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.desugar.constantdynamic;
+
+import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.Definition;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexMethodHandle;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.utils.DescriptorUtils;
+import java.util.function.BiConsumer;
+
+public class LibraryConstantDynamic {
+
+ private static CompilationError throwInvalidLibraryConstantDynamic(
+ String msg, Definition context) {
+ throw new CompilationError("Invalid library ConstantDynamic: " + msg, context.getOrigin());
+ }
+
+ private static boolean methodHandleIsInvokeStaticTo(DexValue dexValue, DexMethod method) {
+ if (!dexValue.isDexValueMethodHandle()) {
+ return false;
+ }
+ DexMethodHandle methodHandle = dexValue.asDexValueMethodHandle().getValue();
+ return methodHandle.type.isInvokeStatic() && methodHandle.asMethod().isIdenticalTo(method);
+ }
+
+ private static boolean isInvokeLibraryConstantDynamic(
+ ConstantDynamicReference constantDynamic,
+ DexType type,
+ int argSize,
+ DexMethod methodHandleMethod,
+ DexItemFactory factory) {
+ DexMethod bootstrapMethod = factory.constantBootstrapsMembers.invoke;
+ return constantDynamic.getType().isIdenticalTo(type)
+ && constantDynamic.getName().isIdenticalTo(bootstrapMethod.getName())
+ && constantDynamic.getBootstrapMethod().asMethod().isIdenticalTo(bootstrapMethod)
+ && constantDynamic.getBootstrapMethodArguments().size() == argSize
+ && methodHandleIsInvokeStaticTo(
+ constantDynamic.getBootstrapMethodArguments().get(0), methodHandleMethod);
+ }
+
+ public static boolean isBoxedBooleanConstantDynamic(
+ ConstantDynamicReference constantDynamic, DexItemFactory factory) {
+ DexMethod bootstrapMethod = factory.constantBootstrapsMembers.getStaticFinal;
+ return constantDynamic.getType().isIdenticalTo(factory.boxedBooleanType)
+ && constantDynamic.getBootstrapMethod().asMethod().isIdenticalTo(bootstrapMethod)
+ && constantDynamic.getBootstrapMethodArguments().size() == 0;
+ }
+
+ public static boolean extractBoxedBooleanConstantDynamic(
+ ConstantDynamicReference constantDynamic, DexItemFactory factory, Definition context) {
+ assert isBoxedBooleanConstantDynamic(constantDynamic, factory);
+ String name = constantDynamic.getName().toString();
+ if (name.equals("TRUE")) {
+ return true;
+ }
+ if (name.equals("FALSE")) {
+ return false;
+ }
+ throw throwInvalidLibraryConstantDynamic("Invalid Boolean arg " + name, context);
+ }
+
+ public static boolean isClassDescConstantDynamic(
+ ConstantDynamicReference constantDynamic, DexItemFactory factory) {
+ return isInvokeLibraryConstantDynamic(
+ constantDynamic, factory.classDescType, 2, factory.classDescMethod, factory);
+ }
+
+ public static DexType extractClassDescConstantDynamic(
+ ConstantDynamicReference constantDynamic, DexItemFactory factory, Definition context) {
+ assert isClassDescConstantDynamic(constantDynamic, factory);
+ DexValue dexValueClassName = constantDynamic.getBootstrapMethodArguments().get(1);
+ if (!dexValueClassName.isDexValueString()) {
+ throw throwInvalidLibraryConstantDynamic("Class name " + dexValueClassName, context);
+ }
+ DexString className = dexValueClassName.asDexValueString().getValue();
+ return factory.createType(DescriptorUtils.javaTypeToDescriptor(className.toString()));
+ }
+
+ public static boolean isEnumDescConstantDynamic(
+ ConstantDynamicReference constantDynamic, DexItemFactory factory) {
+ return isInvokeLibraryConstantDynamic(
+ constantDynamic, factory.enumDescType, 3, factory.enumDescMethod, factory);
+ }
+
+ public static void dispatchEnumDescConstantDynamic(
+ ConstantDynamicReference constantDynamic,
+ DexItemFactory factory,
+ Definition context,
+ BiConsumer<DexType, DexString> consumer) {
+ assert isEnumDescConstantDynamic(constantDynamic, factory);
+ DexValue dexValueFieldName = constantDynamic.getBootstrapMethodArguments().get(2);
+ if (!dexValueFieldName.isDexValueString()) {
+ throw throwInvalidLibraryConstantDynamic("Enum field name " + dexValueFieldName, context);
+ }
+ DexValue dexValueClassCstDynamic = constantDynamic.getBootstrapMethodArguments().get(1);
+ if (!dexValueClassCstDynamic.isDexValueConstDynamic()) {
+ throw throwInvalidLibraryConstantDynamic("Enum class " + dexValueClassCstDynamic, context);
+ }
+ ConstantDynamicReference classCstDynamic =
+ dexValueClassCstDynamic.asDexValueConstDynamic().getValue();
+ if (!isClassDescConstantDynamic(classCstDynamic, factory)) {
+ throw throwInvalidLibraryConstantDynamic("Enum class " + dexValueClassCstDynamic, context);
+ }
+ consumer.accept(
+ extractClassDescConstantDynamic(classCstDynamic, factory, context),
+ dexValueFieldName.asDexValueString().getValue());
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaring.java
index 898f0f9..c0b0146 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaring.java
@@ -4,10 +4,12 @@
package com.android.tools.r8.ir.desugar.typeswitch;
-import static com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper.dispatchEnumField;
+import static com.android.tools.r8.ir.desugar.constantdynamic.LibraryConstantDynamic.dispatchEnumDescConstantDynamic;
+import static com.android.tools.r8.ir.desugar.constantdynamic.LibraryConstantDynamic.extractBoxedBooleanConstantDynamic;
+import static com.android.tools.r8.ir.desugar.constantdynamic.LibraryConstantDynamic.isBoxedBooleanConstantDynamic;
+import static com.android.tools.r8.ir.desugar.constantdynamic.LibraryConstantDynamic.isEnumDescConstantDynamic;
import static com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper.isEnumSwitchCallSite;
import static com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper.isTypeSwitchCallSite;
-import static com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper.methodHandleIsInvokeStaticTo;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
@@ -20,7 +22,6 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaring;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
@@ -30,7 +31,6 @@
import com.android.tools.r8.ir.synthetic.TypeSwitchSyntheticCfCodeProvider.Dispatcher;
import com.google.common.collect.ImmutableList;
import java.util.List;
-import java.util.function.Consumer;
import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
@@ -222,11 +222,12 @@
dexStringConsumer.accept(dexValue.asDexValueString().getValue());
} else if (dexValue.isDexValueConstDynamic()) {
ConstantDynamicReference constDynamic = dexValue.asDexValueConstDynamic().getValue();
- if (constDynamic.getType().isIdenticalTo(factory.boxedBooleanType)) {
- dispatchBooleanField(context, dexValue, booleanConsumer, constDynamic);
+ if (isBoxedBooleanConstantDynamic(constDynamic, factory)) {
+ booleanConsumer.accept(
+ extractBoxedBooleanConstantDynamic(constDynamic, factory, context));
} else {
- assert constDynamic.getType().isIdenticalTo(factory.enumDescType);
- dispatchEnumField(enumConsumer, constDynamic, context, appView.dexItemFactory());
+ assert isEnumDescConstantDynamic(constDynamic, factory);
+ dispatchEnumDescConstantDynamic(constDynamic, factory, context, enumConsumer);
}
} else if (dexValue.isDexValueNumber()) {
assert dexValue.isDexValueDouble()
@@ -240,35 +241,6 @@
};
}
- private void dispatchBooleanField(
- ProgramMethod context,
- DexValue dexValue,
- Consumer<Boolean> booleanConsumer,
- ConstantDynamicReference constDynamic) {
- if (methodHandleIsInvokeStaticTo(
- constDynamic.getBootstrapMethod(),
- factory.createMethod(
- factory.constantBootstrapsType,
- factory.createProto(
- factory.objectType,
- factory.methodHandlesLookupType,
- factory.stringType,
- factory.classType),
- "getStaticFinal"))) {
- String name = constDynamic.getName().toString();
- if (name.equals("TRUE")) {
- booleanConsumer.accept(true);
- return;
- }
- if (name.equals("FALSE")) {
- booleanConsumer.accept(false);
- return;
- }
- }
- throw new CompilationError(
- "Invalid Boolean bootstrap arg for type switch " + dexValue, context.getOrigin());
- }
-
private Scanner typeScanner() {
return (dexValue, intEqCheck, enumCase) -> {
if (dexValue.isDexValueInt()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaringHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaringHelper.java
index 2780c66..d38915a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaringHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaringHelper.java
@@ -4,25 +4,14 @@
package com.android.tools.r8.ir.desugar.typeswitch;
-import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.graph.Definition;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexProto;
-import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.ir.desugar.constantdynamic.ConstantDynamicReference;
-import com.android.tools.r8.utils.DescriptorUtils;
-import java.util.function.BiConsumer;
public class TypeSwitchDesugaringHelper {
- private static CompilationError throwEnumFieldConstantDynamic(String msg, Definition context) {
- throw new CompilationError(
- "Unexpected ConstantDynamic in TypeSwitch: " + msg, context.getOrigin());
- }
private static boolean isTypeSwitchProto(DexProto proto) {
return proto.getReturnType().isIntType()
@@ -42,14 +31,7 @@
&& methodHandleIsInvokeStaticTo(callSite.bootstrapMethod, factory.enumSwitchMethod);
}
- private static boolean methodHandleIsInvokeStaticTo(DexValue dexValue, DexMethod method) {
- if (!dexValue.isDexValueMethodHandle()) {
- return false;
- }
- return methodHandleIsInvokeStaticTo(dexValue.asDexValueMethodHandle().getValue(), method);
- }
-
- public static boolean methodHandleIsInvokeStaticTo(
+ private static boolean methodHandleIsInvokeStaticTo(
DexMethodHandle methodHandle, DexMethod method) {
return methodHandle.type.isInvokeStatic() && methodHandle.asMethod().isIdenticalTo(method);
}
@@ -59,47 +41,4 @@
&& methodProto.getArity() == 2
&& methodProto.getParameter(1).isIdenticalTo(intType);
}
-
- public static void dispatchEnumField(
- BiConsumer<DexType, DexString> enumConsumer,
- ConstantDynamicReference enumCstDynamic,
- Definition context,
- DexItemFactory factory) {
- DexMethod bootstrapMethod = factory.constantDynamicBootstrapMethod;
- if (!(enumCstDynamic.getType().isIdenticalTo(factory.enumDescType)
- && enumCstDynamic.getName().isIdenticalTo(bootstrapMethod.getName())
- && enumCstDynamic.getBootstrapMethod().asMethod().isIdenticalTo(bootstrapMethod)
- && enumCstDynamic.getBootstrapMethodArguments().size() == 3
- && methodHandleIsInvokeStaticTo(
- enumCstDynamic.getBootstrapMethodArguments().get(0), factory.enumDescMethod))) {
- throw throwEnumFieldConstantDynamic("Invalid EnumDesc", context);
- }
- DexValue dexValueFieldName = enumCstDynamic.getBootstrapMethodArguments().get(2);
- if (!dexValueFieldName.isDexValueString()) {
- throw throwEnumFieldConstantDynamic("Field name " + dexValueFieldName, context);
- }
- DexString fieldName = dexValueFieldName.asDexValueString().getValue();
-
- DexValue dexValueClassCstDynamic = enumCstDynamic.getBootstrapMethodArguments().get(1);
- if (!dexValueClassCstDynamic.isDexValueConstDynamic()) {
- throw throwEnumFieldConstantDynamic("Enum class " + dexValueClassCstDynamic, context);
- }
- ConstantDynamicReference classCstDynamic =
- dexValueClassCstDynamic.asDexValueConstDynamic().getValue();
- if (!(classCstDynamic.getType().isIdenticalTo(factory.classDescType)
- && classCstDynamic.getName().isIdenticalTo(bootstrapMethod.getName())
- && classCstDynamic.getBootstrapMethod().asMethod().isIdenticalTo(bootstrapMethod)
- && classCstDynamic.getBootstrapMethodArguments().size() == 2
- && methodHandleIsInvokeStaticTo(
- classCstDynamic.getBootstrapMethodArguments().get(0), factory.classDescMethod))) {
- throw throwEnumFieldConstantDynamic("Class descriptor " + classCstDynamic, context);
- }
- DexValue dexValueClassName = classCstDynamic.getBootstrapMethodArguments().get(1);
- if (!dexValueClassName.isDexValueString()) {
- throw throwEnumFieldConstantDynamic("Class name " + dexValueClassName, context);
- }
- DexString className = dexValueClassName.asDexValueString().getValue();
- DexType type = factory.createType(DescriptorUtils.javaTypeToDescriptor(className.toString()));
- enumConsumer.accept(type, fieldName);
- }
}
diff --git a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
index 1e92c88..d328deb 100644
--- a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
@@ -4,6 +4,9 @@
package com.android.tools.r8.shaking;
+import static com.android.tools.r8.graph.UseRegistry.MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
+import static com.android.tools.r8.ir.desugar.constantdynamic.LibraryConstantDynamic.dispatchEnumDescConstantDynamic;
+import static com.android.tools.r8.ir.desugar.constantdynamic.LibraryConstantDynamic.isEnumDescConstantDynamic;
import static com.android.tools.r8.ir.desugar.records.RecordRewriterHelper.isInvokeDynamicOnRecord;
import static com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper.isEnumSwitchCallSite;
import static com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper.isTypeSwitchCallSite;
@@ -28,7 +31,6 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.ir.desugar.typeswitch.TypeSwitchDesugaringHelper;
import com.google.common.collect.Sets;
import java.util.IdentityHashMap;
import java.util.ListIterator;
@@ -309,21 +311,15 @@
private void registerTypeSwitchCallSiteBootstrapArgs(DexCallSite callSite) {
for (DexValue bootstrapArg : callSite.bootstrapArgs) {
- if (bootstrapArg.isDexValueType()) {
- registerTypeReference(bootstrapArg.asDexValueType().value);
- } else if (bootstrapArg.isDexValueConstDynamic()
- && bootstrapArg
- .asDexValueConstDynamic()
- .getValue()
- .getType()
- .isIdenticalTo(appView.dexItemFactory().enumDescType)) {
- TypeSwitchDesugaringHelper.dispatchEnumField(
- (type, fieldName) -> {
- registerEnumReferencedInTypeSwitchBootstrapArguments(type);
- },
+ registerBoostrapArg(bootstrapArg, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
+ if (bootstrapArg.isDexValueConstDynamic()
+ && isEnumDescConstantDynamic(
+ bootstrapArg.asDexValueConstDynamic().getValue(), dexItemFactory())) {
+ dispatchEnumDescConstantDynamic(
bootstrapArg.asDexValueConstDynamic().getValue(),
+ dexItemFactory(),
getContext(),
- dexItemFactory());
+ (type, name) -> registerEnumReferencedInTypeSwitchBootstrapArguments(type));
}
}
}
@@ -331,9 +327,8 @@
private void registerEnumSwitchCallSiteBootstrapArgs(DexCallSite callSite) {
DexType enumType = callSite.getMethodProto().getParameter(0);
for (DexValue bootstrapArg : callSite.bootstrapArgs) {
- if (bootstrapArg.isDexValueType()) {
- registerTypeReference(bootstrapArg.asDexValueType().value);
- } else if (bootstrapArg.isDexValueString()) {
+ registerBoostrapArg(bootstrapArg, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
+ if (bootstrapArg.isDexValueString()) {
registerEnumReferencedInTypeSwitchBootstrapArguments(enumType);
}
}
@@ -344,7 +339,7 @@
// The Instance Get method handle in invokeDynamicOnRecord are considered:
// - a record use if not a constant value,
// - unused if a constant value.
- registerCallSiteBootstrapArgs(callSite, 0, 2);
+ registerBootstrapArgs(callSite.getBootstrapArgs(), 0, 2, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
for (int i = 2; i < callSite.getBootstrapArgs().size(); i++) {
DexField field = callSite.getBootstrapArgs().get(i).asDexValueMethodHandle().value.asField();
DexEncodedField encodedField =