comparison agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2000-2005 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.compiler;
26
27 import java.util.*;
28
29 import sun.jvm.hotspot.code.*;
30 import sun.jvm.hotspot.debugger.*;
31 import sun.jvm.hotspot.runtime.*;
32 import sun.jvm.hotspot.types.*;
33 import sun.jvm.hotspot.utilities.*;
34
35 public class OopMapSet extends VMObject {
36 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.OopMapSet.DEBUG") != null;
37
38 private static CIntegerField omCountField;
39 private static CIntegerField omSizeField;
40 private static AddressField omDataField;
41 private static int REG_COUNT;
42 private static int SAVED_ON_ENTRY_REG_COUNT;
43 private static int C_SAVED_ON_ENTRY_REG_COUNT;
44 private static class MyVisitor implements OopMapVisitor {
45 private AddressVisitor addressVisitor;
46
47 public MyVisitor(AddressVisitor oopVisitor) {
48 setAddressVisitor(oopVisitor);
49 }
50
51 public void setAddressVisitor(AddressVisitor addressVisitor) {
52 this.addressVisitor = addressVisitor;
53 }
54
55 public void visitOopLocation(Address oopAddr) {
56 addressVisitor.visitAddress(oopAddr);
57 }
58
59 public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {
60 if (VM.getVM().isClientCompiler()) {
61 Assert.that(false, "should not reach here");
62 } else if (VM.getVM().isServerCompiler() &&
63 VM.getVM().useDerivedPointerTable()) {
64 Assert.that(false, "FIXME: add derived pointer table");
65 }
66 }
67
68 public void visitValueLocation(Address valueAddr) {
69 }
70
71 public void visitDeadLocation(Address deadAddr) {
72 }
73 }
74
75 static {
76 VM.registerVMInitializedObserver(new Observer() {
77 public void update(Observable o, Object data) {
78 initialize(VM.getVM().getTypeDataBase());
79 }
80 });
81 }
82
83 private static void initialize(TypeDataBase db) {
84 Type type = db.lookupType("OopMapSet");
85
86 omCountField = type.getCIntegerField("_om_count");
87 omSizeField = type.getCIntegerField("_om_size");
88 omDataField = type.getAddressField("_om_data");
89
90 if (!VM.getVM().isCore()) {
91 REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue();
92 if (VM.getVM().isServerCompiler()) {
93 SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue();
94 C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue();
95 }
96 }
97 }
98
99 public OopMapSet(Address addr) {
100 super(addr);
101 }
102
103 /** Returns the number of OopMaps in this OopMapSet */
104 public long getSize() {
105 return omCountField.getValue(addr);
106 }
107
108 /** returns the OopMap at a given index */
109 public OopMap getMapAt(int index) {
110 if (Assert.ASSERTS_ENABLED) {
111 Assert.that((index >= 0) && (index <= getSize()),"bad index");
112 }
113 Address omDataAddr = omDataField.getValue(addr);
114 Address oopMapAddr = omDataAddr.getAddressAt(index * VM.getVM().getAddressSize());
115 if (oopMapAddr == null) {
116 return null;
117 }
118 return new OopMap(oopMapAddr);
119 }
120
121 public OopMap findMapAtOffset(long pcOffset, boolean debugging) {
122 int i;
123 int len = (int) getSize();
124 if (Assert.ASSERTS_ENABLED) {
125 Assert.that(len > 0, "must have pointer maps");
126 }
127
128 // Scan through oopmaps. Stop when current offset is either equal or greater
129 // than the one we are looking for.
130 for (i = 0; i < len; i++) {
131 if (getMapAt(i).getOffset() >= pcOffset) {
132 break;
133 }
134 }
135
136 if (!debugging) {
137 if (Assert.ASSERTS_ENABLED) {
138 Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len);
139 Assert.that(getMapAt(i).getOffset() == pcOffset, "oopmap not found");
140 }
141 } else {
142 if (i == len) {
143 if (DEBUG) {
144 System.out.println("can't find oopmap at " + pcOffset);
145 System.out.print("Oopmap offsets are [ ");
146 for (i = 0; i < len; i++) {
147 System.out.print(getMapAt(i).getOffset());
148 }
149 System.out.println("]");
150 }
151 i = len - 1;
152 return getMapAt(i);
153 }
154 }
155
156 OopMap m = getMapAt(i);
157 return m;
158 }
159
160 /** Visitation -- iterates through the frame for a compiled method.
161 This is a very generic mechanism that requires the Address to be
162 dereferenced by the callee. Other, more specialized, visitation
163 mechanisms are given below. */
164 public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) {
165 allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging);
166 }
167
168 /** Note that there are 4 required AddressVisitors: one for oops,
169 one for derived oops, one for values, and one for dead values */
170 public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) {
171 if (Assert.ASSERTS_ENABLED) {
172 CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC());
173 Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in");
174 }
175
176 OopMapSet maps = cb.getOopMaps();
177 OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
178 if (Assert.ASSERTS_ENABLED) {
179 Assert.that(map != null, "no ptr map found");
180 }
181
182 // handle derived pointers first (otherwise base pointer may be
183 // changed before derived pointer offset has been collected)
184 OopMapValue omv;
185 {
186 for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) {
187 if (VM.getVM().isClientCompiler()) {
188 Assert.that(false, "should not reach here");
189 }
190 omv = oms.getCurrent();
191 Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
192 if (loc != null) {
193 Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap);
194 Address derivedLoc = loc;
195 visitor.visitDerivedOopLocation(baseLoc, derivedLoc);
196 }
197 }
198 }
199
200 // We want dead, value and oop oop_types
201 OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] {
202 OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.DEAD_VALUE
203 };
204
205 {
206 for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) {
207 omv = oms.getCurrent();
208 Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
209 if (loc != null) {
210 if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) {
211 // This assert commented out because this will be useful
212 // to detect in the debugging system
213 // assert(Universe::is_heap_or_null(*loc), "found non oop pointer");
214 visitor.visitOopLocation(loc);
215 } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) {
216 visitor.visitValueLocation(loc);
217 } else if (omv.getType() == OopMapValue.OopTypes.DEAD_VALUE) {
218 visitor.visitDeadLocation(loc);
219 }
220 }
221 }
222 }
223 }
224
225 /** Update callee-saved register info for the following frame.
226 Should only be called in non-core builds. */
227 public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) {
228 if (Assert.ASSERTS_ENABLED) {
229 Assert.that(!VM.getVM().isCore(), "non-core builds only");
230 }
231
232 if (!VM.getVM().isDebugging()) {
233 if (Assert.ASSERTS_ENABLED) {
234 OopMapSet maps = cb.getOopMaps();
235 Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty OopMapSet for CodeBlob");
236 }
237 } else {
238 // Hack for some topmost frames that have been found with empty
239 // OopMapSets. (Actually have not seen the null case, but don't
240 // want to take any chances.) See HSDB.showThreadStackMemory().
241 OopMapSet maps = cb.getOopMaps();
242 if ((maps == null) || (maps.getSize() == 0)) {
243 return;
244 }
245 }
246
247 // Check if caller must update oop argument
248 regMap.setIncludeArgumentOops(cb.callerMustGCArguments(regMap.getThread()));
249
250 int nofCallee = 0;
251 Address[] locs = new Address[2 * REG_COUNT + 1];
252 VMReg [] regs = new VMReg [2 * REG_COUNT + 1];
253 // ("+1" because REG_COUNT might be zero)
254
255 // Scan through oopmap and find location of all callee-saved registers
256 // (we do not do update in place, since info could be overwritten)
257 OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
258 if (Assert.ASSERTS_ENABLED) {
259 Assert.that(map != null, "no ptr map found");
260 }
261
262 OopMapValue omv = null;
263 for(OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) {
264 omv = oms.getCurrent();
265 if (Assert.ASSERTS_ENABLED) {
266 Assert.that(nofCallee < 2 * REG_COUNT, "overflow");
267 }
268 regs[nofCallee] = omv.getContentReg();
269 locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap);
270 nofCallee++;
271 }
272
273 // Check that runtime stubs save all callee-saved registers
274 // After adapter frames were deleted C2 doesn't use callee save registers at present
275 if (Assert.ASSERTS_ENABLED) {
276 if (VM.getVM().isServerCompiler()) {
277 Assert.that(!cb.isRuntimeStub() ||
278 (nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),
279 "must save all");
280 }
281 }
282
283 // Copy found callee-saved register to reg_map
284 for (int i = 0; i < nofCallee; i++) {
285 regMap.setLocation(regs[i], locs[i]);
286 }
287 }
288 }