1 /*
   2  * Copyright (c) 2001, 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.x86;
  26 
  27 import java.util.*;
  28 import sun.jvm.hotspot.code.*;
  29 import sun.jvm.hotspot.compiler.*;
  30 import sun.jvm.hotspot.debugger.*;
  31 import sun.jvm.hotspot.oops.*;
  32 import sun.jvm.hotspot.runtime.*;
  33 import sun.jvm.hotspot.types.*;
  34 import sun.jvm.hotspot.utilities.*;
  35 
  36 /** Specialization of and implementation of abstract methods of the
  37     Frame class for the x86 family of CPUs. */
  38 
  39 public class X86Frame extends Frame {
  40   private static final boolean DEBUG;
  41   static {
  42     DEBUG = System.getProperty("sun.jvm.hotspot.runtime.x86.X86Frame.DEBUG") != null;
  43   }
  44 
  45   // All frames
  46   private static final int LINK_OFFSET                =  0;
  47   private static final int RETURN_ADDR_OFFSET         =  1;
  48   private static final int SENDER_SP_OFFSET           =  2;
  49 
  50   // Interpreter frames
  51   private static final int INTERPRETER_FRAME_MIRROR_OFFSET    =  2; // for native calls only
  52   private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
  53   private static final int INTERPRETER_FRAME_LAST_SP_OFFSET   = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
  54   private static final int INTERPRETER_FRAME_METHOD_OFFSET    = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
  55   private static       int INTERPRETER_FRAME_MDX_OFFSET;         // Non-core builds only
  56   private static       int INTERPRETER_FRAME_CACHE_OFFSET;
  57   private static       int INTERPRETER_FRAME_LOCALS_OFFSET;
  58   private static       int INTERPRETER_FRAME_BCX_OFFSET;
  59   private static       int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
  60   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
  61   private static       int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
  62 
  63   // Entry frames
  64   private static       int ENTRY_FRAME_CALL_WRAPPER_OFFSET;
  65 
  66   // Native frames
  67   private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET =  2;
  68 
  69   private static VMReg rbp;
  70 
  71   static {
  72     VM.registerVMInitializedObserver(new Observer() {
  73         public void update(Observable o, Object data) {
  74           initialize(VM.getVM().getTypeDataBase());
  75         }
  76       });
  77   }
  78 
  79   private static synchronized void initialize(TypeDataBase db) {
  80     INTERPRETER_FRAME_MDX_OFFSET                  = INTERPRETER_FRAME_METHOD_OFFSET - 1;
  81     INTERPRETER_FRAME_CACHE_OFFSET                = INTERPRETER_FRAME_MDX_OFFSET - 1;
  82     INTERPRETER_FRAME_LOCALS_OFFSET               = INTERPRETER_FRAME_CACHE_OFFSET - 1;
  83     INTERPRETER_FRAME_BCX_OFFSET                  = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
  84     INTERPRETER_FRAME_INITIAL_SP_OFFSET           = INTERPRETER_FRAME_BCX_OFFSET - 1;
  85     INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET    = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
  86     INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
  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 
  96 
  97   // an additional field beyond sp and pc:
  98   Address raw_fp; // frame pointer
  99   private Address raw_unextendedSP;
 100 
 101   private X86Frame() {
 102   }
 103 
 104   private void adjustForDeopt() {
 105     if ( pc != null) {
 106       // Look for a deopt pc and if it is deopted convert to original pc
 107       CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
 108       if (cb != null && cb.isJavaMethod()) {
 109         NMethod nm = (NMethod) cb;
 110         if (pc.equals(nm.deoptHandlerBegin())) {
 111           if (Assert.ASSERTS_ENABLED) {
 112             Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
 113           }
 114           // adjust pc if frame is deoptimized.
 115           pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
 116           deoptimized = true;
 117         }
 118       }
 119     }
 120   }
 121 
 122   public X86Frame(Address raw_sp, Address raw_fp, Address pc) {
 123     this.raw_sp = raw_sp;
 124     this.raw_unextendedSP = raw_sp;
 125     this.raw_fp = raw_fp;
 126     this.pc = pc;
 127     adjustUnextendedSP();
 128 
 129     // Frame must be fully constructed before this call
 130     adjustForDeopt();
 131 
 132     if (DEBUG) {
 133       System.out.println("X86Frame(sp, fp, pc): " + this);
 134       dumpStack();
 135     }
 136   }
 137 
 138   public X86Frame(Address raw_sp, Address raw_fp) {
 139     this.raw_sp = raw_sp;
 140     this.raw_unextendedSP = raw_sp;
 141     this.raw_fp = raw_fp;
 142     this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
 143     adjustUnextendedSP();
 144 
 145     // Frame must be fully constructed before this call
 146     adjustForDeopt();
 147 
 148     if (DEBUG) {
 149       System.out.println("X86Frame(sp, fp): " + this);
 150       dumpStack();
 151     }
 152   }
 153 
 154   public X86Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
 155     this.raw_sp = raw_sp;
 156     this.raw_unextendedSP = raw_unextendedSp;
 157     this.raw_fp = raw_fp;
 158     this.pc = pc;
 159     adjustUnextendedSP();
 160 
 161     // Frame must be fully constructed before this call
 162     adjustForDeopt();
 163 
 164     if (DEBUG) {
 165       System.out.println("X86Frame(sp, unextendedSP, fp, pc): " + this);
 166       dumpStack();
 167     }
 168 
 169   }
 170 
 171   public Object clone() {
 172     X86Frame frame = new X86Frame();
 173     frame.raw_sp = raw_sp;
 174     frame.raw_unextendedSP = raw_unextendedSP;
 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(cb == null) {
 274       cb = VM.getVM().getCodeCache().findBlob(getPC());
 275     } else {
 276       if (Assert.ASSERTS_ENABLED) {
 277         Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
 278       }
 279     }
 280 
 281     if (cb != null) {
 282       return senderForCompiledFrame(map, cb);
 283     }
 284 
 285     // Must be native-compiled frame, i.e. the marshaling code for native
 286     // methods that exists in the core system.
 287     return new X86Frame(getSenderSP(), getLink(), getSenderPC());
 288   }
 289 
 290   private Frame senderForEntryFrame(X86RegisterMap map) {
 291     if (DEBUG) {
 292       System.out.println("senderForEntryFrame");
 293     }
 294     if (Assert.ASSERTS_ENABLED) {
 295       Assert.that(map != null, "map must be set");
 296     }
 297     // Java frame called from C; skip all C frames and return top C
 298     // frame of that chunk as the sender
 299     X86JavaCallWrapper jcw = (X86JavaCallWrapper) getEntryFrameCallWrapper();
 300     if (Assert.ASSERTS_ENABLED) {
 301       Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
 302       Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
 303     }
 304     X86Frame fr;
 305     if (jcw.getLastJavaPC() != null) {
 306       fr = new X86Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
 307     } else {
 308       fr = new X86Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
 309     }
 310     map.clear();
 311     if (Assert.ASSERTS_ENABLED) {
 312       Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
 313     }
 314     return fr;
 315   }
 316 
 317   //------------------------------------------------------------------------------
 318   // frame::adjust_unextended_sp
 319   private void adjustUnextendedSP() {
 320     // If we are returning to a compiled MethodHandle call site, the
 321     // saved_fp will in fact be a saved value of the unextended SP.  The
 322     // simplest way to tell whether we are returning to such a call site
 323     // is as follows:
 324 
 325     CodeBlob cb = cb();
 326     NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
 327     if (senderNm != null) {
 328       // If the sender PC is a deoptimization point, get the original
 329       // PC.  For MethodHandle call site the unextended_sp is stored in
 330       // saved_fp.
 331       if (senderNm.isDeoptMhEntry(getPC())) {
 332         // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP()));
 333         raw_unextendedSP = getFP();
 334       }
 335       else if (senderNm.isDeoptEntry(getPC())) {
 336         // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp));
 337       }
 338       else if (senderNm.isMethodHandleReturn(getPC())) {
 339         raw_unextendedSP = getFP();
 340       }
 341     }
 342   }
 343 
 344   private Frame senderForInterpreterFrame(X86RegisterMap map) {
 345     if (DEBUG) {
 346       System.out.println("senderForInterpreterFrame");
 347     }
 348     Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
 349     Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
 350     // We do not need to update the callee-save register mapping because above
 351     // us is either another interpreter frame or a converter-frame, but never
 352     // directly a compiled frame.
 353     // 11/24/04 SFG. With the removal of adapter frames this is no longer true.
 354     // However c2 no longer uses callee save register for java calls so there
 355     // are no callee register to find.
 356 
 357     if (map.getUpdateMap())
 358       updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET));
 359 
 360     return new X86Frame(sp, unextendedSP, getLink(), getSenderPC());
 361   }
 362 
 363   private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
 364     map.setLocation(rbp, savedFPAddr);
 365   }
 366 
 367   private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
 368     if (DEBUG) {
 369       System.out.println("senderForCompiledFrame");
 370     }
 371 
 372     //
 373     // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess
 374     //
 375 
 376     if (Assert.ASSERTS_ENABLED) {
 377       Assert.that(map != null, "map must be set");
 378     }
 379 
 380     // frame owned by optimizing compiler
 381     if (Assert.ASSERTS_ENABLED) {
 382         Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
 383     }
 384     Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize());
 385 
 386     // On Intel the return_address is always the word on the stack
 387     Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize());
 388 
 389     // This is the saved value of EBP which may or may not really be an FP.
 390     // It is only an FP if the sender is an interpreter frame (or C1?).
 391     Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize());
 392 
 393     if (map.getUpdateMap()) {
 394       // Tell GC to use argument oopmaps for some runtime stubs that need it.
 395       // For C1, the runtime stub might not have oop maps, so set this flag
 396       // outside of update_register_map.
 397       map.setIncludeArgumentOops(cb.callerMustGCArguments());
 398 
 399       if (cb.getOopMaps() != null) {
 400         OopMapSet.updateRegisterMap(this, cb, map, true);
 401       }
 402 
 403       // Since the prolog does the save and restore of EBP there is no oopmap
 404       // for it so we must fill in its location as if there was an oopmap entry
 405       // since if our caller was compiled code there could be live jvm state in it.
 406       updateMapWithSavedLink(map, savedFPAddr);
 407     }
 408 
 409     return new X86Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC);
 410   }
 411 
 412   protected boolean hasSenderPD() {
 413     // FIXME
 414     // Check for null ebp? Need to do some tests.
 415     return true;
 416   }
 417 
 418   public long frameSize() {
 419     return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
 420   }
 421 
 422   public Address getLink() {
 423     return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
 424   }
 425 
 426   // FIXME: not implementable yet
 427   //inline void      frame::set_link(intptr_t* addr)  { *(intptr_t **)addr_at(link_offset) = addr; }
 428 
 429   public Address getUnextendedSP() { return raw_unextendedSP; }
 430 
 431   // Return address:
 432   public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
 433   public Address getSenderPC()     { return getSenderPCAddr().getAddressAt(0);      }
 434 
 435   // return address of param, zero origin index.
 436   public Address getNativeParamAddr(int idx) {
 437     return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
 438   }
 439 
 440   public Address getSenderSP()     { return addressOfStackSlot(SENDER_SP_OFFSET); }
 441 
 442   public Address addressOfInterpreterFrameLocals() {
 443     return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
 444   }
 445 
 446   private Address addressOfInterpreterFrameBCX() {
 447     return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
 448   }
 449 
 450   public int getInterpreterFrameBCI() {
 451     // FIXME: this is not atomic with respect to GC and is unsuitable
 452     // for use in a non-debugging, or reflective, system. Need to
 453     // figure out how to express this.
 454     Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
 455     Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
 456     Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
 457     return bcpToBci(bcp, method);
 458   }
 459 
 460   public Address addressOfInterpreterFrameMDX() {
 461     return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
 462   }
 463 
 464   // FIXME
 465   //inline int frame::interpreter_frame_monitor_size() {
 466   //  return BasicObjectLock::size();
 467   //}
 468 
 469   // expression stack
 470   // (the max_stack arguments are used by the GC; see class FrameClosure)
 471 
 472   public Address addressOfInterpreterFrameExpressionStack() {
 473     Address monitorEnd = interpreterFrameMonitorEnd().address();
 474     return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
 475   }
 476 
 477   public int getInterpreterFrameExpressionStackDirection() { return -1; }
 478 
 479   // top of expression stack
 480   public Address addressOfInterpreterFrameTOS() {
 481     return getSP();
 482   }
 483 
 484   /** Expression stack from top down */
 485   public Address addressOfInterpreterFrameTOSAt(int slot) {
 486     return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
 487   }
 488 
 489   public Address getInterpreterFrameSenderSP() {
 490     if (Assert.ASSERTS_ENABLED) {
 491       Assert.that(isInterpretedFrame(), "interpreted frame expected");
 492     }
 493     return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
 494   }
 495 
 496   // Monitors
 497   public BasicObjectLock interpreterFrameMonitorBegin() {
 498     return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
 499   }
 500 
 501   public BasicObjectLock interpreterFrameMonitorEnd() {
 502     Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
 503     if (Assert.ASSERTS_ENABLED) {
 504       // make sure the pointer points inside the frame
 505       Assert.that(AddressOps.gt(getFP(), result), "result must <  than frame pointer");
 506       Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
 507     }
 508     return new BasicObjectLock(result);
 509   }
 510 
 511   public int interpreterFrameMonitorSize() {
 512     return BasicObjectLock.size();
 513   }
 514 
 515   // Method
 516   public Address addressOfInterpreterFrameMethod() {
 517     return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
 518   }
 519 
 520   // Constant pool cache
 521   public Address addressOfInterpreterFrameCPCache() {
 522     return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
 523   }
 524 
 525   // Entry frames
 526   public JavaCallWrapper getEntryFrameCallWrapper() {
 527     return new X86JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
 528   }
 529 
 530   protected Address addressOfSavedOopResult() {
 531     // offset is 2 for compiler2 and 3 for compiler1
 532     return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
 533                                VM.getVM().getAddressSize());
 534   }
 535 
 536   protected Address addressOfSavedReceiver() {
 537     return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
 538   }
 539 
 540   private void dumpStack() {
 541     if (getFP() != null) {
 542       for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
 543            AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize()));
 544            addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
 545         System.out.println(addr + ": " + addr.getAddressAt(0));
 546       }
 547     } else {
 548       for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
 549            AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
 550            addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
 551         System.out.println(addr + ": " + addr.getAddressAt(0));
 552       }
 553     }
 554   }
 555 }