1/* 2 * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25package sun.jvm.hotspot.debugger.cdbg.basic; 26 27import java.util.*; 28import sun.jvm.hotspot.debugger.*; 29import sun.jvm.hotspot.debugger.cdbg.*; 30import sun.jvm.hotspot.utilities.AddressOps; 31 32public class BasicLineNumberMapping { 33 private List infoList; 34 35 public BasicLineNumberMapping() { 36 } 37 38 /** Add line number information for the given PC. The end PC may be 39 a very loose approximation (i.e., the end of the given DLL) if 40 that information is not available in the debug information. 41 recomputeEndPCs() will recompute them if needed. */ 42 public void addLineNumberInfo(BasicLineNumberInfo info) { 43 if (infoList == null) { 44 infoList = new ArrayList(); 45 } 46 infoList.add(info); 47 } 48 49 /** Sort the line number information by increasing starting program 50 counter. This must be done before any queries are made. */ 51 public void sort() { 52 if (infoList == null) return; 53 Collections.sort(infoList, new Comparator() { 54 public int compare(Object o1, Object o2) { 55 BasicLineNumberInfo l1 = (BasicLineNumberInfo) o1; 56 BasicLineNumberInfo l2 = (BasicLineNumberInfo) o2; 57 Address a1 = l1.getStartPC(); 58 Address a2 = l2.getStartPC(); 59 if (AddressOps.lt(a1, a2)) { return -1; } 60 if (AddressOps.gt(a1, a2)) { return 1; } 61 return 0; 62 } 63 }); 64 } 65 66 /** Recomputes the ending PCs of each interval based on the starting 67 PC of the next one. If this needs to be called, must be called 68 after sort(). */ 69 public void recomputeEndPCs() { 70 if (infoList == null) return; 71 for (int i = 0; i < infoList.size() - 1; i++) { 72 BasicLineNumberInfo i1 = get(i); 73 BasicLineNumberInfo i2 = get(i + 1); 74 i1.setEndPC(i2.getStartPC()); 75 } 76 } 77 78 public BasicLineNumberInfo lineNumberForPC(Address pc) throws DebuggerException { 79 if (infoList == null) return null; 80 return searchLineNumbers(pc, 0, infoList.size() - 1); 81 } 82 83 public void iterate(LineNumberVisitor v) { 84 if (infoList == null) return; 85 for (int i = 0; i < infoList.size(); i++) { 86 v.doLineNumber(get(i)); 87 } 88 } 89 90 //---------------------------------------------------------------------- 91 // Internals only below this point 92 // 93 94 private BasicLineNumberInfo get(int i) { 95 return (BasicLineNumberInfo) infoList.get(i); 96 } 97 98 private BasicLineNumberInfo searchLineNumbers(Address addr, int lowIdx, int highIdx) { 99 if (highIdx < lowIdx) return null; 100 if (lowIdx == highIdx) { 101 // Base case: see whether start PC is less than or equal to addr 102 if (check(addr, lowIdx)) { 103 return get(lowIdx); 104 } else { 105 return null; 106 } 107 } else if (lowIdx == highIdx - 1) { 108 if (check(addr, lowIdx)) { 109 return get(lowIdx); 110 } else if (check(addr, highIdx)) { 111 return get(highIdx); 112 } else { 113 return null; 114 } 115 } 116 int midIdx = (lowIdx + highIdx) >> 1; 117 BasicLineNumberInfo info = get(midIdx); 118 if (AddressOps.lt(addr, info.getStartPC())) { 119 // Always move search down 120 return searchLineNumbers(addr, lowIdx, midIdx); 121 } else if (AddressOps.equal(addr, info.getStartPC())) { 122 return info; 123 } else { 124 // Move search up 125 return searchLineNumbers(addr, midIdx, highIdx); 126 } 127 } 128 129 private boolean check(Address addr, int idx) { 130 BasicLineNumberInfo info = get(idx); 131 if (AddressOps.lte(info.getStartPC(), addr)) { 132 return true; 133 } else { 134 return false; 135 } 136 } 137} 138