0
|
1 /*
|
|
2 * Copyright 2000-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 package sun.jvm.hotspot.runtime;
|
|
26
|
|
27 import java.io.*;
|
|
28 import java.util.*;
|
|
29
|
|
30 import sun.jvm.hotspot.debugger.*;
|
|
31 import sun.jvm.hotspot.interpreter.*;
|
|
32 import sun.jvm.hotspot.code.*;
|
|
33 import sun.jvm.hotspot.types.*;
|
|
34 import 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
|
|
49 public 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 }
|