1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dx.dex.code; 18 19 import com.android.dx.rop.cst.Constant; 20 import com.android.dx.rop.type.Type; 21 import java.util.HashSet; 22 23 /** 24 * Container for all the pieces of a concrete method. Each instance 25 * corresponds to a {@code code} structure in a {@code .dex} file. 26 */ 27 public final class DalvCode { 28 /** 29 * how much position info to preserve; one of the static 30 * constants in {@link PositionList} 31 */ 32 private final int positionInfo; 33 34 /** 35 * {@code null-ok;} the instruction list, ready for final processing; 36 * nulled out in {@link #finishProcessingIfNecessary} 37 */ 38 private OutputFinisher unprocessedInsns; 39 40 /** 41 * {@code non-null;} unprocessed catch table; 42 * nulled out in {@link #finishProcessingIfNecessary} 43 */ 44 private CatchBuilder unprocessedCatches; 45 46 /** 47 * {@code null-ok;} catch table; set in 48 * {@link #finishProcessingIfNecessary} 49 */ 50 private CatchTable catches; 51 52 /** 53 * {@code null-ok;} source positions list; set in 54 * {@link #finishProcessingIfNecessary} 55 */ 56 private PositionList positions; 57 58 /** 59 * {@code null-ok;} local variable list; set in 60 * {@link #finishProcessingIfNecessary} 61 */ 62 private LocalList locals; 63 64 /** 65 * {@code null-ok;} the processed instruction list; set in 66 * {@link #finishProcessingIfNecessary} 67 */ 68 private DalvInsnList insns; 69 70 /** 71 * Constructs an instance. 72 * 73 * @param positionInfo how much position info to preserve; one of the 74 * static constants in {@link PositionList} 75 * @param unprocessedInsns {@code non-null;} the instruction list, ready 76 * for final processing 77 * @param unprocessedCatches {@code non-null;} unprocessed catch 78 * (exception handler) table 79 */ DalvCode(int positionInfo, OutputFinisher unprocessedInsns, CatchBuilder unprocessedCatches)80 public DalvCode(int positionInfo, OutputFinisher unprocessedInsns, 81 CatchBuilder unprocessedCatches) { 82 if (unprocessedInsns == null) { 83 throw new NullPointerException("unprocessedInsns == null"); 84 } 85 86 if (unprocessedCatches == null) { 87 throw new NullPointerException("unprocessedCatches == null"); 88 } 89 90 this.positionInfo = positionInfo; 91 this.unprocessedInsns = unprocessedInsns; 92 this.unprocessedCatches = unprocessedCatches; 93 this.catches = null; 94 this.positions = null; 95 this.locals = null; 96 this.insns = null; 97 } 98 99 /** 100 * Finish up processing of the method. 101 */ finishProcessingIfNecessary()102 private void finishProcessingIfNecessary() { 103 if (insns != null) { 104 return; 105 } 106 107 insns = unprocessedInsns.finishProcessingAndGetList(); 108 positions = PositionList.make(insns, positionInfo); 109 locals = LocalList.make(insns); 110 catches = unprocessedCatches.build(); 111 112 // Let them be gc'ed. 113 unprocessedInsns = null; 114 unprocessedCatches = null; 115 } 116 117 /** 118 * Assign indices in all instructions that need them, using the 119 * given callback to perform lookups. This must be called before 120 * {@link #getInsns}. 121 * 122 * @param callback {@code non-null;} callback object 123 */ assignIndices(AssignIndicesCallback callback)124 public void assignIndices(AssignIndicesCallback callback) { 125 unprocessedInsns.assignIndices(callback); 126 } 127 128 /** 129 * Gets whether this instance has any position data to represent. 130 * 131 * @return {@code true} iff this instance has any position 132 * data to represent 133 */ hasPositions()134 public boolean hasPositions() { 135 return (positionInfo != PositionList.NONE) 136 && unprocessedInsns.hasAnyPositionInfo(); 137 } 138 139 /** 140 * Gets whether this instance has any local variable data to represent. 141 * 142 * @return {@code true} iff this instance has any local variable 143 * data to represent 144 */ hasLocals()145 public boolean hasLocals() { 146 return unprocessedInsns.hasAnyLocalInfo(); 147 } 148 149 /** 150 * Gets whether this instance has any catches at all (either typed 151 * or catch-all). 152 * 153 * @return whether this instance has any catches at all 154 */ hasAnyCatches()155 public boolean hasAnyCatches() { 156 return unprocessedCatches.hasAnyCatches(); 157 } 158 159 /** 160 * Gets the set of catch types handled anywhere in the code. 161 * 162 * @return {@code non-null;} the set of catch types 163 */ getCatchTypes()164 public HashSet<Type> getCatchTypes() { 165 return unprocessedCatches.getCatchTypes(); 166 } 167 168 /** 169 * Gets the set of all constants referred to by instructions in 170 * the code. 171 * 172 * @return {@code non-null;} the set of constants 173 */ getInsnConstants()174 public HashSet<Constant> getInsnConstants() { 175 return unprocessedInsns.getAllConstants(); 176 } 177 178 /** 179 * Gets the list of instructions. 180 * 181 * @return {@code non-null;} the instruction list 182 */ getInsns()183 public DalvInsnList getInsns() { 184 finishProcessingIfNecessary(); 185 return insns; 186 } 187 188 /** 189 * Gets the catch (exception handler) table. 190 * 191 * @return {@code non-null;} the catch table 192 */ getCatches()193 public CatchTable getCatches() { 194 finishProcessingIfNecessary(); 195 return catches; 196 } 197 198 /** 199 * Gets the source positions list. 200 * 201 * @return {@code non-null;} the source positions list 202 */ getPositions()203 public PositionList getPositions() { 204 finishProcessingIfNecessary(); 205 return positions; 206 } 207 208 /** 209 * Gets the source positions list. 210 * 211 * @return {@code non-null;} the source positions list 212 */ getLocals()213 public LocalList getLocals() { 214 finishProcessingIfNecessary(); 215 return locals; 216 } 217 218 /** 219 * Class used as a callback for {@link #assignIndices}. 220 */ 221 public static interface AssignIndicesCallback { 222 /** 223 * Gets the index for the given constant. 224 * 225 * @param cst {@code non-null;} the constant 226 * @return {@code >= -1;} the index or {@code -1} if the constant 227 * shouldn't actually be reified with an index 228 */ getIndex(Constant cst)229 public int getIndex(Constant cst); 230 } 231 } 232