1/* 2 * Copyright (c) 2000, 2006, 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.runtime; 26 27import java.io.*; 28import java.util.*; 29 30import sun.jvm.hotspot.debugger.*; 31import sun.jvm.hotspot.interpreter.*; 32import sun.jvm.hotspot.code.*; 33import sun.jvm.hotspot.types.*; 34import sun.jvm.hotspot.utilities.*; 35 36/** <P> A companion structure used for stack traversal. The 37 RegisterMap contains misc. information needed in order to do 38 correct stack traversal of stack frames. Hence, it must always be 39 passed in as an argument to Frame.sender(RegisterMap). </P> 40 41 <P> The use of RegisterMaps is slightly different in the 42 Serviceability Agent APIs than in the VM itself. In the VM, a 43 RegisterMap is created either for a particular thread or cloned 44 from another RegisterMap. In these APIs, a JavaThread is the 45 top-level factory for RegisterMaps, and RegisterMaps know how to 46 copy themselves (through either the clone() or copy() 47 methods). </P> */ 48 49public abstract class RegisterMap implements Cloneable { 50 /** Location of registers */ 51 protected Address[] location; 52 // FIXME: don't know about LocationValidType 53 protected long[] locationValid; 54 /** Should include argument_oop marked locations for compiler */ 55 protected boolean includeArgumentOops; 56 /** Reference to current thread */ 57 protected JavaThread thread; 58 /** Tells if the register map needs to be updated when traversing the stack */ 59 protected boolean updateMap; 60 /** Location of a frame where the pc is not at a call (NULL if no frame exists) */ 61 protected static int regCount; 62 protected static int locationValidTypeSize; 63 protected static int locationValidSize; 64 65 static { 66 VM.registerVMInitializedObserver(new Observer() { 67 public void update(Observable o, Object data) { 68 initialize(VM.getVM().getTypeDataBase()); 69 } 70 }); 71 } 72 73 private static void initialize(TypeDataBase db) { 74 regCount = db.lookupIntConstant("ConcreteRegisterImpl::number_of_registers").intValue(); 75 // FIXME: don't know about LocationValidType. The LocationValidType is typedef'ed as julong 76 // so used julong to get the size of LocationValidType. 77 locationValidTypeSize = (int)db.lookupType("julong").getSize() * 8; 78 locationValidSize = (regCount + locationValidTypeSize - 1) / locationValidTypeSize; 79 } 80 81 protected RegisterMap(JavaThread thread, boolean updateMap) { 82 this.thread = thread; 83 this.updateMap = updateMap; 84 location = new Address[regCount]; 85 locationValid = new long[locationValidSize]; 86 clear(); 87 } 88 89 /** Makes a copy of map into this */ 90 protected RegisterMap(RegisterMap map) { 91 if (Assert.ASSERTS_ENABLED) { 92 Assert.that(map != null, "RegisterMap must be present"); 93 } 94 this.thread = map.getThread(); 95 this.updateMap = map.getUpdateMap(); 96 this.includeArgumentOops = map.getIncludeArgumentOops(); 97 location = new Address[map.location.length]; 98 locationValid = new long[map.locationValid.length]; 99 initializeFromPD(map); 100 if (updateMap) { 101 for (int i = 0; i < locationValidSize; i++) { 102 long bits = (!getUpdateMap()) ? 0 : map.locationValid[i]; 103 locationValid[i] = bits; 104 // for whichever bits are set, pull in the corresponding map->_location 105 int j = i*locationValidTypeSize; 106 while (bits != 0) { 107 if ((bits & 1) != 0) { 108 if (Assert.ASSERTS_ENABLED) { 109 Assert.that(0 <= j && j < regCount, "range check"); 110 } 111 location[j] = map.location[j]; 112 } 113 bits >>>= 1; 114 j += 1; 115 } 116 } 117 } 118 } 119 120 public abstract Object clone(); 121 122 public RegisterMap copy() { 123 return (RegisterMap) clone(); 124 } 125 126 public void clear() { 127 setIncludeArgumentOops(true); 128 if (!VM.getVM().isCore()) { 129 if (updateMap) { 130 for (int i = 0; i < locationValid.length; i++) { 131 locationValid[i] = 0; 132 } 133 clearPD(); 134 } else { 135 initializePD(); 136 } 137 } 138 } 139 140 public Address getLocation(VMReg reg) { 141 int i = reg.getValue(); 142 int index = i / locationValidTypeSize; 143 if (Assert.ASSERTS_ENABLED) { 144 Assert.that(0 <= i && i < regCount, "sanity check"); 145 Assert.that(0 <= index && index < locationValidSize, "sanity check"); 146 } 147 if ((locationValid[index] & (1 << i % locationValidTypeSize)) != 0) { 148 return location[i]; 149 } else { 150 return getLocationPD(reg); 151 } 152 } 153 154 public void setLocation(VMReg reg, Address loc) { 155 int i = reg.getValue(); 156 int index = i / locationValidTypeSize; 157 if (Assert.ASSERTS_ENABLED) { 158 Assert.that(0 <= i && i < regCount, "sanity check"); 159 Assert.that(0 <= index && index < locationValidSize, "sanity check"); 160 Assert.that(updateMap, "updating map that does not need updating"); 161 } 162 location[i] = loc; 163 locationValid[index] |= (1 << (i % locationValidTypeSize)); 164 } 165 166 public boolean getIncludeArgumentOops() { 167 return includeArgumentOops; 168 } 169 170 public void setIncludeArgumentOops(boolean f) { 171 includeArgumentOops = f; 172 } 173 174 public JavaThread getThread() { 175 return thread; 176 } 177 178 public boolean getUpdateMap() { 179 return updateMap; 180 } 181 182 public void print() { 183 printOn(System.out); 184 } 185 186 public void printOn(PrintStream tty) { 187 tty.println("Register map"); 188 for (int i = 0; i < location.length; i++) { 189 Address src = getLocation(new VMReg(i)); 190 if (src != null) { 191 tty.print(" " + VMRegImpl.getRegisterName(i) + 192 " [" + src + "] = "); 193 if (src.andWithMask(VM.getVM().getAddressSize() - 1) != null) { 194 tty.print("<misaligned>"); 195 } else { 196 tty.print(src.getAddressAt(0)); 197 } 198 } 199 } 200 } 201 202 /** Platform-dependent clear() functionality */ 203 protected abstract void clearPD(); 204 /** Platform-dependent initialize() functionality */ 205 protected abstract void initializePD(); 206 /** Platform-dependent initializeFrom() functionality */ 207 protected abstract void initializeFromPD(RegisterMap map); 208 /** Platform-dependent getLocation() functionality */ 209 protected abstract Address getLocationPD(VMReg reg); 210} 211