• 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.dex.Constants;
7 import com.google.common.collect.Sets;
8 import java.util.Arrays;
9 import java.util.Collections;
10 import java.util.Set;
11 
12 public class ObjectToOffsetMapping {
13 
14   private final int virtualFileId;
15 
16   private final DexProgramClass[] classes;
17   private final DexProto[] protos;
18   private final DexType[] types;
19   private final DexMethod[] methods;
20   private final DexField[] fields;
21   private final DexString[] strings;
22   private final DexCallSite[] callSites;
23   private final DexMethodHandle[] methodHandles;
24   private DexString firstJumboString;
25 
ObjectToOffsetMapping( int virtualFileId, DexApplication application, DexProgramClass[] classes, DexProto[] protos, DexType[] types, DexMethod[] methods, DexField[] fields, DexString[] strings, DexCallSite[] callSites, DexMethodHandle[] methodHandles)26   public ObjectToOffsetMapping(
27       int virtualFileId,
28       DexApplication application,
29       DexProgramClass[] classes,
30       DexProto[] protos,
31       DexType[] types,
32       DexMethod[] methods,
33       DexField[] fields,
34       DexString[] strings,
35       DexCallSite[] callSites,
36       DexMethodHandle[] methodHandles) {
37     assert application != null;
38     assert classes != null;
39     assert protos != null;
40     assert types != null;
41     assert methods != null;
42     assert fields != null;
43     assert strings != null;
44     assert callSites != null;
45     assert methodHandles != null;
46 
47     this.virtualFileId = virtualFileId;
48     this.classes = sortClasses(application, classes);
49     this.protos = protos;
50     this.types = types;
51     this.methods = methods;
52     this.fields = fields;
53     this.strings = strings;
54     this.callSites = callSites;
55     this.methodHandles = methodHandles;
56 
57     Arrays.sort(protos);
58     setIndexes(protos);
59 
60     Arrays.sort(types);
61     setIndexes(types);
62 
63     Arrays.sort(methods);
64     setIndexes(methods);
65 
66     Arrays.sort(fields);
67     setIndexes(fields);
68 
69     Arrays.sort(strings);
70     setIndexes(strings);
71 
72     // No need to sort CallSite, they will be written in data section in the callSites order,
73     // consequently offset of call site used into the call site section will be in ascending order.
74     setIndexes(callSites);
75 
76     // No need to sort method handle
77     setIndexes(methodHandles);
78   }
79 
sortClasses( DexApplication application, DexProgramClass[] classes)80   private static DexProgramClass[] sortClasses(
81       DexApplication application, DexProgramClass[] classes) {
82     Arrays.sort(classes, (o1, o2) -> o1.type.descriptor.slowCompareTo(o2.type.descriptor));
83     SortingProgramClassVisitor classVisitor = new SortingProgramClassVisitor(application, classes);
84     classVisitor.run(classes);
85     return classVisitor.getSortedClasses();
86   }
87 
setIndexes(IndexedDexItem[] items)88   private void setIndexes(IndexedDexItem[] items) {
89     int index = 0;
90     for (IndexedDexItem item : items) {
91       item.assignVirtualFileIndex(virtualFileId, index);
92       // For strings collect the first jumbo string (if any).
93       if (index > Constants.MAX_NON_JUMBO_INDEX) {
94         assert item instanceof DexString;
95         if (index == Constants.FIRST_JUMBO_INDEX) {
96           firstJumboString = (DexString) item;
97         }
98       }
99       index++;
100     }
101   }
102 
getMethods()103   public DexMethod[] getMethods() {
104     return methods;
105   }
106 
getClasses()107   public DexProgramClass[] getClasses() {
108     return classes;
109   }
110 
getTypes()111   public DexType[] getTypes() {
112     return types;
113   }
114 
getProtos()115   public DexProto[] getProtos() {
116     return protos;
117   }
118 
getFields()119   public DexField[] getFields() {
120     return fields;
121   }
122 
getStrings()123   public DexString[] getStrings() {
124     return strings;
125   }
126 
getCallSites()127   public DexCallSite[] getCallSites() {
128     return callSites;
129   }
130 
getMethodHandles()131   public DexMethodHandle[] getMethodHandles() {
132     return methodHandles;
133   }
134 
hasJumboStrings()135   public boolean hasJumboStrings() {
136     return firstJumboString != null;
137   }
138 
getFirstJumboString()139   public DexString getFirstJumboString() {
140     return firstJumboString;
141   }
142 
isContainedInMapping(IndexedDexItem item)143   private boolean isContainedInMapping(IndexedDexItem item) {
144     return item.getVirtualFileIndex(virtualFileId) != IndexedDexItem.UNASSOCIATED_VALUE;
145   }
146 
getOffsetFor(DexProto proto)147   public int getOffsetFor(DexProto proto) {
148     assert isContainedInMapping(proto) : "Missing dependency: " + proto;
149     return proto.getVirtualFileIndex(virtualFileId);
150   }
151 
getOffsetFor(DexField field)152   public int getOffsetFor(DexField field) {
153     assert isContainedInMapping(field) : "Missing dependency: " + field;
154     return field.getVirtualFileIndex(virtualFileId);
155   }
156 
getOffsetFor(DexMethod method)157   public int getOffsetFor(DexMethod method) {
158     assert isContainedInMapping(method) : "Missing dependency: " + method;
159     return method.getVirtualFileIndex(virtualFileId);
160   }
161 
getOffsetFor(DexString string)162   public int getOffsetFor(DexString string) {
163     assert isContainedInMapping(string) : "Missing dependency: " + string;
164     return string.getVirtualFileIndex(virtualFileId);
165   }
166 
getOffsetFor(DexType type)167   public int getOffsetFor(DexType type) {
168     assert isContainedInMapping(type) : "Missing dependency: " + type;
169     return type.getVirtualFileIndex(virtualFileId);
170   }
171 
getOffsetFor(DexCallSite callSite)172   public int getOffsetFor(DexCallSite callSite) {
173     assert isContainedInMapping(callSite) : "Missing dependency: " + callSite;
174     return callSite.getVirtualFileIndex(virtualFileId);
175   }
176 
getOffsetFor(DexMethodHandle methodHandle)177   public int getOffsetFor(DexMethodHandle methodHandle) {
178     assert isContainedInMapping(methodHandle) : "Missing dependency: " + methodHandle;
179     return methodHandle.getVirtualFileIndex(virtualFileId);
180   }
181 
182   private static class SortingProgramClassVisitor extends ProgramClassVisitor {
183     private final Set<DexClass> classSet = Sets.newIdentityHashSet();
184     private final DexProgramClass[] sortedClasses;
185 
186     private int index = 0;
187 
SortingProgramClassVisitor(DexApplication application, DexProgramClass[] classes)188     public SortingProgramClassVisitor(DexApplication application, DexProgramClass[] classes) {
189       super(application);
190       this.sortedClasses = new DexProgramClass[classes.length];
191       Collections.addAll(classSet, classes);
192     }
193 
194     @Override
visit(DexType type)195     public void visit(DexType type) {}
196 
197     @Override
visit(DexClass clazz)198     public void visit(DexClass clazz) {
199       if (classSet.contains(clazz)) {
200         assert index < sortedClasses.length;
201         sortedClasses[index++] = (DexProgramClass) clazz;
202       }
203     }
204 
205     public DexProgramClass[] getSortedClasses() {
206       assert index == sortedClasses.length;
207       return sortedClasses;
208     }
209   }
210 }
211