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.code.SourcePosition; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.FixedSizeList; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * List of source position entries. This class includes a utility 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * method to extract an instance out of a {@link DalvInsnList}. 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class PositionList extends FixedSizeList { 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} empty instance */ 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static final PositionList EMPTY = new PositionList(0); 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * constant for {@link #make} to indicate that no actual position 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * information should be returned 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static final int NONE = 1; 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * constant for {@link #make} to indicate that only line number 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * transitions should be returned 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static final int LINES = 2; 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * constant for {@link #make} to indicate that only "important" position 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * information should be returned. This includes block starts and 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instructions that might throw. 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static final int IMPORTANT = 3; 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Extracts and returns the source position information out of an 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instruction list. 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insns {@code non-null;} instructions to convert 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param howMuch how much information should be included; one of the 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * static constants defined by this class 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the positions list 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static PositionList make(DalvInsnList insns, int howMuch) { 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson switch (howMuch) { 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case NONE: { 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return EMPTY; 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case LINES: 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case IMPORTANT: { 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Valid. 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson break; 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson default: { 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("bogus howMuch"); 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition noInfo = SourcePosition.NO_INFO; 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition cur = noInfo; 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int sz = insns.size(); 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PositionList.Entry[] arr = new PositionList.Entry[sz]; 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean lastWasTarget = false; 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int at = 0; 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < sz; i++) { 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DalvInsn insn = insns.get(i); 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (insn instanceof CodeAddress) { 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson lastWasTarget = true;; 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson continue; 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition pos = insn.getPosition(); 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (pos.equals(noInfo) || pos.sameLine(cur)) { 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson continue; 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((howMuch == IMPORTANT) && !lastWasTarget) { 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson continue; 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson cur = pos; 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson arr[at] = new PositionList.Entry(insn.getAddress(), pos); 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson at++; 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson lastWasTarget = false; 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PositionList result = new PositionList(at); 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < at; i++) { 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson result.set(i, arr[i]); 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson result.setImmutable(); 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return result; 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. All indices initially contain {@code null}. 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param size {@code >= 0;} the size of the list 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public PositionList(int size) { 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super(size); 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the element at the given index. It is an error to call 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * this with the index for an element which was never set; if you 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * do that, this will throw {@code NullPointerException}. 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param n {@code >= 0, < size();} which index 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} element at that index 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Entry get(int n) { 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (Entry) get0(n); 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets the entry at the given index. 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param n {@code >= 0, < size();} which index 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param entry {@code non-null;} the entry to set at {@code n} 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void set(int n, Entry entry) { 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson set0(n, entry); 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Entry in a position list. 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class Entry { 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code >= 0;} address of this entry */ 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int address; 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} corresponding source position information */ 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final SourcePosition position; 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param address {@code >= 0;} address of this entry 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param position {@code non-null;} corresponding source position information 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Entry (int address, SourcePosition position) { 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (address < 0) { 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("address < 0"); 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (position == null) { 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("position == null"); 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.address = address; 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.position = position; 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the address. 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code >= 0;} the address 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getAddress() { 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return address; 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the source position information. 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the position information 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public SourcePosition getPosition() { 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return position; 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 193