• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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