blob: 5b06e4845b7a1d565d039353382ea23b262697c5 [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.shaking;
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.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import java.util.ArrayDeque;
import java.util.Queue;
public class EnqueuerWorklist {
public abstract static class Action {
public abstract void run(Enqueuer enqueuer);
}
static class MarkReachableDirectAction extends Action {
final DexMethod target;
final KeepReason reason;
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;
private final Queue<Action> queue = new ArrayDeque<>();
private EnqueuerWorklist(AppView<?> appView) {
this.appView = appView;
}
public static EnqueuerWorklist createWorklist(AppView<?> appView) {
return new EnqueuerWorklist(appView);
}
public boolean isEmpty() {
return queue.isEmpty();
}
public Action poll() {
return queue.poll();
}
void enqueueMarkReachableDirectAction(DexMethod method, KeepReason reason) {
queue.add(new MarkReachableDirectAction(method, reason));
}
void enqueueMarkReachableVirtualAction(DexMethod method, KeepReason reason) {
queue.add(new MarkReachableVirtualAction(method, reason));
}
void enqueueMarkReachableInterfaceAction(DexMethod method, KeepReason reason) {
queue.add(new MarkReachableInterfaceAction(method, reason));
}
void enqueueMarkReachableSuperAction(DexMethod method, DexEncodedMethod from) {
queue.add(new MarkReachableSuperAction(method, from));
}
public void enqueueMarkReachableFieldAction(
DexProgramClass clazz, DexEncodedField field, KeepReason reason) {
assert field.field.holder == clazz.type;
queue.add(new MarkReachableFieldAction(field, reason));
}
void enqueueMarkInstantiatedAction(DexProgramClass clazz, KeepReason reason) {
assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
queue.add(new MarkInstantiatedAction(clazz, reason));
}
void enqueueMarkMethodLiveAction(
DexProgramClass clazz, DexEncodedMethod method, KeepReason reason) {
assert method.method.holder == clazz.type;
queue.add(new MarkMethodLiveAction(method, reason));
}
void enqueueMarkMethodKeptAction(DexEncodedMethod method, KeepReason reason) {
assert method.isProgramMethod(appView);
queue.add(new MarkMethodKeptAction(method, reason));
}
void enqueueMarkFieldKeptAction(DexEncodedField field, KeepReason reason) {
assert field.isProgramField(appView);
queue.add(new MarkFieldKeptAction(field, reason));
}
}