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