Replace enqueuer action enum kind by action objects.

Change-Id: Icf45ef4e913865442b0f7d6578c0145d6b7f5d66
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 1350e17..4db35df 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1299,7 +1299,8 @@
     }
   }
 
-  private void markNonStaticDirectMethodAsReachable(DexMethod method, KeepReason reason) {
+  // Package protected due to entry point from worklist.
+  void markNonStaticDirectMethodAsReachable(DexMethod method, KeepReason reason) {
     handleInvokeOfDirectTarget(method, reason);
   }
 
@@ -1414,7 +1415,8 @@
    * Adds the class to the set of instantiated classes and marks its fields and methods live
    * depending on the currently seen invokes and field reads.
    */
-  private void processNewlyInstantiatedClass(DexProgramClass clazz, KeepReason reason) {
+  // Package protected due to entry point from worklist.
+  void processNewlyInstantiatedClass(DexProgramClass clazz, KeepReason reason) {
     assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
     // Notify analyses. This is done even if `clazz` has already been marked as instantiated,
     // because each analysis may depend on seeing all the (clazz, reason) pairs. Thus, not doing so
@@ -1765,7 +1767,8 @@
     return directAndIndirectlyInstantiatedTypes.contains(clazz);
   }
 
-  private void markInstanceFieldAsReachable(DexEncodedField encodedField, KeepReason reason) {
+  // Package protected due to entry point from worklist.
+  void markInstanceFieldAsReachable(DexEncodedField encodedField, KeepReason reason) {
     DexField field = encodedField.field;
     if (Log.ENABLED) {
       Log.verbose(getClass(), "Marking instance field `%s` as reachable.", field);
@@ -1799,8 +1802,8 @@
     }
   }
 
-  private void markVirtualMethodAsReachable(
-      DexMethod method, boolean interfaceInvoke, KeepReason reason) {
+  // Package protected due to entry point from worklist.
+  void markVirtualMethodAsReachable(DexMethod method, boolean interfaceInvoke, KeepReason reason) {
     markVirtualMethodAsReachable(method, interfaceInvoke, reason, (x, y) -> true);
   }
 
@@ -2024,7 +2027,8 @@
     }
   }
 
-  private void markSuperMethodAsReachable(DexMethod method, DexEncodedMethod from) {
+  // Package protected due to entry point from worklist.
+  void markSuperMethodAsReachable(DexMethod method, DexEncodedMethod from) {
     // We have to mark the immediate target of the descriptor as targeted, as otherwise
     // the invoke super will fail in the resolution step with a NSM error.
     // See <a
@@ -2206,38 +2210,7 @@
         numOfLiveItems += (long) liveFields.items.size();
         while (!workList.isEmpty()) {
           Action action = workList.poll();
-          switch (action.kind) {
-            case MARK_INSTANTIATED:
-              processNewlyInstantiatedClass((DexProgramClass) action.target, action.reason);
-              break;
-            case MARK_REACHABLE_FIELD:
-              markInstanceFieldAsReachable((DexEncodedField) action.target, action.reason);
-              break;
-            case MARK_REACHABLE_DIRECT:
-              markNonStaticDirectMethodAsReachable((DexMethod) action.target, action.reason);
-              break;
-            case MARK_REACHABLE_VIRTUAL:
-              markVirtualMethodAsReachable((DexMethod) action.target, false, action.reason);
-              break;
-            case MARK_REACHABLE_INTERFACE:
-              markVirtualMethodAsReachable((DexMethod) action.target, true, action.reason);
-              break;
-            case MARK_REACHABLE_SUPER:
-              markSuperMethodAsReachable((DexMethod) action.target,
-                  (DexEncodedMethod) action.context);
-              break;
-            case MARK_METHOD_KEPT:
-              markMethodAsKept((DexEncodedMethod) action.target, action.reason);
-              break;
-            case MARK_FIELD_KEPT:
-              markFieldAsKept((DexEncodedField) action.target, action.reason);
-              break;
-            case MARK_METHOD_LIVE:
-              markMethodAsLive(((DexEncodedMethod) action.target), action.reason);
-              break;
-            default:
-              throw new IllegalArgumentException("" + action.kind);
-          }
+          action.run(this);
         }
 
         // Continue fix-point processing if -if rules are enabled by items that newly became live.
@@ -2341,7 +2314,8 @@
     lambdaMethodsTargetedByInvokeDynamic.clear();
   }
 
-  private void markMethodAsKept(DexEncodedMethod target, KeepReason reason) {
+  // Package protected due to entry point from worklist.
+  void markMethodAsKept(DexEncodedMethod target, KeepReason reason) {
     DexMethod method = target.method;
     DexProgramClass holder = getProgramClassOrNull(method.holder);
     if (holder == null) {
@@ -2380,7 +2354,8 @@
     }
   }
 
-  private void markFieldAsKept(DexEncodedField target, KeepReason reason) {
+  // Package protected due to entry point from worklist.
+  void markFieldAsKept(DexEncodedField target, KeepReason reason) {
     DexProgramClass clazz = getProgramClassOrNull(target.field.holder);
     if (clazz == null) {
       return;
@@ -2433,7 +2408,8 @@
     return false;
   }
 
-  private void markMethodAsLive(DexEncodedMethod method, KeepReason reason) {
+  // Package protected due to entry point from worklist.
+  void markMethodAsLive(DexEncodedMethod method, KeepReason reason) {
     assert liveMethods.contains(method);
 
     DexProgramClass clazz = getProgramClassOrNull(method.method.holder);
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
index bde6b8d..5b06e48 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
@@ -7,7 +7,6 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import java.util.ArrayDeque;
@@ -15,31 +14,143 @@
 
 public class EnqueuerWorklist {
 
-  public static class Action {
+  public abstract static class Action {
+    public abstract void run(Enqueuer enqueuer);
+  }
 
-    public enum Kind {
-      MARK_REACHABLE_DIRECT,
-      MARK_REACHABLE_VIRTUAL,
-      MARK_REACHABLE_INTERFACE,
-      MARK_REACHABLE_SUPER,
-      MARK_REACHABLE_FIELD,
-      MARK_INSTANTIATED,
-      MARK_METHOD_LIVE,
-      MARK_METHOD_KEPT,
-      MARK_FIELD_KEPT
-    }
-
-    final Kind kind;
-    final DexItem target;
-    final DexItem context;
+  static class MarkReachableDirectAction extends Action {
+    final DexMethod target;
     final KeepReason reason;
 
-    private Action(Kind kind, DexItem target, DexItem context, KeepReason reason) {
-      this.kind = kind;
+    MarkReachableDirectAction(DexMethod target, KeepReason reason) {
+      this.target = target;
+      this.reason = reason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markNonStaticDirectMethodAsReachable(target, reason);
+    }
+  }
+
+  static class MarkReachableVirtualAction extends Action {
+    final DexMethod target;
+    final KeepReason reason;
+
+    MarkReachableVirtualAction(DexMethod target, KeepReason reason) {
+      this.target = target;
+      this.reason = reason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markVirtualMethodAsReachable(target, false, reason);
+    }
+  }
+
+  static class MarkReachableInterfaceAction extends Action {
+    final DexMethod target;
+    final KeepReason reason;
+
+    public MarkReachableInterfaceAction(DexMethod target, KeepReason reason) {
+      this.target = target;
+      this.reason = reason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markVirtualMethodAsReachable(target, true, reason);
+    }
+  }
+
+  static class MarkReachableSuperAction extends Action {
+    final DexMethod target;
+    final DexEncodedMethod context;
+
+    public MarkReachableSuperAction(DexMethod target, DexEncodedMethod context) {
       this.target = target;
       this.context = context;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markSuperMethodAsReachable(target, context);
+    }
+  }
+
+  static class MarkReachableFieldAction extends Action {
+    final DexEncodedField target;
+    final KeepReason reason;
+
+    public MarkReachableFieldAction(DexEncodedField target, KeepReason reason) {
+      this.target = target;
       this.reason = reason;
     }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markInstanceFieldAsReachable(target, reason);
+    }
+  }
+
+  static class MarkInstantiatedAction extends Action {
+    final DexProgramClass target;
+    final KeepReason reason;
+
+    public MarkInstantiatedAction(DexProgramClass target, KeepReason reason) {
+      this.target = target;
+      this.reason = reason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.processNewlyInstantiatedClass(target, reason);
+    }
+  }
+
+  static class MarkMethodLiveAction extends Action {
+    final DexEncodedMethod target;
+    final KeepReason reason;
+
+    public MarkMethodLiveAction(DexEncodedMethod target, KeepReason reason) {
+      this.target = target;
+      this.reason = reason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markMethodAsLive(target, reason);
+    }
+  }
+
+  static class MarkMethodKeptAction extends Action {
+    final DexEncodedMethod target;
+    final KeepReason reason;
+
+    public MarkMethodKeptAction(DexEncodedMethod target, KeepReason reason) {
+      this.target = target;
+      this.reason = reason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markMethodAsKept(target, reason);
+    }
+  }
+
+  static class MarkFieldKeptAction extends Action {
+    final DexEncodedField target;
+    final KeepReason reason;
+
+    public MarkFieldKeptAction(DexEncodedField target, KeepReason reason) {
+      this.target = target;
+      this.reason = reason;
+    }
+
+    @Override
+    public void run(Enqueuer enqueuer) {
+      enqueuer.markFieldAsKept(target, reason);
+    }
   }
 
   private final AppView<?> appView;
@@ -62,45 +173,45 @@
   }
 
   void enqueueMarkReachableDirectAction(DexMethod method, KeepReason reason) {
-    queue.add(new Action(Action.Kind.MARK_REACHABLE_DIRECT, method, null, reason));
+    queue.add(new MarkReachableDirectAction(method, reason));
   }
 
   void enqueueMarkReachableVirtualAction(DexMethod method, KeepReason reason) {
-    queue.add(new Action(Action.Kind.MARK_REACHABLE_VIRTUAL, method, null, reason));
+    queue.add(new MarkReachableVirtualAction(method, reason));
   }
 
   void enqueueMarkReachableInterfaceAction(DexMethod method, KeepReason reason) {
-    queue.add(new Action(Action.Kind.MARK_REACHABLE_INTERFACE, method, null, reason));
+    queue.add(new MarkReachableInterfaceAction(method, reason));
   }
 
   void enqueueMarkReachableSuperAction(DexMethod method, DexEncodedMethod from) {
-    queue.add(new Action(Action.Kind.MARK_REACHABLE_SUPER, method, from, null));
+    queue.add(new MarkReachableSuperAction(method, from));
   }
 
   public void enqueueMarkReachableFieldAction(
       DexProgramClass clazz, DexEncodedField field, KeepReason reason) {
     assert field.field.holder == clazz.type;
-    queue.add(new Action(Action.Kind.MARK_REACHABLE_FIELD, field, null, reason));
+    queue.add(new MarkReachableFieldAction(field, reason));
   }
 
   void enqueueMarkInstantiatedAction(DexProgramClass clazz, KeepReason reason) {
     assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
-    queue.add(new Action(Action.Kind.MARK_INSTANTIATED, clazz, null, reason));
+    queue.add(new MarkInstantiatedAction(clazz, reason));
   }
 
   void enqueueMarkMethodLiveAction(
       DexProgramClass clazz, DexEncodedMethod method, KeepReason reason) {
     assert method.method.holder == clazz.type;
-    queue.add(new Action(Action.Kind.MARK_METHOD_LIVE, method, null, reason));
+    queue.add(new MarkMethodLiveAction(method, reason));
   }
 
   void enqueueMarkMethodKeptAction(DexEncodedMethod method, KeepReason reason) {
     assert method.isProgramMethod(appView);
-    queue.add(new Action(Action.Kind.MARK_METHOD_KEPT, method, null, reason));
+    queue.add(new MarkMethodKeptAction(method, reason));
   }
 
   void enqueueMarkFieldKeptAction(DexEncodedField field, KeepReason reason) {
     assert field.isProgramField(appView);
-    queue.add(new Action(Action.Kind.MARK_FIELD_KEPT, field, null, reason));
+    queue.add(new MarkFieldKeptAction(field, reason));
   }
 }