blob: 439ef05ea470418fd7dd3238b8f8e1a221964421 [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.graph;
import com.android.tools.r8.utils.ObjectUtils;
import com.android.tools.r8.utils.SetUtils;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
public class FieldAccessInfoCollectionImpl
implements FieldAccessInfoCollection<FieldAccessInfoImpl> {
private final Map<DexField, FieldAccessInfoImpl> infos;
public FieldAccessInfoCollectionImpl() {
this(new IdentityHashMap<>());
}
public FieldAccessInfoCollectionImpl(Map<DexField, FieldAccessInfoImpl> infos) {
this.infos = infos;
}
@Override
public void destroyAccessContexts() {
infos.values().forEach(FieldAccessInfoImpl::destroyAccessContexts);
}
@Override
public void flattenAccessContexts() {
infos.values().forEach(FieldAccessInfoImpl::flattenAccessContexts);
}
public FieldAccessInfoImpl computeIfAbsent(
DexField field, Function<DexField, FieldAccessInfoImpl> fn) {
return infos.computeIfAbsent(field, fn);
}
@Override
public boolean contains(DexField field) {
return infos.containsKey(field);
}
@Override
public FieldAccessInfoImpl get(DexField field) {
return infos.get(field);
}
public FieldAccessInfoImpl extend(DexField field, FieldAccessInfoImpl info) {
assert !infos.containsKey(field);
infos.put(field, info);
return info;
}
@Override
public void forEach(Consumer<FieldAccessInfoImpl> consumer) {
// Verify that the mapping os one-to-one, otherwise the caller could receive duplicates.
assert verifyMappingIsOneToOne();
infos.values().forEach(consumer);
}
@Override
public void removeIf(BiPredicate<DexField, FieldAccessInfoImpl> predicate) {
infos.entrySet().removeIf(entry -> predicate.test(entry.getKey(), entry.getValue()));
}
@Override
public void restrictToProgram(DexDefinitionSupplier definitions) {
removeIf((field, info) -> !definitions.definitionForHolder(field).isProgramClass());
}
public FieldAccessInfoCollectionImpl rewrittenWithLens(
DexDefinitionSupplier definitions, GraphLens lens) {
FieldAccessInfoCollectionImpl collection = new FieldAccessInfoCollectionImpl();
Consumer<FieldAccessInfoImpl> rewriteAndMergeFieldInfo =
info -> {
FieldAccessInfoImpl rewrittenInfo = info.rewrittenWithLens(definitions, lens);
DexField newField = rewrittenInfo.getField();
collection.infos.compute(
newField,
(ignore, oldInfo) ->
ObjectUtils.mapNotNullOrDefault(oldInfo, rewrittenInfo, rewrittenInfo::join));
};
infos.values().forEach(rewriteAndMergeFieldInfo);
return collection;
}
// This is used to verify that the temporary mappings inserted into `infos` by the Enqueuer are
// removed.
public boolean verifyMappingIsOneToOne() {
assert infos.values().size() == SetUtils.newIdentityHashSet(infos.values()).size();
return true;
}
}