blob: 60694aefdd2e0c6686f010fc616af4eeae46c3f6 [file] [log] [blame]
// Copyright (c) 2024, 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.verticalclassmerging;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.ClasspathMethod;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.RetracerForCodePrinting;
/**
* A short-lived piece of code that will be converted into {@link CfCode} using the method {@link
* IncompleteVerticalClassMergerBridgeCode#toCfCode(DexItemFactory, VerticalClassMergerGraphLens)}.
*/
public class IncompleteVerticalClassMergerBridgeCode extends Code {
private DexMethod method;
private DexMethod invocationTarget;
private final InvokeType type;
private final boolean isInterface;
public IncompleteVerticalClassMergerBridgeCode(
DexMethod method, InvokeType type, boolean isInterface) {
this.method = method;
this.invocationTarget = null;
this.type = type;
this.isInterface = isInterface;
}
@Override
public Code getCodeAsInlining(
DexMethod caller,
boolean isCallerD8R8Synthesized,
DexMethod callee,
boolean isCalleeD8R8Synthesized,
DexItemFactory factory) {
// This code object is synthesized so "inlining" just "strips" the callee position.
assert isCalleeD8R8Synthesized;
return this;
}
public DexMethod getMethod() {
return method;
}
public DexMethod getTarget() {
return invocationTarget;
}
// By the time the synthesized code object is created, vertical class merging still has not
// finished. Therefore it is possible that the method signatures `method` and `invocationTarget`
// will change as a result of additional class merging operations. To deal with this, the
// vertical class merger explicitly invokes this method to update `method` and `invocation-
// Target` when vertical class merging has finished.
//
// Note that, without this step, these method signatures might refer to intermediate signatures
// that are only present in the middle of vertical class merging, which means that the graph
// lens will not work properly (since the graph lens generated by vertical class merging only
// expects to be applied to method signatures from *before* vertical class merging or *after*
// vertical class merging).
public void updateMethodSignatures(VerticalClassMergerGraphLens lens) {
invocationTarget = lens.getNextImplementationMethodSignature(method);
method = lens.getNextBridgeMethodSignature(method);
}
public CfCode toCfCode(DexItemFactory dexItemFactory, VerticalClassMergerGraphLens lens) {
return ForwardMethodBuilder.builder(dexItemFactory)
.applyIf(
type.isStatic(),
builder -> builder.setStaticTarget(invocationTarget, isInterface),
builder -> builder.setVirtualTarget(invocationTarget, isInterface))
.setNonStaticSource(method)
.setCodeLens(lens)
.build();
}
// Implement Code.
@Override
public IRCode buildIR(
ProgramMethod method,
AppView<?> appView,
Origin origin,
MutableMethodConversionOptions conversionOptions) {
throw new Unreachable();
}
@Override
protected boolean computeEquals(Object other) {
throw new Unreachable();
}
@Override
protected int computeHashCode() {
throw new Unreachable();
}
@Override
public int estimatedDexCodeSizeUpperBoundInBytes() {
throw new Unreachable();
}
@Override
public boolean isEmptyVoidMethod() {
throw new Unreachable();
}
@Override
public void registerCodeReferences(ProgramMethod method, UseRegistry registry) {
throw new Unreachable();
}
@Override
public void registerCodeReferencesForDesugaring(ClasspathMethod method, UseRegistry registry) {
throw new Unreachable();
}
@Override
public String toString() {
return "IncompleteVerticalClassMergerBridgeCode";
}
@Override
public String toString(DexEncodedMethod method, RetracerForCodePrinting retracer) {
return toString();
}
}