blob: b81161f0b2d43025b44fa3d7edd325c345116248 [file] [log] [blame]
// Copyright (c) 2023, 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.ir.optimize.numberunboxer;
import static com.android.tools.r8.ir.conversion.ExtraUnusedParameter.computeExtraUnusedParameters;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.lens.NestedGraphLensWithCustomLensCodeRewriter;
import com.android.tools.r8.graph.proto.ArgumentInfoCollection;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.graph.proto.RewrittenTypeInfo;
import com.android.tools.r8.ir.conversion.ExtraUnusedParameter;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
import com.android.tools.r8.utils.collections.BidirectionalOneToOneHashMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalOneToOneMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
public class NumberUnboxerLens extends NestedGraphLensWithCustomLensCodeRewriter {
private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod;
NumberUnboxerLens(
AppView<AppInfoWithLiveness> appView,
BidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod> renamedSignatures,
Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod,
NumberUnboxerRewriter numberUnboxerRewriter) {
super(appView, EMPTY_FIELD_MAP, renamedSignatures, EMPTY_TYPE_MAP, numberUnboxerRewriter);
this.prototypeChangesPerMethod = prototypeChangesPerMethod;
}
@Override
protected RewrittenPrototypeDescription internalDescribePrototypeChanges(
RewrittenPrototypeDescription previousPrototypeChanges,
DexMethod previousMethod,
DexMethod newMethod) {
RewrittenPrototypeDescription prototypeChanges =
prototypeChangesPerMethod.getOrDefault(newMethod, RewrittenPrototypeDescription.none());
return previousPrototypeChanges.combine(prototypeChanges);
}
@Override
public boolean isNumberUnboxerLens() {
return true;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private final Map<DexMethod, RewrittenPrototypeDescription> prototypeChangesPerMethod =
new IdentityHashMap<>();
private final MutableBidirectionalOneToOneMap<DexMethod, DexMethod> newMethodSignatures =
new BidirectionalOneToOneHashMap<>();
public RewrittenPrototypeDescription move(DexEncodedMethod fromEncoded, DexMethod to) {
DexMethod from = fromEncoded.getReference();
assert !from.isIdenticalTo(to);
List<ExtraUnusedParameter> extraUnusedParameters = computeExtraUnusedParameters(from, to);
RewrittenPrototypeDescription prototypeChanges =
computePrototypeChanges(from, to, fromEncoded.isStatic(), extraUnusedParameters);
synchronized (this) {
newMethodSignatures.put(from, to);
prototypeChangesPerMethod.put(to, prototypeChanges);
}
return prototypeChanges;
}
private RewrittenPrototypeDescription computePrototypeChanges(
DexMethod from,
DexMethod to,
boolean staticMethod,
List<ExtraUnusedParameter> extraUnusedParameters) {
assert from.getArity() + extraUnusedParameters.size() == to.getArity();
ArgumentInfoCollection.Builder builder =
ArgumentInfoCollection.builder()
.setArgumentInfosSize(from.getNumberOfArguments(staticMethod));
int shift = BooleanUtils.intValue(!staticMethod);
for (int i = 0; i < from.getParameters().size(); i++) {
DexType fromType = from.getParameter(i);
DexType toType = to.getParameter(i);
if (!fromType.isIdenticalTo(toType)) {
builder.addArgumentInfo(
shift + i,
RewrittenTypeInfo.builder().setOldType(fromType).setNewType(toType).build());
}
}
RewrittenTypeInfo returnInfo =
from.getReturnType().isIdenticalTo(to.getReturnType())
? null
: RewrittenTypeInfo.builder()
.setOldType(from.getReturnType())
.setNewType(to.getReturnType())
.build();
return RewrittenPrototypeDescription.create(
extraUnusedParameters, returnInfo, builder.build());
}
public NumberUnboxerLens build(
AppView<AppInfoWithLiveness> appView, NumberUnboxerRewriter numberUnboxerRewriter) {
return new NumberUnboxerLens(
appView, newMethodSignatures, prototypeChangesPerMethod, numberUnboxerRewriter);
}
}
}