blob: b963b3f4c5b116cde28b8bdc7b94c3a49151f01a [file] [log] [blame]
// Copyright (c) 2019, 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.naming;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.naming.MethodReservationState.InternalReservationState;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.google.common.base.Equivalence.Wrapper;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
class MethodReservationState<KeyType>
extends MethodNamingStateBase<KeyType, InternalReservationState> {
private final MethodReservationState<KeyType> parentNamingState;
private MethodReservationState(
MethodReservationState<KeyType> parentNamingState,
Function<DexMethod, KeyType> keyTransform) {
super(keyTransform);
this.parentNamingState = parentNamingState;
}
public static <KeyType> MethodReservationState<KeyType> createRoot(
Function<DexMethod, KeyType> keyTransform) {
return new MethodReservationState<>(null, keyTransform);
}
MethodReservationState<KeyType> createChild() {
return new MethodReservationState<>(this, this.keyTransform);
}
void reserveName(DexString reservedName, DexEncodedMethod method) {
try {
getOrCreateInternalState(method.getReference()).reserveName(method, reservedName);
} catch (AssertionError err) {
throw new RuntimeException(
String.format(
"Assertion error when trying to reserve name '%s' for method '%s'",
reservedName, method),
err);
}
}
boolean isReserved(DexString name, DexMethod method) {
InternalReservationState internalState = getInternalState(method);
if (internalState != null && internalState.isReserved(name)) {
return true;
}
if (parentNamingState != null) {
return parentNamingState.isReserved(name, method);
}
return false;
}
Set<DexString> getReservedNamesFor(DexMethod method) {
InternalReservationState internalState = getInternalState(method);
Set<DexString> reservedName = null;
if (internalState != null) {
reservedName = internalState.getAssignedNamesFor(method);
}
if (reservedName == null && parentNamingState != null) {
reservedName = parentNamingState.getReservedNamesFor(method);
}
return reservedName;
}
@Override
InternalReservationState createInternalState(DexMethod method) {
return new InternalReservationState();
}
static class InternalReservationState {
private Map<Wrapper<DexMethod>, Set<DexString>> originalToReservedNames = null;
private Set<DexString> reservedNames = null;
boolean isReserved(DexString name) {
return reservedNames != null && reservedNames.contains(name);
}
Set<DexString> getAssignedNamesFor(DexMethod method) {
if (originalToReservedNames == null) {
return null;
}
return originalToReservedNames.get(MethodSignatureEquivalence.get().wrap(method));
}
void reserveName(DexEncodedMethod method, DexString name) {
if (reservedNames == null) {
assert originalToReservedNames == null;
originalToReservedNames = new HashMap<>();
reservedNames = new HashSet<>();
}
final Wrapper<DexMethod> wrapped =
MethodSignatureEquivalence.get().wrap(method.getReference());
originalToReservedNames.computeIfAbsent(wrapped, ignore -> new HashSet<>()).add(name);
reservedNames.add(name);
}
}
}