1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.code; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.HashSet; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Container for all the pieces of a concrete method. Each instance 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * corresponds to a {@code code} structure in a {@code .dex} file. 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class DalvCode { 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * how much position info to preserve; one of the static 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constants in {@link PositionList} 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int positionInfo; 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} the instruction list, ready for final processing; 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * nulled out in {@link #finishProcessingIfNecessary} 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private OutputFinisher unprocessedInsns; 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code non-null;} unprocessed catch table; 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * nulled out in {@link #finishProcessingIfNecessary} 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private CatchBuilder unprocessedCatches; 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} catch table; set in 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #finishProcessingIfNecessary} 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private CatchTable catches; 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} source positions list; set in 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #finishProcessingIfNecessary} 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private PositionList positions; 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} local variable list; set in 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #finishProcessingIfNecessary} 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private LocalList locals; 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} the processed instruction list; set in 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #finishProcessingIfNecessary} 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private DalvInsnList insns; 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param positionInfo how much position info to preserve; one of the 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * static constants in {@link PositionList} 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param unprocessedInsns {@code non-null;} the instruction list, ready 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for final processing 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param unprocessedCatches {@code non-null;} unprocessed catch 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * (exception handler) table 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public DalvCode(int positionInfo, OutputFinisher unprocessedInsns, 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CatchBuilder unprocessedCatches) { 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (unprocessedInsns == null) { 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("unprocessedInsns == null"); 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (unprocessedCatches == null) { 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("unprocessedCatches == null"); 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.positionInfo = positionInfo; 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.unprocessedInsns = unprocessedInsns; 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.unprocessedCatches = unprocessedCatches; 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.catches = null; 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.positions = null; 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.locals = null; 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.insns = null; 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Finish up processing of the method. 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void finishProcessingIfNecessary() { 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (insns != null) { 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return; 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul insns = unprocessedInsns.finishProcessingAndGetList(); 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul positions = PositionList.make(insns, positionInfo); 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul locals = LocalList.make(insns); 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul catches = unprocessedCatches.build(); 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Let them be gc'ed. 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul unprocessedInsns = null; 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul unprocessedCatches = null; 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Assign indices in all instructions that need them, using the 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * given callback to perform lookups. This must be called before 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #getInsns}. 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param callback {@code non-null;} callback object 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void assignIndices(AssignIndicesCallback callback) { 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul unprocessedInsns.assignIndices(callback); 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets whether this instance has any position data to represent. 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff this instance has any position 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * data to represent 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean hasPositions() { 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (positionInfo != PositionList.NONE) 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && unprocessedInsns.hasAnyPositionInfo(); 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets whether this instance has any local variable data to represent. 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff this instance has any local variable 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * data to represent 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean hasLocals() { 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return unprocessedInsns.hasAnyLocalInfo(); 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets whether this instance has any catches at all (either typed 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * or catch-all). 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return whether this instance has any catches at all 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean hasAnyCatches() { 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return unprocessedCatches.hasAnyCatches(); 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the set of catch types handled anywhere in the code. 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the set of catch types 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public HashSet<Type> getCatchTypes() { 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return unprocessedCatches.getCatchTypes(); 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the set of all constants referred to by instructions in 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the code. 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the set of constants 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public HashSet<Constant> getInsnConstants() { 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return unprocessedInsns.getAllConstants(); 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the list of instructions. 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the instruction list 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public DalvInsnList getInsns() { 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul finishProcessingIfNecessary(); 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return insns; 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the catch (exception handler) table. 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the catch table 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public CatchTable getCatches() { 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul finishProcessingIfNecessary(); 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return catches; 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the source positions list. 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the source positions list 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public PositionList getPositions() { 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul finishProcessingIfNecessary(); 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return positions; 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the source positions list. 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the source positions list 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public LocalList getLocals() { 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul finishProcessingIfNecessary(); 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return locals; 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Class used as a callback for {@link #assignIndices}. 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static interface AssignIndicesCallback { 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the index for the given constant. 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param cst {@code non-null;} the constant 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= -1;} the index or {@code -1} if the constant 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * shouldn't actually be reified with an index 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getIndex(Constant cst); 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 233