blob: 2568376c567ee7b474347354f7e52b268ff524d5 [file] [log] [blame]
// Copyright (c) 2022, 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.profile.art;
import static com.android.tools.r8.utils.SystemPropertyUtils.parseSystemPropertyOrDefault;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
public class ArtProfileOptions {
public static final String COMPLETENESS_PROPERTY_KEY =
"com.android.tools.r8.artprofilerewritingcompletenesscheck";
private Collection<ArtProfileForRewriting> artProfilesForRewriting = Collections.emptyList();
private boolean enableCompletenessCheckForTesting =
parseSystemPropertyOrDefault(COMPLETENESS_PROPERTY_KEY, false);
private boolean enableNopCheckForTesting;
private boolean hasReadArtProfileProviders = false;
private boolean allowReadingEmptyArtProfileProvidersMultipleTimesForTesting = false;
private final InternalOptions options;
private String nopCheckForTestingHashCode;
public ArtProfileOptions(InternalOptions options) {
this.options = options;
}
public Collection<ArtProfileForRewriting> getArtProfilesForRewriting() {
return artProfilesForRewriting;
}
public Collection<ArtProfileProvider> getArtProfileProviders() {
assert !hasReadArtProfileProviders
|| (allowReadingEmptyArtProfileProvidersMultipleTimesForTesting
&& artProfilesForRewriting.isEmpty());
hasReadArtProfileProviders = true;
return ListUtils.map(artProfilesForRewriting, ArtProfileForRewriting::getArtProfileProvider);
}
public InternalOptions getOptions() {
return options;
}
public boolean isCompletenessCheckForTestingEnabled() {
return enableCompletenessCheckForTesting
&& !options.isDesugaredLibraryCompilation()
&& !options.getStartupOptions().isStartupCompletenessCheckForTestingEnabled()
&& !options.getInstrumentationOptions().isInstrumentationEnabled();
}
public boolean isNopCheckForTestingEnabled() {
return enableNopCheckForTesting;
}
public boolean isIncludingApiReferenceStubs() {
// We only include API reference stubs in the residual ART profiles for completeness testing.
// This is because the API reference stubs should never be used at runtime except for
// verification, meaning there should be no need to AOT them.
return enableCompletenessCheckForTesting;
}
public boolean isIncludingBackportedClasses() {
// Similar to isIncludingVarHandleClasses().
return enableCompletenessCheckForTesting;
}
public boolean isIncludingConstantDynamicClass() {
// Similar to isIncludingVarHandleClasses().
return enableCompletenessCheckForTesting;
}
public boolean isIncludingDesugaredLibraryRetargeterForwardingMethodsUnconditionally() {
// TODO(b/265729283): If we get as input the profile for the desugared library, maybe we can
// tell if the method targeted by the forwarding method is in the profile, e.g.:
// java.time.Instant java.util.DesugarDate.toInstant(java.util.Date).
return enableCompletenessCheckForTesting;
}
public boolean isIncludingThrowingMethods() {
// The throw methods we insert should generally be dead a runtime, so no need for them to be
// optimized.
return enableCompletenessCheckForTesting;
}
public boolean isIncludingVarHandleClasses() {
// We only include var handle classes in the residual ART profiles for completeness testing,
// since the classes synthesized by var handle desugaring are fairly large and may not be that
// important for runtime performance.
return enableCompletenessCheckForTesting;
}
public ArtProfileOptions setAllowReadingEmptyArtProfileProvidersMultipleTimesForTesting(
boolean allowReadingEmptyArtProfileProvidersMultipleTimesForTesting) {
this.allowReadingEmptyArtProfileProvidersMultipleTimesForTesting =
allowReadingEmptyArtProfileProvidersMultipleTimesForTesting;
return this;
}
public ArtProfileOptions setArtProfilesForRewriting(Collection<ArtProfileForRewriting> inputs) {
this.artProfilesForRewriting = inputs;
return this;
}
public ArtProfileOptions setEnableCompletenessCheckForTesting(
boolean enableCompletenessCheckForTesting) {
this.enableCompletenessCheckForTesting = enableCompletenessCheckForTesting;
return this;
}
public ArtProfileOptions setEnableNopCheckForTesting() {
this.enableNopCheckForTesting = true;
return this;
}
public boolean setNopCheckForTestingHashCode(AppInfo appInfo) {
if (nopCheckForTestingHashCode != null) {
String hashCode = computeNopCheckForTestingHashCode(appInfo);
assert hashCode.equals(nopCheckForTestingHashCode);
} else {
nopCheckForTestingHashCode = computeNopCheckForTestingHashCode(appInfo);
}
return true;
}
private static String computeNopCheckForTestingHashCode(AppInfo appInfo) {
Hasher hasher = Hashing.sha256().newHasher();
for (DexProgramClass clazz : appInfo.classesWithDeterministicOrder()) {
hasher.putString(clazz.getType().toDescriptorString(), StandardCharsets.UTF_8);
for (DexEncodedMethod method : clazz.methods()) {
hasher.putString(method.getReference().toSmaliString(), StandardCharsets.UTF_8);
}
}
return hasher.hash().toString();
}
public boolean verifyHasNopCheckForTestingHashCode() {
assert nopCheckForTestingHashCode != null;
return true;
}
}