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, &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 }