1418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
2418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// for details. All rights reserved. Use of this source code is governed by a
3418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager// BSD-style license that can be found in the LICENSE file.
4418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerpackage com.android.tools.r8.optimize;
5418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
62da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhutimport com.android.tools.r8.errors.Unreachable;
7418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexClass;
8418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexEncodedField;
9418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexEncodedMethod;
10418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexField;
11418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexMethod;
122da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhutimport com.android.tools.r8.graph.DexProgramClass;
13418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.DexType;
14418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.graph.GraphLense;
15418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
16418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport com.google.common.collect.Sets;
17418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.Set;
182da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhutimport java.util.function.BiConsumer;
19418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.function.BiFunction;
20418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerimport java.util.function.Function;
21418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
22418d1ca139ea11316113beafbb3b3dd3fd5587aMads Agerpublic class MemberRebindingAnalysis {
232da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut
24418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private final AppInfoWithLiveness appInfo;
25418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private final GraphLense lense;
26d5aa09296ee17dd3ef20fc07eed18a9708331e5bStephan Herhut  private final GraphLense.Builder builder = GraphLense.builder();
27418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
28418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public MemberRebindingAnalysis(AppInfoWithLiveness appInfo, GraphLense lense) {
29418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    assert lense.isContextFree();
30418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    this.appInfo = appInfo;
31418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    this.lense = lense;
32418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
33418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
34418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private DexMethod validTargetFor(DexMethod target, DexMethod original,
35418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      BiFunction<DexClass, DexMethod, DexEncodedMethod> lookup) {
36418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    DexClass clazz = appInfo.definitionFor(target.getHolder());
37418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    assert clazz != null;
38418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    if (!clazz.isLibraryClass()) {
39418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      return target;
40418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
41418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    DexType newHolder;
42418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    if (clazz.isInterface()) {
43418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      newHolder = firstLibraryClassForInterfaceTarget(target, original.getHolder(), lookup);
44418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    } else {
45418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      newHolder = firstLibraryClass(target.getHolder(), original.getHolder());
46418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
47418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return appInfo.dexItemFactory.createMethod(newHolder, original.proto, original.name);
48418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
49418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
50418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private DexField validTargetFor(DexField target, DexField original,
51418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      BiFunction<DexClass, DexField, DexEncodedField> lookup) {
52418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    DexClass clazz = appInfo.definitionFor(target.getHolder());
53418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    assert clazz != null;
54418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    if (!clazz.isLibraryClass()) {
55418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      return target;
56418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
57418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    DexType newHolder;
58418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    if (clazz.isInterface()) {
59418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      newHolder = firstLibraryClassForInterfaceTarget(target, original.getHolder(), lookup);
60418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    } else {
61418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      newHolder = firstLibraryClass(target.getHolder(), original.getHolder());
62418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
63418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return appInfo.dexItemFactory.createField(newHolder, original.type, original.name);
64418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
65418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
66418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private <T> DexType firstLibraryClassForInterfaceTarget(T target, DexType current,
67418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      BiFunction<DexClass, T, ?> lookup) {
68418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    DexClass clazz = appInfo.definitionFor(current);
69418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    Object potential = lookup.apply(clazz, target);
70418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    if (potential != null) {
71418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      // Found, return type.
72418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      return current;
73418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
74418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    if (clazz.superType != null) {
75418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      DexType matchingSuper = firstLibraryClassForInterfaceTarget(target, clazz.superType, lookup);
76418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      if (matchingSuper != null) {
77418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        // Found in supertype, return first libray class.
78418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        return clazz.isLibraryClass() ? current : matchingSuper;
79418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      }
80418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
81418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    for (DexType iface : clazz.interfaces.values) {
82418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      DexType matchingIface = firstLibraryClassForInterfaceTarget(target, iface, lookup);
83418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      if (matchingIface != null) {
84418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        // Found in interface, return first library class.
85418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        return clazz.isLibraryClass() ? current : matchingIface;
86418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      }
87418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
88418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return null;
89418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
90418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
91418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private DexType firstLibraryClass(DexType top, DexType bottom) {
92418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    assert appInfo.definitionFor(top).isLibraryClass();
93418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    DexClass searchClass = appInfo.definitionFor(bottom);
94418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    while (!searchClass.isLibraryClass()) {
95418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      searchClass = appInfo.definitionFor(searchClass.superType);
96418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
97418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return searchClass.type;
98418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
99418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
100418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private DexEncodedMethod virtualLookup(DexMethod method) {
101418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return appInfo.lookupVirtualDefinition(method.getHolder(), method);
102418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
103418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
104418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private DexEncodedMethod superLookup(DexMethod method) {
105418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    return appInfo.lookupVirtualTarget(method.getHolder(), method);
106418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
107418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
108418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private void computeMethodRebinding(Set<DexMethod> methods,
109418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      Function<DexMethod, DexEncodedMethod> lookupTarget,
1102da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      BiFunction<DexClass, DexMethod, DexEncodedMethod> lookupTargetOnClass,
1112da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      BiConsumer<DexProgramClass, DexEncodedMethod> addMethod) {
112418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    for (DexMethod method : methods) {
113418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      method = lense.lookupMethod(method, null);
114418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      // We can safely ignore array types, as the corresponding methods are defined in a library.
115418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      if (!method.getHolder().isClassType()) {
116418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        continue;
117418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      }
1182da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      DexClass originalClass = appInfo.definitionFor(method.holder);
1192da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      // We can safely ignore calls to library classes, as those cannot be rebound.
1202da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      if (originalClass == null || originalClass.isLibraryClass()) {
1212da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        continue;
1222da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      }
123418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      DexEncodedMethod target = lookupTarget.apply(method);
124418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      // Rebind to the lowest library class or program class.
125418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      if (target != null && target.method != method) {
1262da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        DexClass targetClass = appInfo.definitionFor(target.method.holder);
1272da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        // If the targetclass is not public but the targeted method is, we might run into
1282da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        // visibility problems when rebinding.
1292da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        if (!targetClass.accessFlags.isPublic() && target.accessFlags.isPublic()) {
1302da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut          // If the original class is public and this method is public, it might have been called
1312da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut          // from anywhere, so we need a bridge. Likewise, if the original is in a different
1322da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut          // package, we might need a bridge, too.
1332da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut          String packageDescriptor =
1342da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut              originalClass.accessFlags.isPublic() ? null : method.holder.getPackageDescriptor();
1352da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut          if (packageDescriptor == null
1362da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut              || !packageDescriptor.equals(targetClass.type.getPackageDescriptor())) {
1372da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut            DexProgramClass bridgeHolder = findBridgeMethodHolder(originalClass, targetClass,
1382da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut                packageDescriptor);
1392da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut            assert bridgeHolder != null;
1402da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut            DexEncodedMethod bridgeMethod = target
1412da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut                .toForwardingMethod(bridgeHolder, appInfo.dexItemFactory);
1422da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut            addMethod.accept(bridgeHolder, bridgeMethod);
1432da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut            assert lookupTarget.apply(method) == bridgeMethod;
1442da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut            target = bridgeMethod;
1452da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut          }
1462da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        }
14774f1c6f2254f82fcec7612df782d125e621049b9Stephan Herhut        builder.map(method, validTargetFor(target.method, method, lookupTargetOnClass));
148418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      }
149418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
150418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
151418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
1522da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut  private DexProgramClass findBridgeMethodHolder(DexClass originalClass, DexClass targetClass,
1532da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      String packageDescriptor) {
1542da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    if (originalClass == targetClass || originalClass.isLibraryClass()) {
1552da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      return null;
1562da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    }
1572da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    DexProgramClass newHolder = null;
1582da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    // Recurse through supertype chain.
15952c0414fff5db9769a60a3e2880acd8781a88ab1Denis Vnukov    if (originalClass.superType.isSubtypeOf(targetClass.type, appInfo)) {
1602da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      DexClass superClass = appInfo.definitionFor(originalClass.superType);
1612da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      newHolder = findBridgeMethodHolder(superClass, targetClass, packageDescriptor);
1622da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    } else {
1632da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      for (DexType iface : originalClass.interfaces.values) {
16452c0414fff5db9769a60a3e2880acd8781a88ab1Denis Vnukov        if (iface.isSubtypeOf(targetClass.type, appInfo)) {
1652da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut          DexClass interfaceClass = appInfo.definitionFor(iface);
1662da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut          newHolder = findBridgeMethodHolder(interfaceClass, targetClass, packageDescriptor);
1672da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        }
1682da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      }
1692da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    }
1702da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    if (newHolder != null) {
1712da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      // A supertype fulfills the visibility requirements.
1722da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      return newHolder;
1732da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    } else if (originalClass.accessFlags.isPublic()
1742da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        || originalClass.type.getPackageDescriptor().equals(packageDescriptor)) {
1752da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      // This class is visible. Return it if it is a program class, otherwise null.
1762da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut      return originalClass.asProgramClass();
1772da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    }
1782da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    return null;
1792da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut  }
1802da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut
181418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  private void computeFieldRebinding(Set<DexField> fields,
182418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      BiFunction<DexType, DexField, DexEncodedField> lookup,
183418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      BiFunction<DexClass, DexField, DexEncodedField> lookupTargetOnClass) {
184418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    for (DexField field : fields) {
185418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      field = lense.lookupField(field, null);
186418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      DexEncodedField target = lookup.apply(field.getHolder(), field);
187fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut      // Rebind to the lowest library class or program class. Do not rebind accesses to fields that
188fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut      // are not public, as this might lead to access violation errors.
189fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut      if (target != null && target.field != field && isVisibleFromOtherClasses(target)) {
190418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        builder.map(field, validTargetFor(target.field, field, lookupTargetOnClass));
191418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager      }
192418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    }
193418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
194418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
195fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut  private boolean isVisibleFromOtherClasses(DexEncodedField field) {
196fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut    // If the field is not public, the visibility on the class can not be a further constraint.
197fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut    if (!field.accessFlags.isPublic()) {
198fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut      return true;
199fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut    }
200fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut    // If the field is public, then a non-public holder class will further constrain visibility.
201fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut    return appInfo.definitionFor(field.field.getHolder()).accessFlags.isPublic();
202fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut  }
203fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut
2042da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut  private static void privateMethodsCheck(DexProgramClass clazz, DexEncodedMethod method) {
2052da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    throw new Unreachable("Direct invokes should not require forwarding.");
2062da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut  }
2072da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut
208418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  public GraphLense run() {
209418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    computeMethodRebinding(appInfo.virtualInvokes, this::virtualLookup,
2102da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        DexClass::findVirtualTarget, DexProgramClass::addVirtualMethod);
2112da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut    computeMethodRebinding(appInfo.superInvokes, this::superLookup, DexClass::findVirtualTarget,
2122da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        DexProgramClass::addVirtualMethod);
213418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    computeMethodRebinding(appInfo.directInvokes, appInfo::lookupDirectTarget,
2142da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        DexClass::findDirectTarget, MemberRebindingAnalysis::privateMethodsCheck);
215418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager    computeMethodRebinding(appInfo.staticInvokes, appInfo::lookupStaticTarget,
2162da874a28e1a98dc5d2500a554f9143d6309a132Stephan Herhut        DexClass::findDirectTarget, DexProgramClass::addStaticMethod);
217418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager
218fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut    computeFieldRebinding(Sets.union(appInfo.staticFieldReads, appInfo.staticFieldWrites),
219418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        appInfo::lookupStaticTarget, DexClass::findStaticTarget);
220fd8a4de5f510bf261a438e050cad712a4321ea82Stephan Herhut    computeFieldRebinding(Sets.union(appInfo.instanceFieldReads, appInfo.instanceFieldWrites),
221418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager        appInfo::lookupInstanceTarget, DexClass::findInstanceTarget);
222d5aa09296ee17dd3ef20fc07eed18a9708331e5bStephan Herhut    return builder.build(lense, appInfo.dexItemFactory);
223418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager  }
224418d1ca139ea11316113beafbb3b3dd3fd5587aMads Ager}
225