blob: 0173fb28efd2c712a9604dae3ace70aaf9e6146b [file] [log] [blame]
// Copyright (c) 2020, 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;
/** Immutable keep requirements for a method. */
public final class KeepMethodInfo extends KeepMemberInfo<KeepMethodInfo.Builder, KeepMethodInfo> {
// Requires all aspects of a method to be kept.
private static final KeepMethodInfo TOP = new Builder().makeTop().build();
// Requires no aspects of a method to be kept.
private static final KeepMethodInfo BOTTOM = new Builder().makeBottom().build();
public static KeepMethodInfo top() {
return TOP;
}
public static KeepMethodInfo bottom() {
return BOTTOM;
}
public static Joiner newEmptyJoiner() {
return bottom().joiner();
}
private final boolean allowClassInlining;
private final boolean allowClosedWorldReasoning;
private final boolean allowConstantArgumentOptimization;
private final boolean allowInlining;
private final boolean allowMethodStaticizing;
private final boolean allowParameterReordering;
private final boolean allowParameterTypeStrengthening;
private final boolean allowReturnTypeStrengthening;
private final boolean allowUnusedArgumentOptimization;
private final boolean allowUnusedReturnValueOptimization;
private KeepMethodInfo(Builder builder) {
super(builder);
this.allowClassInlining = builder.isClassInliningAllowed();
this.allowClosedWorldReasoning = builder.isClosedWorldReasoningAllowed();
this.allowConstantArgumentOptimization = builder.isConstantArgumentOptimizationAllowed();
this.allowInlining = builder.isInliningAllowed();
this.allowMethodStaticizing = builder.isMethodStaticizingAllowed();
this.allowParameterReordering = builder.isParameterReorderingAllowed();
this.allowParameterTypeStrengthening = builder.isParameterTypeStrengtheningAllowed();
this.allowReturnTypeStrengthening = builder.isReturnTypeStrengtheningAllowed();
this.allowUnusedArgumentOptimization = builder.isUnusedArgumentOptimizationAllowed();
this.allowUnusedReturnValueOptimization = builder.isUnusedReturnValueOptimizationAllowed();
}
// This builder is not private as there are known instances where it is safe to modify keep info
// in a non-upwards direction.
@Override
Builder builder() {
return new Builder(this);
}
public boolean isArgumentPropagationAllowed(GlobalKeepInfoConfiguration configuration) {
return isParameterRemovalAllowed(configuration);
}
public boolean isParameterRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
return isClosedWorldReasoningAllowed(configuration)
&& isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& !isCheckDiscardedEnabled(configuration);
}
public boolean isClassInliningAllowed(GlobalKeepInfoConfiguration configuration) {
return isOptimizationAllowed(configuration) && internalIsClassInliningAllowed();
}
boolean internalIsClassInliningAllowed() {
return allowClassInlining;
}
public boolean isClosedWorldReasoningAllowed(GlobalKeepInfoConfiguration configuration) {
return isOptimizationAllowed(configuration) && internalIsClosedWorldReasoningAllowed();
}
boolean internalIsClosedWorldReasoningAllowed() {
return allowClosedWorldReasoning;
}
public boolean isConstantArgumentOptimizationAllowed(GlobalKeepInfoConfiguration configuration) {
return isOptimizationAllowed(configuration) && internalIsConstantArgumentOptimizationAllowed();
}
boolean internalIsConstantArgumentOptimizationAllowed() {
return allowConstantArgumentOptimization;
}
public boolean isInliningAllowed(GlobalKeepInfoConfiguration configuration) {
return isOptimizationAllowed(configuration) && internalIsInliningAllowed();
}
boolean internalIsInliningAllowed() {
return allowInlining;
}
public boolean isMethodStaticizingAllowed(GlobalKeepInfoConfiguration configuration) {
return isClosedWorldReasoningAllowed(configuration)
&& isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& configuration.isMethodStaticizingEnabled()
&& internalIsMethodStaticizingAllowed();
}
boolean internalIsMethodStaticizingAllowed() {
return allowMethodStaticizing;
}
public boolean isParameterReorderingAllowed(GlobalKeepInfoConfiguration configuration) {
return isClosedWorldReasoningAllowed(configuration)
&& isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsParameterReorderingAllowed();
}
boolean internalIsParameterReorderingAllowed() {
return allowParameterReordering;
}
public boolean isParameterTypeStrengtheningAllowed(GlobalKeepInfoConfiguration configuration) {
return isClosedWorldReasoningAllowed(configuration)
&& isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsParameterTypeStrengtheningAllowed();
}
boolean internalIsParameterTypeStrengtheningAllowed() {
return allowParameterTypeStrengthening;
}
public boolean isReturnTypeStrengtheningAllowed(GlobalKeepInfoConfiguration configuration) {
return isClosedWorldReasoningAllowed(configuration)
&& isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsReturnTypeStrengtheningAllowed();
}
boolean internalIsReturnTypeStrengtheningAllowed() {
return allowReturnTypeStrengthening;
}
public boolean isUnusedArgumentOptimizationAllowed(GlobalKeepInfoConfiguration configuration) {
return isClosedWorldReasoningAllowed(configuration)
&& isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsUnusedArgumentOptimizationAllowed();
}
boolean internalIsUnusedArgumentOptimizationAllowed() {
return allowUnusedArgumentOptimization;
}
public boolean isUnusedReturnValueOptimizationAllowed(GlobalKeepInfoConfiguration configuration) {
return isClosedWorldReasoningAllowed(configuration)
&& isOptimizationAllowed(configuration)
&& isShrinkingAllowed(configuration)
&& internalIsUnusedReturnValueOptimizationAllowed();
}
boolean internalIsUnusedReturnValueOptimizationAllowed() {
return allowUnusedReturnValueOptimization;
}
public Joiner joiner() {
assert !isTop();
return new Joiner(this);
}
@Override
public boolean isTop() {
return this.equals(top());
}
@Override
public boolean isBottom() {
return this.equals(bottom());
}
public static class Builder extends KeepInfo.Builder<Builder, KeepMethodInfo> {
private boolean allowClassInlining;
private boolean allowClosedWorldReasoning;
private boolean allowConstantArgumentOptimization;
private boolean allowInlining;
private boolean allowMethodStaticizing;
private boolean allowParameterReordering;
private boolean allowParameterTypeStrengthening;
private boolean allowReturnTypeStrengthening;
private boolean allowUnusedArgumentOptimization;
private boolean allowUnusedReturnValueOptimization;
private Builder() {
super();
}
private Builder(KeepMethodInfo original) {
super(original);
allowClassInlining = original.internalIsClassInliningAllowed();
allowClosedWorldReasoning = original.internalIsClosedWorldReasoningAllowed();
allowConstantArgumentOptimization = original.internalIsConstantArgumentOptimizationAllowed();
allowInlining = original.internalIsInliningAllowed();
allowMethodStaticizing = original.internalIsMethodStaticizingAllowed();
allowParameterReordering = original.internalIsParameterReorderingAllowed();
allowParameterTypeStrengthening = original.internalIsParameterTypeStrengtheningAllowed();
allowReturnTypeStrengthening = original.internalIsReturnTypeStrengtheningAllowed();
allowUnusedArgumentOptimization = original.internalIsUnusedArgumentOptimizationAllowed();
allowUnusedReturnValueOptimization =
original.internalIsUnusedReturnValueOptimizationAllowed();
}
// Class inlining.
public boolean isClassInliningAllowed() {
return allowClassInlining;
}
public Builder setAllowClassInlining(boolean allowClassInlining) {
this.allowClassInlining = allowClassInlining;
return self();
}
public Builder allowClassInlining() {
return setAllowClassInlining(true);
}
public Builder disallowClassInlining() {
return setAllowClassInlining(false);
}
// Closed world reasoning.
public boolean isClosedWorldReasoningAllowed() {
return allowClosedWorldReasoning;
}
public Builder setAllowClosedWorldReasoning(boolean allowClosedWorldReasoning) {
this.allowClosedWorldReasoning = allowClosedWorldReasoning;
return self();
}
public Builder allowClosedWorldReasoning() {
return setAllowClosedWorldReasoning(true);
}
public Builder disallowClosedWorldReasoning() {
return setAllowClosedWorldReasoning(false);
}
// Constant argument optimization.
public boolean isConstantArgumentOptimizationAllowed() {
return allowConstantArgumentOptimization;
}
public Builder setAllowConstantArgumentOptimization(boolean allowConstantArgumentOptimization) {
this.allowConstantArgumentOptimization = allowConstantArgumentOptimization;
return self();
}
public Builder allowConstantArgumentOptimization() {
return setAllowConstantArgumentOptimization(true);
}
public Builder disallowConstantArgumentOptimization() {
return setAllowConstantArgumentOptimization(false);
}
// Inlining.
public boolean isInliningAllowed() {
return allowInlining;
}
public Builder setAllowInlining(boolean allowInlining) {
this.allowInlining = allowInlining;
return self();
}
public Builder allowInlining() {
return setAllowInlining(true);
}
public Builder disallowInlining() {
return setAllowInlining(false);
}
// Method staticizing.
public boolean isMethodStaticizingAllowed() {
return allowMethodStaticizing;
}
public Builder setAllowMethodStaticizing(boolean allowMethodStaticizing) {
this.allowMethodStaticizing = allowMethodStaticizing;
return self();
}
public Builder allowMethodStaticizing() {
return setAllowMethodStaticizing(true);
}
public Builder disallowMethodStaticizing() {
return setAllowMethodStaticizing(false);
}
// Parameter reordering.
public boolean isParameterReorderingAllowed() {
return allowParameterReordering;
}
public Builder setAllowParameterReordering(boolean allowParameterReordering) {
this.allowParameterReordering = allowParameterReordering;
return self();
}
public Builder allowParameterReordering() {
return setAllowParameterReordering(true);
}
public Builder disallowParameterReordering() {
return setAllowParameterReordering(false);
}
// Parameter type strengthening.
public boolean isParameterTypeStrengtheningAllowed() {
return allowParameterTypeStrengthening;
}
public Builder setAllowParameterTypeStrengthening(boolean allowParameterTypeStrengthening) {
this.allowParameterTypeStrengthening = allowParameterTypeStrengthening;
return self();
}
public Builder allowParameterTypeStrengthening() {
return setAllowParameterTypeStrengthening(true);
}
public Builder disallowParameterTypeStrengthening() {
return setAllowParameterTypeStrengthening(false);
}
// Return type strengthening.
public boolean isReturnTypeStrengtheningAllowed() {
return allowReturnTypeStrengthening;
}
public Builder setAllowReturnTypeStrengthening(boolean allowReturnTypeStrengthening) {
this.allowReturnTypeStrengthening = allowReturnTypeStrengthening;
return self();
}
public Builder allowReturnTypeStrengthening() {
return setAllowReturnTypeStrengthening(true);
}
public Builder disallowReturnTypeStrengthening() {
return setAllowReturnTypeStrengthening(false);
}
// Unused argument optimization.
public boolean isUnusedArgumentOptimizationAllowed() {
return allowUnusedArgumentOptimization;
}
public Builder setAllowUnusedArgumentOptimization(boolean allowUnusedArgumentOptimization) {
this.allowUnusedArgumentOptimization = allowUnusedArgumentOptimization;
return self();
}
public Builder allowUnusedArgumentOptimization() {
return setAllowUnusedArgumentOptimization(true);
}
public Builder disallowUnusedArgumentOptimization() {
return setAllowUnusedArgumentOptimization(false);
}
// Unused return value optimization.
public boolean isUnusedReturnValueOptimizationAllowed() {
return allowUnusedReturnValueOptimization;
}
public Builder setAllowUnusedReturnValueOptimization(
boolean allowUnusedReturnValueOptimization) {
this.allowUnusedReturnValueOptimization = allowUnusedReturnValueOptimization;
return self();
}
public Builder allowUnusedReturnValueOptimization() {
return setAllowUnusedReturnValueOptimization(true);
}
public Builder disallowUnusedReturnValueOptimization() {
return setAllowUnusedReturnValueOptimization(false);
}
@Override
public Builder self() {
return this;
}
@Override
public KeepMethodInfo getTopInfo() {
return TOP;
}
@Override
public KeepMethodInfo getBottomInfo() {
return BOTTOM;
}
@Override
public boolean isEqualTo(KeepMethodInfo other) {
return internalIsEqualTo(other);
}
@Override
boolean internalIsEqualTo(KeepMethodInfo other) {
return super.internalIsEqualTo(other)
&& isClassInliningAllowed() == other.internalIsClassInliningAllowed()
&& isClosedWorldReasoningAllowed() == other.internalIsClosedWorldReasoningAllowed()
&& isConstantArgumentOptimizationAllowed()
== other.internalIsConstantArgumentOptimizationAllowed()
&& isInliningAllowed() == other.internalIsInliningAllowed()
&& isMethodStaticizingAllowed() == other.internalIsMethodStaticizingAllowed()
&& isParameterReorderingAllowed() == other.internalIsParameterReorderingAllowed()
&& isParameterTypeStrengtheningAllowed()
== other.internalIsParameterTypeStrengtheningAllowed()
&& isReturnTypeStrengtheningAllowed() == other.internalIsReturnTypeStrengtheningAllowed()
&& isUnusedArgumentOptimizationAllowed()
== other.internalIsUnusedArgumentOptimizationAllowed()
&& isUnusedReturnValueOptimizationAllowed()
== other.internalIsUnusedReturnValueOptimizationAllowed();
}
@Override
public KeepMethodInfo doBuild() {
return new KeepMethodInfo(this);
}
@Override
public Builder makeTop() {
return super.makeTop()
.disallowClassInlining()
.disallowClosedWorldReasoning()
.disallowConstantArgumentOptimization()
.disallowInlining()
.disallowMethodStaticizing()
.disallowParameterReordering()
.disallowParameterTypeStrengthening()
.disallowReturnTypeStrengthening()
.disallowUnusedArgumentOptimization()
.disallowUnusedReturnValueOptimization();
}
@Override
public Builder makeBottom() {
return super.makeBottom()
.allowClassInlining()
.allowClosedWorldReasoning()
.allowConstantArgumentOptimization()
.allowInlining()
.allowMethodStaticizing()
.allowParameterReordering()
.allowParameterTypeStrengthening()
.allowReturnTypeStrengthening()
.allowUnusedArgumentOptimization()
.allowUnusedReturnValueOptimization();
}
}
public static class Joiner extends KeepInfo.Joiner<Joiner, Builder, KeepMethodInfo> {
public Joiner(KeepMethodInfo info) {
super(info.builder());
}
public Joiner disallowClassInlining() {
builder.disallowClassInlining();
return self();
}
public Joiner disallowClosedWorldReasoning() {
builder.disallowClosedWorldReasoning();
return self();
}
public Joiner disallowConstantArgumentOptimization() {
builder.disallowConstantArgumentOptimization();
return self();
}
public Joiner disallowInlining() {
builder.disallowInlining();
return self();
}
public Joiner disallowMethodStaticizing() {
builder.disallowMethodStaticizing();
return self();
}
public Joiner disallowParameterReordering() {
builder.disallowParameterReordering();
return self();
}
public Joiner disallowParameterTypeStrengthening() {
builder.disallowParameterTypeStrengthening();
return self();
}
public Joiner disallowReturnTypeStrengthening() {
builder.disallowReturnTypeStrengthening();
return self();
}
public Joiner disallowUnusedArgumentOptimization() {
builder.disallowUnusedArgumentOptimization();
return self();
}
public Joiner disallowUnusedReturnValueOptimization() {
builder.disallowUnusedReturnValueOptimization();
return self();
}
@Override
public Joiner asMethodJoiner() {
return this;
}
@Override
public Joiner merge(Joiner joiner) {
// Should be extended to merge the fields of this class in case any are added.
return super.merge(joiner)
.applyIf(!joiner.builder.isClassInliningAllowed(), Joiner::disallowClassInlining)
.applyIf(
!joiner.builder.isClosedWorldReasoningAllowed(), Joiner::disallowClosedWorldReasoning)
.applyIf(
!joiner.builder.isConstantArgumentOptimizationAllowed(),
Joiner::disallowConstantArgumentOptimization)
.applyIf(!joiner.builder.isInliningAllowed(), Joiner::disallowInlining)
.applyIf(!joiner.builder.isMethodStaticizingAllowed(), Joiner::disallowMethodStaticizing)
.applyIf(
!joiner.builder.isParameterReorderingAllowed(), Joiner::disallowParameterReordering)
.applyIf(
!joiner.builder.isParameterTypeStrengtheningAllowed(),
Joiner::disallowParameterTypeStrengthening)
.applyIf(
!joiner.builder.isReturnTypeStrengtheningAllowed(),
Joiner::disallowReturnTypeStrengthening)
.applyIf(
!joiner.builder.isUnusedArgumentOptimizationAllowed(),
Joiner::disallowUnusedArgumentOptimization)
.applyIf(
!joiner.builder.isUnusedReturnValueOptimizationAllowed(),
Joiner::disallowUnusedReturnValueOptimization);
}
@Override
Joiner self() {
return this;
}
}
}