Mercurial > hg > truffle
comparison agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | a5838065ab24 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 package sun.jvm.hotspot.runtime.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; | |
239 if (pc.equals(nm.deoptBegin())) { | |
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 } | |
425 // These are hacks to keep us out of trouble. | |
426 // The problem with these is that they mask other problems | |
427 if (getFP().lessThanOrEqual(getSP())) { // this attempts to deal with unsigned comparison above | |
428 return false; | |
429 } | |
430 if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { // stack frames shouldn't be large. | |
431 return false; | |
432 } | |
433 // FIXME: this is not atomic with respect to GC and is unsuitable | |
434 // for use in a non-debugging, or reflective, system. Need to | |
435 // figure out how to express this. | |
436 if (addressOfInterpreterFrameBCX().getAddressAt(0) == null) { | |
437 return false; // BCP not yet set up | |
438 } | |
439 return true; | |
440 } | |
441 | |
442 //-------------------------------------------------------------------------------- | |
443 // Accessors: | |
444 // | |
445 | |
446 /** Accessors */ | |
447 | |
448 public long frameSize() { | |
449 return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); | |
450 } | |
451 | |
452 public Address getLink() { | |
453 return unBiasSP(getFP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); | |
454 } | |
455 | |
456 // FIXME: not implementable yet | |
457 // public void setLink(Address addr) { | |
458 // if (Assert.ASSERTS_ENABLED) { | |
459 // Assert.that(getLink().equals(addr), "frame nesting is controlled by hardware"); | |
460 // } | |
461 // } | |
462 | |
463 public Frame sender(RegisterMap regMap, CodeBlob cb) { | |
464 SPARCRegisterMap map = (SPARCRegisterMap) regMap; | |
465 | |
466 if (Assert.ASSERTS_ENABLED) { | |
467 Assert.that(map != null, "map must be set"); | |
468 } | |
469 | |
470 // Default is we don't have to follow them. The sender_for_xxx | |
471 // will update it accordingly | |
472 map.setIncludeArgumentOops(false); | |
473 | |
474 if (cb == null && isEntryFrame()) { | |
475 return senderForEntryFrame(map); | |
476 } | |
477 | |
478 Address youngerSP = getSP(); | |
479 Address sp = getSenderSP(); | |
480 boolean isInterpreted = false; | |
481 | |
482 // FIXME: this is a hack to get stackwalking to work in the face | |
483 // of a signal like a SEGV. For debugging purposes it's important | |
484 // that (a) we are able to traverse the stack if we take a signal | |
485 // and (b) that we get the correct program counter in this | |
486 // situation. If we are not using alternate signal stacks then (a) | |
487 // seems to work all the time (on SPARC), but (b) is violated for | |
488 // the frame just below the signal handler. | |
489 | |
490 // The mechanism for finding the ucontext is not robust. In | |
491 // addition, we may find that we need to be able to fetch more | |
492 // registers from the ucontext than just the program counter, | |
493 // since the register windows on the stack are "stale". This will | |
494 // require substantial restructuring of this frame code, so has | |
495 // been avoided for now. | |
496 | |
497 // It is difficult to find a clean solution for mixing debugging | |
498 // situations with VM frame traversal. One could consider | |
499 // implementing generic frame traversal in the dbx style and only | |
500 // using the VM's stack walking mechanism on a per-frame basis, | |
501 // for example to traverse Java-level activations in a compiled | |
502 // frame. However, this will probably not interact well with the | |
503 // mechanism for finding oops on the stack. | |
504 | |
505 if (VM.getVM().isDebugging()) { | |
506 // If we are a signal handler frame, use a trick: make the | |
507 // youngerSP of the caller frame point to the top of the | |
508 // ucontext's contained register set. This should allow fetching | |
509 // of the registers for the frame just below the signal handler | |
510 // frame in the usual fashion. | |
511 if (isSignalHandlerFrameDbg()) { | |
512 | |
513 if (DEBUG) { | |
514 System.out.println("SPARCFrame.sender: found signal handler frame"); | |
515 } | |
516 | |
517 // Try to give a valid SP and PC for a "deficient frame" since | |
518 // we don't have a real register save area; making this class | |
519 // work by reading its information from a ucontext as well as | |
520 // a register save area is a major undertaking and has been | |
521 // deferred for now. It is very important that the PC is | |
522 // correct, which is why we don't just fall through to the | |
523 // other code (which would read the PC from the stale register | |
524 // window and thereby fail to get the actual location of the | |
525 // fault). | |
526 | |
527 long offset = getMContextAreaOffsetInUContext(); | |
528 Address fp = sp; | |
529 // System.out.println(" FP: " + fp); | |
530 fp = fp.addOffsetTo(getUContextOffset() + getMContextAreaOffsetInUContext()); | |
531 // System.out.println(" start of mcontext: " + fp); | |
532 // FIXME: put these elsewhere. These are the register numbers | |
533 // in /usr/include/sys/regset.h. They might belong in | |
534 // SPARCReigsters.java, but we currently don't have that list | |
535 // of numbers in the SA code (because all of the registers are | |
536 // listed as instances of SPARCRegister) and it appears that | |
537 // our numbering of the registers and this one don't match up. | |
538 int PC_OFFSET_IN_GREGSET = 1; | |
539 int SP_OFFSET_IN_GREGSET = 17; | |
540 raw_sp = fp.getAddressAt(VM.getVM().getAddressSize() * SP_OFFSET_IN_GREGSET); | |
541 Address pc = fp.getAddressAt(VM.getVM().getAddressSize() * PC_OFFSET_IN_GREGSET); | |
542 // System.out.println(" next frame's SP: " + sp + " PC: " + pc); | |
543 return new SPARCFrame(raw_sp, pc); | |
544 } | |
545 } | |
546 | |
547 if (!VM.getVM().isCore()) { | |
548 // Note: The version of this operation on any platform with callee-save | |
549 // registers must update the register map (if not null). | |
550 // In order to do this correctly, the various subtypes of | |
551 // of frame (interpreted, compiled, glue, native), | |
552 // must be distinguished. There is no need on SPARC for | |
553 // such distinctions, because all callee-save registers are | |
554 // preserved for all frames via SPARC-specific mechanisms. | |
555 // | |
556 // *** HOWEVER, *** if and when we make any floating-point | |
557 // registers callee-saved, then we will have to copy over | |
558 // the RegisterMap update logic from the Intel code. | |
559 | |
560 | |
561 // The constructor of the sender must know whether this frame is interpreted so it can set the | |
562 // sender's _interpreter_sp_adjustment field. | |
563 if (VM.getVM().getInterpreter().contains(pc)) { | |
564 isInterpreted = true; | |
565 if (VM.getVM().isClientCompiler()) { | |
566 map.makeIntegerRegsUnsaved(); | |
567 map.shiftWindow(sp, youngerSP); | |
568 } | |
569 } else { | |
570 // Find a CodeBlob containing this frame's pc or elide the lookup and use the | |
571 // supplied blob which is already known to be associated with this frame. | |
572 cb = VM.getVM().getCodeCache().findBlob(pc); | |
573 if (cb != null) { | |
574 | |
575 if (cb.callerMustGCArguments(map.getThread())) { | |
576 map.setIncludeArgumentOops(true); | |
577 } | |
578 | |
579 // Update the location of all implicitly saved registers | |
580 // as the address of these registers in the register save | |
581 // area (for %o registers we use the address of the %i | |
582 // register in the next younger frame) | |
583 map.shiftWindow(sp, youngerSP); | |
584 if (map.getUpdateMap()) { | |
585 if (cb.getOopMaps() != null) { | |
586 OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); | |
587 } | |
588 } | |
589 } | |
590 } | |
591 } // #ifndef CORE | |
592 | |
593 return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted); | |
594 } | |
595 | |
596 protected boolean hasSenderPD() { | |
597 try { | |
598 // FIXME: should not happen!!! | |
599 if (getSP() == null) { | |
600 return false; | |
601 } | |
602 if ( unBiasSP(getSP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())) == null ) { | |
603 return false; | |
604 } | |
605 return true; | |
606 } catch (RuntimeException e) { | |
607 if (DEBUG) { | |
608 System.out.println("Bad frame " + this); | |
609 } | |
610 throw e; | |
611 } | |
612 } | |
613 | |
614 //-------------------------------------------------------------------------------- | |
615 // Return address: | |
616 // | |
617 | |
618 public Address getSenderPC() { | |
619 return addressOfI7().getAddressAt(0).addOffsetTo(PC_RETURN_OFFSET); | |
620 } | |
621 | |
622 // FIXME: currently unimplementable | |
623 // inline void frame::set_sender_pc(address addr) { *I7_addr() = addr - pc_return_offset; } | |
624 | |
625 public Address getUnextendedSP() { | |
626 return getSP().addOffsetTo(interpreterSPAdjustmentOffset); | |
627 } | |
628 | |
629 public Address getSenderSP() { | |
630 return getFP(); | |
631 } | |
632 | |
633 /** Given the next-younger sp for a given frame's sp, compute the | |
634 frame. We need the next-younger sp, because its register save | |
635 area holds the flushed copy of its I7, which is the PC of the | |
636 frame we are interested in. */ | |
637 public SPARCFrame afterSave() { | |
638 return new SPARCFrame(biasSP(getYoungerSP()), null); | |
639 } | |
640 | |
641 /** Accessors for the instance variables */ | |
642 public Address getFP() { | |
643 Address sp = getSP(); | |
644 if (sp == null) { | |
645 System.out.println("SPARCFrame.getFP(): sp == null"); | |
646 } | |
647 Address fpAddr = sp.addOffsetTo(SPARCRegisters.FP.spOffsetInSavedWindow()); | |
648 try { | |
649 Address fp = unBiasSP(fpAddr.getAddressAt(0)); | |
650 if (fp == null) { | |
651 System.out.println("SPARCFrame.getFP(): fp == null (&fp == " + fpAddr + ")"); | |
652 } | |
653 return fp; | |
654 } catch (RuntimeException e) { | |
655 System.out.println("SPARCFrame.getFP(): is bad (&fp == " + fpAddr + " sp = " + sp + ")"); | |
656 return null; | |
657 } | |
658 } | |
659 | |
660 private Address addressOfFPSlot(int index) { | |
661 return getFP().addOffsetTo(index * VM.getVM().getAddressSize()); | |
662 } | |
663 | |
664 // FIXME: temporarily elided | |
665 // // All frames | |
666 // | |
667 // intptr_t* fp_addr_at(int index) const { return &fp()[index]; } | |
668 // intptr_t* sp_addr_at(int index) const { return &sp()[index]; } | |
669 // intptr_t fp_at( int index) const { return *fp_addr_at(index); } | |
670 // intptr_t sp_at( int index) const { return *sp_addr_at(index); } | |
671 // | |
672 // private: | |
673 // inline address* I7_addr() const; | |
674 // inline address* O7_addr() const; | |
675 // | |
676 // inline address* I0_addr() const; | |
677 // inline address* O0_addr() const; | |
678 // | |
679 // public: | |
680 // // access to SPARC arguments and argument registers | |
681 // | |
682 // intptr_t* register_addr(Register reg) const { | |
683 // return sp_addr_at(reg.sp_offset_in_saved_window()); | |
684 // } | |
685 // intptr_t* memory_param_addr(int param_ix, bool is_in) const { | |
686 // int offset = callee_register_argument_save_area_sp_offset + param_ix; | |
687 // if (is_in) | |
688 // return fp_addr_at(offset); | |
689 // else | |
690 // return sp_addr_at(offset); | |
691 // } | |
692 // intptr_t* param_addr(int param_ix, bool is_in) const { | |
693 // if (param_ix >= callee_register_argument_save_area_words) | |
694 // return memory_param_addr(param_ix, is_in); | |
695 // else if (is_in) | |
696 // return register_addr(Argument(param_ix, true).as_register()); | |
697 // else { | |
698 // // the registers are stored in the next younger frame | |
699 // // %%% is this really necessary? | |
700 // frame next_younger = after_save(); | |
701 // return next_younger.register_addr(Argument(param_ix, true).as_register()); | |
702 // } | |
703 // } | |
704 | |
705 //-------------------------------------------------------------------------------- | |
706 // Interpreter frames: | |
707 // | |
708 | |
709 /** 2 words, also used to save float regs across calls to C */ | |
710 public static final int INTERPRETER_FRAME_D_SCRATCH_FP_OFFSET = -2; | |
711 public static final int INTERPRETER_FRAME_L_SCRATCH_FP_OFFSET = -4; | |
712 /** For native calls only */ | |
713 public static final int INTERPRETER_FRAME_PADDING_OFFSET = -5; | |
714 /** For native calls only */ | |
715 public static final int INTERPRETER_FRAME_MIRROR_OFFSET = -6; | |
716 /** Should be same as above, and should be zero mod 8 */ | |
717 public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET = -6; | |
718 public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET; | |
719 | |
720 /** Interpreter frame set-up needs to save 2 extra words in outgoing | |
721 param area for class and jnienv arguments for native stubs (see | |
722 nativeStubGen_sparc.cpp) */ | |
723 public static final int INTERPRETER_FRAME_EXTRA_OUTGOING_ARGUMENT_WORDS = 2; | |
724 | |
725 // FIXME: elided for now | |
726 // | |
727 // // the compiler frame has many of the same fields as the interpreter frame | |
728 // // %%%%% factor out declarations of the shared fields | |
729 // enum compiler_frame_fixed_locals { | |
730 // compiler_frame_d_scratch_fp_offset = -2, | |
731 // compiler_frame_vm_locals_fp_offset = -2, // should be same as above | |
732 // | |
733 // compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset | |
734 // }; | |
735 // | |
736 // private: | |
737 // | |
738 // // where LcpoolCache is saved: | |
739 // constantPoolCacheOop* interpreter_frame_cpoolcache_addr() const { | |
740 // return (constantPoolCacheOop*)sp_addr_at( LcpoolCache.sp_offset_in_saved_window()); | |
741 // } | |
742 // | |
743 // // where Lmonitors is saved: | |
744 // BasicObjectLock** interpreter_frame_monitors_addr() const { | |
745 // return (BasicObjectLock**) sp_addr_at( Lmonitors.sp_offset_in_saved_window()); | |
746 // } | |
747 // intptr_t** interpreter_frame_esp_addr() const { | |
748 // return (intptr_t**)sp_addr_at( Lesp.sp_offset_in_saved_window()); | |
749 // } | |
750 // | |
751 // inline void interpreter_frame_set_tos_address(intptr_t* x); | |
752 // | |
753 // // next two fns read and write Lmonitors value, | |
754 // private: | |
755 // BasicObjectLock* interpreter_frame_monitors() const { return *interpreter_frame_monitors_addr(); } | |
756 // void interpreter_frame_set_monitors(BasicObjectLock* monitors) { *interpreter_frame_monitors_addr() = monitors; } | |
757 // | |
758 //#ifndef CORE | |
759 //inline oop *frame::pd_compiled_argument_to_location(VMReg::Name reg, RegisterMap reg_map, int arg_size) const { | |
760 // COMPILER1_ONLY(return (oop *) (arg_size - 1 - reg + sp() + memory_parameter_word_sp_offset); ) | |
761 // COMPILER2_ONLY(return oopmapreg_to_location(reg, ®_map); ) | |
762 //} | |
763 //#endif | |
764 | |
765 // FIXME: NOT FINISHED | |
766 public Address addressOfInterpreterFrameLocals() { | |
767 return getSP().addOffsetTo(SPARCRegisters.Llocals.spOffsetInSavedWindow()); | |
768 } | |
769 | |
770 // FIXME: this is not atomic with respect to GC and is unsuitable | |
771 // for use in a non-debugging, or reflective, system. | |
772 private Address addressOfInterpreterFrameBCX() { | |
773 // %%%%% reinterpreting Lbcp as a bcx | |
774 return getSP().addOffsetTo(SPARCRegisters.Lbcp.spOffsetInSavedWindow()); | |
775 } | |
776 | |
777 public int getInterpreterFrameBCI() { | |
778 // FIXME: this is not atomic with respect to GC and is unsuitable | |
779 // for use in a non-debugging, or reflective, system. Need to | |
780 // figure out how to express this. | |
781 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); | |
782 OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0); | |
783 Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle); | |
784 return bcpToBci(bcp, method); | |
785 } | |
786 | |
787 public Address addressOfInterpreterFrameExpressionStack() { | |
788 return addressOfInterpreterFrameMonitors().addOffsetTo(-1 * VM.getVM().getAddressSize()); | |
789 } | |
790 | |
791 public int getInterpreterFrameExpressionStackDirection() { | |
792 return -1; | |
793 } | |
794 | |
795 /** Top of expression stack */ | |
796 public Address addressOfInterpreterFrameTOS() { | |
797 return getSP().getAddressAt(SPARCRegisters.Lesp.spOffsetInSavedWindow()).addOffsetTo(VM.getVM().getAddressSize()); | |
798 } | |
799 | |
800 /** Expression stack from top down */ | |
801 public Address addressOfInterpreterFrameTOSAt(int slot) { | |
802 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); | |
803 } | |
804 | |
805 public Address getInterpreterFrameSenderSP() { | |
806 if (Assert.ASSERTS_ENABLED) { | |
807 Assert.that(isInterpretedFrame(), "interpreted frame expected"); | |
808 } | |
809 return getFP(); | |
810 } | |
811 | |
812 // FIXME: elided for now | |
813 //inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) { | |
814 // *interpreter_frame_esp_addr() = x - 1; | |
815 //} | |
816 | |
817 //-------------------------------------------------------------------------------- | |
818 // Monitors: | |
819 // | |
820 | |
821 private Address addressOfInterpreterFrameMonitors() { | |
822 return getSP().addOffsetTo(SPARCRegisters.Lmonitors.spOffsetInSavedWindow()).getAddressAt(0); | |
823 } | |
824 | |
825 // Monitors | |
826 public BasicObjectLock interpreterFrameMonitorBegin() { | |
827 int roundedVMLocalWords = Bits.roundTo(INTERPRETER_FRAME_VM_LOCAL_WORDS, WORDS_PER_LONG); | |
828 return new BasicObjectLock(addressOfFPSlot(-1 * roundedVMLocalWords)); | |
829 } | |
830 | |
831 public BasicObjectLock interpreterFrameMonitorEnd() { | |
832 return new BasicObjectLock(addressOfInterpreterFrameMonitors()); | |
833 } | |
834 | |
835 public int interpreterFrameMonitorSize() { | |
836 return Bits.roundTo(BasicObjectLock.size(), WORDS_PER_LONG * (int) VM.getVM().getAddressSize()); | |
837 } | |
838 | |
839 // FIXME: elided for now | |
840 // // monitor elements | |
841 // | |
842 // // in keeping with Intel side: end is lower in memory than begin; | |
843 // // and beginning element is oldest element | |
844 // // Also begin is one past last monitor. | |
845 // | |
846 // inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const { | |
847 // int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); | |
848 // return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words); | |
849 // } | |
850 // | |
851 // inline BasicObjectLock* frame::interpreter_frame_monitor_end() const { | |
852 // return interpreter_frame_monitors(); | |
853 // } | |
854 // | |
855 // | |
856 // inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) { | |
857 // interpreter_frame_set_monitors(value); | |
858 // } | |
859 // | |
860 // | |
861 // inline int frame::interpreter_frame_monitor_size() { | |
862 // return round_to(BasicObjectLock::size(), WordsPerLong); | |
863 // } | |
864 | |
865 public Address addressOfInterpreterFrameMethod() { | |
866 return getSP().addOffsetTo(SPARCRegisters.Lmethod.spOffsetInSavedWindow()); | |
867 } | |
868 | |
869 public Address addressOfInterpreterFrameCPCache() { | |
870 return getSP().addOffsetTo(SPARCRegisters.LcpoolCache.spOffsetInSavedWindow()); | |
871 } | |
872 | |
873 //-------------------------------------------------------------------------------- | |
874 // Entry frames: | |
875 // | |
876 | |
877 public JavaCallWrapper getEntryFrameCallWrapper() { | |
878 // Note: adjust this code if the link argument in StubGenerator::call_stub() changes! | |
879 SPARCArgument link = new SPARCArgument(0, false); | |
880 return (JavaCallWrapper) VMObjectFactory.newObject(JavaCallWrapper.class, | |
881 getSP().getAddressAt(link.asIn().asRegister().spOffsetInSavedWindow())); | |
882 } | |
883 | |
884 // | |
885 // | |
886 // inline JavaCallWrapper* frame::entry_frame_call_wrapper() const { | |
887 // // note: adjust this code if the link argument in StubGenerator::call_stub() changes! | |
888 // const Argument link = Argument(0, false); | |
889 // return (JavaCallWrapper*)sp()[link.as_in().as_register().sp_offset_in_saved_window()]; | |
890 // } | |
891 | |
892 //-------------------------------------------------------------------------------- | |
893 // Safepoints: | |
894 // | |
895 | |
896 protected Address addressOfSavedOopResult() { | |
897 return addressOfO0(); | |
898 } | |
899 | |
900 protected Address addressOfSavedReceiver() { | |
901 return addressOfO0(); | |
902 } | |
903 | |
904 | |
905 //-------------------------------------------------------------------------------- | |
906 // Internals only below this point | |
907 // | |
908 | |
909 private Address addressOfI7() { | |
910 return getSP().addOffsetTo(SPARCRegisters.I7.spOffsetInSavedWindow()); | |
911 } | |
912 | |
913 private Address addressOfO7() { | |
914 return afterSave().addressOfI7(); | |
915 } | |
916 | |
917 private Address addressOfI0() { | |
918 return getSP().addOffsetTo(SPARCRegisters.I0.spOffsetInSavedWindow()); | |
919 } | |
920 | |
921 private Address addressOfO0() { | |
922 return afterSave().addressOfI0(); | |
923 } | |
924 | |
925 private static boolean addressesEqual(Address a1, Address a2) { | |
926 if ((a1 == null) && (a2 == null)) { | |
927 return true; | |
928 } | |
929 | |
930 if ((a1 == null) || (a2 == null)) { | |
931 return false; | |
932 } | |
933 | |
934 return (a1.equals(a2)); | |
935 } | |
936 | |
937 | |
938 private Frame senderForEntryFrame(RegisterMap regMap) { | |
939 SPARCRegisterMap map = (SPARCRegisterMap) regMap; | |
940 | |
941 if (Assert.ASSERTS_ENABLED) { | |
942 Assert.that(map != null, "map must be set"); | |
943 } | |
944 // Java frame called from C; skip all C frames and return top C | |
945 // frame of that chunk as the sender | |
946 JavaCallWrapper jcw = getEntryFrameCallWrapper(); | |
947 if (Assert.ASSERTS_ENABLED) { | |
948 Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); | |
949 Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); | |
950 } | |
951 Address lastJavaSP = jcw.getLastJavaSP(); | |
952 Address lastJavaPC = jcw.getLastJavaPC(); | |
953 map.clear(); | |
954 | |
955 if (!VM.getVM().isCore()) { | |
956 map.makeIntegerRegsUnsaved(); | |
957 map.shiftWindow(lastJavaSP, null); | |
958 } | |
959 | |
960 if (Assert.ASSERTS_ENABLED) { | |
961 Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); | |
962 } | |
963 | |
964 if (lastJavaPC != null) { | |
965 return new SPARCFrame(biasSP(lastJavaSP), lastJavaPC); | |
966 } else { | |
967 Address youngerSP = getNextYoungerSP(lastJavaSP, getSP()); | |
968 return new SPARCFrame(biasSP(lastJavaSP), biasSP(youngerSP), false); | |
969 } | |
970 } | |
971 | |
972 private static Address getNextYoungerSP(Address oldSP, Address youngSP) { | |
973 Address sp = getNextYoungerSPOrNull(oldSP, youngSP, null); | |
974 if (Assert.ASSERTS_ENABLED) { | |
975 Assert.that(sp != null, "missed the SP"); | |
976 } | |
977 return sp; | |
978 } | |
979 | |
980 private static Address getNextYoungerSPOrNull(Address oldSP, Address youngSP, Address sp) { | |
981 if (youngSP == null) { | |
982 // FIXME | |
983 throw new RuntimeException("can not handle null youngSP in debugging system (seems to require register window flush)"); | |
984 } | |
985 | |
986 if (sp == null) { | |
987 sp = youngSP; | |
988 } | |
989 | |
990 Address previousSP = null; | |
991 | |
992 /** Minimum frame size is 16 */ | |
993 int maxFrames = (int) (oldSP.minus(sp) / (16 * VM.getVM().getAddressSize())); | |
994 | |
995 while(!sp.equals(oldSP) && spIsValid(oldSP, youngSP, sp)) { | |
996 if (maxFrames-- <= 0) { | |
997 // too many frames have gone by; invalid parameters given to this function | |
998 break; | |
999 } | |
1000 previousSP = sp; | |
1001 sp = unBiasSP(sp.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); | |
1002 } | |
1003 | |
1004 return (sp.equals(oldSP) ? previousSP : null); | |
1005 } | |
1006 | |
1007 private static boolean spIsValid(Address oldSP, Address youngSP, Address sp) { | |
1008 long mask = VM.getVM().getAddressSize(); | |
1009 mask = 2 * mask - 1; | |
1010 return ((sp.andWithMask(mask) == null) && | |
1011 (sp.lessThanOrEqual(oldSP)) && | |
1012 (sp.greaterThanOrEqual(youngSP))); | |
1013 } | |
1014 | |
1015 // FIXME: this is a hopefully temporary hack (not sure what is going on) | |
1016 public long getUContextOffset() { | |
1017 // FIXME: there is something I clearly don't understand about the | |
1018 // way the signal handler frame is laid out, because I shouldn't need this extra offset | |
1019 int MAJOR_HACK_OFFSET = 8; | |
1020 // System.out.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + ", fp = " + fp + ", youngerSP = " + youngerSP); | |
1021 return VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET); | |
1022 } | |
1023 | |
1024 public long getMContextAreaOffsetInUContext() { | |
1025 // From dbx-related sources: | |
1026 // /* | |
1027 // * struct sigframe is declaredf in the kernel sources in | |
1028 // * .../uts/sun4c/os/machdep.c/sendsig() | |
1029 // * unfortunately we only get a pointer to the 'uc' passed | |
1030 // * to the sighandler so we need to do this stuff to get | |
1031 // * to 'rwin'. | |
1032 // * Have to do it like this to take account of alignment. | |
1033 // */ | |
1034 // static struct sigframe { | |
1035 // struct rwindow rwin; | |
1036 // ucontext_t uc; | |
1037 // } sf_help; | |
1038 | |
1039 // From /usr/include/sys/ucontext.h: | |
1040 // #if !defined(_XPG4_2) || defined(__EXTENSIONS__) | |
1041 // struct ucontext { | |
1042 // #else | |
1043 // struct __ucontext { | |
1044 // #endif | |
1045 // uint_t uc_flags; | |
1046 // ucontext_t *uc_link; | |
1047 // sigset_t uc_sigmask; | |
1048 // stack_t uc_stack; | |
1049 // mcontext_t uc_mcontext; | |
1050 // #ifdef __sparcv9 | |
1051 // long uc_filler[4]; | |
1052 // #else /* __sparcv9 */ | |
1053 // long uc_filler[23]; | |
1054 // #endif /* __sparcv9 */ | |
1055 // }; | |
1056 | |
1057 // This walks to the start of the gregs in the mcontext_t | |
1058 // (first entry in that data structure). Really should read | |
1059 // this from header file. | |
1060 | |
1061 // Also not sure exactly how alignment works...maybe should read these offsets from the target VM | |
1062 // (When you have a hammer, everything looks like a nail) | |
1063 long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize()); // uc_flags | |
1064 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // uc_link plus | |
1065 // doubleword alignment for structs? | |
1066 offset += 16 + // uc_sigmask | |
1067 2 * VM.getVM().getAddressSize() + 4; // uc_stack | |
1068 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // doubleword alignment for structs? | |
1069 | |
1070 // System.out.println("SPARCFrame.getMContextAreaOffsetInUContext: offset = " + offset); | |
1071 | |
1072 return offset; | |
1073 } | |
1074 } |