blob: dee0f55829bd4380d1acb89cc45c5a051fc60f06 [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.dex;
import com.android.tools.r8.dex.FileWriter.MixedSectionOffsets;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationDirectory;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexEncodedArray;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexWritableCode;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.utils.collections.ProgramMethodMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
public class DefaultMixedSectionLayoutStrategy extends MixedSectionLayoutStrategy {
final AppView<?> appView;
final MixedSectionOffsets mixedSectionOffsets;
public DefaultMixedSectionLayoutStrategy(
AppView<?> appView, MixedSectionOffsets mixedSectionOffsets) {
this.appView = appView;
this.mixedSectionOffsets = mixedSectionOffsets;
}
@Override
public Collection<DexAnnotation> getAnnotationLayout() {
return mixedSectionOffsets.getAnnotations();
}
@Override
public Collection<DexAnnotationDirectory> getAnnotationDirectoryLayout() {
return mixedSectionOffsets.getAnnotationDirectories();
}
@Override
public Collection<DexAnnotationSet> getAnnotationSetLayout() {
return mixedSectionOffsets.getAnnotationSets();
}
@Override
public Collection<ParameterAnnotationsList> getAnnotationSetRefListLayout() {
return mixedSectionOffsets.getAnnotationSetRefLists();
}
@Override
public Collection<DexProgramClass> getClassDataLayout() {
return mixedSectionOffsets.getClassesWithData();
}
@Override
public Collection<ProgramMethod> getCodeLayout() {
return getCodeLayoutForClasses(mixedSectionOffsets.getClassesWithData());
}
final Collection<ProgramMethod> getCodeLayoutForClasses(Collection<DexProgramClass> classes) {
ProgramMethodMap<String> codeToSignatureMap = ProgramMethodMap.create();
List<ProgramMethod> codesSorted = new ArrayList<>();
for (DexProgramClass clazz : classes) {
clazz.forEachProgramMethodMatching(
DexEncodedMethod::hasCode,
method -> {
DexWritableCode code = method.getDefinition().getDexWritableCodeOrNull();
assert code != null || method.getDefinition().shouldNotHaveCode();
if (code != null) {
codesSorted.add(method);
codeToSignatureMap.put(
method, getKeyForDexCodeSorting(method, appView.app().getProguardMap()));
}
});
}
codesSorted.sort(Comparator.comparing(codeToSignatureMap::get));
return codesSorted;
}
private static String getKeyForDexCodeSorting(ProgramMethod method, ClassNameMapper proguardMap) {
// TODO(b/173999869): Could this instead compute sorting using dex items?
Signature signature;
String originalClassName;
if (proguardMap != null) {
signature = proguardMap.originalSignatureOf(method.getReference());
originalClassName = proguardMap.originalNameOf(method.getHolderType());
} else {
signature = MethodSignature.fromDexMethod(method.getReference());
originalClassName = method.getHolderType().toSourceString();
}
return originalClassName + signature;
}
@Override
public Collection<DexEncodedArray> getEncodedArrayLayout() {
return mixedSectionOffsets.getEncodedArrays();
}
@Override
public Collection<DexString> getStringDataLayout() {
return mixedSectionOffsets.getStringData();
}
@Override
public Collection<DexTypeList> getTypeListLayout() {
return mixedSectionOffsets.getTypeLists();
}
}