Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java @ 10343:6bd680e9ea35
8003421: NPG: Move oops out of InstanceKlass into mirror
Summary: Inject protection_domain, signers, init_lock into java_lang_Class
Reviewed-by: stefank, dholmes, sla
author | coleenp |
---|---|
date | Wed, 22 May 2013 14:37:49 -0400 |
parents | da91efe96a93 |
children |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2 * Copyright (c) 2000, 2012, 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:
218
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
218
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:
218
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.runtime.sparc; | |
26 | |
27 import java.util.*; | |
28 | |
29 import sun.jvm.hotspot.asm.sparc.*; | |
30 import sun.jvm.hotspot.code.*; | |
31 import sun.jvm.hotspot.compiler.*; | |
32 import sun.jvm.hotspot.debugger.*; | |
33 import sun.jvm.hotspot.debugger.cdbg.*; | |
34 import sun.jvm.hotspot.oops.*; | |
35 import sun.jvm.hotspot.runtime.*; | |
36 import sun.jvm.hotspot.runtime.posix.*; | |
37 import sun.jvm.hotspot.types.*; | |
38 import sun.jvm.hotspot.utilities.*; | |
39 | |
40 /** Specialization of and implementation of abstract methods of the | |
41 Frame class for the SPARC CPU. (FIXME: this is as quick a port as | |
42 possible to get things running; will have to do a better job right | |
43 away.) */ | |
44 | |
45 public class SPARCFrame extends Frame { | |
46 // The pc value is the raw return address, plus 8 (pcReturnOffset()). | |
47 // the value of sp and youngerSP that is stored in this object | |
48 // is always, always, always the value that would be found in the | |
49 // register (or window save area) while the target VM was executing. | |
50 // The caller of the constructor will alwasy know if has a biased or | |
51 // unbiased version of the stack pointer and can convert real (unbiased) | |
52 // value via a helper routine we supply. | |
53 // Whenever we return sp or youngerSP values we do not return the internal | |
54 // value but the real (unbiased) pointers since these are the true, usable | |
55 // memory addresses. The outlier case is that of the null pointer. The current | |
56 // mechanism makes null pointers always look null whether biased or not. | |
57 // This seems to cause no problems. In theory null real pointers could be biased | |
58 // just like other values however this has impact on things like addOffsetTo() | |
59 // to be able to take an Address that represents null and add an offset to it. | |
60 // This doesn't seem worth the bother and the impact on the rest of the code | |
61 // when the biasSP and unbiasSP can make this invisible. | |
62 // | |
63 // The general rule in this code is that when we have a variable like FP, youngerSP, SP | |
64 // that these are real (i.e. unbiased) addresses. The instance variables in a Frame are | |
65 // always raw values. The other rule is that it except for the frame constructors and | |
66 // the unBiasSP helper all methods accept parameters that are real addresses. | |
67 // | |
68 | |
69 /** Optional next-younger SP (used to locate O7, the PC) */ | |
70 private Address raw_youngerSP; | |
71 | |
72 /** Intepreter adjusts the stack pointer to make all locals contiguous */ | |
73 private long interpreterSPAdjustmentOffset; | |
74 | |
75 /** Number of stack entries for longs */ | |
76 private static final int WORDS_PER_LONG = 2; | |
77 | |
78 /** Normal SPARC return is 2 words past PC */ | |
79 public static final int PC_RETURN_OFFSET = 8; | |
80 | |
81 /** Size of each block, in order of increasing address */ | |
82 public static final int REGISTER_SAVE_WORDS = 16; | |
83 // FIXME: read these from the remote process | |
84 //#ifdef _LP64 | |
85 // callee_aggregate_return_pointer_words = 0, | |
86 //#else | |
87 // callee_aggregate_return_pointer_words = 1, | |
88 //#endif | |
89 public static final int CALLEE_AGGREGATE_RETURN_POINTER_WORDS = 1; | |
90 public static final int CALLEE_REGISTER_ARGUMENT_SAVE_AREA_WORDS = 6; | |
91 | |
92 // offset of each block, in order of increasing address: | |
93 public static final int REGISTER_SAVE_WORDS_SP_OFFSET = 0; | |
94 public static final int CALLEE_AGGREGATE_RETURN_POINTER_SP_OFFSET = REGISTER_SAVE_WORDS_SP_OFFSET + REGISTER_SAVE_WORDS; | |
95 public static final int CALLEE_REGISTER_ARGUMENT_SAVE_AREA_SP_OFFSET = (CALLEE_AGGREGATE_RETURN_POINTER_SP_OFFSET + | |
96 CALLEE_AGGREGATE_RETURN_POINTER_WORDS); | |
97 public static final int MEMORY_PARAMETER_WORD_SP_OFFSET = (CALLEE_REGISTER_ARGUMENT_SAVE_AREA_SP_OFFSET + | |
98 CALLEE_REGISTER_ARGUMENT_SAVE_AREA_WORDS); | |
99 public static final int VARARGS_OFFSET = MEMORY_PARAMETER_WORD_SP_OFFSET; | |
100 | |
101 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.sparc.SPARCFrame.DEBUG") != null; | |
102 | |
103 public static Address unBiasSP(Address raw_sp) { | |
104 if (raw_sp != null) { | |
105 return raw_sp.addOffsetTo(VM.getVM().getStackBias()); | |
106 } else { | |
107 return null; | |
108 } | |
109 } | |
110 | |
111 public static Address biasSP(Address real_sp) { | |
112 if (real_sp != null) { | |
113 if (DEBUG) { | |
114 System.out.println("biasing realsp: " + real_sp + " biased: " + real_sp.addOffsetTo(-VM.getVM().getStackBias()) ); | |
115 } | |
116 return real_sp.addOffsetTo(-VM.getVM().getStackBias()); | |
117 } else { | |
118 if (DEBUG) { | |
119 System.out.println("biasing null realsp"); | |
120 } | |
121 return null; | |
122 } | |
123 } | |
124 // | |
125 // This is used to find the younger sp for a thread thatn has stopped but hasn't | |
126 // conveniently told us the information where we can find the pc or the frame | |
127 // containing the pc that corresponds to last_java_sp. This method will walk | |
128 // the frames trying to find the frame which we contains the data we need. | |
129 // | |
130 public static Address findYoungerSP(Address top, Address find) { | |
131 // top and find are unBiased sp values | |
132 // we return an unBiased value | |
133 Address findRaw = biasSP(find); | |
134 if (top == null || find == null || findRaw == null) { | |
135 throw new RuntimeException("bad values for findYoungerSP top: " + top + " find: " + find); | |
136 } | |
137 // It would be unusual to find more than 20 native frames before we find the java frame | |
138 // we are looking for. | |
139 final int maxFrames = 20; | |
140 int count = 0; | |
141 Address search = top; | |
142 Address next; | |
143 Address pc; | |
144 if (DEBUG) { | |
145 System.out.println("findYoungerSP top: " + top + " find: " + find + " findRaw: " + findRaw); | |
146 } | |
147 while ( count != maxFrames && search != null) { | |
148 next = search.getAddressAt(SPARCRegisters.I6.spOffsetInSavedWindow()); | |
149 pc = search.getAddressAt(SPARCRegisters.I7.spOffsetInSavedWindow()); | |
150 if (DEBUG) { | |
151 System.out.println("findYoungerSP next: " + next + " pc: " + pc); | |
152 } | |
153 if (next.equals(findRaw)) { | |
154 return search; | |
155 } | |
156 search = unBiasSP(next); | |
157 } | |
158 if (DEBUG) { | |
159 System.out.println("findYoungerSP: never found younger, top: " + top + " find: " + find); | |
160 } | |
161 return null; | |
162 } | |
163 | |
164 public Address getSP() { | |
165 if (DEBUG) { | |
166 System.out.println("getSP raw: " + raw_sp + " unbiased: " + unBiasSP(raw_sp)); | |
167 } | |
168 return unBiasSP(raw_sp); | |
169 } | |
170 | |
171 public Address getID() { | |
172 return getSP(); | |
173 } | |
174 | |
175 public Address getYoungerSP() { | |
176 if (DEBUG) { | |
177 System.out.println("getYoungerSP: " + raw_youngerSP + " unbiased: " + unBiasSP(raw_youngerSP)); | |
178 } | |
179 return unBiasSP(raw_youngerSP); | |
180 } | |
181 | |
182 /** This constructor relies on the fact that the creator of a frame | |
183 has flushed register windows which the frame will refer to, and | |
184 that those register windows will not be reloaded until the frame | |
185 is done reading and writing the stack. Moreover, if the | |
186 "younger_pc" argument points into the register save area of the | |
187 next younger frame (though it need not), the register window for | |
188 that next younger frame must also stay flushed. (The caller is | |
189 responsible for ensuring this.) */ | |
190 public SPARCFrame(Address raw_sp, Address raw_youngerSP, boolean youngerFrameIsInterpreted) { | |
191 super(); | |
192 if (DEBUG) { | |
193 System.out.println("Constructing frame(1) raw_sp: " + raw_sp + " raw_youngerSP: " + raw_youngerSP); | |
194 } | |
195 if (Assert.ASSERTS_ENABLED) { | |
196 Assert.that((unBiasSP(raw_sp).andWithMask(VM.getVM().getAddressSize() - 1) == null), | |
197 "Expected raw sp likely got real sp, value was " + raw_sp); | |
198 if (raw_youngerSP != null) { | |
199 Assert.that((unBiasSP(raw_youngerSP).andWithMask(VM.getVM().getAddressSize() - 1) == null), | |
200 "Expected raw youngerSP likely got real youngerSP, value was " + raw_youngerSP); | |
201 } | |
202 } | |
203 this.raw_sp = raw_sp; | |
204 this.raw_youngerSP = raw_youngerSP; | |
205 if (raw_youngerSP == null) { | |
206 // make a deficient frame which doesn't know where its PC is | |
207 pc = null; | |
208 } else { | |
209 Address youngerSP = unBiasSP(raw_youngerSP); | |
210 pc = youngerSP.getAddressAt(SPARCRegisters.I7.spOffsetInSavedWindow()).addOffsetTo(PC_RETURN_OFFSET); | |
211 | |
212 if (Assert.ASSERTS_ENABLED) { | |
213 Assert.that(youngerSP.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow()). | |
214 equals(raw_sp), | |
215 "youngerSP must be valid"); | |
216 } | |
217 } | |
218 | |
219 if (youngerFrameIsInterpreted) { | |
220 long IsavedSP = SPARCRegisters.IsavedSP.spOffsetInSavedWindow(); | |
221 // compute adjustment to this frame's SP made by its interpreted callee | |
222 interpreterSPAdjustmentOffset = 0; | |
223 Address savedSP = unBiasSP(getYoungerSP().getAddressAt(IsavedSP)); | |
224 if (savedSP == null) { | |
225 if ( DEBUG) { | |
226 System.out.println("WARNING: IsavedSP was null for frame " + this); | |
227 } | |
228 } else { | |
229 interpreterSPAdjustmentOffset = savedSP.minus(getSP()); | |
230 } | |
231 } else { | |
232 interpreterSPAdjustmentOffset = 0; | |
233 } | |
234 if ( pc != null) { | |
235 // Look for a deopt pc and if it is deopted convert to original pc | |
236 CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); | |
237 if (cb != null && cb.isJavaMethod()) { | |
238 NMethod nm = (NMethod) cb; | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
239 if (pc.equals(nm.deoptHandlerBegin())) { |
0 | 240 // adjust pc if frame is deoptimized. |
241 pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); | |
242 deoptimized = true; | |
243 } | |
244 } | |
245 } | |
246 } | |
247 | |
248 /** Make a deficient frame which doesn't know where its PC is (note | |
249 no youngerSP argument) */ | |
250 public SPARCFrame(Address raw_sp, Address pc) { | |
251 super(); | |
252 if (DEBUG) { | |
253 System.out.println("Constructing frame(2) raw_sp: " + raw_sp ); | |
254 } | |
255 this.raw_sp = raw_sp; | |
256 if (Assert.ASSERTS_ENABLED) { | |
257 Assert.that((unBiasSP(raw_sp).andWithMask(VM.getVM().getAddressSize() - 1) == null), | |
258 "Expected raw sp likely got real sp, value was " + raw_sp); | |
259 } | |
260 raw_youngerSP = null; | |
261 this.pc = pc; | |
262 interpreterSPAdjustmentOffset = 0; | |
263 } | |
264 | |
265 /** Only used internally */ | |
266 private SPARCFrame() { | |
267 } | |
268 | |
269 public Object clone() { | |
270 SPARCFrame frame = new SPARCFrame(); | |
271 frame.raw_sp = raw_sp; | |
272 frame.pc = pc; | |
273 frame.raw_youngerSP = raw_youngerSP; | |
274 frame.interpreterSPAdjustmentOffset = interpreterSPAdjustmentOffset; | |
275 frame.deoptimized = deoptimized; | |
276 return frame; | |
277 } | |
278 | |
279 public boolean equals(Object arg) { | |
280 if (arg == null) { | |
281 return false; | |
282 } | |
283 | |
284 if (!(arg instanceof SPARCFrame)) { | |
285 return false; | |
286 } | |
287 | |
288 SPARCFrame other = (SPARCFrame) arg; | |
289 | |
290 return (AddressOps.equal(getSP(), other.getSP()) && | |
291 AddressOps.equal(getFP(), other.getFP()) && | |
292 AddressOps.equal(getPC(), other.getPC())); | |
293 } | |
294 | |
295 public int hashCode() { | |
296 if (raw_sp == null) { | |
297 return 0; | |
298 } | |
299 | |
300 return raw_sp.hashCode(); | |
301 } | |
302 | |
303 public String toString() { | |
304 Address fp = getFP(); | |
305 Address sp = getSP(); | |
306 Address youngerSP = getYoungerSP(); | |
307 | |
308 return "sp: " + (sp == null? "null" : sp.toString()) + | |
309 ", younger_sp: " + (youngerSP == null? "null" : youngerSP.toString()) + | |
310 ", fp: " + (fp == null? "null" : fp.toString()) + | |
311 ", pc: " + (pc == null? "null" : pc.toString()); | |
312 } | |
313 | |
314 /** <P> Identifies a signal handler frame on the stack. </P> | |
315 | |
316 <P> There are a few different algorithms for doing this, and | |
317 they vary from platform to platform. For example, based on a | |
318 conversation with Dave Dice, Solaris/x86 will be substantially | |
319 simpler to handle than Solaris/SPARC because the signal handler | |
320 frame can be identified because of a program counter == -1. </P> | |
321 | |
322 <P> The dbx group provided code and advice on these topics; the | |
323 code below evolved from theirs, but is not correct/robust. | |
324 Without going into too many details, it seems that looking for | |
325 the incoming argument to the sigacthandler frame (which is what | |
326 this code identifies) is not guaranteed to be stable across | |
327 versions of Solaris, since that function is supplied by | |
328 libthread and is not guaranteed not to clobber I2 before it | |
329 calls __sighndlr later. From discussions, it sounds like a | |
330 robust algorithm which wouldn't require traversal of the | |
331 ucontext chain (used by dbx, but which Dave Dice thinks isn't | |
332 robust in the face of libthread -- need to follow up) would be | |
333 to be able to properly identify the __sighndlr frame, then get | |
334 I2 and treat that as a ucontext. To identify __sighndlr we would | |
335 need to look up that symbol in the remote process and look for a | |
336 program counter within a certain (small) distance. </P> | |
337 | |
338 <P> If the underlying Debugger supports CDebugger interface, we | |
339 take the approach of __sighnldr symbol. This approach is more robust | |
340 compared to the original hueristic approach. Of course, if there | |
341 is no CDebugger support, we fallback to the hueristic approach. </P> | |
342 | |
343 <P> The current implementation seems to work with Solaris 2.8. | |
344 A nice property of this system is that if we find a core file | |
345 this algorithm doesn't work on, we can change the code and try | |
346 again, so I'm putting this in as the current mechanism for | |
347 finding signal handler frames on Solaris/SPARC. </P> */ | |
348 public boolean isSignalHandlerFrameDbg() { | |
349 CDebugger cdbg = VM.getVM().getDebugger().getCDebugger(); | |
350 if (cdbg != null) { | |
351 LoadObject dso = cdbg.loadObjectContainingPC(getPC()); | |
352 if (dso != null) { | |
353 ClosestSymbol cs = dso.closestSymbolToPC(getPC()); | |
354 if (cs != null && cs.getName().equals("__sighndlr")) { | |
355 return true; | |
356 } else { | |
357 return false; | |
358 } | |
359 } else { | |
360 return false; | |
361 } | |
362 } else { | |
363 if (getYoungerSP() == null) { | |
364 // System.err.println(" SPARCFrame.isSignalHandlerFrameDbg: youngerSP = " + getYoungerSP()); | |
365 return false; | |
366 } | |
367 Address i2 = getSP().getAddressAt(SPARCRegisters.I2.spOffsetInSavedWindow()); | |
368 if (i2 == null) { | |
369 return false; | |
370 } | |
371 Address fp = getFP(); | |
372 // My (mistaken) understanding of the dbx group's code was that | |
373 // the signal handler frame could be identified by testing the | |
374 // incoming argument to see whether it was a certain distance | |
375 // below the frame pointer; in fact, their code did substantially | |
376 // more than this (traversal of the ucontext chain, which this | |
377 // code can't do because the topmost ucontext is not currently | |
378 // available via the proc_service APIs in dbx). The current code | |
379 // appears to work, but is probably not robust. | |
380 int MAJOR_HACK_OFFSET = 8; // Difference between expected location of the ucontext and reality | |
381 // System.err.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + | |
382 // ", fp = " + fp + ", raw_youngerSP = " + getYoungerSP()); | |
383 boolean res = i2.equals(fp.addOffsetTo(VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET))); | |
384 if (res) { | |
385 // Qualify this with another test (FIXME: this is a gross heuristic found while testing) | |
386 Address sigInfoAddr = getSP().getAddressAt(SPARCRegisters.I5.spOffsetInSavedWindow()); | |
387 if (sigInfoAddr == null) { | |
388 System.err.println("Frame with fp = " + fp + " looked like a signal handler frame but wasn't"); | |
389 res = false; | |
390 } | |
391 } | |
392 return res; | |
393 } | |
394 } | |
395 | |
396 public int getSignalNumberDbg() { | |
397 // From looking at the stack trace in dbx, it looks like the | |
398 // siginfo* comes into sigacthandler in I5. It would be much more | |
399 // robust to look at the __sighndlr frame instead, but we can't | |
400 // currently identify that frame. | |
401 | |
402 Address sigInfoAddr = getSP().getAddressAt(SPARCRegisters.I5.spOffsetInSavedWindow()); | |
403 // Read si_signo out of siginfo* | |
404 return (int) sigInfoAddr.getCIntegerAt(0, 4, false); | |
405 } | |
406 | |
407 public String getSignalNameDbg() { | |
408 return POSIXSignals.getSignalName(getSignalNumberDbg()); | |
409 } | |
410 | |
411 public boolean isInterpretedFrameValid() { | |
412 if (Assert.ASSERTS_ENABLED) { | |
413 Assert.that(isInterpretedFrame(), "Not an interpreted frame"); | |
414 } | |
415 // These are reasonable sanity checks | |
416 if (getFP() == null || (getFP().andWithMask(2 * VM.getVM().getAddressSize() - 1)) != null) { | |
417 return false; | |
418 } | |
419 if (getSP() == null || (getSP().andWithMask(2 * VM.getVM().getAddressSize() - 1)) != null) { | |
420 return false; | |
421 } | |
422 if (getFP().addOffsetTo(INTERPRETER_FRAME_VM_LOCAL_WORDS * VM.getVM().getAddressSize()).lessThan(getSP())) { | |
423 return false; | |
424 } | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
425 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
426 Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
427 |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
428 if (VM.getVM().getObjectHeap().isValidMethod(methodHandle) == false) { |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
429 return false; |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
430 } |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
431 |
0 | 432 // These are hacks to keep us out of trouble. |
433 // The problem with these is that they mask other problems | |
434 if (getFP().lessThanOrEqual(getSP())) { // this attempts to deal with unsigned comparison above | |
435 return false; | |
436 } | |
437 if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { // stack frames shouldn't be large. | |
438 return false; | |
439 } | |
440 // FIXME: this is not atomic with respect to GC and is unsuitable | |
441 // for use in a non-debugging, or reflective, system. Need to | |
442 // figure out how to express this. | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
443 Address bcx = addressOfInterpreterFrameBCX().getAddressAt(0); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
444 |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
445 Method method; |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
446 try { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
447 method = (Method)Metadata.instantiateWrapperFor(methodHandle); |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
448 } catch (UnknownOopException ex) { |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
449 return false; |
0 | 450 } |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
451 int bci = bcpToBci(bcx, method); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
452 //validate bci |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
453 if (bci < 0) return false; |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
454 |
0 | 455 return true; |
456 } | |
457 | |
458 //-------------------------------------------------------------------------------- | |
459 // Accessors: | |
460 // | |
461 | |
462 /** Accessors */ | |
463 | |
464 public long frameSize() { | |
465 return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); | |
466 } | |
467 | |
468 public Address getLink() { | |
469 return unBiasSP(getFP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); | |
470 } | |
471 | |
472 // FIXME: not implementable yet | |
473 // public void setLink(Address addr) { | |
474 // if (Assert.ASSERTS_ENABLED) { | |
475 // Assert.that(getLink().equals(addr), "frame nesting is controlled by hardware"); | |
476 // } | |
477 // } | |
478 | |
479 public Frame sender(RegisterMap regMap, CodeBlob cb) { | |
480 SPARCRegisterMap map = (SPARCRegisterMap) regMap; | |
481 | |
482 if (Assert.ASSERTS_ENABLED) { | |
483 Assert.that(map != null, "map must be set"); | |
484 } | |
485 | |
486 // Default is we don't have to follow them. The sender_for_xxx | |
487 // will update it accordingly | |
488 map.setIncludeArgumentOops(false); | |
489 | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
490 if (isEntryFrame()) { |
0 | 491 return senderForEntryFrame(map); |
492 } | |
493 | |
494 Address youngerSP = getSP(); | |
495 Address sp = getSenderSP(); | |
496 boolean isInterpreted = false; | |
497 | |
498 // FIXME: this is a hack to get stackwalking to work in the face | |
499 // of a signal like a SEGV. For debugging purposes it's important | |
500 // that (a) we are able to traverse the stack if we take a signal | |
501 // and (b) that we get the correct program counter in this | |
502 // situation. If we are not using alternate signal stacks then (a) | |
503 // seems to work all the time (on SPARC), but (b) is violated for | |
504 // the frame just below the signal handler. | |
505 | |
506 // The mechanism for finding the ucontext is not robust. In | |
507 // addition, we may find that we need to be able to fetch more | |
508 // registers from the ucontext than just the program counter, | |
509 // since the register windows on the stack are "stale". This will | |
510 // require substantial restructuring of this frame code, so has | |
511 // been avoided for now. | |
512 | |
513 // It is difficult to find a clean solution for mixing debugging | |
514 // situations with VM frame traversal. One could consider | |
515 // implementing generic frame traversal in the dbx style and only | |
516 // using the VM's stack walking mechanism on a per-frame basis, | |
517 // for example to traverse Java-level activations in a compiled | |
518 // frame. However, this will probably not interact well with the | |
519 // mechanism for finding oops on the stack. | |
520 | |
521 if (VM.getVM().isDebugging()) { | |
522 // If we are a signal handler frame, use a trick: make the | |
523 // youngerSP of the caller frame point to the top of the | |
524 // ucontext's contained register set. This should allow fetching | |
525 // of the registers for the frame just below the signal handler | |
526 // frame in the usual fashion. | |
527 if (isSignalHandlerFrameDbg()) { | |
528 | |
529 if (DEBUG) { | |
530 System.out.println("SPARCFrame.sender: found signal handler frame"); | |
531 } | |
532 | |
533 // Try to give a valid SP and PC for a "deficient frame" since | |
534 // we don't have a real register save area; making this class | |
535 // work by reading its information from a ucontext as well as | |
536 // a register save area is a major undertaking and has been | |
537 // deferred for now. It is very important that the PC is | |
538 // correct, which is why we don't just fall through to the | |
539 // other code (which would read the PC from the stale register | |
540 // window and thereby fail to get the actual location of the | |
541 // fault). | |
542 | |
543 long offset = getMContextAreaOffsetInUContext(); | |
544 Address fp = sp; | |
545 // System.out.println(" FP: " + fp); | |
546 fp = fp.addOffsetTo(getUContextOffset() + getMContextAreaOffsetInUContext()); | |
547 // System.out.println(" start of mcontext: " + fp); | |
548 // FIXME: put these elsewhere. These are the register numbers | |
549 // in /usr/include/sys/regset.h. They might belong in | |
550 // SPARCReigsters.java, but we currently don't have that list | |
551 // of numbers in the SA code (because all of the registers are | |
552 // listed as instances of SPARCRegister) and it appears that | |
553 // our numbering of the registers and this one don't match up. | |
554 int PC_OFFSET_IN_GREGSET = 1; | |
555 int SP_OFFSET_IN_GREGSET = 17; | |
556 raw_sp = fp.getAddressAt(VM.getVM().getAddressSize() * SP_OFFSET_IN_GREGSET); | |
557 Address pc = fp.getAddressAt(VM.getVM().getAddressSize() * PC_OFFSET_IN_GREGSET); | |
558 return new SPARCFrame(raw_sp, pc); | |
559 } | |
560 } | |
561 | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
562 // Note: The version of this operation on any platform with callee-save |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
563 // registers must update the register map (if not null). |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
564 // In order to do this correctly, the various subtypes of |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
565 // of frame (interpreted, compiled, glue, native), |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
566 // must be distinguished. There is no need on SPARC for |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
567 // such distinctions, because all callee-save registers are |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
568 // preserved for all frames via SPARC-specific mechanisms. |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
569 // |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
570 // *** HOWEVER, *** if and when we make any floating-point |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
571 // registers callee-saved, then we will have to copy over |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
572 // the RegisterMap update logic from the Intel code. |
0 | 573 |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
574 // The constructor of the sender must know whether this frame is interpreted so it can set the |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
575 // sender's _interpreter_sp_adjustment field. |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
576 if (VM.getVM().getInterpreter().contains(pc)) { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
577 isInterpreted = true; |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
578 map.makeIntegerRegsUnsaved(); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
579 map.shiftWindow(sp, youngerSP); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
580 } else { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
581 // Find a CodeBlob containing this frame's pc or elide the lookup and use the |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
582 // supplied blob which is already known to be associated with this frame. |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
583 cb = VM.getVM().getCodeCache().findBlob(pc); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
584 if (cb != null) { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
585 // Update the location of all implicitly saved registers |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
586 // as the address of these registers in the register save |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
587 // area (for %o registers we use the address of the %i |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
588 // register in the next younger frame) |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
0
diff
changeset
|
589 map.shiftWindow(sp, youngerSP); |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
590 if (map.getUpdateMap()) { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
591 if (cb.callerMustGCArguments()) { |
0 | 592 map.setIncludeArgumentOops(true); |
593 } | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
594 if (cb.getOopMaps() != null) { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
595 OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); |
0 | 596 } |
597 } | |
598 } | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
599 } |
0 | 600 |
601 return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted); | |
602 } | |
603 | |
604 protected boolean hasSenderPD() { | |
605 try { | |
606 // FIXME: should not happen!!! | |
607 if (getSP() == null) { | |
608 return false; | |
609 } | |
610 if ( unBiasSP(getSP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())) == null ) { | |
611 return false; | |
612 } | |
613 return true; | |
614 } catch (RuntimeException e) { | |
615 if (DEBUG) { | |
616 System.out.println("Bad frame " + this); | |
617 } | |
618 throw e; | |
619 } | |
620 } | |
621 | |
622 //-------------------------------------------------------------------------------- | |
623 // Return address: | |
624 // | |
625 | |
626 public Address getSenderPC() { | |
627 return addressOfI7().getAddressAt(0).addOffsetTo(PC_RETURN_OFFSET); | |
628 } | |
629 | |
630 // FIXME: currently unimplementable | |
631 // inline void frame::set_sender_pc(address addr) { *I7_addr() = addr - pc_return_offset; } | |
632 | |
633 public Address getUnextendedSP() { | |
634 return getSP().addOffsetTo(interpreterSPAdjustmentOffset); | |
635 } | |
636 | |
637 public Address getSenderSP() { | |
638 return getFP(); | |
639 } | |
640 | |
641 /** Given the next-younger sp for a given frame's sp, compute the | |
642 frame. We need the next-younger sp, because its register save | |
643 area holds the flushed copy of its I7, which is the PC of the | |
644 frame we are interested in. */ | |
645 public SPARCFrame afterSave() { | |
646 return new SPARCFrame(biasSP(getYoungerSP()), null); | |
647 } | |
648 | |
649 /** Accessors for the instance variables */ | |
650 public Address getFP() { | |
651 Address sp = getSP(); | |
652 if (sp == null) { | |
653 System.out.println("SPARCFrame.getFP(): sp == null"); | |
654 } | |
655 Address fpAddr = sp.addOffsetTo(SPARCRegisters.FP.spOffsetInSavedWindow()); | |
656 try { | |
657 Address fp = unBiasSP(fpAddr.getAddressAt(0)); | |
658 if (fp == null) { | |
659 System.out.println("SPARCFrame.getFP(): fp == null (&fp == " + fpAddr + ")"); | |
660 } | |
661 return fp; | |
662 } catch (RuntimeException e) { | |
663 System.out.println("SPARCFrame.getFP(): is bad (&fp == " + fpAddr + " sp = " + sp + ")"); | |
664 return null; | |
665 } | |
666 } | |
667 | |
668 private Address addressOfFPSlot(int index) { | |
669 return getFP().addOffsetTo(index * VM.getVM().getAddressSize()); | |
670 } | |
671 | |
672 // FIXME: temporarily elided | |
673 // // All frames | |
674 // | |
675 // intptr_t* fp_addr_at(int index) const { return &fp()[index]; } | |
676 // intptr_t* sp_addr_at(int index) const { return &sp()[index]; } | |
677 // intptr_t fp_at( int index) const { return *fp_addr_at(index); } | |
678 // intptr_t sp_at( int index) const { return *sp_addr_at(index); } | |
679 // | |
680 // private: | |
681 // inline address* I7_addr() const; | |
682 // inline address* O7_addr() const; | |
683 // | |
684 // inline address* I0_addr() const; | |
685 // inline address* O0_addr() const; | |
686 // | |
687 // public: | |
688 // // access to SPARC arguments and argument registers | |
689 // | |
690 // intptr_t* register_addr(Register reg) const { | |
691 // return sp_addr_at(reg.sp_offset_in_saved_window()); | |
692 // } | |
693 // intptr_t* memory_param_addr(int param_ix, bool is_in) const { | |
694 // int offset = callee_register_argument_save_area_sp_offset + param_ix; | |
695 // if (is_in) | |
696 // return fp_addr_at(offset); | |
697 // else | |
698 // return sp_addr_at(offset); | |
699 // } | |
700 // intptr_t* param_addr(int param_ix, bool is_in) const { | |
701 // if (param_ix >= callee_register_argument_save_area_words) | |
702 // return memory_param_addr(param_ix, is_in); | |
703 // else if (is_in) | |
704 // return register_addr(Argument(param_ix, true).as_register()); | |
705 // else { | |
706 // // the registers are stored in the next younger frame | |
707 // // %%% is this really necessary? | |
708 // frame next_younger = after_save(); | |
709 // return next_younger.register_addr(Argument(param_ix, true).as_register()); | |
710 // } | |
711 // } | |
712 | |
713 //-------------------------------------------------------------------------------- | |
714 // Interpreter frames: | |
715 // | |
716 | |
717 /** 2 words, also used to save float regs across calls to C */ | |
718 public static final int INTERPRETER_FRAME_D_SCRATCH_FP_OFFSET = -2; | |
719 public static final int INTERPRETER_FRAME_L_SCRATCH_FP_OFFSET = -4; | |
720 /** For native calls only */ | |
721 public static final int INTERPRETER_FRAME_PADDING_OFFSET = -5; | |
722 /** For native calls only */ | |
723 public static final int INTERPRETER_FRAME_MIRROR_OFFSET = -6; | |
724 /** Should be same as above, and should be zero mod 8 */ | |
725 public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET = -6; | |
726 public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET; | |
727 | |
728 /** Interpreter frame set-up needs to save 2 extra words in outgoing | |
729 param area for class and jnienv arguments for native stubs (see | |
730 nativeStubGen_sparc.cpp) */ | |
731 public static final int INTERPRETER_FRAME_EXTRA_OUTGOING_ARGUMENT_WORDS = 2; | |
732 | |
733 // FIXME: elided for now | |
734 // | |
735 // // the compiler frame has many of the same fields as the interpreter frame | |
736 // // %%%%% factor out declarations of the shared fields | |
737 // enum compiler_frame_fixed_locals { | |
738 // compiler_frame_d_scratch_fp_offset = -2, | |
739 // compiler_frame_vm_locals_fp_offset = -2, // should be same as above | |
740 // | |
741 // compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset | |
742 // }; | |
743 // | |
744 // private: | |
745 // | |
746 // // where LcpoolCache is saved: | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
747 // ConstantPoolCache** interpreter_frame_cpoolcache_addr() const { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
748 // return (ConstantPoolCache**)sp_addr_at( LcpoolCache.sp_offset_in_saved_window()); |
0 | 749 // } |
750 // | |
751 // // where Lmonitors is saved: | |
752 // BasicObjectLock** interpreter_frame_monitors_addr() const { | |
753 // return (BasicObjectLock**) sp_addr_at( Lmonitors.sp_offset_in_saved_window()); | |
754 // } | |
755 // intptr_t** interpreter_frame_esp_addr() const { | |
756 // return (intptr_t**)sp_addr_at( Lesp.sp_offset_in_saved_window()); | |
757 // } | |
758 // | |
759 // inline void interpreter_frame_set_tos_address(intptr_t* x); | |
760 // | |
761 // // next two fns read and write Lmonitors value, | |
762 // private: | |
763 // BasicObjectLock* interpreter_frame_monitors() const { return *interpreter_frame_monitors_addr(); } | |
764 // void interpreter_frame_set_monitors(BasicObjectLock* monitors) { *interpreter_frame_monitors_addr() = monitors; } | |
765 // | |
766 //#ifndef CORE | |
767 //inline oop *frame::pd_compiled_argument_to_location(VMReg::Name reg, RegisterMap reg_map, int arg_size) const { | |
768 // COMPILER1_ONLY(return (oop *) (arg_size - 1 - reg + sp() + memory_parameter_word_sp_offset); ) | |
769 // COMPILER2_ONLY(return oopmapreg_to_location(reg, ®_map); ) | |
770 //} | |
771 //#endif | |
772 | |
773 // FIXME: NOT FINISHED | |
774 public Address addressOfInterpreterFrameLocals() { | |
775 return getSP().addOffsetTo(SPARCRegisters.Llocals.spOffsetInSavedWindow()); | |
776 } | |
777 | |
778 // FIXME: this is not atomic with respect to GC and is unsuitable | |
779 // for use in a non-debugging, or reflective, system. | |
780 private Address addressOfInterpreterFrameBCX() { | |
781 // %%%%% reinterpreting Lbcp as a bcx | |
782 return getSP().addOffsetTo(SPARCRegisters.Lbcp.spOffsetInSavedWindow()); | |
783 } | |
784 | |
785 public int getInterpreterFrameBCI() { | |
786 // FIXME: this is not atomic with respect to GC and is unsuitable | |
787 // for use in a non-debugging, or reflective, system. Need to | |
788 // figure out how to express this. | |
789 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
790 Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
791 Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); |
0 | 792 return bcpToBci(bcp, method); |
793 } | |
794 | |
795 public Address addressOfInterpreterFrameExpressionStack() { | |
796 return addressOfInterpreterFrameMonitors().addOffsetTo(-1 * VM.getVM().getAddressSize()); | |
797 } | |
798 | |
799 public int getInterpreterFrameExpressionStackDirection() { | |
800 return -1; | |
801 } | |
802 | |
803 /** Top of expression stack */ | |
804 public Address addressOfInterpreterFrameTOS() { | |
805 return getSP().getAddressAt(SPARCRegisters.Lesp.spOffsetInSavedWindow()).addOffsetTo(VM.getVM().getAddressSize()); | |
806 } | |
807 | |
808 /** Expression stack from top down */ | |
809 public Address addressOfInterpreterFrameTOSAt(int slot) { | |
810 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); | |
811 } | |
812 | |
813 public Address getInterpreterFrameSenderSP() { | |
814 if (Assert.ASSERTS_ENABLED) { | |
815 Assert.that(isInterpretedFrame(), "interpreted frame expected"); | |
816 } | |
817 return getFP(); | |
818 } | |
819 | |
820 // FIXME: elided for now | |
821 //inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) { | |
822 // *interpreter_frame_esp_addr() = x - 1; | |
823 //} | |
824 | |
825 //-------------------------------------------------------------------------------- | |
826 // Monitors: | |
827 // | |
828 | |
829 private Address addressOfInterpreterFrameMonitors() { | |
830 return getSP().addOffsetTo(SPARCRegisters.Lmonitors.spOffsetInSavedWindow()).getAddressAt(0); | |
831 } | |
832 | |
833 // Monitors | |
834 public BasicObjectLock interpreterFrameMonitorBegin() { | |
835 int roundedVMLocalWords = Bits.roundTo(INTERPRETER_FRAME_VM_LOCAL_WORDS, WORDS_PER_LONG); | |
836 return new BasicObjectLock(addressOfFPSlot(-1 * roundedVMLocalWords)); | |
837 } | |
838 | |
839 public BasicObjectLock interpreterFrameMonitorEnd() { | |
840 return new BasicObjectLock(addressOfInterpreterFrameMonitors()); | |
841 } | |
842 | |
843 public int interpreterFrameMonitorSize() { | |
844 return Bits.roundTo(BasicObjectLock.size(), WORDS_PER_LONG * (int) VM.getVM().getAddressSize()); | |
845 } | |
846 | |
847 // FIXME: elided for now | |
848 // // monitor elements | |
849 // | |
850 // // in keeping with Intel side: end is lower in memory than begin; | |
851 // // and beginning element is oldest element | |
852 // // Also begin is one past last monitor. | |
853 // | |
854 // inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const { | |
855 // int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); | |
856 // return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words); | |
857 // } | |
858 // | |
859 // inline BasicObjectLock* frame::interpreter_frame_monitor_end() const { | |
860 // return interpreter_frame_monitors(); | |
861 // } | |
862 // | |
863 // | |
864 // inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) { | |
865 // interpreter_frame_set_monitors(value); | |
866 // } | |
867 // | |
868 // | |
869 // inline int frame::interpreter_frame_monitor_size() { | |
870 // return round_to(BasicObjectLock::size(), WordsPerLong); | |
871 // } | |
872 | |
873 public Address addressOfInterpreterFrameMethod() { | |
874 return getSP().addOffsetTo(SPARCRegisters.Lmethod.spOffsetInSavedWindow()); | |
875 } | |
876 | |
877 public Address addressOfInterpreterFrameCPCache() { | |
878 return getSP().addOffsetTo(SPARCRegisters.LcpoolCache.spOffsetInSavedWindow()); | |
879 } | |
880 | |
881 //-------------------------------------------------------------------------------- | |
882 // Entry frames: | |
883 // | |
884 | |
885 public JavaCallWrapper getEntryFrameCallWrapper() { | |
886 // Note: adjust this code if the link argument in StubGenerator::call_stub() changes! | |
887 SPARCArgument link = new SPARCArgument(0, false); | |
888 return (JavaCallWrapper) VMObjectFactory.newObject(JavaCallWrapper.class, | |
889 getSP().getAddressAt(link.asIn().asRegister().spOffsetInSavedWindow())); | |
890 } | |
891 | |
892 // | |
893 // | |
894 // inline JavaCallWrapper* frame::entry_frame_call_wrapper() const { | |
895 // // note: adjust this code if the link argument in StubGenerator::call_stub() changes! | |
896 // const Argument link = Argument(0, false); | |
897 // return (JavaCallWrapper*)sp()[link.as_in().as_register().sp_offset_in_saved_window()]; | |
898 // } | |
899 | |
900 //-------------------------------------------------------------------------------- | |
901 // Safepoints: | |
902 // | |
903 | |
904 protected Address addressOfSavedOopResult() { | |
905 return addressOfO0(); | |
906 } | |
907 | |
908 protected Address addressOfSavedReceiver() { | |
909 return addressOfO0(); | |
910 } | |
911 | |
912 | |
913 //-------------------------------------------------------------------------------- | |
914 // Internals only below this point | |
915 // | |
916 | |
917 private Address addressOfI7() { | |
918 return getSP().addOffsetTo(SPARCRegisters.I7.spOffsetInSavedWindow()); | |
919 } | |
920 | |
921 private Address addressOfO7() { | |
922 return afterSave().addressOfI7(); | |
923 } | |
924 | |
925 private Address addressOfI0() { | |
926 return getSP().addOffsetTo(SPARCRegisters.I0.spOffsetInSavedWindow()); | |
927 } | |
928 | |
929 private Address addressOfO0() { | |
930 return afterSave().addressOfI0(); | |
931 } | |
932 | |
933 private static boolean addressesEqual(Address a1, Address a2) { | |
934 if ((a1 == null) && (a2 == null)) { | |
935 return true; | |
936 } | |
937 | |
938 if ((a1 == null) || (a2 == null)) { | |
939 return false; | |
940 } | |
941 | |
942 return (a1.equals(a2)); | |
943 } | |
944 | |
945 | |
946 private Frame senderForEntryFrame(RegisterMap regMap) { | |
947 SPARCRegisterMap map = (SPARCRegisterMap) regMap; | |
948 | |
949 if (Assert.ASSERTS_ENABLED) { | |
950 Assert.that(map != null, "map must be set"); | |
951 } | |
952 // Java frame called from C; skip all C frames and return top C | |
953 // frame of that chunk as the sender | |
954 JavaCallWrapper jcw = getEntryFrameCallWrapper(); | |
955 if (Assert.ASSERTS_ENABLED) { | |
956 Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); | |
957 Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); | |
958 } | |
959 Address lastJavaSP = jcw.getLastJavaSP(); | |
960 Address lastJavaPC = jcw.getLastJavaPC(); | |
961 map.clear(); | |
962 | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
963 map.makeIntegerRegsUnsaved(); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
964 map.shiftWindow(lastJavaSP, null); |
0 | 965 |
966 if (Assert.ASSERTS_ENABLED) { | |
967 Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); | |
968 } | |
969 | |
970 if (lastJavaPC != null) { | |
971 return new SPARCFrame(biasSP(lastJavaSP), lastJavaPC); | |
972 } else { | |
973 Address youngerSP = getNextYoungerSP(lastJavaSP, getSP()); | |
974 return new SPARCFrame(biasSP(lastJavaSP), biasSP(youngerSP), false); | |
975 } | |
976 } | |
977 | |
978 private static Address getNextYoungerSP(Address oldSP, Address youngSP) { | |
979 Address sp = getNextYoungerSPOrNull(oldSP, youngSP, null); | |
980 if (Assert.ASSERTS_ENABLED) { | |
981 Assert.that(sp != null, "missed the SP"); | |
982 } | |
983 return sp; | |
984 } | |
985 | |
986 private static Address getNextYoungerSPOrNull(Address oldSP, Address youngSP, Address sp) { | |
987 if (youngSP == null) { | |
988 // FIXME | |
989 throw new RuntimeException("can not handle null youngSP in debugging system (seems to require register window flush)"); | |
990 } | |
991 | |
992 if (sp == null) { | |
993 sp = youngSP; | |
994 } | |
995 | |
996 Address previousSP = null; | |
997 | |
998 /** Minimum frame size is 16 */ | |
999 int maxFrames = (int) (oldSP.minus(sp) / (16 * VM.getVM().getAddressSize())); | |
1000 | |
1001 while(!sp.equals(oldSP) && spIsValid(oldSP, youngSP, sp)) { | |
1002 if (maxFrames-- <= 0) { | |
1003 // too many frames have gone by; invalid parameters given to this function | |
1004 break; | |
1005 } | |
1006 previousSP = sp; | |
1007 sp = unBiasSP(sp.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); | |
1008 } | |
1009 | |
1010 return (sp.equals(oldSP) ? previousSP : null); | |
1011 } | |
1012 | |
1013 private static boolean spIsValid(Address oldSP, Address youngSP, Address sp) { | |
1014 long mask = VM.getVM().getAddressSize(); | |
1015 mask = 2 * mask - 1; | |
1016 return ((sp.andWithMask(mask) == null) && | |
1017 (sp.lessThanOrEqual(oldSP)) && | |
1018 (sp.greaterThanOrEqual(youngSP))); | |
1019 } | |
1020 | |
1021 // FIXME: this is a hopefully temporary hack (not sure what is going on) | |
1022 public long getUContextOffset() { | |
1023 // FIXME: there is something I clearly don't understand about the | |
1024 // way the signal handler frame is laid out, because I shouldn't need this extra offset | |
1025 int MAJOR_HACK_OFFSET = 8; | |
1026 // System.out.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + ", fp = " + fp + ", youngerSP = " + youngerSP); | |
1027 return VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET); | |
1028 } | |
1029 | |
1030 public long getMContextAreaOffsetInUContext() { | |
1031 // From dbx-related sources: | |
1032 // /* | |
1033 // * struct sigframe is declaredf in the kernel sources in | |
1034 // * .../uts/sun4c/os/machdep.c/sendsig() | |
1035 // * unfortunately we only get a pointer to the 'uc' passed | |
1036 // * to the sighandler so we need to do this stuff to get | |
1037 // * to 'rwin'. | |
1038 // * Have to do it like this to take account of alignment. | |
1039 // */ | |
1040 // static struct sigframe { | |
1041 // struct rwindow rwin; | |
1042 // ucontext_t uc; | |
1043 // } sf_help; | |
1044 | |
1045 // From /usr/include/sys/ucontext.h: | |
1046 // #if !defined(_XPG4_2) || defined(__EXTENSIONS__) | |
1047 // struct ucontext { | |
1048 // #else | |
1049 // struct __ucontext { | |
1050 // #endif | |
1051 // uint_t uc_flags; | |
1052 // ucontext_t *uc_link; | |
1053 // sigset_t uc_sigmask; | |
1054 // stack_t uc_stack; | |
1055 // mcontext_t uc_mcontext; | |
1056 // #ifdef __sparcv9 | |
1057 // long uc_filler[4]; | |
1058 // #else /* __sparcv9 */ | |
1059 // long uc_filler[23]; | |
1060 // #endif /* __sparcv9 */ | |
1061 // }; | |
1062 | |
1063 // This walks to the start of the gregs in the mcontext_t | |
1064 // (first entry in that data structure). Really should read | |
1065 // this from header file. | |
1066 | |
1067 // Also not sure exactly how alignment works...maybe should read these offsets from the target VM | |
1068 // (When you have a hammer, everything looks like a nail) | |
1069 long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize()); // uc_flags | |
1070 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // uc_link plus | |
1071 // doubleword alignment for structs? | |
1072 offset += 16 + // uc_sigmask | |
1073 2 * VM.getVM().getAddressSize() + 4; // uc_stack | |
1074 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // doubleword alignment for structs? | |
1075 | |
1076 // System.out.println("SPARCFrame.getMContextAreaOffsetInUContext: offset = " + offset); | |
1077 | |
1078 return offset; | |
1079 } | |
1080 } |