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