blob: 07ad580c7a5785ba0e11e6c41e559bab461915c2 [file] [log] [blame]
// Copyright (c) 2017, 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.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.google.common.base.Equivalence;
import com.google.common.base.Equivalence.Wrapper;
import java.util.HashMap;
import java.util.Map;
class ScopedDexMethodSet {
public enum AddMethodIfMoreVisibleResult {
NOT_ADDED,
ADDED_NOT_EXISTING,
ADDED_MORE_VISIBLE
}
private static final Equivalence<DexMethod> METHOD_EQUIVALENCE = MethodSignatureEquivalence.get();
private ScopedDexMethodSet parent;
private final Map<Wrapper<DexMethod>, DexEncodedMethod> items = new HashMap<>();
public ScopedDexMethodSet() {
this(null);
}
private ScopedDexMethodSet(ScopedDexMethodSet parent) {
this.parent = parent;
}
public ScopedDexMethodSet newNestedScope() {
return new ScopedDexMethodSet(this);
}
private DexEncodedMethod lookup(Wrapper<DexMethod> item) {
DexEncodedMethod ownMethod = items.get(item);
return ownMethod != null ? ownMethod : (parent != null ? parent.lookup(item) : null);
}
private boolean contains(Wrapper<DexMethod> item) {
return lookup(item) != null;
}
public boolean addMethod(DexEncodedMethod method) {
Wrapper<DexMethod> wrapped = METHOD_EQUIVALENCE.wrap(method.getReference());
if (contains(wrapped)) {
return false;
}
items.put(wrapped, method);
return true;
}
public AddMethodIfMoreVisibleResult addMethodIfMoreVisible(DexEncodedMethod method) {
Wrapper<DexMethod> wrapped = METHOD_EQUIVALENCE.wrap(method.getReference());
DexEncodedMethod existing = lookup(wrapped);
if (existing == null) {
items.put(wrapped, method);
return AddMethodIfMoreVisibleResult.ADDED_NOT_EXISTING;
}
if (method.accessFlags.isMoreVisibleThan(
existing.accessFlags,
method.getHolderType().getPackageName(),
existing.getHolderType().getPackageName())) {
items.put(wrapped, method);
return AddMethodIfMoreVisibleResult.ADDED_MORE_VISIBLE;
}
return AddMethodIfMoreVisibleResult.NOT_ADDED;
}
public ScopedDexMethodSet getParent() {
return parent;
}
public void setParent(ScopedDexMethodSet parent) {
this.parent = parent;
}
}