blob: ab8999a1b61dd3775cf1ff06e694853f0f0b9c40 [file] [log] [blame]
// Copyright (c) 2018, 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.optimize;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.GraphLense.NestedGraphLense;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import java.util.Set;
final class PublicizerLense extends NestedGraphLense {
private final AppView appView;
private final Set<DexMethod> publicizedMethods;
private PublicizerLense(AppView appView, Set<DexMethod> publicizedMethods) {
super(
ImmutableMap.of(),
ImmutableMap.of(),
ImmutableMap.of(),
null,
null,
appView.graphLense(),
appView.dexItemFactory());
this.appView = appView;
this.publicizedMethods = publicizedMethods;
}
@Override
protected boolean isLegitimateToHaveEmptyMappings() {
// This lense does not map any DexItem's at all.
// It will just tweak invoke type for publicized methods from invoke-direct to invoke-virtual.
return true;
}
@Override
public GraphLenseLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
GraphLenseLookupResult previous = previousLense.lookupMethod(method, context, type);
method = previous.getMethod();
type = previous.getType();
if (type == Type.DIRECT && publicizedMethods.contains(method)) {
assert publicizedMethodIsPresentOnHolder(method, context);
return new GraphLenseLookupResult(method, Type.VIRTUAL);
}
return super.lookupMethod(method, context, type);
}
private boolean publicizedMethodIsPresentOnHolder(DexMethod method, DexMethod context) {
GraphLenseLookupResult lookup =
appView.graphLense().lookupMethod(method, context, Type.VIRTUAL);
DexMethod signatureInCurrentWorld = lookup.getMethod();
DexClass clazz = appView.definitionFor(signatureInCurrentWorld.holder);
assert clazz != null;
DexEncodedMethod actualEncodedTarget = clazz.lookupVirtualMethod(signatureInCurrentWorld);
assert actualEncodedTarget != null;
assert actualEncodedTarget.isPublicized();
return true;
}
static PublicizedLenseBuilder createBuilder() {
return new PublicizedLenseBuilder();
}
static class PublicizedLenseBuilder {
private final Set<DexMethod> publicizedMethods = Sets.newIdentityHashSet();
private PublicizedLenseBuilder() {
}
public GraphLense build(AppView appView) {
if (publicizedMethods.isEmpty()) {
return appView.graphLense();
}
return new PublicizerLense(appView, publicizedMethods);
}
public void add(DexMethod publicizedMethod) {
publicizedMethods.add(publicizedMethod);
}
}
}