1 /*
   2  * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * 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.deoptHandlerBegin())) {
 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     Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(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)Metadata.instantiateWrapperFor(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     // Note:  The version of this operation on any platform with callee-save
 563     //        registers must update the register map (if not null).
 564     //        In order to do this correctly, the various subtypes of
 565     //        of frame (interpreted, compiled, glue, native),
 566     //        must be distinguished.  There is no need on SPARC for
 567     //        such distinctions, because all callee-save registers are
 568     //        preserved for all frames via SPARC-specific mechanisms.
 569     //
 570     //        *** HOWEVER, *** if and when we make any floating-point
 571     //        registers callee-saved, then we will have to copy over
 572     //        the RegisterMap update logic from the Intel code.
 573 
 574     // The constructor of the sender must know whether this frame is interpreted so it can set the
 575     // sender's _interpreter_sp_adjustment field.
 576     if (VM.getVM().getInterpreter().contains(pc)) {
 577       isInterpreted = true;
 578       map.makeIntegerRegsUnsaved();
 579       map.shiftWindow(sp, youngerSP);
 580     } else {
 581       // Find a CodeBlob containing this frame's pc or elide the lookup and use the
 582       // supplied blob which is already known to be associated with this frame.
 583       cb = VM.getVM().getCodeCache().findBlob(pc);
 584       if (cb != null) {
 585         // Update the location of all implicitly saved registers
 586         // as the address of these registers in the register save
 587         // area (for %o registers we use the address of the %i
 588         // register in the next younger frame)
 589         map.shiftWindow(sp, youngerSP);
 590         if (map.getUpdateMap()) {
 591           if (cb.callerMustGCArguments()) {
 592             map.setIncludeArgumentOops(true);
 593           }
 594           if (cb.getOopMaps() != null) {
 595             OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging());
 596           }
 597         }
 598       }
 599     }
 600 
 601     return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted);
 602   }
 603 
 604   protected boolean hasSenderPD() {
 605     try {
 606       // FIXME: should not happen!!!
 607       if (getSP() == null) {
 608         return false;
 609       }
 610       if ( unBiasSP(getSP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())) == null ) {
 611         return false;
 612       }
 613       return true;
 614     } catch (RuntimeException e) {
 615       if (DEBUG) {
 616         System.out.println("Bad frame " + this);
 617       }
 618       throw e;
 619     }
 620   }
 621 
 622   //--------------------------------------------------------------------------------
 623   // Return address:
 624   //
 625 
 626   public Address getSenderPC() {
 627     return addressOfI7().getAddressAt(0).addOffsetTo(PC_RETURN_OFFSET);
 628   }
 629 
 630   // FIXME: currently unimplementable
 631   // inline void     frame::set_sender_pc(address addr) { *I7_addr() = addr - pc_return_offset; }
 632 
 633   public Address getUnextendedSP() {
 634     return getSP().addOffsetTo(interpreterSPAdjustmentOffset);
 635   }
 636 
 637   public Address getSenderSP() {
 638     return getFP();
 639   }
 640 
 641   /** Given the next-younger sp for a given frame's sp, compute the
 642       frame. We need the next-younger sp, because its register save
 643       area holds the flushed copy of its I7, which is the PC of the
 644       frame we are interested in. */
 645   public SPARCFrame afterSave() {
 646     return new SPARCFrame(biasSP(getYoungerSP()), null);
 647   }
 648 
 649   /** Accessors for the instance variables */
 650   public Address getFP() {
 651     Address sp = getSP();
 652     if (sp == null) {
 653       System.out.println("SPARCFrame.getFP(): sp == null");
 654     }
 655     Address fpAddr = sp.addOffsetTo(SPARCRegisters.FP.spOffsetInSavedWindow());
 656     try {
 657       Address fp = unBiasSP(fpAddr.getAddressAt(0));
 658       if (fp == null) {
 659         System.out.println("SPARCFrame.getFP(): fp == null (&fp == " + fpAddr + ")");
 660       }
 661       return fp;
 662     } catch (RuntimeException e) {
 663       System.out.println("SPARCFrame.getFP(): is bad (&fp == " + fpAddr + " sp = " + sp + ")");
 664       return null;
 665     }
 666   }
 667 
 668   private Address addressOfFPSlot(int index) {
 669     return getFP().addOffsetTo(index * VM.getVM().getAddressSize());
 670   }
 671 
 672   // FIXME: temporarily elided
 673   //  // All frames
 674   //
 675   //  intptr_t*  fp_addr_at(int index) const   { return &fp()[index];    }
 676   //  intptr_t*  sp_addr_at(int index) const   { return &sp()[index];    }
 677   //  intptr_t    fp_at(     int index) const   { return *fp_addr_at(index); }
 678   //  intptr_t    sp_at(     int index) const   { return *sp_addr_at(index); }
 679   //
 680   // private:
 681   //  inline address* I7_addr() const;
 682   //  inline address* O7_addr() const;
 683   //
 684   //  inline address* I0_addr() const;
 685   //  inline address* O0_addr() const;
 686   //
 687   // public:
 688   //  // access to SPARC arguments and argument registers
 689   //
 690   //  intptr_t*     register_addr(Register reg) const {
 691   //    return sp_addr_at(reg.sp_offset_in_saved_window());
 692   //  }
 693   //  intptr_t* memory_param_addr(int param_ix, bool is_in) const {
 694   //    int offset = callee_register_argument_save_area_sp_offset + param_ix;
 695   //    if (is_in)
 696   //      return fp_addr_at(offset);
 697   //    else
 698   //      return sp_addr_at(offset);
 699   //  }
 700   //  intptr_t*        param_addr(int param_ix, bool is_in) const {
 701   //    if (param_ix >= callee_register_argument_save_area_words)
 702   //      return memory_param_addr(param_ix, is_in);
 703   //    else if (is_in)
 704   //      return register_addr(Argument(param_ix, true).as_register());
 705   //    else {
 706   //      // the registers are stored in the next younger frame
 707   //      // %%% is this really necessary?
 708   //      frame next_younger = after_save();
 709   //      return next_younger.register_addr(Argument(param_ix, true).as_register());
 710   //    }
 711   //  }
 712 
 713   //--------------------------------------------------------------------------------
 714   // Interpreter frames:
 715   //
 716 
 717   /** 2 words, also used to save float regs across  calls to C */
 718   public static final int INTERPRETER_FRAME_D_SCRATCH_FP_OFFSET           = -2;
 719   public static final int INTERPRETER_FRAME_L_SCRATCH_FP_OFFSET           = -4;
 720   /** For native calls only */
 721   public static final int INTERPRETER_FRAME_PADDING_OFFSET                = -5;
 722   /** For native calls only */
 723   public static final int INTERPRETER_FRAME_MIRROR_OFFSET                 = -6;
 724   /** Should be same as above, and should be zero mod 8 */
 725   public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET           = -6;
 726   public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS                = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET;
 727 
 728   /** Interpreter frame set-up needs to save 2 extra words in outgoing
 729       param area for class and jnienv arguments for native stubs (see
 730       nativeStubGen_sparc.cpp) */
 731   public static final int INTERPRETER_FRAME_EXTRA_OUTGOING_ARGUMENT_WORDS = 2;
 732 
 733   // FIXME: elided for now
 734   //
 735   //  // the compiler frame has many of the same fields as the interpreter frame
 736   //  // %%%%% factor out declarations of the shared fields
 737   //  enum compiler_frame_fixed_locals {
 738   //       compiler_frame_d_scratch_fp_offset          = -2,
 739   //       compiler_frame_vm_locals_fp_offset          = -2, // should be same as above
 740   //
 741   //       compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset
 742   //  };
 743   //
 744   // private:
 745   //
 746   //  // where LcpoolCache is saved:
 747   //  ConstantPoolCache** interpreter_frame_cpoolcache_addr() const {
 748   //    return (ConstantPoolCache**)sp_addr_at( LcpoolCache.sp_offset_in_saved_window());
 749   //  }
 750   //
 751   //  // where Lmonitors is saved:
 752   //  BasicObjectLock**  interpreter_frame_monitors_addr() const {
 753   //    return (BasicObjectLock**) sp_addr_at( Lmonitors.sp_offset_in_saved_window());
 754   //  }
 755   //  intptr_t** interpreter_frame_esp_addr() const {
 756   //    return (intptr_t**)sp_addr_at( Lesp.sp_offset_in_saved_window());
 757   //  }
 758   //
 759   //  inline void interpreter_frame_set_tos_address(intptr_t* x);
 760   //
 761   //  // next two fns read and write Lmonitors value,
 762   // private:
 763   //  BasicObjectLock* interpreter_frame_monitors()           const  { return *interpreter_frame_monitors_addr(); }
 764   //  void interpreter_frame_set_monitors(BasicObjectLock* monitors) {        *interpreter_frame_monitors_addr() = monitors; }
 765   //
 766   //#ifndef CORE
 767   //inline oop *frame::pd_compiled_argument_to_location(VMReg::Name reg, RegisterMap reg_map, int arg_size) const {
 768   //  COMPILER1_ONLY(return (oop *) (arg_size - 1 - reg + sp() + memory_parameter_word_sp_offset);   )
 769   //  COMPILER2_ONLY(return oopmapreg_to_location(reg, &reg_map); )
 770   //}
 771   //#endif
 772 
 773   // FIXME: NOT FINISHED
 774   public Address addressOfInterpreterFrameLocals() {
 775     return getSP().addOffsetTo(SPARCRegisters.Llocals.spOffsetInSavedWindow());
 776   }
 777 
 778   // FIXME: this is not atomic with respect to GC and is unsuitable
 779   // for use in a non-debugging, or reflective, system.
 780   private Address addressOfInterpreterFrameBCX() {
 781     // %%%%% reinterpreting Lbcp as a bcx
 782     return getSP().addOffsetTo(SPARCRegisters.Lbcp.spOffsetInSavedWindow());
 783   }
 784 
 785   public int getInterpreterFrameBCI() {
 786     // FIXME: this is not atomic with respect to GC and is unsuitable
 787     // for use in a non-debugging, or reflective, system. Need to
 788     // figure out how to express this.
 789     Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
 790     Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
 791     Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
 792     return bcpToBci(bcp, method);
 793   }
 794 
 795   public Address addressOfInterpreterFrameExpressionStack() {
 796     return addressOfInterpreterFrameMonitors().addOffsetTo(-1 * VM.getVM().getAddressSize());
 797   }
 798 
 799   public int getInterpreterFrameExpressionStackDirection() {
 800     return -1;
 801   }
 802 
 803   /** Top of expression stack */
 804   public Address addressOfInterpreterFrameTOS() {
 805     return getSP().getAddressAt(SPARCRegisters.Lesp.spOffsetInSavedWindow()).addOffsetTo(VM.getVM().getAddressSize());
 806   }
 807 
 808   /** Expression stack from top down */
 809   public Address addressOfInterpreterFrameTOSAt(int slot) {
 810     return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
 811   }
 812 
 813   public Address getInterpreterFrameSenderSP() {
 814     if (Assert.ASSERTS_ENABLED) {
 815       Assert.that(isInterpretedFrame(), "interpreted frame expected");
 816     }
 817     return getFP();
 818   }
 819 
 820   // FIXME: elided for now
 821   //inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) {
 822   //  *interpreter_frame_esp_addr() = x - 1;
 823   //}
 824 
 825   //--------------------------------------------------------------------------------
 826   // Monitors:
 827   //
 828 
 829   private Address addressOfInterpreterFrameMonitors() {
 830     return getSP().addOffsetTo(SPARCRegisters.Lmonitors.spOffsetInSavedWindow()).getAddressAt(0);
 831   }
 832 
 833   // Monitors
 834   public BasicObjectLock interpreterFrameMonitorBegin() {
 835     int roundedVMLocalWords = Bits.roundTo(INTERPRETER_FRAME_VM_LOCAL_WORDS, WORDS_PER_LONG);
 836     return new BasicObjectLock(addressOfFPSlot(-1 * roundedVMLocalWords));
 837   }
 838 
 839   public BasicObjectLock interpreterFrameMonitorEnd() {
 840     return new BasicObjectLock(addressOfInterpreterFrameMonitors());
 841   }
 842 
 843   public int interpreterFrameMonitorSize() {
 844     return Bits.roundTo(BasicObjectLock.size(), WORDS_PER_LONG * (int) VM.getVM().getAddressSize());
 845   }
 846 
 847   // FIXME: elided for now
 848   // // monitor elements
 849   //
 850   // // in keeping with Intel side: end is lower in memory than begin;
 851   // // and beginning element is oldest element
 852   // // Also begin is one past last monitor.
 853   //
 854   // inline BasicObjectLock* frame::interpreter_frame_monitor_begin()       const  {
 855   //   int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong);
 856   //   return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words);
 857   // }
 858   //
 859   // inline BasicObjectLock* frame::interpreter_frame_monitor_end()         const  {
 860   //   return interpreter_frame_monitors();
 861   // }
 862   //
 863   //
 864   // inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
 865   //   interpreter_frame_set_monitors(value);
 866   // }
 867   //
 868   //
 869   // inline int frame::interpreter_frame_monitor_size() {
 870   //   return round_to(BasicObjectLock::size(), WordsPerLong);
 871   // }
 872 
 873   public Address addressOfInterpreterFrameMethod() {
 874     return getSP().addOffsetTo(SPARCRegisters.Lmethod.spOffsetInSavedWindow());
 875   }
 876 
 877   public Address addressOfInterpreterFrameCPCache() {
 878     return getSP().addOffsetTo(SPARCRegisters.LcpoolCache.spOffsetInSavedWindow());
 879   }
 880 
 881   //--------------------------------------------------------------------------------
 882   // Entry frames:
 883   //
 884 
 885   public JavaCallWrapper getEntryFrameCallWrapper() {
 886     // Note: adjust this code if the link argument in StubGenerator::call_stub() changes!
 887     SPARCArgument link = new SPARCArgument(0, false);
 888     return (JavaCallWrapper) VMObjectFactory.newObject(JavaCallWrapper.class,
 889                                                        getSP().getAddressAt(link.asIn().asRegister().spOffsetInSavedWindow()));
 890   }
 891 
 892   //
 893   //
 894   // inline JavaCallWrapper* frame::entry_frame_call_wrapper() const {
 895   //   // note: adjust this code if the link argument in StubGenerator::call_stub() changes!
 896   //   const Argument link = Argument(0, false);
 897   //   return (JavaCallWrapper*)sp()[link.as_in().as_register().sp_offset_in_saved_window()];
 898   // }
 899 
 900   //--------------------------------------------------------------------------------
 901   // Safepoints:
 902   //
 903 
 904   protected Address addressOfSavedOopResult() {
 905     return addressOfO0();
 906   }
 907 
 908   protected Address addressOfSavedReceiver() {
 909     return addressOfO0();
 910   }
 911 
 912 
 913   //--------------------------------------------------------------------------------
 914   // Internals only below this point
 915   //
 916 
 917   private Address addressOfI7() {
 918     return getSP().addOffsetTo(SPARCRegisters.I7.spOffsetInSavedWindow());
 919   }
 920 
 921   private Address addressOfO7() {
 922     return afterSave().addressOfI7();
 923   }
 924 
 925   private Address addressOfI0() {
 926     return getSP().addOffsetTo(SPARCRegisters.I0.spOffsetInSavedWindow());
 927   }
 928 
 929   private Address addressOfO0() {
 930     return afterSave().addressOfI0();
 931   }
 932 
 933   private static boolean addressesEqual(Address a1, Address a2) {
 934     if ((a1 == null) && (a2 == null)) {
 935       return true;
 936     }
 937 
 938     if ((a1 == null) || (a2 == null)) {
 939       return false;
 940     }
 941 
 942     return (a1.equals(a2));
 943   }
 944 
 945 
 946   private Frame senderForEntryFrame(RegisterMap regMap) {
 947     SPARCRegisterMap map = (SPARCRegisterMap) regMap;
 948 
 949     if (Assert.ASSERTS_ENABLED) {
 950       Assert.that(map != null, "map must be set");
 951     }
 952     // Java frame called from C; skip all C frames and return top C
 953     // frame of that chunk as the sender
 954     JavaCallWrapper jcw = getEntryFrameCallWrapper();
 955     if (Assert.ASSERTS_ENABLED) {
 956       Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
 957       Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
 958     }
 959     Address lastJavaSP = jcw.getLastJavaSP();
 960     Address lastJavaPC = jcw.getLastJavaPC();
 961     map.clear();
 962 
 963     map.makeIntegerRegsUnsaved();
 964     map.shiftWindow(lastJavaSP, null);
 965 
 966     if (Assert.ASSERTS_ENABLED) {
 967       Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
 968     }
 969 
 970     if (lastJavaPC != null) {
 971       return new SPARCFrame(biasSP(lastJavaSP), lastJavaPC);
 972     } else {
 973       Address youngerSP  = getNextYoungerSP(lastJavaSP, getSP());
 974       return new SPARCFrame(biasSP(lastJavaSP), biasSP(youngerSP), false);
 975     }
 976   }
 977 
 978   private static Address getNextYoungerSP(Address oldSP, Address youngSP) {
 979     Address sp = getNextYoungerSPOrNull(oldSP, youngSP, null);
 980     if (Assert.ASSERTS_ENABLED) {
 981       Assert.that(sp != null, "missed the SP");
 982     }
 983     return sp;
 984   }
 985 
 986   private static Address getNextYoungerSPOrNull(Address oldSP, Address youngSP, Address sp) {
 987     if (youngSP == null) {
 988       // FIXME
 989       throw new RuntimeException("can not handle null youngSP in debugging system (seems to require register window flush)");
 990     }
 991 
 992     if (sp == null) {
 993       sp = youngSP;
 994     }
 995 
 996     Address previousSP = null;
 997 
 998     /** Minimum frame size is 16 */
 999     int maxFrames = (int) (oldSP.minus(sp) / (16 * VM.getVM().getAddressSize()));
1000 
1001     while(!sp.equals(oldSP) && spIsValid(oldSP, youngSP, sp)) {
1002       if (maxFrames-- <= 0) {
1003         // too many frames have gone by; invalid parameters given to this function
1004         break;
1005       }
1006       previousSP = sp;
1007       sp = unBiasSP(sp.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow()));
1008     }
1009 
1010     return (sp.equals(oldSP) ? previousSP : null);
1011   }
1012 
1013   private static boolean spIsValid(Address oldSP, Address youngSP, Address sp) {
1014     long mask = VM.getVM().getAddressSize();
1015     mask = 2 * mask - 1;
1016     return ((sp.andWithMask(mask) == null) &&
1017             (sp.lessThanOrEqual(oldSP)) &&
1018             (sp.greaterThanOrEqual(youngSP)));
1019   }
1020 
1021   // FIXME: this is a hopefully temporary hack (not sure what is going on)
1022   public long getUContextOffset() {
1023     // FIXME: there is something I clearly don't understand about the
1024     // way the signal handler frame is laid out, because I shouldn't need this extra offset
1025     int MAJOR_HACK_OFFSET = 8;
1026     //    System.out.println("  SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + ", fp = " + fp + ", youngerSP = " + youngerSP);
1027     return VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET);
1028   }
1029 
1030   public long getMContextAreaOffsetInUContext() {
1031     // From dbx-related sources:
1032     // /*
1033     //  * struct sigframe is declaredf in the kernel sources in
1034     //  * .../uts/sun4c/os/machdep.c/sendsig()
1035     //  * unfortunately we only get a pointer to the 'uc' passed
1036     //  * to the sighandler so we need to do this stuff to get
1037     //  * to 'rwin'.
1038     //  * Have to do it like this to take account of alignment.
1039     //  */
1040     // static struct sigframe {
1041     //     struct rwindow rwin;
1042     //     ucontext_t uc;
1043     // } sf_help;
1044 
1045     // From /usr/include/sys/ucontext.h:
1046     // #if !defined(_XPG4_2) || defined(__EXTENSIONS__)
1047     // struct   ucontext {
1048     // #else
1049     // struct   __ucontext {
1050     // #endif
1051     //  uint_t          uc_flags;
1052     //  ucontext_t      *uc_link;
1053     //  sigset_t        uc_sigmask;
1054     //  stack_t         uc_stack;
1055     //  mcontext_t      uc_mcontext;
1056     // #ifdef   __sparcv9
1057     //  long            uc_filler[4];
1058     // #else    /* __sparcv9 */
1059     //  long            uc_filler[23];
1060     // #endif   /* __sparcv9 */
1061     // };
1062 
1063     // This walks to the start of the gregs in the mcontext_t
1064     // (first entry in that data structure). Really should read
1065     // this from header file.
1066 
1067     // Also not sure exactly how alignment works...maybe should read these offsets from the target VM
1068     // (When you have a hammer, everything looks like a nail)
1069     long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize());   // uc_flags
1070     offset      = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // uc_link plus
1071                                                                         // doubleword alignment for structs?
1072     offset     += 16 +                                                  // uc_sigmask
1073                    2 * VM.getVM().getAddressSize() + 4;                 // uc_stack
1074     offset      = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // doubleword alignment for structs?
1075 
1076     //    System.out.println("SPARCFrame.getMContextAreaOffsetInUContext: offset = " + offset);
1077 
1078     return offset;
1079   }
1080 }