1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file 2 // for details. All rights reserved. Use of this source code is governed by a 3 // BSD-style license that can be found in the LICENSE file. 4 package com.android.tools.r8.graph; 5 6 import com.android.tools.r8.errors.InternalCompilerError; 7 import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType; 8 import com.android.tools.r8.utils.InternalOptions; 9 import java.util.List; 10 import org.objectweb.asm.Type; 11 12 /** 13 * Common structures used while reading in a Java application from jar files. 14 * 15 * The primary use of this class is to canonicalize dex items during read. 16 * The addition of classes to the builder also takes place through this class. 17 * It does not currently support multithreaded reading. 18 */ 19 public class JarApplicationReader { 20 public final InternalOptions options; 21 JarApplicationReader(InternalOptions options)22 public JarApplicationReader(InternalOptions options) { 23 this.options = options; 24 } 25 getFactory()26 public DexItemFactory getFactory() { 27 return options.itemFactory; 28 } 29 getString(String string)30 public DexString getString(String string) { 31 return options.itemFactory.createString(string); 32 } 33 getType(Type type)34 public DexType getType(Type type) { 35 return getTypeFromDescriptor(type.getDescriptor()); 36 } 37 getTypeFromName(String name)38 public DexType getTypeFromName(String name) { 39 assert isValidInternalName(name); 40 return getType(Type.getObjectType(name)); 41 } 42 getTypeFromDescriptor(String desc)43 public DexType getTypeFromDescriptor(String desc) { 44 assert isValidDescriptor(desc); 45 return options.itemFactory.createType(getString(desc)); 46 } 47 getTypeListFromNames(String[] names)48 public DexTypeList getTypeListFromNames(String[] names) { 49 if (names.length == 0) { 50 return DexTypeList.empty(); 51 } 52 DexType[] types = new DexType[names.length]; 53 for (int i = 0; i < names.length; i++) { 54 types[i] = getTypeFromName(names[i]); 55 } 56 return new DexTypeList(types); 57 } 58 getTypeListFromDescriptors(String[] descriptors)59 public DexTypeList getTypeListFromDescriptors(String[] descriptors) { 60 if (descriptors.length == 0) { 61 return DexTypeList.empty(); 62 } 63 DexType[] types = new DexType[descriptors.length]; 64 for (int i = 0; i < descriptors.length; i++) { 65 types[i] = getTypeFromDescriptor(descriptors[i]); 66 } 67 return new DexTypeList(types); 68 } 69 getField(String owner, String name, String desc)70 public DexField getField(String owner, String name, String desc) { 71 return getField(getTypeFromName(owner), name, desc); 72 } 73 getField(DexType owner, String name, String desc)74 public DexField getField(DexType owner, String name, String desc) { 75 return options.itemFactory.createField(owner, getTypeFromDescriptor(desc), getString(name)); 76 } 77 getMethod(String owner, String name, String desc)78 public DexMethod getMethod(String owner, String name, String desc) { 79 return getMethod(getTypeFromName(owner), name, desc); 80 } 81 getMethod(DexType owner, String name, String desc)82 public DexMethod getMethod(DexType owner, String name, String desc) { 83 return options.itemFactory.createMethod(owner, getProto(desc), getString(name)); 84 } 85 getCallSite(String methodName, String methodProto, DexMethodHandle bootstrapMethod, List<DexValue> bootstrapArgs)86 public DexCallSite getCallSite(String methodName, String methodProto, 87 DexMethodHandle bootstrapMethod, List<DexValue> bootstrapArgs) { 88 return options.itemFactory.createCallSite( 89 getString(methodName), getProto(methodProto), bootstrapMethod, bootstrapArgs); 90 } 91 getMethodHandle( MethodHandleType type, Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod)92 public DexMethodHandle getMethodHandle( 93 MethodHandleType type, Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod) { 94 return options.itemFactory.createMethodHandle(type, fieldOrMethod); 95 } 96 getProto(String desc)97 public DexProto getProto(String desc) { 98 assert isValidDescriptor(desc); 99 Type returnType = Type.getReturnType(desc); 100 Type[] arguments = Type.getArgumentTypes(desc); 101 102 StringBuilder shortyDescriptor = new StringBuilder(); 103 String[] argumentDescriptors = new String[arguments.length]; 104 shortyDescriptor.append(getShortyDescriptor(returnType)); 105 for (int i = 0; i < arguments.length; i++) { 106 shortyDescriptor.append(getShortyDescriptor(arguments[i])); 107 argumentDescriptors[i] = arguments[i].getDescriptor(); 108 } 109 DexProto proto = options.itemFactory.createProto( 110 getString(shortyDescriptor.toString()), 111 getTypeFromDescriptor(returnType.getDescriptor()), 112 getTypeListFromDescriptors(argumentDescriptors)); 113 return proto; 114 } 115 getShortyDescriptor(Type type)116 private static String getShortyDescriptor(Type type) { 117 switch (type.getSort()) { 118 case Type.METHOD: 119 throw new InternalCompilerError("Cannot produce a shorty decriptor for methods"); 120 case Type.ARRAY: 121 case Type.OBJECT: 122 return "L"; 123 default: 124 return type.getDescriptor(); 125 } 126 } 127 isValidDescriptor(String desc)128 private boolean isValidDescriptor(String desc) { 129 return Type.getType(desc).getDescriptor().equals(desc); 130 } 131 isValidInternalName(String name)132 private boolean isValidInternalName(String name) { 133 return Type.getObjectType(name).getInternalName().equals(name); 134 } 135 } 136