hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
changeset 1 489c9b5090e2
child 5547 f4b087cbb361
equal deleted inserted replaced
0:fd16c54261b3 1:489c9b5090e2
       
     1 /*
       
     2  * Copyright 2001-2006 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  *
       
    23  */
       
    24 
       
    25 package sun.jvm.hotspot.runtime.x86;
       
    26 
       
    27 import java.util.*;
       
    28 import sun.jvm.hotspot.asm.x86.*;
       
    29 import sun.jvm.hotspot.code.*;
       
    30 import sun.jvm.hotspot.compiler.*;
       
    31 import sun.jvm.hotspot.debugger.*;
       
    32 import sun.jvm.hotspot.oops.*;
       
    33 import sun.jvm.hotspot.runtime.*;
       
    34 import sun.jvm.hotspot.types.*;
       
    35 import sun.jvm.hotspot.utilities.*;
       
    36 
       
    37 /** Specialization of and implementation of abstract methods of the
       
    38     Frame class for the x86 family of CPUs. */
       
    39 
       
    40 public class X86Frame extends Frame {
       
    41   private static final boolean DEBUG;
       
    42   static {
       
    43     DEBUG = System.getProperty("sun.jvm.hotspot.runtime.x86.X86Frame.DEBUG") != null;
       
    44   }
       
    45 
       
    46   // All frames
       
    47   private static final int LINK_OFFSET                =  0;
       
    48   private static final int RETURN_ADDR_OFFSET         =  1;
       
    49   private static final int SENDER_SP_OFFSET           =  2;
       
    50 
       
    51   // Interpreter frames
       
    52   private static final int INTERPRETER_FRAME_MIRROR_OFFSET    =  2; // for native calls only
       
    53   private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
       
    54   private static final int INTERPRETER_FRAME_LAST_SP_OFFSET   = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
       
    55   private static final int INTERPRETER_FRAME_METHOD_OFFSET    = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
       
    56   private static       int INTERPRETER_FRAME_MDX_OFFSET;         // Non-core builds only
       
    57   private static       int INTERPRETER_FRAME_CACHE_OFFSET;
       
    58   private static       int INTERPRETER_FRAME_LOCALS_OFFSET;
       
    59   private static       int INTERPRETER_FRAME_BCX_OFFSET;
       
    60   private static       int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
       
    61   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
       
    62   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
       
    63 
       
    64   // Entry frames
       
    65   private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET   =  2;
       
    66 
       
    67   // Native frames
       
    68   private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET =  2;
       
    69 
       
    70   static {
       
    71     VM.registerVMInitializedObserver(new Observer() {
       
    72         public void update(Observable o, Object data) {
       
    73           initialize(VM.getVM().getTypeDataBase());
       
    74         }
       
    75       });
       
    76   }
       
    77 
       
    78   private static synchronized void initialize(TypeDataBase db) {
       
    79     if (VM.getVM().isCore()) {
       
    80       INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
       
    81     } else {
       
    82       INTERPRETER_FRAME_MDX_OFFSET   = INTERPRETER_FRAME_METHOD_OFFSET - 1;
       
    83       INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
       
    84     }
       
    85     INTERPRETER_FRAME_LOCALS_OFFSET               = INTERPRETER_FRAME_CACHE_OFFSET - 1;
       
    86     INTERPRETER_FRAME_BCX_OFFSET                  = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
       
    87     INTERPRETER_FRAME_INITIAL_SP_OFFSET           = INTERPRETER_FRAME_BCX_OFFSET - 1;
       
    88     INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET    = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
       
    89     INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
       
    90   }
       
    91 
       
    92   // an additional field beyond sp and pc:
       
    93   Address raw_fp; // frame pointer
       
    94   private Address raw_unextendedSP;
       
    95 
       
    96   private X86Frame() {
       
    97   }
       
    98 
       
    99   private void adjustForDeopt() {
       
   100     if ( pc != null) {
       
   101       // Look for a deopt pc and if it is deopted convert to original pc
       
   102       CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
       
   103       if (cb != null && cb.isJavaMethod()) {
       
   104         NMethod nm = (NMethod) cb;
       
   105         if (pc.equals(nm.deoptBegin())) {
       
   106           if (Assert.ASSERTS_ENABLED) {
       
   107             Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
       
   108           }
       
   109           // adjust pc if frame is deoptimized.
       
   110           pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
       
   111           deoptimized = true;
       
   112         }
       
   113       }
       
   114     }
       
   115   }
       
   116 
       
   117   public X86Frame(Address raw_sp, Address raw_fp, Address pc) {
       
   118     this.raw_sp = raw_sp;
       
   119     this.raw_unextendedSP = raw_sp;
       
   120     this.raw_fp = raw_fp;
       
   121     this.pc = pc;
       
   122 
       
   123     // Frame must be fully constructed before this call
       
   124     adjustForDeopt();
       
   125 
       
   126     if (DEBUG) {
       
   127       System.out.println("X86Frame(sp, fp, pc): " + this);
       
   128       dumpStack();
       
   129     }
       
   130   }
       
   131 
       
   132   public X86Frame(Address raw_sp, Address raw_fp) {
       
   133     this.raw_sp = raw_sp;
       
   134     this.raw_unextendedSP = raw_sp;
       
   135     this.raw_fp = raw_fp;
       
   136     this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
       
   137 
       
   138     // Frame must be fully constructed before this call
       
   139     adjustForDeopt();
       
   140 
       
   141     if (DEBUG) {
       
   142       System.out.println("X86Frame(sp, fp): " + this);
       
   143       dumpStack();
       
   144     }
       
   145   }
       
   146 
       
   147   // This constructor should really take the unextended SP as an arg
       
   148   // but then the constructor is ambiguous with constructor that takes
       
   149   // a PC so take an int and convert it.
       
   150   public X86Frame(Address raw_sp, Address raw_fp, long extension) {
       
   151     this.raw_sp = raw_sp;
       
   152     if (raw_sp == null) {
       
   153       this.raw_unextendedSP = null;
       
   154     } else {
       
   155       this.raw_unextendedSP = raw_sp.addOffsetTo(extension);
       
   156     }
       
   157     this.raw_fp = raw_fp;
       
   158     this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
       
   159 
       
   160     // Frame must be fully constructed before this call
       
   161     adjustForDeopt();
       
   162 
       
   163     if (DEBUG) {
       
   164       System.out.println("X86Frame(sp, fp): " + this);
       
   165       dumpStack();
       
   166     }
       
   167 
       
   168   }
       
   169 
       
   170   public Object clone() {
       
   171     X86Frame frame = new X86Frame();
       
   172     frame.raw_sp = raw_sp;
       
   173     frame.raw_unextendedSP = raw_unextendedSP;
       
   174     frame.raw_fp = raw_fp;
       
   175     frame.raw_fp = raw_fp;
       
   176     frame.pc = pc;
       
   177     frame.deoptimized = deoptimized;
       
   178     return frame;
       
   179   }
       
   180 
       
   181   public boolean equals(Object arg) {
       
   182     if (arg == null) {
       
   183       return false;
       
   184     }
       
   185 
       
   186     if (!(arg instanceof X86Frame)) {
       
   187       return false;
       
   188     }
       
   189 
       
   190     X86Frame other = (X86Frame) arg;
       
   191 
       
   192     return (AddressOps.equal(getSP(), other.getSP()) &&
       
   193             AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
       
   194             AddressOps.equal(getFP(), other.getFP()) &&
       
   195             AddressOps.equal(getPC(), other.getPC()));
       
   196   }
       
   197 
       
   198   public int hashCode() {
       
   199     if (raw_sp == null) {
       
   200       return 0;
       
   201     }
       
   202 
       
   203     return raw_sp.hashCode();
       
   204   }
       
   205 
       
   206   public String toString() {
       
   207     return "sp: " + (getSP() == null? "null" : getSP().toString()) +
       
   208          ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) +
       
   209          ", fp: " + (getFP() == null? "null" : getFP().toString()) +
       
   210          ", pc: " + (pc == null? "null" : pc.toString());
       
   211   }
       
   212 
       
   213   // accessors for the instance variables
       
   214   public Address getFP() { return raw_fp; }
       
   215   public Address getSP() { return raw_sp; }
       
   216   public Address getID() { return raw_sp; }
       
   217 
       
   218   // FIXME: not implemented yet (should be done for Solaris/X86)
       
   219   public boolean isSignalHandlerFrameDbg() { return false; }
       
   220   public int     getSignalNumberDbg()      { return 0;     }
       
   221   public String  getSignalNameDbg()        { return null;  }
       
   222 
       
   223   public boolean isInterpretedFrameValid() {
       
   224     if (Assert.ASSERTS_ENABLED) {
       
   225       Assert.that(isInterpretedFrame(), "Not an interpreted frame");
       
   226     }
       
   227 
       
   228     // These are reasonable sanity checks
       
   229     if (getFP() == null || getFP().andWithMask(0x3) != null) {
       
   230       return false;
       
   231     }
       
   232 
       
   233     if (getSP() == null || getSP().andWithMask(0x3) != null) {
       
   234       return false;
       
   235     }
       
   236 
       
   237     if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) {
       
   238       return false;
       
   239     }
       
   240 
       
   241     // These are hacks to keep us out of trouble.
       
   242     // The problem with these is that they mask other problems
       
   243     if (getFP().lessThanOrEqual(getSP())) {
       
   244       // this attempts to deal with unsigned comparison above
       
   245       return false;
       
   246     }
       
   247 
       
   248     if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
       
   249       // stack frames shouldn't be large.
       
   250       return false;
       
   251     }
       
   252 
       
   253     return true;
       
   254   }
       
   255 
       
   256   // FIXME: not applicable in current system
       
   257   //  void    patch_pc(Thread* thread, address pc);
       
   258 
       
   259   public Frame sender(RegisterMap regMap, CodeBlob cb) {
       
   260     X86RegisterMap map = (X86RegisterMap) regMap;
       
   261 
       
   262     if (Assert.ASSERTS_ENABLED) {
       
   263       Assert.that(map != null, "map must be set");
       
   264     }
       
   265 
       
   266     // Default is we done have to follow them. The sender_for_xxx will
       
   267     // update it accordingly
       
   268     map.setIncludeArgumentOops(false);
       
   269 
       
   270     if (isEntryFrame())       return senderForEntryFrame(map);
       
   271     if (isInterpretedFrame()) return senderForInterpreterFrame(map);
       
   272 
       
   273     if (!VM.getVM().isCore()) {
       
   274       if(cb == null) {
       
   275         cb = VM.getVM().getCodeCache().findBlob(getPC());
       
   276       } else {
       
   277         if (Assert.ASSERTS_ENABLED) {
       
   278           Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
       
   279         }
       
   280       }
       
   281 
       
   282       if (cb != null) {
       
   283          return senderForCompiledFrame(map, cb);
       
   284       }
       
   285     }
       
   286 
       
   287     // Must be native-compiled frame, i.e. the marshaling code for native
       
   288     // methods that exists in the core system.
       
   289     return new X86Frame(getSenderSP(), getLink(), getSenderPC());
       
   290   }
       
   291 
       
   292   private Frame senderForEntryFrame(X86RegisterMap map) {
       
   293     if (Assert.ASSERTS_ENABLED) {
       
   294       Assert.that(map != null, "map must be set");
       
   295     }
       
   296     // Java frame called from C; skip all C frames and return top C
       
   297     // frame of that chunk as the sender
       
   298     X86JavaCallWrapper jcw = (X86JavaCallWrapper) getEntryFrameCallWrapper();
       
   299     if (Assert.ASSERTS_ENABLED) {
       
   300       Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
       
   301       Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
       
   302     }
       
   303     X86Frame fr;
       
   304     if (jcw.getLastJavaPC() != null) {
       
   305       fr = new X86Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
       
   306     } else {
       
   307       fr = new X86Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
       
   308     }
       
   309     map.clear();
       
   310     if (Assert.ASSERTS_ENABLED) {
       
   311       Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
       
   312     }
       
   313     return fr;
       
   314   }
       
   315 
       
   316   private Frame senderForInterpreterFrame(X86RegisterMap map) {
       
   317     Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
       
   318     Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
       
   319     // We do not need to update the callee-save register mapping because above
       
   320     // us is either another interpreter frame or a converter-frame, but never
       
   321     // directly a compiled frame.
       
   322     // 11/24/04 SFG. With the removal of adapter frames this is no longer true.
       
   323     // However c2 no longer uses callee save register for java calls so there
       
   324     // are no callee register to find.
       
   325 
       
   326     return new X86Frame(sp, getLink(), unextendedSP.minus(sp));
       
   327   }
       
   328 
       
   329   private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
       
   330     //
       
   331     // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess
       
   332     //
       
   333 
       
   334     if (Assert.ASSERTS_ENABLED) {
       
   335       Assert.that(map != null, "map must be set");
       
   336     }
       
   337 
       
   338     // frame owned by optimizing compiler
       
   339     Address        sender_sp = null;
       
   340 
       
   341     if (VM.getVM().isClientCompiler()) {
       
   342       sender_sp        = addressOfStackSlot(SENDER_SP_OFFSET);
       
   343     } else {
       
   344       if (Assert.ASSERTS_ENABLED) {
       
   345         Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use");
       
   346       }
       
   347       sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize());
       
   348     }
       
   349 
       
   350     // On Intel the return_address is always the word on the stack
       
   351     Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
       
   352 
       
   353     if (map.getUpdateMap() && cb.getOopMaps() != null) {
       
   354       OopMapSet.updateRegisterMap(this, cb, map, true);
       
   355     }
       
   356 
       
   357     if (VM.getVM().isClientCompiler()) {
       
   358       // Move this here for C1 and collecting oops in arguments (According to Rene)
       
   359       map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread()));
       
   360     }
       
   361 
       
   362     Address saved_fp = null;
       
   363     if (VM.getVM().isClientCompiler()) {
       
   364       saved_fp = getFP().getAddressAt(0);
       
   365     } else if (VM.getVM().isServerCompiler() &&
       
   366                (VM.getVM().getInterpreter().contains(sender_pc) ||
       
   367                VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) {
       
   368       // C2 prologue saves EBP in the usual place.
       
   369       // however only use it if the sender had link infomration in it.
       
   370       saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize());
       
   371     }
       
   372 
       
   373     return new X86Frame(sender_sp, saved_fp, sender_pc);
       
   374   }
       
   375 
       
   376   protected boolean hasSenderPD() {
       
   377     // FIXME
       
   378     // Check for null ebp? Need to do some tests.
       
   379     return true;
       
   380   }
       
   381 
       
   382   public long frameSize() {
       
   383     return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
       
   384   }
       
   385 
       
   386   public Address getLink() {
       
   387     return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
       
   388   }
       
   389 
       
   390   // FIXME: not implementable yet
       
   391   //inline void      frame::set_link(intptr_t* addr)  { *(intptr_t **)addr_at(link_offset) = addr; }
       
   392 
       
   393   public Address getUnextendedSP() { return raw_unextendedSP; }
       
   394 
       
   395   // Return address:
       
   396   public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
       
   397   public Address getSenderPC()     { return getSenderPCAddr().getAddressAt(0);      }
       
   398 
       
   399   // return address of param, zero origin index.
       
   400   public Address getNativeParamAddr(int idx) {
       
   401     return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
       
   402   }
       
   403 
       
   404   public Address getSenderSP()     { return addressOfStackSlot(SENDER_SP_OFFSET); }
       
   405 
       
   406   public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) {
       
   407     if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) {
       
   408       throw new RuntimeException("Should not reach here");
       
   409     }
       
   410 
       
   411     return oopMapRegToLocation(reg, regMap);
       
   412   }
       
   413 
       
   414   public Address addressOfInterpreterFrameLocals() {
       
   415     return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
       
   416   }
       
   417 
       
   418   private Address addressOfInterpreterFrameBCX() {
       
   419     return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
       
   420   }
       
   421 
       
   422   public int getInterpreterFrameBCI() {
       
   423     // FIXME: this is not atomic with respect to GC and is unsuitable
       
   424     // for use in a non-debugging, or reflective, system. Need to
       
   425     // figure out how to express this.
       
   426     Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
       
   427     OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0);
       
   428     Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle);
       
   429     return bcpToBci(bcp, method);
       
   430   }
       
   431 
       
   432   public Address addressOfInterpreterFrameMDX() {
       
   433     return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
       
   434   }
       
   435 
       
   436   // FIXME
       
   437   //inline int frame::interpreter_frame_monitor_size() {
       
   438   //  return BasicObjectLock::size();
       
   439   //}
       
   440 
       
   441   // expression stack
       
   442   // (the max_stack arguments are used by the GC; see class FrameClosure)
       
   443 
       
   444   public Address addressOfInterpreterFrameExpressionStack() {
       
   445     Address monitorEnd = interpreterFrameMonitorEnd().address();
       
   446     return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
       
   447   }
       
   448 
       
   449   public int getInterpreterFrameExpressionStackDirection() { return -1; }
       
   450 
       
   451   // top of expression stack
       
   452   public Address addressOfInterpreterFrameTOS() {
       
   453     return getSP();
       
   454   }
       
   455 
       
   456   /** Expression stack from top down */
       
   457   public Address addressOfInterpreterFrameTOSAt(int slot) {
       
   458     return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
       
   459   }
       
   460 
       
   461   public Address getInterpreterFrameSenderSP() {
       
   462     if (Assert.ASSERTS_ENABLED) {
       
   463       Assert.that(isInterpretedFrame(), "interpreted frame expected");
       
   464     }
       
   465     return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
       
   466   }
       
   467 
       
   468   // Monitors
       
   469   public BasicObjectLock interpreterFrameMonitorBegin() {
       
   470     return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
       
   471   }
       
   472 
       
   473   public BasicObjectLock interpreterFrameMonitorEnd() {
       
   474     Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
       
   475     if (Assert.ASSERTS_ENABLED) {
       
   476       // make sure the pointer points inside the frame
       
   477       Assert.that(AddressOps.gt(getFP(), result), "result must <  than frame pointer");
       
   478       Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
       
   479     }
       
   480     return new BasicObjectLock(result);
       
   481   }
       
   482 
       
   483   public int interpreterFrameMonitorSize() {
       
   484     return BasicObjectLock.size();
       
   485   }
       
   486 
       
   487   // Method
       
   488   public Address addressOfInterpreterFrameMethod() {
       
   489     return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
       
   490   }
       
   491 
       
   492   // Constant pool cache
       
   493   public Address addressOfInterpreterFrameCPCache() {
       
   494     return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
       
   495   }
       
   496 
       
   497   // Entry frames
       
   498   public JavaCallWrapper getEntryFrameCallWrapper() {
       
   499     return new X86JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
       
   500   }
       
   501 
       
   502   protected Address addressOfSavedOopResult() {
       
   503     // offset is 2 for compiler2 and 3 for compiler1
       
   504     return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
       
   505                                VM.getVM().getAddressSize());
       
   506   }
       
   507 
       
   508   protected Address addressOfSavedReceiver() {
       
   509     return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
       
   510   }
       
   511 
       
   512   private void dumpStack() {
       
   513     if (getFP() != null) {
       
   514       for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
       
   515            AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize()));
       
   516            addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
       
   517         System.out.println(addr + ": " + addr.getAddressAt(0));
       
   518       }
       
   519     } else {
       
   520       for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
       
   521            AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
       
   522            addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
       
   523         System.out.println(addr + ": " + addr.getAddressAt(0));
       
   524       }
       
   525     }
       
   526   }
       
   527 }