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