1 /*
   2  * Copyright (c) 2001, 2015, 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   private static VMReg rbp;
  67 
  68   static {
  69     VM.registerVMInitializedObserver(new Observer() {
  70         public void update(Observable o, Object data) {
  71           initialize(VM.getVM().getTypeDataBase());
  72         }
  73       });
  74   }
  75 
  76   private static synchronized void initialize(TypeDataBase db) {
  77     INTERPRETER_FRAME_MDX_OFFSET                  = INTERPRETER_FRAME_METHOD_OFFSET - 1;
  78     INTERPRETER_FRAME_CACHE_OFFSET                = INTERPRETER_FRAME_MDX_OFFSET - 1;
  79     INTERPRETER_FRAME_LOCALS_OFFSET               = INTERPRETER_FRAME_CACHE_OFFSET - 1;
  80     INTERPRETER_FRAME_BCX_OFFSET                  = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
  81     INTERPRETER_FRAME_INITIAL_SP_OFFSET           = INTERPRETER_FRAME_BCX_OFFSET - 1;
  82     INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET    = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
  83     INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
  84 
  85     ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset");
  86     if (VM.getVM().getAddressSize() == 4) {
  87       rbp = new VMReg(5);
  88     } else {
  89       rbp = new VMReg(5 << 1);
  90     }
  91   }
  92 
  93 
  94   // an additional field beyond sp and pc:
  95   Address raw_fp; // frame pointer
  96   private Address raw_unextendedSP;
  97 
  98   private X86Frame() {
  99   }
 100 
 101   private void adjustForDeopt() {
 102     if ( pc != null) {
 103       // Look for a deopt pc and if it is deopted convert to original pc
 104       CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
 105       if (cb != null && cb.isJavaMethod()) {
 106         NMethod nm = (NMethod) cb;
 107         if (pc.equals(nm.deoptHandlerBegin())) {
 108           if (Assert.ASSERTS_ENABLED) {
 109             Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
 110           }
 111           // adjust pc if frame is deoptimized.
 112           pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
 113           deoptimized = true;
 114         }
 115       }
 116     }
 117   }
 118 
 119   public X86Frame(Address raw_sp, Address raw_fp, Address pc) {
 120     this.raw_sp = raw_sp;
 121     this.raw_unextendedSP = raw_sp;
 122     this.raw_fp = raw_fp;
 123     this.pc = pc;
 124     adjustUnextendedSP();
 125 
 126     // Frame must be fully constructed before this call
 127     adjustForDeopt();
 128 
 129     if (DEBUG) {
 130       System.out.println("X86Frame(sp, fp, pc): " + this);
 131       dumpStack();
 132     }
 133   }
 134 
 135   public X86Frame(Address raw_sp, Address raw_fp) {
 136     this.raw_sp = raw_sp;
 137     this.raw_unextendedSP = raw_sp;
 138     this.raw_fp = raw_fp;
 139     this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
 140     adjustUnextendedSP();
 141 
 142     // Frame must be fully constructed before this call
 143     adjustForDeopt();
 144 
 145     if (DEBUG) {
 146       System.out.println("X86Frame(sp, fp): " + this);
 147       dumpStack();
 148     }
 149   }
 150 
 151   public X86Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
 152     this.raw_sp = raw_sp;
 153     this.raw_unextendedSP = raw_unextendedSp;
 154     this.raw_fp = raw_fp;
 155     this.pc = pc;
 156     adjustUnextendedSP();
 157 
 158     // Frame must be fully constructed before this call
 159     adjustForDeopt();
 160 
 161     if (DEBUG) {
 162       System.out.println("X86Frame(sp, unextendedSP, fp, pc): " + this);
 163       dumpStack();
 164     }
 165 
 166   }
 167 
 168   public Object clone() {
 169     X86Frame frame = new X86Frame();
 170     frame.raw_sp = raw_sp;
 171     frame.raw_unextendedSP = raw_unextendedSP;
 172     frame.raw_fp = raw_fp;
 173     frame.pc = pc;
 174     frame.deoptimized = deoptimized;
 175     return frame;
 176   }
 177 
 178   public boolean equals(Object arg) {
 179     if (arg == null) {
 180       return false;
 181     }
 182 
 183     if (!(arg instanceof X86Frame)) {
 184       return false;
 185     }
 186 
 187     X86Frame other = (X86Frame) arg;
 188 
 189     return (AddressOps.equal(getSP(), other.getSP()) &&
 190             AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
 191             AddressOps.equal(getFP(), other.getFP()) &&
 192             AddressOps.equal(getPC(), other.getPC()));
 193   }
 194 
 195   public int hashCode() {
 196     if (raw_sp == null) {
 197       return 0;
 198     }
 199 
 200     return raw_sp.hashCode();
 201   }
 202 
 203   public String toString() {
 204     return "sp: " + (getSP() == null? "null" : getSP().toString()) +
 205          ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) +
 206          ", fp: " + (getFP() == null? "null" : getFP().toString()) +
 207          ", pc: " + (pc == null? "null" : pc.toString());
 208   }
 209 
 210   // accessors for the instance variables
 211   public Address getFP() { return raw_fp; }
 212   public Address getSP() { return raw_sp; }
 213   public Address getID() { return raw_sp; }
 214 
 215   // FIXME: not implemented yet (should be done for Solaris/X86)
 216   public boolean isSignalHandlerFrameDbg() { return false; }
 217   public int     getSignalNumberDbg()      { return 0;     }
 218   public String  getSignalNameDbg()        { return null;  }
 219 
 220   public boolean isInterpretedFrameValid() {
 221     if (Assert.ASSERTS_ENABLED) {
 222       Assert.that(isInterpretedFrame(), "Not an interpreted frame");
 223     }
 224 
 225     // These are reasonable sanity checks
 226     if (getFP() == null || getFP().andWithMask(0x3) != null) {
 227       return false;
 228     }
 229 
 230     if (getSP() == null || getSP().andWithMask(0x3) != null) {
 231       return false;
 232     }
 233 
 234     if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) {
 235       return false;
 236     }
 237 
 238     // These are hacks to keep us out of trouble.
 239     // The problem with these is that they mask other problems
 240     if (getFP().lessThanOrEqual(getSP())) {
 241       // this attempts to deal with unsigned comparison above
 242       return false;
 243     }
 244 
 245     if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
 246       // stack frames shouldn't be large.
 247       return false;
 248     }
 249 
 250     return true;
 251   }
 252 
 253   // FIXME: not applicable in current system
 254   //  void    patch_pc(Thread* thread, address pc);
 255 
 256   public Frame sender(RegisterMap regMap, CodeBlob cb) {
 257     X86RegisterMap map = (X86RegisterMap) regMap;
 258 
 259     if (Assert.ASSERTS_ENABLED) {
 260       Assert.that(map != null, "map must be set");
 261     }
 262 
 263     // Default is we done have to follow them. The sender_for_xxx will
 264     // update it accordingly
 265     map.setIncludeArgumentOops(false);
 266 
 267     if (isEntryFrame())       return senderForEntryFrame(map);
 268     if (isInterpretedFrame()) return senderForInterpreterFrame(map);
 269 
 270     if(cb == null) {
 271       cb = VM.getVM().getCodeCache().findBlob(getPC());
 272     } else {
 273       if (Assert.ASSERTS_ENABLED) {
 274         Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
 275       }
 276     }
 277 
 278     if (cb != null) {
 279       return senderForCompiledFrame(map, cb);
 280     }
 281 
 282     // Must be native-compiled frame, i.e. the marshaling code for native
 283     // methods that exists in the core system.
 284     return new X86Frame(getSenderSP(), getLink(), getSenderPC());
 285   }
 286 
 287   private Frame senderForEntryFrame(X86RegisterMap map) {
 288     if (DEBUG) {
 289       System.out.println("senderForEntryFrame");
 290     }
 291     if (Assert.ASSERTS_ENABLED) {
 292       Assert.that(map != null, "map must be set");
 293     }
 294     // Java frame called from C; skip all C frames and return top C
 295     // frame of that chunk as the sender
 296     X86JavaCallWrapper jcw = (X86JavaCallWrapper) getEntryFrameCallWrapper();
 297     if (Assert.ASSERTS_ENABLED) {
 298       Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
 299       Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
 300     }
 301     X86Frame fr;
 302     if (jcw.getLastJavaPC() != null) {
 303       fr = new X86Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
 304     } else {
 305       fr = new X86Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
 306     }
 307     map.clear();
 308     if (Assert.ASSERTS_ENABLED) {
 309       Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
 310     }
 311     return fr;
 312   }
 313 
 314   //------------------------------------------------------------------------------
 315   // frame::adjust_unextended_sp
 316   private void adjustUnextendedSP() {
 317     // If we are returning to a compiled MethodHandle call site, the
 318     // saved_fp will in fact be a saved value of the unextended SP.  The
 319     // simplest way to tell whether we are returning to such a call site
 320     // is as follows:
 321 
 322     CodeBlob cb = cb();
 323     NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
 324     if (senderNm != null) {
 325       // If the sender PC is a deoptimization point, get the original
 326       // PC.  For MethodHandle call site the unextended_sp is stored in
 327       // saved_fp.
 328       if (senderNm.isDeoptMhEntry(getPC())) {
 329         // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP()));
 330         raw_unextendedSP = getFP();
 331       }
 332       else if (senderNm.isDeoptEntry(getPC())) {
 333         // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp));
 334       }
 335       else if (senderNm.isMethodHandleReturn(getPC())) {
 336         raw_unextendedSP = getFP();
 337       }
 338     }
 339   }
 340 
 341   private Frame senderForInterpreterFrame(X86RegisterMap map) {
 342     if (DEBUG) {
 343       System.out.println("senderForInterpreterFrame");
 344     }
 345     Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
 346     Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
 347     // We do not need to update the callee-save register mapping because above
 348     // us is either another interpreter frame or a converter-frame, but never
 349     // directly a compiled frame.
 350     // 11/24/04 SFG. With the removal of adapter frames this is no longer true.
 351     // However c2 no longer uses callee save register for java calls so there
 352     // are no callee register to find.
 353 
 354     if (map.getUpdateMap())
 355       updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET));
 356 
 357     return new X86Frame(sp, unextendedSP, getLink(), getSenderPC());
 358   }
 359 
 360   private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
 361     map.setLocation(rbp, savedFPAddr);
 362   }
 363 
 364   private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
 365     if (DEBUG) {
 366       System.out.println("senderForCompiledFrame");
 367     }
 368 
 369     //
 370     // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess
 371     //
 372 
 373     if (Assert.ASSERTS_ENABLED) {
 374       Assert.that(map != null, "map must be set");
 375     }
 376 
 377     // frame owned by optimizing compiler
 378     if (Assert.ASSERTS_ENABLED) {
 379         Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
 380     }
 381     Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize());
 382 
 383     // On Intel the return_address is always the word on the stack
 384     Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize());
 385 
 386     // This is the saved value of EBP which may or may not really be an FP.
 387     // It is only an FP if the sender is an interpreter frame (or C1?).
 388     Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize());
 389 
 390     if (map.getUpdateMap()) {
 391       // Tell GC to use argument oopmaps for some runtime stubs that need it.
 392       // For C1, the runtime stub might not have oop maps, so set this flag
 393       // outside of update_register_map.
 394       map.setIncludeArgumentOops(cb.callerMustGCArguments());
 395 
 396       if (cb.getOopMaps() != null) {
 397         ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
 398       }
 399 
 400       // Since the prolog does the save and restore of EBP there is no oopmap
 401       // for it so we must fill in its location as if there was an oopmap entry
 402       // since if our caller was compiled code there could be live jvm state in it.
 403       updateMapWithSavedLink(map, savedFPAddr);
 404     }
 405 
 406     return new X86Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC);
 407   }
 408 
 409   protected boolean hasSenderPD() {
 410     // FIXME
 411     // Check for null ebp? Need to do some tests.
 412     return true;
 413   }
 414 
 415   public long frameSize() {
 416     return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
 417   }
 418 
 419   public Address getLink() {
 420     return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
 421   }
 422 
 423   public Address getUnextendedSP() { return raw_unextendedSP; }
 424 
 425   // Return address:
 426   public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
 427   public Address getSenderPC()     { return getSenderPCAddr().getAddressAt(0);      }
 428 
 429   public Address getSenderSP()     { return addressOfStackSlot(SENDER_SP_OFFSET); }
 430 
 431   public Address addressOfInterpreterFrameLocals() {
 432     return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
 433   }
 434 
 435   private Address addressOfInterpreterFrameBCX() {
 436     return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
 437   }
 438 
 439   public int getInterpreterFrameBCI() {
 440     // FIXME: this is not atomic with respect to GC and is unsuitable
 441     // for use in a non-debugging, or reflective, system. Need to
 442     // figure out how to express this.
 443     Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
 444     Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
 445     Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
 446     return bcpToBci(bcp, method);
 447   }
 448 
 449   public Address addressOfInterpreterFrameMDX() {
 450     return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
 451   }
 452 
 453   // FIXME
 454   //inline int frame::interpreter_frame_monitor_size() {
 455   //  return BasicObjectLock::size();
 456   //}
 457 
 458   // expression stack
 459   // (the max_stack arguments are used by the GC; see class FrameClosure)
 460 
 461   public Address addressOfInterpreterFrameExpressionStack() {
 462     Address monitorEnd = interpreterFrameMonitorEnd().address();
 463     return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
 464   }
 465 
 466   public int getInterpreterFrameExpressionStackDirection() { return -1; }
 467 
 468   // top of expression stack
 469   public Address addressOfInterpreterFrameTOS() {
 470     return getSP();
 471   }
 472 
 473   /** Expression stack from top down */
 474   public Address addressOfInterpreterFrameTOSAt(int slot) {
 475     return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
 476   }
 477 
 478   public Address getInterpreterFrameSenderSP() {
 479     if (Assert.ASSERTS_ENABLED) {
 480       Assert.that(isInterpretedFrame(), "interpreted frame expected");
 481     }
 482     return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
 483   }
 484 
 485   // Monitors
 486   public BasicObjectLock interpreterFrameMonitorBegin() {
 487     return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
 488   }
 489 
 490   public BasicObjectLock interpreterFrameMonitorEnd() {
 491     Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
 492     if (Assert.ASSERTS_ENABLED) {
 493       // make sure the pointer points inside the frame
 494       Assert.that(AddressOps.gt(getFP(), result), "result must <  than frame pointer");
 495       Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
 496     }
 497     return new BasicObjectLock(result);
 498   }
 499 
 500   public int interpreterFrameMonitorSize() {
 501     return BasicObjectLock.size();
 502   }
 503 
 504   // Method
 505   public Address addressOfInterpreterFrameMethod() {
 506     return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
 507   }
 508 
 509   // Constant pool cache
 510   public Address addressOfInterpreterFrameCPCache() {
 511     return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
 512   }
 513 
 514   // Entry frames
 515   public JavaCallWrapper getEntryFrameCallWrapper() {
 516     return new X86JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
 517   }
 518 
 519   protected Address addressOfSavedOopResult() {
 520     // offset is 2 for compiler2 and 3 for compiler1
 521     return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
 522                                VM.getVM().getAddressSize());
 523   }
 524 
 525   protected Address addressOfSavedReceiver() {
 526     return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
 527   }
 528 
 529   private void dumpStack() {
 530     if (getFP() != null) {
 531       for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
 532            AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize()));
 533            addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
 534         System.out.println(addr + ": " + addr.getAddressAt(0));
 535       }
 536     } else {
 537       for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
 538            AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
 539            addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
 540         System.out.println(addr + ": " + addr.getAddressAt(0));
 541       }
 542     }
 543   }
 544 }