hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
changeset 10517 f92c9ff3a15f
parent 5547 f4b087cbb361
child 13391 30245956af37
equal deleted inserted replaced
10516:2797e487c09f 10517:f92c9ff3a15f
    23  */
    23  */
    24 
    24 
    25 package sun.jvm.hotspot.runtime.x86;
    25 package sun.jvm.hotspot.runtime.x86;
    26 
    26 
    27 import java.util.*;
    27 import java.util.*;
    28 import sun.jvm.hotspot.asm.x86.*;
       
    29 import sun.jvm.hotspot.code.*;
    28 import sun.jvm.hotspot.code.*;
    30 import sun.jvm.hotspot.compiler.*;
    29 import sun.jvm.hotspot.compiler.*;
    31 import sun.jvm.hotspot.debugger.*;
    30 import sun.jvm.hotspot.debugger.*;
    32 import sun.jvm.hotspot.oops.*;
    31 import sun.jvm.hotspot.oops.*;
    33 import sun.jvm.hotspot.runtime.*;
    32 import sun.jvm.hotspot.runtime.*;
    60   private static       int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
    59   private static       int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
    61   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
    60   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
    62   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
    61   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
    63 
    62 
    64   // Entry frames
    63   // Entry frames
    65   private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET   =  2;
    64   private static       int ENTRY_FRAME_CALL_WRAPPER_OFFSET;
    66 
    65 
    67   // Native frames
    66   // Native frames
    68   private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET =  2;
    67   private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET =  2;
       
    68 
       
    69   private static VMReg rbp;
    69 
    70 
    70   static {
    71   static {
    71     VM.registerVMInitializedObserver(new Observer() {
    72     VM.registerVMInitializedObserver(new Observer() {
    72         public void update(Observable o, Object data) {
    73         public void update(Observable o, Object data) {
    73           initialize(VM.getVM().getTypeDataBase());
    74           initialize(VM.getVM().getTypeDataBase());
    74         }
    75         }
    75       });
    76       });
    76   }
    77   }
    77 
    78 
    78   private static synchronized void initialize(TypeDataBase db) {
    79   private static synchronized void initialize(TypeDataBase db) {
    79     if (VM.getVM().isCore()) {
    80     INTERPRETER_FRAME_MDX_OFFSET                  = INTERPRETER_FRAME_METHOD_OFFSET - 1;
    80       INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
    81     INTERPRETER_FRAME_CACHE_OFFSET                = INTERPRETER_FRAME_MDX_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;
    82     INTERPRETER_FRAME_LOCALS_OFFSET               = INTERPRETER_FRAME_CACHE_OFFSET - 1;
    86     INTERPRETER_FRAME_BCX_OFFSET                  = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
    83     INTERPRETER_FRAME_BCX_OFFSET                  = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
    87     INTERPRETER_FRAME_INITIAL_SP_OFFSET           = INTERPRETER_FRAME_BCX_OFFSET - 1;
    84     INTERPRETER_FRAME_INITIAL_SP_OFFSET           = INTERPRETER_FRAME_BCX_OFFSET - 1;
    88     INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET    = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
    85     INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET    = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
    89     INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
    86     INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
    90   }
    87 
       
    88     ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset");
       
    89     if (VM.getVM().getAddressSize() == 4) {
       
    90       rbp = new VMReg(5);
       
    91     } else {
       
    92       rbp = new VMReg(5 << 1);
       
    93     }
       
    94   }
       
    95 
    91 
    96 
    92   // an additional field beyond sp and pc:
    97   // an additional field beyond sp and pc:
    93   Address raw_fp; // frame pointer
    98   Address raw_fp; // frame pointer
    94   private Address raw_unextendedSP;
    99   private Address raw_unextendedSP;
    95 
   100 
   100     if ( pc != null) {
   105     if ( pc != null) {
   101       // Look for a deopt pc and if it is deopted convert to original pc
   106       // Look for a deopt pc and if it is deopted convert to original pc
   102       CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
   107       CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
   103       if (cb != null && cb.isJavaMethod()) {
   108       if (cb != null && cb.isJavaMethod()) {
   104         NMethod nm = (NMethod) cb;
   109         NMethod nm = (NMethod) cb;
   105         if (pc.equals(nm.deoptBegin())) {
   110         if (pc.equals(nm.deoptHandlerBegin())) {
   106           if (Assert.ASSERTS_ENABLED) {
   111           if (Assert.ASSERTS_ENABLED) {
   107             Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
   112             Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
   108           }
   113           }
   109           // adjust pc if frame is deoptimized.
   114           // adjust pc if frame is deoptimized.
   110           pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
   115           pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
   117   public X86Frame(Address raw_sp, Address raw_fp, Address pc) {
   122   public X86Frame(Address raw_sp, Address raw_fp, Address pc) {
   118     this.raw_sp = raw_sp;
   123     this.raw_sp = raw_sp;
   119     this.raw_unextendedSP = raw_sp;
   124     this.raw_unextendedSP = raw_sp;
   120     this.raw_fp = raw_fp;
   125     this.raw_fp = raw_fp;
   121     this.pc = pc;
   126     this.pc = pc;
       
   127     adjustUnextendedSP();
   122 
   128 
   123     // Frame must be fully constructed before this call
   129     // Frame must be fully constructed before this call
   124     adjustForDeopt();
   130     adjustForDeopt();
   125 
   131 
   126     if (DEBUG) {
   132     if (DEBUG) {
   132   public X86Frame(Address raw_sp, Address raw_fp) {
   138   public X86Frame(Address raw_sp, Address raw_fp) {
   133     this.raw_sp = raw_sp;
   139     this.raw_sp = raw_sp;
   134     this.raw_unextendedSP = raw_sp;
   140     this.raw_unextendedSP = raw_sp;
   135     this.raw_fp = raw_fp;
   141     this.raw_fp = raw_fp;
   136     this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
   142     this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
       
   143     adjustUnextendedSP();
   137 
   144 
   138     // Frame must be fully constructed before this call
   145     // Frame must be fully constructed before this call
   139     adjustForDeopt();
   146     adjustForDeopt();
   140 
   147 
   141     if (DEBUG) {
   148     if (DEBUG) {
   142       System.out.println("X86Frame(sp, fp): " + this);
   149       System.out.println("X86Frame(sp, fp): " + this);
   143       dumpStack();
   150       dumpStack();
   144     }
   151     }
   145   }
   152   }
   146 
   153 
   147   // This constructor should really take the unextended SP as an arg
   154   public X86Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
   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;
   155     this.raw_sp = raw_sp;
   152     if (raw_sp == null) {
   156     this.raw_unextendedSP = raw_unextendedSp;
   153       this.raw_unextendedSP = null;
       
   154     } else {
       
   155       this.raw_unextendedSP = raw_sp.addOffsetTo(extension);
       
   156     }
       
   157     this.raw_fp = raw_fp;
   157     this.raw_fp = raw_fp;
   158     this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
   158     this.pc = pc;
       
   159     adjustUnextendedSP();
   159 
   160 
   160     // Frame must be fully constructed before this call
   161     // Frame must be fully constructed before this call
   161     adjustForDeopt();
   162     adjustForDeopt();
   162 
   163 
   163     if (DEBUG) {
   164     if (DEBUG) {
   164       System.out.println("X86Frame(sp, fp): " + this);
   165       System.out.println("X86Frame(sp, unextendedSP, fp, pc): " + this);
   165       dumpStack();
   166       dumpStack();
   166     }
   167     }
   167 
   168 
   168   }
   169   }
   169 
   170 
   170   public Object clone() {
   171   public Object clone() {
   171     X86Frame frame = new X86Frame();
   172     X86Frame frame = new X86Frame();
   172     frame.raw_sp = raw_sp;
   173     frame.raw_sp = raw_sp;
   173     frame.raw_unextendedSP = raw_unextendedSP;
   174     frame.raw_unextendedSP = raw_unextendedSP;
   174     frame.raw_fp = raw_fp;
   175     frame.raw_fp = raw_fp;
   175     frame.raw_fp = raw_fp;
       
   176     frame.pc = pc;
   176     frame.pc = pc;
   177     frame.deoptimized = deoptimized;
   177     frame.deoptimized = deoptimized;
   178     return frame;
   178     return frame;
   179   }
   179   }
   180 
   180 
   267     // update it accordingly
   267     // update it accordingly
   268     map.setIncludeArgumentOops(false);
   268     map.setIncludeArgumentOops(false);
   269 
   269 
   270     if (isEntryFrame())       return senderForEntryFrame(map);
   270     if (isEntryFrame())       return senderForEntryFrame(map);
   271     if (isInterpretedFrame()) return senderForInterpreterFrame(map);
   271     if (isInterpretedFrame()) return senderForInterpreterFrame(map);
   272 
   272     if (isRicochetFrame())    return senderForRicochetFrame(map);
   273     if (!VM.getVM().isCore()) {
   273 
   274       if(cb == null) {
   274     if(cb == null) {
   275         cb = VM.getVM().getCodeCache().findBlob(getPC());
   275       cb = VM.getVM().getCodeCache().findBlob(getPC());
   276       } else {
   276     } else {
   277         if (Assert.ASSERTS_ENABLED) {
   277       if (Assert.ASSERTS_ENABLED) {
   278           Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
   278         Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
   279         }
   279       }
   280       }
   280     }
   281 
   281 
   282       if (cb != null) {
   282     if (cb != null) {
   283          return senderForCompiledFrame(map, cb);
   283       return senderForCompiledFrame(map, cb);
   284       }
       
   285     }
   284     }
   286 
   285 
   287     // Must be native-compiled frame, i.e. the marshaling code for native
   286     // Must be native-compiled frame, i.e. the marshaling code for native
   288     // methods that exists in the core system.
   287     // methods that exists in the core system.
   289     return new X86Frame(getSenderSP(), getLink(), getSenderPC());
   288     return new X86Frame(getSenderSP(), getLink(), getSenderPC());
   290   }
   289   }
   291 
   290 
       
   291   private Frame senderForRicochetFrame(X86RegisterMap map) {
       
   292     if (DEBUG) {
       
   293       System.out.println("senderForRicochetFrame");
       
   294     }
       
   295     X86RicochetFrame f = X86RicochetFrame.fromFrame(this);
       
   296     if (map.getUpdateMap())
       
   297       updateMapWithSavedLink(map, f.senderLinkAddress());
       
   298     return new X86Frame(f.extendedSenderSP(), f.exactSenderSP(), f.senderLink(), f.senderPC());
       
   299   }
       
   300 
   292   private Frame senderForEntryFrame(X86RegisterMap map) {
   301   private Frame senderForEntryFrame(X86RegisterMap map) {
       
   302     if (DEBUG) {
       
   303       System.out.println("senderForEntryFrame");
       
   304     }
   293     if (Assert.ASSERTS_ENABLED) {
   305     if (Assert.ASSERTS_ENABLED) {
   294       Assert.that(map != null, "map must be set");
   306       Assert.that(map != null, "map must be set");
   295     }
   307     }
   296     // Java frame called from C; skip all C frames and return top C
   308     // Java frame called from C; skip all C frames and return top C
   297     // frame of that chunk as the sender
   309     // frame of that chunk as the sender
   311       Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
   323       Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
   312     }
   324     }
   313     return fr;
   325     return fr;
   314   }
   326   }
   315 
   327 
       
   328   //------------------------------------------------------------------------------
       
   329   // frame::adjust_unextended_sp
       
   330   private void adjustUnextendedSP() {
       
   331     // If we are returning to a compiled MethodHandle call site, the
       
   332     // saved_fp will in fact be a saved value of the unextended SP.  The
       
   333     // simplest way to tell whether we are returning to such a call site
       
   334     // is as follows:
       
   335 
       
   336     CodeBlob cb = cb();
       
   337     NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
       
   338     if (senderNm != null) {
       
   339       // If the sender PC is a deoptimization point, get the original
       
   340       // PC.  For MethodHandle call site the unextended_sp is stored in
       
   341       // saved_fp.
       
   342       if (senderNm.isDeoptMhEntry(getPC())) {
       
   343         // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP()));
       
   344         raw_unextendedSP = getFP();
       
   345       }
       
   346       else if (senderNm.isDeoptEntry(getPC())) {
       
   347         // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp));
       
   348       }
       
   349       else if (senderNm.isMethodHandleReturn(getPC())) {
       
   350         raw_unextendedSP = getFP();
       
   351       }
       
   352     }
       
   353   }
       
   354 
   316   private Frame senderForInterpreterFrame(X86RegisterMap map) {
   355   private Frame senderForInterpreterFrame(X86RegisterMap map) {
       
   356     if (DEBUG) {
       
   357       System.out.println("senderForInterpreterFrame");
       
   358     }
   317     Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
   359     Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
   318     Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
   360     Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
   319     // We do not need to update the callee-save register mapping because above
   361     // 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
   362     // us is either another interpreter frame or a converter-frame, but never
   321     // directly a compiled frame.
   363     // directly a compiled frame.
   322     // 11/24/04 SFG. With the removal of adapter frames this is no longer true.
   364     // 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
   365     // However c2 no longer uses callee save register for java calls so there
   324     // are no callee register to find.
   366     // are no callee register to find.
   325 
   367 
   326     return new X86Frame(sp, getLink(), unextendedSP.minus(sp));
   368     if (map.getUpdateMap())
       
   369       updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET));
       
   370 
       
   371     return new X86Frame(sp, unextendedSP, getLink(), getSenderPC());
       
   372   }
       
   373 
       
   374   private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
       
   375     map.setLocation(rbp, savedFPAddr);
   327   }
   376   }
   328 
   377 
   329   private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
   378   private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
       
   379     if (DEBUG) {
       
   380       System.out.println("senderForCompiledFrame");
       
   381     }
       
   382 
   330     //
   383     //
   331     // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess
   384     // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess
   332     //
   385     //
   333 
   386 
   334     if (Assert.ASSERTS_ENABLED) {
   387     if (Assert.ASSERTS_ENABLED) {
   335       Assert.that(map != null, "map must be set");
   388       Assert.that(map != null, "map must be set");
   336     }
   389     }
   337 
   390 
   338     // frame owned by optimizing compiler
   391     // frame owned by optimizing compiler
   339     Address        sender_sp = null;
   392     if (Assert.ASSERTS_ENABLED) {
   340 
   393         Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
   341     if (VM.getVM().isClientCompiler()) {
   394     }
   342       sender_sp        = addressOfStackSlot(SENDER_SP_OFFSET);
   395     Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize());
   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 
   396 
   350     // On Intel the return_address is always the word on the stack
   397     // On Intel the return_address is always the word on the stack
   351     Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
   398     Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize());
   352 
   399 
   353     if (map.getUpdateMap() && cb.getOopMaps() != null) {
   400     // This is the saved value of EBP which may or may not really be an FP.
   354       OopMapSet.updateRegisterMap(this, cb, map, true);
   401     // It is only an FP if the sender is an interpreter frame (or C1?).
   355     }
   402     Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize());
   356 
   403 
   357     if (VM.getVM().isClientCompiler()) {
   404     if (map.getUpdateMap()) {
   358       // Move this here for C1 and collecting oops in arguments (According to Rene)
   405       // Tell GC to use argument oopmaps for some runtime stubs that need it.
   359       map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread()));
   406       // For C1, the runtime stub might not have oop maps, so set this flag
   360     }
   407       // outside of update_register_map.
   361 
   408       map.setIncludeArgumentOops(cb.callerMustGCArguments());
   362     Address saved_fp = null;
   409 
   363     if (VM.getVM().isClientCompiler()) {
   410       if (cb.getOopMaps() != null) {
   364       saved_fp = getFP().getAddressAt(0);
   411         OopMapSet.updateRegisterMap(this, cb, map, true);
   365     } else if (VM.getVM().isServerCompiler() &&
   412       }
   366                (VM.getVM().getInterpreter().contains(sender_pc) ||
   413 
   367                VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) {
   414       // Since the prolog does the save and restore of EBP there is no oopmap
   368       // C2 prologue saves EBP in the usual place.
   415       // for it so we must fill in its location as if there was an oopmap entry
   369       // however only use it if the sender had link infomration in it.
   416       // since if our caller was compiled code there could be live jvm state in it.
   370       saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize());
   417       updateMapWithSavedLink(map, savedFPAddr);
   371     }
   418     }
   372 
   419 
   373     return new X86Frame(sender_sp, saved_fp, sender_pc);
   420     return new X86Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC);
   374   }
   421   }
   375 
   422 
   376   protected boolean hasSenderPD() {
   423   protected boolean hasSenderPD() {
   377     // FIXME
   424     // FIXME
   378     // Check for null ebp? Need to do some tests.
   425     // Check for null ebp? Need to do some tests.
   400   public Address getNativeParamAddr(int idx) {
   447   public Address getNativeParamAddr(int idx) {
   401     return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
   448     return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
   402   }
   449   }
   403 
   450 
   404   public Address getSenderSP()     { return addressOfStackSlot(SENDER_SP_OFFSET); }
   451   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 
   452 
   414   public Address addressOfInterpreterFrameLocals() {
   453   public Address addressOfInterpreterFrameLocals() {
   415     return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
   454     return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
   416   }
   455   }
   417 
   456