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.dexgen.dex.code; 18 19 import com.android.dexgen.rop.code.SourcePosition; 20 import com.android.dexgen.util.FixedSizeList; 21 22 /** 23 * List of source position entries. This class includes a utility 24 * method to extract an instance out of a {@link DalvInsnList}. 25 */ 26 public final class PositionList extends FixedSizeList { 27 /** {@code non-null;} empty instance */ 28 public static final PositionList EMPTY = new PositionList(0); 29 30 /** 31 * constant for {@link #make} to indicate that no actual position 32 * information should be returned 33 */ 34 public static final int NONE = 1; 35 36 /** 37 * constant for {@link #make} to indicate that only line number 38 * transitions should be returned 39 */ 40 public static final int LINES = 2; 41 42 /** 43 * constant for {@link #make} to indicate that only "important" position 44 * information should be returned. This includes block starts and 45 * instructions that might throw. 46 */ 47 public static final int IMPORTANT = 3; 48 49 /** 50 * Extracts and returns the source position information out of an 51 * instruction list. 52 * 53 * @param insns {@code non-null;} instructions to convert 54 * @param howMuch how much information should be included; one of the 55 * static constants defined by this class 56 * @return {@code non-null;} the positions list 57 */ make(DalvInsnList insns, int howMuch)58 public static PositionList make(DalvInsnList insns, int howMuch) { 59 switch (howMuch) { 60 case NONE: { 61 return EMPTY; 62 } 63 case LINES: 64 case IMPORTANT: { 65 // Valid. 66 break; 67 } 68 default: { 69 throw new IllegalArgumentException("bogus howMuch"); 70 } 71 } 72 73 SourcePosition noInfo = SourcePosition.NO_INFO; 74 SourcePosition cur = noInfo; 75 int sz = insns.size(); 76 PositionList.Entry[] arr = new PositionList.Entry[sz]; 77 boolean lastWasTarget = false; 78 int at = 0; 79 80 for (int i = 0; i < sz; i++) { 81 DalvInsn insn = insns.get(i); 82 83 if (insn instanceof CodeAddress) { 84 lastWasTarget = true;; 85 continue; 86 } 87 88 SourcePosition pos = insn.getPosition(); 89 90 if (pos.equals(noInfo) || pos.sameLine(cur)) { 91 continue; 92 } 93 94 if ((howMuch == IMPORTANT) && !lastWasTarget) { 95 continue; 96 } 97 98 cur = pos; 99 arr[at] = new PositionList.Entry(insn.getAddress(), pos); 100 at++; 101 102 lastWasTarget = false; 103 } 104 105 PositionList result = new PositionList(at); 106 for (int i = 0; i < at; i++) { 107 result.set(i, arr[i]); 108 } 109 110 result.setImmutable(); 111 return result; 112 } 113 114 /** 115 * Constructs an instance. All indices initially contain {@code null}. 116 * 117 * @param size {@code >= 0;} the size of the list 118 */ PositionList(int size)119 public PositionList(int size) { 120 super(size); 121 } 122 123 /** 124 * Gets the element at the given index. It is an error to call 125 * this with the index for an element which was never set; if you 126 * do that, this will throw {@code NullPointerException}. 127 * 128 * @param n {@code >= 0, < size();} which index 129 * @return {@code non-null;} element at that index 130 */ get(int n)131 public Entry get(int n) { 132 return (Entry) get0(n); 133 } 134 135 /** 136 * Sets the entry at the given index. 137 * 138 * @param n {@code >= 0, < size();} which index 139 * @param entry {@code non-null;} the entry to set at {@code n} 140 */ set(int n, Entry entry)141 public void set(int n, Entry entry) { 142 set0(n, entry); 143 } 144 145 /** 146 * Entry in a position list. 147 */ 148 public static class Entry { 149 /** {@code >= 0;} address of this entry */ 150 private final int address; 151 152 /** {@code non-null;} corresponding source position information */ 153 private final SourcePosition position; 154 155 /** 156 * Constructs an instance. 157 * 158 * @param address {@code >= 0;} address of this entry 159 * @param position {@code non-null;} corresponding source position information 160 */ Entry(int address, SourcePosition position)161 public Entry (int address, SourcePosition position) { 162 if (address < 0) { 163 throw new IllegalArgumentException("address < 0"); 164 } 165 166 if (position == null) { 167 throw new NullPointerException("position == null"); 168 } 169 170 this.address = address; 171 this.position = position; 172 } 173 174 /** 175 * Gets the address. 176 * 177 * @return {@code >= 0;} the address 178 */ getAddress()179 public int getAddress() { 180 return address; 181 } 182 183 /** 184 * Gets the source position information. 185 * 186 * @return {@code non-null;} the position information 187 */ getPosition()188 public SourcePosition getPosition() { 189 return position; 190 } 191 } 192 } 193