blob: 00fb0d271ced7141f43882227bbadf9beff818a5 [file] [log] [blame]
// Copyright (c) 2025, 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.analysis.EnqueuerAnalysisCollection;
import com.android.tools.r8.graph.analysis.FinishedEnqueuerAnalysis;
import com.android.tools.r8.graph.analysis.FixpointEnqueuerAnalysis;
import com.android.tools.r8.threading.TaskCollection;
import com.android.tools.r8.threading.ThreadingModule;
import com.android.tools.r8.utils.timing.Timing;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
public class EnqueuerTaskCollection implements FixpointEnqueuerAnalysis, FinishedEnqueuerAnalysis {
private final Enqueuer enqueuer;
// A task collection that stores tasks that may enqueue worklist items. The enqueuer therefore
// needs to await this task collection upon each intermediate fixpoint.
private final TaskCollection<Void> enqueuerDependentTaskCollection;
// A task collection that stores tasks that the Enqueuer does not need to await until it is
// entirely done.
private final TaskCollection<Void> enqueuerIndependentTaskCollection;
EnqueuerTaskCollection(
Enqueuer enqueuer, ThreadingModule threadingModule, ExecutorService executorService) {
this.enqueuer = enqueuer;
this.enqueuerDependentTaskCollection = new TaskCollection<>(threadingModule, executorService);
this.enqueuerIndependentTaskCollection = new TaskCollection<>(threadingModule, executorService);
}
public void register(EnqueuerAnalysisCollection.Builder analysesBuilder) {
analysesBuilder.addFixpointAnalysis(this).addFinishedAnalysis(this);
}
public void submitEnqueuerDependentTask(Callable<Void> callable) {
enqueuerDependentTaskCollection.submitUnchecked(callable);
}
public void submitEnqueuerIndependentTask(Runnable runnable) {
enqueuerIndependentTaskCollection.submitUnchecked(
() -> {
// Conservatively acquire the app read lock. This ensures that the execution of Enqueuer
// independent tasks is mutually exclusive with desugaring.
enqueuer.withAppReadLock(runnable);
return null;
});
}
public void awaitEnqueuerIndependentTasks() throws ExecutionException {
enqueuerIndependentTaskCollection.await();
}
/** Returns true if all Enqueuer dependent tasks were removed due to their completion. */
public boolean removeCompletedEnqueuerDependentTasks() {
enqueuerDependentTaskCollection.removeCompletedFutures();
return enqueuerDependentTaskCollection.isEmpty();
}
@Override
public void notifyFixpoint(
Enqueuer enqueuer, EnqueuerWorklist worklist, ExecutorService executorService, Timing timing)
throws ExecutionException {
enqueuerDependentTaskCollection.await();
enqueuerIndependentTaskCollection.removeCompletedFutures();
}
@Override
public void done(Enqueuer enqueuer, ExecutorService executorService) {
assert enqueuerDependentTaskCollection.isEmpty();
assert enqueuerIndependentTaskCollection.isEmpty();
}
public boolean verifyNoEnqueuerDependentTasks() {
assert enqueuerDependentTaskCollection.isEmpty();
return true;
}
}