Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/debugger/cdbg/basic/BasicCDebugInfoDataBase.java @ 17467:55fb97c4c58d hs25-b65
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
Summary: Copyright year updated for files modified during 2013
Reviewed-by: twisti, iveresov
author | mikael |
---|---|
date | Tue, 24 Dec 2013 11:48:39 -0800 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.debugger.cdbg.basic; | |
26 | |
27 import java.util.*; | |
28 import sun.jvm.hotspot.debugger.*; | |
29 import sun.jvm.hotspot.debugger.cdbg.*; | |
30 import sun.jvm.hotspot.utilities.AddressOps; | |
31 import sun.jvm.hotspot.utilities.Assert; | |
32 | |
33 public class BasicCDebugInfoDataBase implements CDebugInfoDataBase { | |
34 private static final int INITIALIZED_STATE = 0; | |
35 private static final int CONSTRUCTION_STATE = 1; | |
36 private static final int RESOLVED_STATE = 2; | |
37 private static final int COMPLETE_STATE = 3; | |
38 | |
39 private int state = INITIALIZED_STATE; | |
40 | |
41 /////////// | |
42 // Types // | |
43 /////////// | |
44 | |
45 // Used only during construction | |
46 private Map lazyTypeMap; | |
47 | |
48 // Used during construction and at run time for iteration | |
49 private List types; | |
50 | |
51 // Used only during runtime | |
52 private Map nameToTypeMap; | |
53 | |
54 ///////////// | |
55 // Symbols // | |
56 ///////////// | |
57 | |
58 // Used only during construction | |
59 private Map lazySymMap; | |
60 | |
61 // List of blocks in increasing order by starting address. These can | |
62 // then be binary searched. | |
63 private List blocks; | |
64 | |
65 // Name-to-global symbol table | |
66 private Map nameToSymMap; | |
67 | |
68 ////////////////// | |
69 // Line numbers // | |
70 ////////////////// | |
71 | |
72 private BasicLineNumberMapping lineNumbers; | |
73 | |
74 /** Supports lazy instantiation and references between types and | |
75 symbols via insertion using arbitrary Object keys that are | |
76 wrapped by LazyTypes. Once the database has been fully | |
77 constructed and all types are present, one should call | |
78 resolveTypes(), which will resolve all LazyTypes down to | |
79 concrete types (and signal an error if some lazy types were | |
80 unresolved). */ | |
81 public void beginConstruction() { | |
82 if (Assert.ASSERTS_ENABLED) { | |
83 Assert.that(state == INITIALIZED_STATE, "wrong state"); | |
84 } | |
85 state = CONSTRUCTION_STATE; | |
86 | |
87 // Types | |
88 lazyTypeMap = new HashMap(); | |
89 types = new ArrayList(); | |
90 | |
91 // Symbols | |
92 lazySymMap = new HashMap(); | |
93 blocks = new ArrayList(); | |
94 nameToSymMap = new HashMap(); | |
95 | |
96 // Line numbers | |
97 lineNumbers = new BasicLineNumberMapping(); | |
98 } | |
99 | |
100 /** Add a type which may later in construction be referred to via a | |
101 LazyType with this key. lazyKey may be null. */ | |
102 public void addType(Object lazyKey, Type type) { | |
103 if (Assert.ASSERTS_ENABLED) { | |
104 Assert.that(state == CONSTRUCTION_STATE, "wrong state"); | |
105 } | |
106 if (lazyKey != null) { | |
107 if (lazyTypeMap.put(lazyKey, type) != null) { | |
108 throw new RuntimeException("Type redefined for lazy key " + lazyKey); | |
109 } | |
110 } else { | |
111 types.add(type); | |
112 } | |
113 } | |
114 | |
115 public void resolve(ResolveListener listener) { | |
116 if (Assert.ASSERTS_ENABLED) { | |
117 Assert.that(state == CONSTRUCTION_STATE, "wrong state"); | |
118 } | |
119 // Go through all types in lazyTypeMap and types. | |
120 // Resolve all LazyTypes. | |
121 resolveLazyMap(listener); | |
122 for (ListIterator iter = types.listIterator(); iter.hasNext(); ) { | |
123 BasicType t = (BasicType) iter.next(); | |
124 BasicType t2 = (BasicType) t.resolveTypes(this, listener); | |
125 if (t != t2) { | |
126 iter.set(t2); | |
127 } | |
128 } | |
129 // Go through all symbols and resolve references to types and | |
130 // references to other symbols | |
131 for (Iterator iter = blocks.iterator(); iter.hasNext(); ) { | |
132 ((BasicSym) iter.next()).resolve(this, listener); | |
133 } | |
134 for (Iterator iter = nameToSymMap.values().iterator(); iter.hasNext(); ) { | |
135 ((BasicSym) iter.next()).resolve(this, listener); | |
136 } | |
137 | |
138 // Sort blocks in ascending order of starting address (but do not | |
139 // change ordering among blocks with the same starting address) | |
140 Collections.sort(blocks, new Comparator() { | |
141 public int compare(Object o1, Object o2) { | |
142 BlockSym b1 = (BlockSym) o1; | |
143 BlockSym b2 = (BlockSym) o2; | |
144 Address a1 = b1.getAddress(); | |
145 Address a2 = b2.getAddress(); | |
146 if (AddressOps.lt(a1, a2)) { return -1; } | |
147 if (AddressOps.gt(a1, a2)) { return 1; } | |
148 return 0; | |
149 } | |
150 }); | |
151 | |
152 state = RESOLVED_STATE; | |
153 } | |
154 | |
155 public void endConstruction() { | |
156 if (Assert.ASSERTS_ENABLED) { | |
157 Assert.that(state == RESOLVED_STATE, "wrong state"); | |
158 } | |
159 // Move all types to type list | |
160 for (Iterator iter = lazyTypeMap.values().iterator(); iter.hasNext(); ) { | |
161 types.add(iter.next()); | |
162 } | |
163 // Build name-to-type map | |
164 nameToTypeMap = new HashMap(); | |
165 for (Iterator iter = types.iterator(); iter.hasNext(); ) { | |
166 Type t = (Type) iter.next(); | |
167 if (!t.isConst() && !t.isVolatile()) { | |
168 nameToTypeMap.put(t.getName(), t); | |
169 } | |
170 } | |
171 // Lose lazy maps | |
172 lazyTypeMap = null; | |
173 lazySymMap = null; | |
174 // Sort and finish line number information | |
175 lineNumbers.sort(); | |
176 // FIXME: on some platforms it might not be necessary to call | |
177 // recomputeEndPCs(). Will have to see what stabs information | |
178 // looks like. Should make configurable whether we make this call | |
179 // or not. | |
180 lineNumbers.recomputeEndPCs(); | |
181 | |
182 state = COMPLETE_STATE; | |
183 } | |
184 | |
185 public Type lookupType(String name) { | |
186 return lookupType(name, 0); | |
187 } | |
188 | |
189 public Type lookupType(String name, int cvAttributes) { | |
190 if (Assert.ASSERTS_ENABLED) { | |
191 Assert.that(state == COMPLETE_STATE, "wrong state"); | |
192 } | |
193 BasicType t = (BasicType) nameToTypeMap.get(name); | |
194 if (t != null) { | |
195 if (cvAttributes != 0) { | |
196 t = (BasicType) t.getCVVariant(cvAttributes); | |
197 } | |
198 } | |
199 return t; | |
200 } | |
201 | |
202 public void iterate(TypeVisitor v) { | |
203 if (Assert.ASSERTS_ENABLED) { | |
204 Assert.that(state == COMPLETE_STATE, "wrong state"); | |
205 } | |
206 for (Iterator iter = types.iterator(); iter.hasNext(); ) { | |
207 BasicType t = (BasicType) iter.next(); | |
208 t.visit(v); | |
209 } | |
210 } | |
211 | |
212 /** Add a BlockSym to the debug information database. The given | |
213 BlockSym may be referred to by a LazyBlockSym wrapping the given | |
214 Object key, which must be non-null. Any references to other | |
215 blocks (for example, the parent scope) should be made with | |
216 LazyBlockSyms. These references will be resolved after the | |
217 database is built. */ | |
218 public void addBlock(Object key, BlockSym block) { | |
219 if (Assert.ASSERTS_ENABLED) { | |
220 Assert.that(key != null, "key must be non-null"); | |
221 } | |
222 lazySymMap.put(key, block); | |
223 blocks.add(block); | |
224 } | |
225 | |
226 public void addGlobalSym(GlobalSym sym) { | |
227 nameToSymMap.put(sym.getName(), sym); | |
228 } | |
229 | |
230 public BlockSym debugInfoForPC(Address pc) { | |
231 return searchBlocks(pc, 0, blocks.size() - 1); | |
232 } | |
233 | |
234 public GlobalSym lookupSym(String name) { | |
235 return (GlobalSym) nameToSymMap.get(name); | |
236 } | |
237 | |
238 public void addLineNumberInfo(BasicLineNumberInfo info) { | |
239 lineNumbers.addLineNumberInfo(info); | |
240 } | |
241 | |
242 public LineNumberInfo lineNumberForPC(Address pc) throws DebuggerException { | |
243 return lineNumbers.lineNumberForPC(pc); | |
244 } | |
245 | |
246 public void iterate(LineNumberVisitor v) { | |
247 lineNumbers.iterate(v); | |
248 } | |
249 | |
250 //---------------------------------------------------------------------- | |
251 // Internals only below this point | |
252 // | |
253 | |
254 /** Intended only to be used by the BasicType implementation. */ | |
255 public Type resolveType(Type containingType, Type targetType, ResolveListener listener, String detail) { | |
256 BasicType basicTargetType = (BasicType) targetType; | |
257 if (Assert.ASSERTS_ENABLED) { | |
258 Assert.that(state == CONSTRUCTION_STATE, "wrong state"); | |
259 } | |
260 if (basicTargetType.isLazy()) { | |
261 BasicType resolved = (BasicType) lazyTypeMap.get(((LazyType) targetType).getKey()); | |
262 // FIXME: would like to have an assert here that the target is | |
263 // non-null, but apparently have bugs here with forward | |
264 // references of pointer types | |
265 if (resolved == null) { | |
266 listener.resolveFailed(containingType, (LazyType) targetType, detail + " because target type was not found"); | |
267 return targetType; | |
268 } | |
269 if (resolved.isLazy()) { | |
270 // Might happen for const/var variants for forward references | |
271 if (resolved.isConst() || resolved.isVolatile()) { | |
272 resolved = (BasicType) resolved.resolveTypes(this, listener); | |
273 } | |
274 if (resolved.isLazy()) { | |
275 listener.resolveFailed(containingType, (LazyType) targetType, | |
276 detail + " because target type (with key " + | |
277 ((Integer) ((LazyType) resolved).getKey()).intValue() + | |
278 (resolved.isConst() ? ", const" : ", not const") + | |
279 (resolved.isVolatile() ? ", volatile" : ", not volatile") + | |
280 ") was lazy"); | |
281 } | |
282 } | |
283 return resolved; | |
284 } | |
285 return targetType; | |
286 } | |
287 | |
288 /** Intended only to be usd by the BasicSym implementation. */ | |
289 public Type resolveType(Sym containingSymbol, Type targetType, ResolveListener listener, String detail) { | |
290 BasicType basicTargetType = (BasicType) targetType; | |
291 if (Assert.ASSERTS_ENABLED) { | |
292 Assert.that(state == CONSTRUCTION_STATE, "wrong state"); | |
293 } | |
294 if (basicTargetType.isLazy()) { | |
295 BasicType resolved = (BasicType) lazyTypeMap.get(((LazyType) targetType).getKey()); | |
296 // FIXME: would like to have an assert here that the target is | |
297 // non-null, but apparently have bugs here | |
298 if (resolved == null) { | |
299 listener.resolveFailed(containingSymbol, (LazyType) targetType, detail); | |
300 return targetType; | |
301 } | |
302 if (resolved.isLazy()) { | |
303 // Might happen for const/var variants for forward references | |
304 if (resolved.isConst() || resolved.isVolatile()) { | |
305 resolved = (BasicType) resolved.resolveTypes(this, listener); | |
306 } | |
307 if (resolved.isLazy()) { | |
308 listener.resolveFailed(containingSymbol, (LazyType) targetType, detail); | |
309 } | |
310 } | |
311 return resolved; | |
312 } | |
313 return targetType; | |
314 } | |
315 | |
316 /** Intended only to be usd by the BasicSym implementation. */ | |
317 public Sym resolveSym(Sym containingSymbol, Sym targetSym, ResolveListener listener, String detail) { | |
318 if (targetSym == null) return null; | |
319 BasicSym basicTargetSym = (BasicSym) targetSym; | |
320 if (Assert.ASSERTS_ENABLED) { | |
321 Assert.that(state == CONSTRUCTION_STATE, "wrong state"); | |
322 } | |
323 if (basicTargetSym.isLazy()) { | |
324 BasicSym resolved = (BasicSym) lazySymMap.get(((LazyBlockSym) targetSym).getKey()); | |
325 // FIXME: would like to have an assert here that the target is | |
326 // non-null, but apparently have bugs here | |
327 if (resolved == null) { | |
328 listener.resolveFailed(containingSymbol, (LazyBlockSym) targetSym, detail); | |
329 return targetSym; | |
330 } | |
331 if (resolved.isLazy()) { | |
332 listener.resolveFailed(containingSymbol, (LazyBlockSym) targetSym, detail); | |
333 } | |
334 return resolved; | |
335 } | |
336 return targetSym; | |
337 } | |
338 | |
339 private void resolveLazyMap(ResolveListener listener) { | |
340 for (Iterator iter = lazyTypeMap.entrySet().iterator(); iter.hasNext(); ) { | |
341 Map.Entry entry = (Map.Entry) iter.next(); | |
342 BasicType t = (BasicType) entry.getValue(); | |
343 BasicType t2 = (BasicType) t.resolveTypes(this, listener); | |
344 if (t2 != t) { | |
345 entry.setValue(t2); | |
346 } | |
347 } | |
348 } | |
349 | |
350 /** Find the block whose starting address is closest to but less | |
351 than the given address. */ | |
352 private BlockSym searchBlocks(Address addr, int lowIdx, int highIdx) { | |
353 if (highIdx < lowIdx) return null; | |
354 if ((lowIdx == highIdx) || (lowIdx == highIdx - 1)) { | |
355 // Base case: start with highIdx and walk backward. See whether | |
356 // addr is greater than any of the blocks' starting addresses, | |
357 // and if so, return that block. | |
358 Address lastAddr = null; | |
359 BlockSym ret = null; | |
360 for (int i = highIdx; i >= 0; --i) { | |
361 BlockSym block = (BlockSym) blocks.get(i); | |
362 if (AddressOps.lte(block.getAddress(), addr)) { | |
363 if ((lastAddr == null) || (AddressOps.equal(block.getAddress(), lastAddr))) { | |
364 lastAddr = block.getAddress(); | |
365 ret = block; | |
366 } else { | |
367 break; | |
368 } | |
369 } | |
370 } | |
371 return ret; | |
372 } | |
373 int midIdx = (lowIdx + highIdx) >> 1; | |
374 BlockSym block = (BlockSym) blocks.get(midIdx); | |
375 // See address relationship | |
376 if (AddressOps.lte(block.getAddress(), addr)) { | |
377 // Always move search up | |
378 return searchBlocks(addr, midIdx, highIdx); | |
379 } else { | |
380 // Always move search down | |
381 return searchBlocks(addr, lowIdx, midIdx); | |
382 } | |
383 } | |
384 } |