Shared implementation for ensuring synthetic methods.
Change-Id: I4a079356dd5e2face5233555f36c7c2791d74a92
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index 9dba1b5..79afbf8 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -1254,15 +1254,15 @@
}
appView
.getSyntheticItems()
- .ensureDirectMethodOnSyntheticClasspathClass(
+ .ensureFixedClasspathClassMethod(
+ rewritten.getName(),
+ rewritten.getProto(),
SyntheticKind.COMPANION_CLASS,
context,
appView,
- rewritten,
- builder ->
- builder
- .setName(rewritten.name)
- .setProto(rewritten.proto)
+ classBuilder -> {},
+ methodBuilder ->
+ methodBuilder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setCode(DexEncodedMethod::buildEmptyThrowingCfCode));
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index 44bb7e7..2d0970f 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
@@ -21,6 +22,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.graph.MethodCollection;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
@@ -556,21 +558,9 @@
DexProgramClass clazz =
ensureFixedClass(kind, context, appView, buildClassCallback, ignored -> {});
DexMethod methodReference = appView.dexItemFactory().createMethod(clazz.getType(), proto, name);
- DexEncodedMethod methodDefinition = clazz.getMethodCollection().getMethod(methodReference);
- if (methodDefinition != null) {
- return new ProgramMethod(clazz, methodDefinition);
- }
- // TODO(b/183998768): Make this thread safe and safe to use for recursive definitions.
- SyntheticMethodBuilder builder =
- new SyntheticMethodBuilder(appView.dexItemFactory(), clazz.getType(), kind);
- builder.setName(name);
- builder.setProto(proto);
- buildMethodCallback.accept(builder);
- DexEncodedMethod method = builder.build();
- assert method.getName() == name;
- assert method.getProto() == proto;
- clazz.addMethod(method);
- return new ProgramMethod(clazz, method);
+ DexEncodedMethod methodDefinition =
+ internalEnsureMethod(methodReference, clazz, kind, appView, buildMethodCallback);
+ return new ProgramMethod(clazz, methodDefinition);
}
public DexClasspathClass createFixedClasspathClass(
@@ -617,22 +607,50 @@
}
}
- public void ensureDirectMethodOnSyntheticClasspathClass(
+ public DexClassAndMethod ensureFixedClasspathClassMethod(
+ DexString methodName,
+ DexProto methodProto,
SyntheticKind kind,
ClasspathOrLibraryClass context,
AppView<?> appView,
- DexMethod method,
- Consumer<SyntheticMethodBuilder> builderConsumer) {
- DexClasspathClass syntheticClass =
- ensureFixedClasspathClass(kind, context, appView, ignored -> {}, ignored -> {});
- synchronized (syntheticClass) {
- if (syntheticClass.lookupMethod(method) != null) {
- return;
+ Consumer<SyntheticClasspathClassBuilder> buildClassCallback,
+ Consumer<SyntheticMethodBuilder> buildMethodCallback) {
+ DexClasspathClass clazz =
+ ensureFixedClasspathClass(kind, context, appView, buildClassCallback, ignored -> {});
+ DexMethod methodReference =
+ appView.dexItemFactory().createMethod(clazz.getType(), methodProto, methodName);
+ DexEncodedMethod methodDefinition =
+ internalEnsureMethod(methodReference, clazz, kind, appView, buildMethodCallback);
+ return DexClassAndMethod.create(clazz, methodDefinition);
+ }
+
+ private DexEncodedMethod internalEnsureMethod(
+ DexMethod methodReference,
+ DexClass clazz,
+ SyntheticKind kind,
+ AppView<?> appView,
+ Consumer<SyntheticMethodBuilder> buildMethodCallback) {
+ MethodCollection methodCollection = clazz.getMethodCollection();
+ DexEncodedMethod methodDefinition = methodCollection.getMethod(methodReference);
+ if (methodDefinition != null) {
+ return methodDefinition;
+ }
+ synchronized (methodCollection) {
+ methodDefinition = methodCollection.getMethod(methodReference);
+ if (methodDefinition != null) {
+ return methodDefinition;
}
- SyntheticMethodBuilder syntheticMethodBuilder =
- new SyntheticMethodBuilder(appView.dexItemFactory(), syntheticClass.type, kind);
- builderConsumer.accept(syntheticMethodBuilder);
- syntheticClass.addDirectMethod(syntheticMethodBuilder.build());
+ SyntheticMethodBuilder builder =
+ new SyntheticMethodBuilder(appView.dexItemFactory(), clazz.getType(), kind);
+ builder.setName(methodReference.getName());
+ builder.setProto(methodReference.getProto());
+ buildMethodCallback.accept(builder);
+ // TODO(b/183998768): Make this safe for recursive definitions.
+ // For example, the builder should be split into the creation of the method structure
+ // and the creation of the method code. The code can then be constructed outside the lock.
+ methodDefinition = builder.build();
+ methodCollection.addMethod(methodDefinition);
+ return methodDefinition;
}
}