blob: 356ef8c67f00a14d46b64ce60acf85302aa3c7a2 [file] [log] [blame]
// Copyright (c) 2024, 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.shaking;
import com.android.tools.r8.shaking.KeepInfoEquivalenceNoAnnotations.ClassEquivalenceNoAnnotations;
import com.android.tools.r8.shaking.KeepInfoEquivalenceNoAnnotations.FieldEquivalenceNoAnnotations;
import com.android.tools.r8.shaking.KeepInfoEquivalenceNoAnnotations.MethodEquivalenceNoAnnotations;
import com.android.tools.r8.utils.LRUCache;
import com.google.common.base.Equivalence;
import java.util.Map;
public abstract class KeepInfoCanonicalizer {
private static final int CACHE_SIZE = 25;
public static KeepInfoCanonicalizer newCanonicalizer() {
return new KeepInfoConcreteCanonicalizer();
}
public static KeepInfoCanonicalizer newNopCanonicalizer() {
return new KeepInfoNopCanonicalizer();
}
public abstract KeepClassInfo canonicalizeKeepClassInfo(KeepClassInfo classInfo);
public abstract KeepMethodInfo canonicalizeKeepMethodInfo(KeepMethodInfo methodInfo);
public abstract KeepFieldInfo canonicalizeKeepFieldInfo(KeepFieldInfo fieldInfo);
static class KeepInfoConcreteCanonicalizer extends KeepInfoCanonicalizer {
private final ClassEquivalenceNoAnnotations classEquivalence =
new ClassEquivalenceNoAnnotations();
private final Map<Equivalence.Wrapper<KeepClassInfo>, Equivalence.Wrapper<KeepClassInfo>>
keepClassInfos = new LRUCache<>(CACHE_SIZE);
private final MethodEquivalenceNoAnnotations methodEquivalence =
new MethodEquivalenceNoAnnotations();
private final Map<Equivalence.Wrapper<KeepMethodInfo>, Equivalence.Wrapper<KeepMethodInfo>>
keepMethodInfos = new LRUCache<>(CACHE_SIZE);
private final FieldEquivalenceNoAnnotations fieldEquivalence =
new FieldEquivalenceNoAnnotations();
private final Map<Equivalence.Wrapper<KeepFieldInfo>, Equivalence.Wrapper<KeepFieldInfo>>
keepFieldInfos = new LRUCache<>(CACHE_SIZE);
private boolean hasNonTrivialKeepInfoAnnotationInfo(KeepInfo<?, ?> info) {
return !info.internalAnnotationsInfo().isTopOrBottom()
|| !info.internalTypeAnnotationsInfo().isTopOrBottom();
}
@Override
public KeepClassInfo canonicalizeKeepClassInfo(KeepClassInfo classInfo) {
if (hasNonTrivialKeepInfoAnnotationInfo(classInfo)) {
return classInfo;
}
return keepClassInfos.computeIfAbsent(classEquivalence.wrap(classInfo), w -> w).get();
}
@Override
public KeepMethodInfo canonicalizeKeepMethodInfo(KeepMethodInfo methodInfo) {
if (hasNonTrivialKeepInfoAnnotationInfo(methodInfo)
|| !methodInfo.internalParameterAnnotationsInfo().isTopOrBottom()) {
return methodInfo;
}
return keepMethodInfos.computeIfAbsent(methodEquivalence.wrap(methodInfo), w -> w).get();
}
@Override
public KeepFieldInfo canonicalizeKeepFieldInfo(KeepFieldInfo fieldInfo) {
if (hasNonTrivialKeepInfoAnnotationInfo(fieldInfo)) {
return fieldInfo;
}
return keepFieldInfos.computeIfAbsent(fieldEquivalence.wrap(fieldInfo), w -> w).get();
}
}
static class KeepInfoNopCanonicalizer extends KeepInfoCanonicalizer {
@Override
public KeepClassInfo canonicalizeKeepClassInfo(KeepClassInfo classInfo) {
return classInfo;
}
@Override
public KeepMethodInfo canonicalizeKeepMethodInfo(KeepMethodInfo methodInfo) {
return methodInfo;
}
@Override
public KeepFieldInfo canonicalizeKeepFieldInfo(KeepFieldInfo fieldInfo) {
return fieldInfo;
}
}
}