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.code.SourcePosition; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.FixedSizeList; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * List of source position entries. This class includes a utility 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * method to extract an instance out of a {@link DalvInsnList}. 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class PositionList extends FixedSizeList { 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} empty instance */ 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static final PositionList EMPTY = new PositionList(0); 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constant for {@link #make} to indicate that no actual position 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * information should be returned 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static final int NONE = 1; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constant for {@link #make} to indicate that only line number 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * transitions should be returned 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static final int LINES = 2; 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constant for {@link #make} to indicate that only "important" position 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * information should be returned. This includes block starts and 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instructions that might throw. 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static final int IMPORTANT = 3; 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Extracts and returns the source position information out of an 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instruction list. 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insns {@code non-null;} instructions to convert 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param howMuch how much information should be included; one of the 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * static constants defined by this class 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the positions list 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static PositionList make(DalvInsnList insns, int howMuch) { 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul switch (howMuch) { 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case NONE: { 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return EMPTY; 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case LINES: 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case IMPORTANT: { 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Valid. 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul default: { 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bogus howMuch"); 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition noInfo = SourcePosition.NO_INFO; 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition cur = noInfo; 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = insns.size(); 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul PositionList.Entry[] arr = new PositionList.Entry[sz]; 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean lastWasTarget = false; 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int at = 0; 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul DalvInsn insn = insns.get(i); 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (insn instanceof CodeAddress) { 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul lastWasTarget = true;; 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition pos = insn.getPosition(); 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (pos.equals(noInfo) || pos.sameLine(cur)) { 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((howMuch == IMPORTANT) && !lastWasTarget) { 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul cur = pos; 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul arr[at] = new PositionList.Entry(insn.getAddress(), pos); 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul at++; 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul lastWasTarget = false; 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul PositionList result = new PositionList(at); 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < at; i++) { 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.set(i, arr[i]); 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.setImmutable(); 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. All indices initially contain {@code null}. 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param size {@code >= 0;} the size of the list 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public PositionList(int size) { 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(size); 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the element at the given index. It is an error to call 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this with the index for an element which was never set; if you 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * do that, this will throw {@code NullPointerException}. 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n {@code >= 0, < size();} which index 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} element at that index 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Entry get(int n) { 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (Entry) get0(n); 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Sets the entry at the given index. 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param n {@code >= 0, < size();} which index 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param entry {@code non-null;} the entry to set at {@code n} 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void set(int n, Entry entry) { 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul set0(n, entry); 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Entry in a position list. 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static class Entry { 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} address of this entry */ 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int address; 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} corresponding source position information */ 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final SourcePosition position; 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param address {@code >= 0;} address of this entry 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param position {@code non-null;} corresponding source position information 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Entry (int address, SourcePosition position) { 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (address < 0) { 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("address < 0"); 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (position == null) { 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("position == null"); 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.address = address; 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.position = position; 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the address. 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the address 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getAddress() { 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return address; 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the source position information. 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the position information 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public SourcePosition getPosition() { 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return position; 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 193