src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java
changeset 47216 71c04702a3d5
parent 46620 750c6edff33b
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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   public static final int INTERPRETER_FRAME_MIRROR_OFFSET                 = -5;
       
   718   public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET           = -6;
       
   719   public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS                = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET;
       
   720 
       
   721   /** Interpreter frame set-up needs to save 2 extra words in outgoing
       
   722       param area for class and jnienv arguments for native stubs (see
       
   723       nativeStubGen_sparc.cpp) */
       
   724   public static final int INTERPRETER_FRAME_EXTRA_OUTGOING_ARGUMENT_WORDS = 2;
       
   725 
       
   726   // FIXME: elided for now
       
   727   //
       
   728   //  // the compiler frame has many of the same fields as the interpreter frame
       
   729   //  // %%%%% factor out declarations of the shared fields
       
   730   //  enum compiler_frame_fixed_locals {
       
   731   //       compiler_frame_d_scratch_fp_offset          = -2,
       
   732   //       compiler_frame_vm_locals_fp_offset          = -2, // should be same as above
       
   733   //
       
   734   //       compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset
       
   735   //  };
       
   736   //
       
   737   // private:
       
   738   //
       
   739   //  // where LcpoolCache is saved:
       
   740   //  ConstantPoolCache** interpreter_frame_cpoolcache_addr() const {
       
   741   //    return (ConstantPoolCache**)sp_addr_at( LcpoolCache.sp_offset_in_saved_window());
       
   742   //  }
       
   743   //
       
   744   //  // where Lmonitors is saved:
       
   745   //  BasicObjectLock**  interpreter_frame_monitors_addr() const {
       
   746   //    return (BasicObjectLock**) sp_addr_at( Lmonitors.sp_offset_in_saved_window());
       
   747   //  }
       
   748   //  intptr_t** interpreter_frame_esp_addr() const {
       
   749   //    return (intptr_t**)sp_addr_at( Lesp.sp_offset_in_saved_window());
       
   750   //  }
       
   751   //
       
   752   //  inline void interpreter_frame_set_tos_address(intptr_t* x);
       
   753   //
       
   754   //  // next two fns read and write Lmonitors value,
       
   755   // private:
       
   756   //  BasicObjectLock* interpreter_frame_monitors()           const  { return *interpreter_frame_monitors_addr(); }
       
   757   //  void interpreter_frame_set_monitors(BasicObjectLock* monitors) {        *interpreter_frame_monitors_addr() = monitors; }
       
   758   //
       
   759   //#ifndef CORE
       
   760   //inline oop *frame::pd_compiled_argument_to_location(VMReg::Name reg, RegisterMap reg_map, int arg_size) const {
       
   761   //  COMPILER1_ONLY(return (oop *) (arg_size - 1 - reg + sp() + memory_parameter_word_sp_offset);   )
       
   762   //  COMPILER2_ONLY(return oopmapreg_to_location(reg, &reg_map); )
       
   763   //}
       
   764   //#endif
       
   765 
       
   766   // FIXME: NOT FINISHED
       
   767   public Address addressOfInterpreterFrameLocals() {
       
   768     return getSP().addOffsetTo(SPARCRegisters.Llocals.spOffsetInSavedWindow());
       
   769   }
       
   770 
       
   771   // FIXME: this is not atomic with respect to GC and is unsuitable
       
   772   // for use in a non-debugging, or reflective, system.
       
   773   private Address addressOfInterpreterFrameBCX() {
       
   774     // %%%%% reinterpreting Lbcp as a bcx
       
   775     return getSP().addOffsetTo(SPARCRegisters.Lbcp.spOffsetInSavedWindow());
       
   776   }
       
   777 
       
   778   public int getInterpreterFrameBCI() {
       
   779     // FIXME: this is not atomic with respect to GC and is unsuitable
       
   780     // for use in a non-debugging, or reflective, system. Need to
       
   781     // figure out how to express this.
       
   782     Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
       
   783     Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
       
   784     Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
       
   785     return bcpToBci(bcp, method);
       
   786   }
       
   787 
       
   788   public Address addressOfInterpreterFrameExpressionStack() {
       
   789     return addressOfInterpreterFrameMonitors().addOffsetTo(-1 * VM.getVM().getAddressSize());
       
   790   }
       
   791 
       
   792   public int getInterpreterFrameExpressionStackDirection() {
       
   793     return -1;
       
   794   }
       
   795 
       
   796   /** Top of expression stack */
       
   797   public Address addressOfInterpreterFrameTOS() {
       
   798     return getSP().getAddressAt(SPARCRegisters.Lesp.spOffsetInSavedWindow()).addOffsetTo(VM.getVM().getAddressSize());
       
   799   }
       
   800 
       
   801   /** Expression stack from top down */
       
   802   public Address addressOfInterpreterFrameTOSAt(int slot) {
       
   803     return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
       
   804   }
       
   805 
       
   806   public Address getInterpreterFrameSenderSP() {
       
   807     if (Assert.ASSERTS_ENABLED) {
       
   808       Assert.that(isInterpretedFrame(), "interpreted frame expected");
       
   809     }
       
   810     return getFP();
       
   811   }
       
   812 
       
   813   // FIXME: elided for now
       
   814   //inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) {
       
   815   //  *interpreter_frame_esp_addr() = x - 1;
       
   816   //}
       
   817 
       
   818   //--------------------------------------------------------------------------------
       
   819   // Monitors:
       
   820   //
       
   821 
       
   822   private Address addressOfInterpreterFrameMonitors() {
       
   823     return getSP().addOffsetTo(SPARCRegisters.Lmonitors.spOffsetInSavedWindow()).getAddressAt(0);
       
   824   }
       
   825 
       
   826   // Monitors
       
   827   public BasicObjectLock interpreterFrameMonitorBegin() {
       
   828     int roundedVMLocalWords = Bits.roundTo(INTERPRETER_FRAME_VM_LOCAL_WORDS, WORDS_PER_LONG);
       
   829     return new BasicObjectLock(addressOfFPSlot(-1 * roundedVMLocalWords));
       
   830   }
       
   831 
       
   832   public BasicObjectLock interpreterFrameMonitorEnd() {
       
   833     return new BasicObjectLock(addressOfInterpreterFrameMonitors());
       
   834   }
       
   835 
       
   836   public int interpreterFrameMonitorSize() {
       
   837     return Bits.roundTo(BasicObjectLock.size(), WORDS_PER_LONG * (int) VM.getVM().getAddressSize());
       
   838   }
       
   839 
       
   840   // FIXME: elided for now
       
   841   // // monitor elements
       
   842   //
       
   843   // // in keeping with Intel side: end is lower in memory than begin;
       
   844   // // and beginning element is oldest element
       
   845   // // Also begin is one past last monitor.
       
   846   //
       
   847   // inline BasicObjectLock* frame::interpreter_frame_monitor_begin()       const  {
       
   848   //   int rounded_vm_local_words = align_up(frame::interpreter_frame_vm_local_words, WordsPerLong);
       
   849   //   return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words);
       
   850   // }
       
   851   //
       
   852   // inline BasicObjectLock* frame::interpreter_frame_monitor_end()         const  {
       
   853   //   return interpreter_frame_monitors();
       
   854   // }
       
   855   //
       
   856   //
       
   857   // inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
       
   858   //   interpreter_frame_set_monitors(value);
       
   859   // }
       
   860   //
       
   861   //
       
   862   // inline int frame::interpreter_frame_monitor_size() {
       
   863   //   return align_up(BasicObjectLock::size(), WordsPerLong);
       
   864   // }
       
   865 
       
   866   public Address addressOfInterpreterFrameMethod() {
       
   867     return getSP().addOffsetTo(SPARCRegisters.Lmethod.spOffsetInSavedWindow());
       
   868   }
       
   869 
       
   870   public Address addressOfInterpreterFrameCPCache() {
       
   871     return getSP().addOffsetTo(SPARCRegisters.LcpoolCache.spOffsetInSavedWindow());
       
   872   }
       
   873 
       
   874   //--------------------------------------------------------------------------------
       
   875   // Entry frames:
       
   876   //
       
   877 
       
   878   public JavaCallWrapper getEntryFrameCallWrapper() {
       
   879     // Note: adjust this code if the link argument in StubGenerator::call_stub() changes!
       
   880     SPARCArgument link = new SPARCArgument(0, false);
       
   881     return (JavaCallWrapper) VMObjectFactory.newObject(JavaCallWrapper.class,
       
   882                                                        getSP().getAddressAt(link.asIn().asRegister().spOffsetInSavedWindow()));
       
   883   }
       
   884 
       
   885   //
       
   886   //
       
   887   // inline JavaCallWrapper* frame::entry_frame_call_wrapper() const {
       
   888   //   // note: adjust this code if the link argument in StubGenerator::call_stub() changes!
       
   889   //   const Argument link = Argument(0, false);
       
   890   //   return (JavaCallWrapper*)sp()[link.as_in().as_register().sp_offset_in_saved_window()];
       
   891   // }
       
   892 
       
   893   //--------------------------------------------------------------------------------
       
   894   // Safepoints:
       
   895   //
       
   896 
       
   897   protected Address addressOfSavedOopResult() {
       
   898     return addressOfO0();
       
   899   }
       
   900 
       
   901   protected Address addressOfSavedReceiver() {
       
   902     return addressOfO0();
       
   903   }
       
   904 
       
   905 
       
   906   //--------------------------------------------------------------------------------
       
   907   // Internals only below this point
       
   908   //
       
   909 
       
   910   private Address addressOfI7() {
       
   911     return getSP().addOffsetTo(SPARCRegisters.I7.spOffsetInSavedWindow());
       
   912   }
       
   913 
       
   914   private Address addressOfO7() {
       
   915     return afterSave().addressOfI7();
       
   916   }
       
   917 
       
   918   private Address addressOfI0() {
       
   919     return getSP().addOffsetTo(SPARCRegisters.I0.spOffsetInSavedWindow());
       
   920   }
       
   921 
       
   922   private Address addressOfO0() {
       
   923     return afterSave().addressOfI0();
       
   924   }
       
   925 
       
   926   private static boolean addressesEqual(Address a1, Address a2) {
       
   927     if ((a1 == null) && (a2 == null)) {
       
   928       return true;
       
   929     }
       
   930 
       
   931     if ((a1 == null) || (a2 == null)) {
       
   932       return false;
       
   933     }
       
   934 
       
   935     return (a1.equals(a2));
       
   936   }
       
   937 
       
   938 
       
   939   private Frame senderForEntryFrame(RegisterMap regMap) {
       
   940     SPARCRegisterMap map = (SPARCRegisterMap) regMap;
       
   941 
       
   942     if (Assert.ASSERTS_ENABLED) {
       
   943       Assert.that(map != null, "map must be set");
       
   944     }
       
   945     // Java frame called from C; skip all C frames and return top C
       
   946     // frame of that chunk as the sender
       
   947     JavaCallWrapper jcw = getEntryFrameCallWrapper();
       
   948     if (Assert.ASSERTS_ENABLED) {
       
   949       Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
       
   950       Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
       
   951     }
       
   952     Address lastJavaSP = jcw.getLastJavaSP();
       
   953     Address lastJavaPC = jcw.getLastJavaPC();
       
   954     map.clear();
       
   955 
       
   956     map.makeIntegerRegsUnsaved();
       
   957     map.shiftWindow(lastJavaSP, null);
       
   958 
       
   959     if (Assert.ASSERTS_ENABLED) {
       
   960       Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
       
   961     }
       
   962 
       
   963     if (lastJavaPC != null) {
       
   964       return new SPARCFrame(biasSP(lastJavaSP), lastJavaPC);
       
   965     } else {
       
   966       Address youngerSP  = getNextYoungerSP(lastJavaSP, getSP());
       
   967       return new SPARCFrame(biasSP(lastJavaSP), biasSP(youngerSP), false);
       
   968     }
       
   969   }
       
   970 
       
   971   private static Address getNextYoungerSP(Address oldSP, Address youngSP) {
       
   972     Address sp = getNextYoungerSPOrNull(oldSP, youngSP, null);
       
   973     if (Assert.ASSERTS_ENABLED) {
       
   974       Assert.that(sp != null, "missed the SP");
       
   975     }
       
   976     return sp;
       
   977   }
       
   978 
       
   979   private static Address getNextYoungerSPOrNull(Address oldSP, Address youngSP, Address sp) {
       
   980     if (youngSP == null) {
       
   981       // FIXME
       
   982       throw new RuntimeException("can not handle null youngSP in debugging system (seems to require register window flush)");
       
   983     }
       
   984 
       
   985     if (sp == null) {
       
   986       sp = youngSP;
       
   987     }
       
   988 
       
   989     Address previousSP = null;
       
   990 
       
   991     /** Minimum frame size is 16 */
       
   992     int maxFrames = (int) (oldSP.minus(sp) / (16 * VM.getVM().getAddressSize()));
       
   993 
       
   994     while(!sp.equals(oldSP) && spIsValid(oldSP, youngSP, sp)) {
       
   995       if (maxFrames-- <= 0) {
       
   996         // too many frames have gone by; invalid parameters given to this function
       
   997         break;
       
   998       }
       
   999       previousSP = sp;
       
  1000       sp = unBiasSP(sp.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow()));
       
  1001     }
       
  1002 
       
  1003     return (sp.equals(oldSP) ? previousSP : null);
       
  1004   }
       
  1005 
       
  1006   private static boolean spIsValid(Address oldSP, Address youngSP, Address sp) {
       
  1007     long mask = VM.getVM().getAddressSize();
       
  1008     mask = 2 * mask - 1;
       
  1009     return ((sp.andWithMask(mask) == null) &&
       
  1010             (sp.lessThanOrEqual(oldSP)) &&
       
  1011             (sp.greaterThanOrEqual(youngSP)));
       
  1012   }
       
  1013 
       
  1014   // FIXME: this is a hopefully temporary hack (not sure what is going on)
       
  1015   public long getUContextOffset() {
       
  1016     // FIXME: there is something I clearly don't understand about the
       
  1017     // way the signal handler frame is laid out, because I shouldn't need this extra offset
       
  1018     int MAJOR_HACK_OFFSET = 8;
       
  1019     //    System.out.println("  SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + ", fp = " + fp + ", youngerSP = " + youngerSP);
       
  1020     return VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET);
       
  1021   }
       
  1022 
       
  1023   public long getMContextAreaOffsetInUContext() {
       
  1024     // From dbx-related sources:
       
  1025     // /*
       
  1026     //  * struct sigframe is declaredf in the kernel sources in
       
  1027     //  * .../uts/sun4c/os/machdep.c/sendsig()
       
  1028     //  * unfortunately we only get a pointer to the 'uc' passed
       
  1029     //  * to the sighandler so we need to do this stuff to get
       
  1030     //  * to 'rwin'.
       
  1031     //  * Have to do it like this to take account of alignment.
       
  1032     //  */
       
  1033     // static struct sigframe {
       
  1034     //     struct rwindow rwin;
       
  1035     //     ucontext_t uc;
       
  1036     // } sf_help;
       
  1037 
       
  1038     // From /usr/include/sys/ucontext.h:
       
  1039     // #if !defined(_XPG4_2) || defined(__EXTENSIONS__)
       
  1040     // struct   ucontext {
       
  1041     // #else
       
  1042     // struct   __ucontext {
       
  1043     // #endif
       
  1044     //  uint_t          uc_flags;
       
  1045     //  ucontext_t      *uc_link;
       
  1046     //  sigset_t        uc_sigmask;
       
  1047     //  stack_t         uc_stack;
       
  1048     //  mcontext_t      uc_mcontext;
       
  1049     // #ifdef   __sparcv9
       
  1050     //  long            uc_filler[4];
       
  1051     // #else    /* __sparcv9 */
       
  1052     //  long            uc_filler[23];
       
  1053     // #endif   /* __sparcv9 */
       
  1054     // };
       
  1055 
       
  1056     // This walks to the start of the gregs in the mcontext_t
       
  1057     // (first entry in that data structure). Really should read
       
  1058     // this from header file.
       
  1059 
       
  1060     // Also not sure exactly how alignment works...maybe should read these offsets from the target VM
       
  1061     // (When you have a hammer, everything looks like a nail)
       
  1062     long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize());   // uc_flags
       
  1063     offset      = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // uc_link plus
       
  1064                                                                         // doubleword alignment for structs?
       
  1065     offset     += 16 +                                                  // uc_sigmask
       
  1066                    2 * VM.getVM().getAddressSize() + 4;                 // uc_stack
       
  1067     offset      = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // doubleword alignment for structs?
       
  1068 
       
  1069     //    System.out.println("SPARCFrame.getMContextAreaOffsetInUContext: offset = " + offset);
       
  1070 
       
  1071     return offset;
       
  1072   }
       
  1073 }