1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.dex.code; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.Constant; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.Type; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.HashSet; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Container for all the pieces of a concrete method. Each instance 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * corresponds to a {@code code} structure in a {@code .dex} file. 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class DalvCode { 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * how much position info to preserve; one of the static 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * constants in {@link PositionList} 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int positionInfo; 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} the instruction list, ready for final processing; 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * nulled out in {@link #finishProcessingIfNecessary} 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private OutputFinisher unprocessedInsns; 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code non-null;} unprocessed catch table; 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * nulled out in {@link #finishProcessingIfNecessary} 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private CatchBuilder unprocessedCatches; 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} catch table; set in 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #finishProcessingIfNecessary} 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private CatchTable catches; 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} source positions list; set in 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #finishProcessingIfNecessary} 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private PositionList positions; 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} local variable list; set in 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #finishProcessingIfNecessary} 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private LocalList locals; 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} the processed instruction list; set in 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #finishProcessingIfNecessary} 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private DalvInsnList insns; 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param positionInfo how much position info to preserve; one of the 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * static constants in {@link PositionList} 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param unprocessedInsns {@code non-null;} the instruction list, ready 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * for final processing 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param unprocessedCatches {@code non-null;} unprocessed catch 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * (exception handler) table 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public DalvCode(int positionInfo, OutputFinisher unprocessedInsns, 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CatchBuilder unprocessedCatches) { 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (unprocessedInsns == null) { 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("unprocessedInsns == null"); 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (unprocessedCatches == null) { 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("unprocessedCatches == null"); 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.positionInfo = positionInfo; 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.unprocessedInsns = unprocessedInsns; 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.unprocessedCatches = unprocessedCatches; 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.catches = null; 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.positions = null; 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.locals = null; 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.insns = null; 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Finish up processing of the method. 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void finishProcessingIfNecessary() { 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (insns != null) { 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return; 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson insns = unprocessedInsns.finishProcessingAndGetList(); 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson positions = PositionList.make(insns, positionInfo); 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson locals = LocalList.make(insns); 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson catches = unprocessedCatches.build(); 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Let them be gc'ed. 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson unprocessedInsns = null; 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson unprocessedCatches = null; 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Assign indices in all instructions that need them, using the 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * given callback to perform lookups. This must be called before 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #getInsns}. 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param callback {@code non-null;} callback object 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void assignIndices(AssignIndicesCallback callback) { 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson unprocessedInsns.assignIndices(callback); 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets whether this instance has any position data to represent. 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code true} iff this instance has any position 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * data to represent 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean hasPositions() { 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (positionInfo != PositionList.NONE) 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && unprocessedInsns.hasAnyPositionInfo(); 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets whether this instance has any local variable data to represent. 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code true} iff this instance has any local variable 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * data to represent 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean hasLocals() { 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return unprocessedInsns.hasAnyLocalInfo(); 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets whether this instance has any catches at all (either typed 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * or catch-all). 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return whether this instance has any catches at all 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean hasAnyCatches() { 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return unprocessedCatches.hasAnyCatches(); 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the set of catch types handled anywhere in the code. 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the set of catch types 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HashSet<Type> getCatchTypes() { 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return unprocessedCatches.getCatchTypes(); 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the set of all constants referred to by instructions in 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the code. 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the set of constants 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HashSet<Constant> getInsnConstants() { 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return unprocessedInsns.getAllConstants(); 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the list of instructions. 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the instruction list 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public DalvInsnList getInsns() { 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson finishProcessingIfNecessary(); 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return insns; 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the catch (exception handler) table. 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the catch table 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public CatchTable getCatches() { 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson finishProcessingIfNecessary(); 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return catches; 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the source positions list. 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the source positions list 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public PositionList getPositions() { 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson finishProcessingIfNecessary(); 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return positions; 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the source positions list. 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the source positions list 213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public LocalList getLocals() { 215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson finishProcessingIfNecessary(); 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return locals; 217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Class used as a callback for {@link #assignIndices}. 221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static interface AssignIndicesCallback { 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the index for the given constant. 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param cst {@code non-null;} the constant 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code >= -1;} the index or {@code -1} if the constant 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * shouldn't actually be reified with an index 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getIndex(Constant cst); 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 233