Add context sensitive definition lookup methods.

Change-Id: I9ba2b74d1553c07c5447fc84665af57cd23f3bb2
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
index 47223c0..cc91bcd 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinitionSupplier.java
@@ -6,17 +6,76 @@
 
 public interface DexDefinitionSupplier {
 
+  /**
+   * Lookup for the definition of a type independent of context.
+   *
+   * <p>This will make use of the compilers program, library and classpath precedence.
+   *
+   * @param type Type to look up the defintion for.
+   * @return Definition of the type or null if no definition exists.
+   */
+  default DexClass contextIndependentDefinitionFor(DexType type) {
+    return definitionFor(type);
+  }
+
+  /**
+   * Lookup for the definition of a type from a given context.
+   *
+   * <p>This ensures that a context overrides the usual lookup precedence if looking up itself.
+   *
+   * @param type Type to look up a definition for.
+   * @param context Context from which the lookup is taking place.
+   * @return Definition of the type or null if no definition exists.
+   */
+  default DexClass definitionFor(DexType type, DexProgramClass context) {
+    return type == context.type ? context : contextIndependentDefinitionFor(type);
+  }
+
+  /**
+   * Lookup for the program definition of a type from a given context.
+   *
+   * <p>This ensures that a context overrides the usual lookup precedence if looking up itself.
+   *
+   * @param type Type to look up a definition for.
+   * @param context Context from which the lookup is taking place.
+   * @return Definition of the type if it is a program type or null if not or no definition exists.
+   */
+  default DexProgramClass programDefinitionFor(DexType type, DexProgramClass context) {
+    return DexProgramClass.asProgramClassOrNull(definitionFor(type, context));
+  }
+
+  default <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
+      DexClass definitionForHolder(DexEncodedMember<D, R> member, ProgramMethod context) {
+    return definitionForHolder(member.toReference(), context.getHolder());
+  }
+
+  default <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
+      DexClass definitionForHolder(DexEncodedMember<D, R> member, DexProgramClass context) {
+    return definitionForHolder(member.toReference(), context);
+  }
+
+  default <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
+      DexClass definitionForHolder(DexMember<D, R> member, ProgramMethod context) {
+    return definitionFor(member.holder, context.getHolder());
+  }
+
+  default <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
+      DexClass definitionForHolder(DexMember<D, R> member, DexProgramClass context) {
+    return definitionFor(member.holder, context);
+  }
+
+  // Use definitionFor with a context or contextIndependentDefinitionFor without.
+  @Deprecated
   DexClass definitionFor(DexType type);
 
+  // Use programDefinitionFor with a context.
+  @Deprecated
   default DexProgramClass definitionForProgramType(DexType type) {
     return DexProgramClass.asProgramClassOrNull(definitionFor(type));
   }
 
-  default <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
-      DexClass definitionForHolder(DexEncodedMember<D, R> member) {
-    return definitionForHolder(member.toReference());
-  }
-
+  // Use definitionForHolder with a context.
+  @Deprecated
   default <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
       DexClass definitionForHolder(DexMember<D, R> member) {
     return definitionFor(member.holder);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
index 5b1dd91..0df3c80 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
@@ -202,8 +202,8 @@
   }
 
   private void recordAllFieldPutsProcessed(
-      DexEncodedField field, OptimizationFeedbackDelayed feedback) {
-    DexProgramClass clazz = asProgramClassOrNull(appView.definitionForHolder(field));
+      DexEncodedField field, ProgramMethod context, OptimizationFeedbackDelayed feedback) {
+    DexProgramClass clazz = asProgramClassOrNull(appView.definitionForHolder(field, context));
     if (clazz == null) {
       assert false;
       return;
@@ -282,7 +282,8 @@
     // therefore important that the optimization info has been flushed in advance.
     assert feedback.noUpdatesLeft();
     for (ProgramMethod method : wave) {
-      fieldAccessGraph.markProcessed(method, field -> recordAllFieldPutsProcessed(field, feedback));
+      fieldAccessGraph.markProcessed(
+          method, field -> recordAllFieldPutsProcessed(field, method, feedback));
       objectAllocationGraph.markProcessed(
           method, clazz -> recordAllAllocationsSitesProcessed(clazz, feedback));
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index 6fe0808..a078c9b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -121,7 +121,7 @@
             InvokeSuper invoke = current.asInvokeSuper();
             DexEncodedMethod singleTarget = invoke.lookupSingleTarget(appView, context);
             if (singleTarget != null) {
-              DexClass holder = appView.definitionForHolder(singleTarget);
+              DexClass holder = appView.definitionForHolder(singleTarget, context);
               assert holder != null;
               DexMethod invokedMethod = invoke.getInvokedMethod();
               DexEncodedMethod newSingleTarget =