| // 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.utils; | |
| import com.android.tools.r8.CompatProguardCommandBuilder; | |
| import java.io.IOException; | |
| import java.lang.reflect.Method; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.util.ArrayList; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.function.Consumer; | |
| import java.util.function.Function; | |
| public class CompileDumpBase { | |
| static void setEnableExperimentalMissingLibraryApiModeling( | |
| Object builder, boolean enableMissingLibraryApiModeling) { | |
| getReflectiveBuilderMethod( | |
| builder, "setEnableExperimentalMissingLibraryApiModeling", boolean.class) | |
| .accept(new Object[] {enableMissingLibraryApiModeling}); | |
| } | |
| static void setAndroidPlatformBuild(Object builder, boolean androidPlatformBuild) { | |
| getReflectiveBuilderMethod(builder, "setAndroidPlatformBuild", boolean.class) | |
| .accept(new Object[] {androidPlatformBuild}); | |
| } | |
| static void addArtProfilesForRewriting(Object builder, Map<Path, Path> artProfileFiles) { | |
| try { | |
| Class<?> artProfileProviderClass = | |
| Class.forName("com.android.tools.r8.profile.art.ArtProfileProvider"); | |
| Class<?> artProfileConsumerClass = | |
| Class.forName("com.android.tools.r8.profile.art.ArtProfileConsumer"); | |
| artProfileFiles.forEach( | |
| (artProfile, residualArtProfile) -> | |
| getReflectiveBuilderMethod( | |
| builder, | |
| "addArtProfileForRewriting", | |
| artProfileProviderClass, | |
| artProfileConsumerClass) | |
| .accept( | |
| new Object[] { | |
| createArtProfileProvider(artProfile), | |
| createResidualArtProfileConsumer(residualArtProfile) | |
| })); | |
| } catch (ClassNotFoundException e) { | |
| // Ignore. | |
| } | |
| } | |
| static void addStartupProfileProviders(Object builder, List<Path> startupProfileFiles) { | |
| getReflectiveBuilderMethod(builder, "addStartupProfileProviders", Collection.class) | |
| .accept(new Object[] {createStartupProfileProviders(startupProfileFiles)}); | |
| } | |
| static Object createArtProfileProvider(Path artProfile) { | |
| Object[] artProfileProvider = new Object[1]; | |
| boolean found = | |
| callReflectiveUtilsMethod( | |
| "createArtProfileProviderFromDumpFile", | |
| new Class<?>[] {Path.class}, | |
| fn -> artProfileProvider[0] = fn.apply(new Object[] {artProfile})); | |
| if (!found) { | |
| System.out.println( | |
| "Unable to add art profiles as input. " | |
| + "Method createArtProfileProviderFromDumpFile() was not found."); | |
| return null; | |
| } | |
| System.out.println(artProfileProvider[0]); | |
| return artProfileProvider[0]; | |
| } | |
| static Object createResidualArtProfileConsumer(Path residualArtProfile) { | |
| Object[] residualArtProfileConsumer = new Object[1]; | |
| boolean found = | |
| callReflectiveUtilsMethod( | |
| "createResidualArtProfileConsumerFromDumpFile", | |
| new Class<?>[] {Path.class}, | |
| fn -> residualArtProfileConsumer[0] = fn.apply(new Object[] {residualArtProfile})); | |
| if (!found) { | |
| System.out.println( | |
| "Unable to add art profiles as input. " | |
| + "Method createResidualArtProfileConsumerFromDumpFile() was not found."); | |
| return null; | |
| } | |
| System.out.println(residualArtProfileConsumer[0]); | |
| return residualArtProfileConsumer[0]; | |
| } | |
| static Collection<Object> createStartupProfileProviders(List<Path> startupProfileFiles) { | |
| List<Object> startupProfileProviders = new ArrayList<>(); | |
| for (Path startupProfileFile : startupProfileFiles) { | |
| boolean found = | |
| callReflectiveUtilsMethod( | |
| "createStartupProfileProviderFromDumpFile", | |
| new Class<?>[] {Path.class}, | |
| fn -> startupProfileProviders.add(fn.apply(new Object[] {startupProfileFile}))); | |
| if (!found) { | |
| System.out.println( | |
| "Unable to add startup profiles as input. " | |
| + "Method createStartupProfileProviderFromDumpFile() was not found."); | |
| break; | |
| } | |
| } | |
| return startupProfileProviders; | |
| } | |
| static Consumer<Object[]> getReflectiveBuilderMethod( | |
| Object builder, String setter, Class<?>... parameters) { | |
| try { | |
| Method declaredMethod = CompatProguardCommandBuilder.class.getMethod(setter, parameters); | |
| return args -> { | |
| try { | |
| declaredMethod.invoke(builder, args); | |
| } catch (Exception e) { | |
| throw new RuntimeException(e); | |
| } | |
| }; | |
| } catch (NoSuchMethodException e) { | |
| System.out.println(setter + " is not available on the compiledump version."); | |
| // The option is not available so we just return an empty consumer | |
| return args -> {}; | |
| } | |
| } | |
| static boolean callReflectiveUtilsMethod( | |
| String methodName, Class<?>[] parameters, Consumer<Function<Object[], Object>> fnConsumer) { | |
| Class<?> utilsClass; | |
| try { | |
| utilsClass = Class.forName("com.android.tools.r8.utils.CompileDumpUtils"); | |
| } catch (ClassNotFoundException e) { | |
| return false; | |
| } | |
| Method declaredMethod; | |
| try { | |
| declaredMethod = utilsClass.getDeclaredMethod(methodName, parameters); | |
| } catch (NoSuchMethodException e) { | |
| return false; | |
| } | |
| fnConsumer.accept( | |
| args -> { | |
| try { | |
| return declaredMethod.invoke(null, args); | |
| } catch (Exception e) { | |
| throw new RuntimeException(e); | |
| } | |
| }); | |
| return true; | |
| } | |
| // We cannot use StringResource since this class is added to the class path and has access only | |
| // to the public APIs. | |
| static String readAllBytesJava7(Path filePath) { | |
| String content = ""; | |
| try { | |
| content = new String(Files.readAllBytes(filePath)); | |
| } catch (IOException e) { | |
| e.printStackTrace(); | |
| } | |
| return content; | |
| } | |
| } |