1 /* 2 * Copyright (c) 2014, 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.ppc64; 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 ppc64 family of CPUs. */ 38 39 public class PPC64Frame extends Frame { 40 private static final boolean DEBUG; 41 static { 42 DEBUG = System.getProperty("sun.jvm.hotspot.runtime.ppc64.PPC64Frame.DEBUG") != null; 43 } 44 45 // All frames 46 private static final int SENDER_SP_OFFSET = 0; 47 48 // Interpreter frames 49 private static final int INTERPRETER_FRAME_MIRROR_OFFSET = -3; // for native calls only 50 private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -4; 51 private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1; 52 private static final int INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET -1; 53 private static final int INTERPRETER_FRAME_ESP_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; 54 private static final int INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_ESP_OFFSET - 1; 55 private static final int INTERPRETER_FRAME_CACHE_OFFSET =INTERPRETER_FRAME_BCX_OFFSET - 1; 56 private static final int INTERPRETER_FRAME_MONITORS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; 57 private static final int INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_MONITORS_OFFSET - 1; 58 private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; 59 private static final int INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; // FIXME: probably wrong, but unused anyway 60 private static final int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; 61 private static final int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; 62 63 // Entry frames 64 private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; 65 66 static { 67 VM.registerVMInitializedObserver(new Observer() { 68 public void update(Observable o, Object data) { 69 initialize(VM.getVM().getTypeDataBase()); 70 } 71 }); 72 } 73 74 private static synchronized void initialize(TypeDataBase db) { 75 int entry_frame_locals_size = db.lookupIntConstant("frame::entry_frame_locals_size").intValue(); 76 int wordLength = (int) VM.getVM().getAddressSize(); 77 ENTRY_FRAME_CALL_WRAPPER_OFFSET = -entry_frame_locals_size/wordLength; 78 } 79 80 81 // an additional field beyond sp and pc: 82 Address raw_fp; // frame pointer 83 private Address raw_unextendedSP; 84 85 private PPC64Frame() { 86 } 87 88 private void adjustForDeopt() { 89 if ( pc != null) { 90 // Look for a deopt pc and if it is deopted convert to original pc 91 CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); 92 if (cb != null && cb.isJavaMethod()) { 93 NMethod nm = (NMethod) cb; 94 if (pc.equals(nm.deoptHandlerBegin())) { 95 if (Assert.ASSERTS_ENABLED) { 96 Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); 97 } 98 // adjust pc if frame is deoptimized. 99 pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); 100 deoptimized = true; 101 } 102 } 103 } 104 } 105 106 public PPC64Frame(Address raw_sp, Address raw_fp, Address pc) { 107 this.raw_sp = raw_sp; 108 this.raw_unextendedSP = raw_sp; 109 if (raw_fp == null) { 110 this.raw_fp = raw_sp.getAddressAt(0); 111 } else { 112 this.raw_fp = raw_fp; 113 } 114 if (pc == null) { 115 this.pc = raw_sp.getAddressAt(2 * VM.getVM().getAddressSize()); 116 } else { 117 this.pc = pc; 118 } 119 adjustUnextendedSP(); 120 121 // Frame must be fully constructed before this call 122 adjustForDeopt(); 123 124 if (DEBUG) { 125 System.out.println("PPC64Frame(sp, fp, pc): " + this); 126 dumpStack(); 127 } 128 } 129 130 public PPC64Frame(Address raw_sp, Address raw_fp) { 131 this.raw_sp = raw_sp; 132 this.raw_unextendedSP = raw_sp; 133 if (raw_fp == null) { 134 this.raw_fp = raw_sp.getAddressAt(0); 135 } else { 136 this.raw_fp = raw_fp; 137 } 138 this.pc = raw_sp.getAddressAt(2 * VM.getVM().getAddressSize()); 139 adjustUnextendedSP(); 140 141 // Frame must be fully constructed before this call 142 adjustForDeopt(); 143 144 if (DEBUG) { 145 System.out.println("PPC64Frame(sp, fp): " + this); 146 dumpStack(); 147 } 148 } 149 150 public PPC64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { 151 this.raw_sp = raw_sp; 152 this.raw_unextendedSP = raw_unextendedSp; 153 if (raw_fp == null) { 154 this.raw_fp = raw_sp.getAddressAt(0); 155 } else { 156 this.raw_fp = raw_fp; 157 } 158 if (pc == null) { 159 this.pc = raw_sp.getAddressAt(2 * VM.getVM().getAddressSize()); 160 } else { 161 this.pc = pc; 162 } 163 adjustUnextendedSP(); 164 165 // Frame must be fully constructed before this call 166 adjustForDeopt(); 167 168 if (DEBUG) { 169 System.out.println("PPC64Frame(sp, unextendedSP, fp, pc): " + this); 170 dumpStack(); 171 } 172 173 } 174 175 public Object clone() { 176 PPC64Frame frame = new PPC64Frame(); 177 frame.raw_sp = raw_sp; 178 frame.raw_unextendedSP = raw_unextendedSP; 179 frame.raw_fp = raw_fp; 180 frame.pc = pc; 181 frame.deoptimized = deoptimized; 182 return frame; 183 } 184 185 public boolean equals(Object arg) { 186 if (arg == null) { 187 return false; 188 } 189 190 if (!(arg instanceof PPC64Frame)) { 191 return false; 192 } 193 194 PPC64Frame other = (PPC64Frame) arg; 195 196 return (AddressOps.equal(getSP(), other.getSP()) && 197 AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) && 198 AddressOps.equal(getFP(), other.getFP()) && 199 AddressOps.equal(getPC(), other.getPC())); 200 } 201 202 public int hashCode() { 203 if (raw_sp == null) { 204 return 0; 205 } 206 207 return raw_sp.hashCode(); 208 } 209 210 public String toString() { 211 return "sp: " + (getSP() == null ? "null" : getSP().toString()) + 212 ", unextendedSP: " + (getUnextendedSP() == null ? "null" : getUnextendedSP().toString()) + 213 ", fp: " + (getFP() == null ? "null" : getFP().toString()) + 214 ", pc: " + (pc == null ? "null" : pc.toString()); 215 } 216 217 // accessors for the instance variables 218 public Address getFP() { return raw_fp; } 219 public Address getSP() { return raw_sp; } 220 public Address getID() { return raw_sp; } 221 222 // FIXME: not implemented yet (should be done for Solaris/PPC64) 223 public boolean isSignalHandlerFrameDbg() { return false; } 224 public int getSignalNumberDbg() { return 0; } 225 public String getSignalNameDbg() { return null; } 226 227 public boolean isInterpretedFrameValid() { 228 if (Assert.ASSERTS_ENABLED) { 229 Assert.that(isInterpretedFrame(), "Not an interpreted frame"); 230 } 231 232 // These are reasonable sanity checks 233 if (getFP() == null || getFP().andWithMask(0x3) != null) { 234 return false; 235 } 236 237 if (getSP() == null || getSP().andWithMask(0x3) != null) { 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 PPC64RegisterMap map = (PPC64RegisterMap) 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 PPC64Frame(getSenderSP(), getLink(), getSenderPC()); 288 } 289 290 private Frame senderForEntryFrame(PPC64RegisterMap 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 PPC64JavaCallWrapper jcw = (PPC64JavaCallWrapper) 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 PPC64Frame fr; 305 if (jcw.getLastJavaPC() != null) { 306 fr = new PPC64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC()); 307 } else { 308 fr = new PPC64Frame(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 raw_unextendedSP = getFP(); 321 } 322 private Frame senderForInterpreterFrame(PPC64RegisterMap map) { 323 if (DEBUG) { 324 System.out.println("senderForInterpreterFrame"); 325 } 326 Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); 327 Address sp = getSenderSP(); 328 329 return new PPC64Frame(sp, unextendedSP, getLink(), getSenderPC()); 330 } 331 332 333 private Frame senderForCompiledFrame(PPC64RegisterMap map, CodeBlob cb) { 334 if (DEBUG) { 335 System.out.println("senderForCompiledFrame"); 336 } 337 338 // 339 // NOTE: some of this code is (unfortunately) duplicated in PPC64CurrentFrameGuess 340 // 341 342 if (Assert.ASSERTS_ENABLED) { 343 Assert.that(map != null, "map must be set"); 344 } 345 346 // frame owned by optimizing compiler 347 if (Assert.ASSERTS_ENABLED) { 348 Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); 349 } 350 Address senderSP = getSenderSP(); 351 352 Address senderPC = getSenderPC(); 353 354 if (map.getUpdateMap()) { 355 // Tell GC to use argument oopmaps for some runtime stubs that need it. 356 // For C1, the runtime stub might not have oop maps, so set this flag 357 // outside of update_register_map. 358 map.setIncludeArgumentOops(cb.callerMustGCArguments()); 359 360 if (cb.getOopMaps() != null) { 361 ImmutableOopMapSet.updateRegisterMap(this, cb, map, true); 362 } 363 } 364 365 return new PPC64Frame(senderSP, getLink(), senderPC); 366 } 367 368 protected boolean hasSenderPD() { 369 // FIXME 370 return true; 371 } 372 373 public long frameSize() { 374 return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); 375 } 376 377 public Address getLink() { 378 return getSenderSP().getAddressAt(0); 379 } 380 381 public Address getUnextendedSP() { return raw_unextendedSP; } 382 383 // Return address: 384 public Address getSenderPC() { return getSenderSP().getAddressAt(2 * VM.getVM().getAddressSize()); } 385 386 public Address getSenderSP() { return getFP(); } 387 public Address addressOfInterpreterFrameLocals() { 388 return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); 389 } 390 391 private Address addressOfInterpreterFrameBCX() { 392 return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET); 393 } 394 395 public int getInterpreterFrameBCI() { 396 // FIXME: this is not atomic with respect to GC and is unsuitable 397 // for use in a non-debugging, or reflective, system. Need to 398 // figure out how to express this. 399 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); 400 Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); 401 Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); 402 return bcpToBci(bcp, method); 403 } 404 405 public Address addressOfInterpreterFrameMDX() { 406 return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET); 407 } 408 409 // FIXME 410 //inline int frame::interpreter_frame_monitor_size() { 411 // return BasicObjectLock::size(); 412 //} 413 414 // expression stack 415 // (the max_stack arguments are used by the GC; see class FrameClosure) 416 417 public Address addressOfInterpreterFrameExpressionStack() { 418 Address monitorEnd = interpreterFrameMonitorEnd().address(); 419 return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize()); 420 } 421 422 public int getInterpreterFrameExpressionStackDirection() { return -1; } 423 424 // top of expression stack 425 public Address addressOfInterpreterFrameTOS() { 426 return getSP(); 427 } 428 429 /** Expression stack from top down */ 430 public Address addressOfInterpreterFrameTOSAt(int slot) { 431 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); 432 } 433 434 public Address getInterpreterFrameSenderSP() { 435 if (Assert.ASSERTS_ENABLED) { 436 Assert.that(isInterpretedFrame(), "interpreted frame expected"); 437 } 438 return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); 439 } 440 441 // Monitors 442 public BasicObjectLock interpreterFrameMonitorBegin() { 443 return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET)); 444 } 445 446 public BasicObjectLock interpreterFrameMonitorEnd() { 447 Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0); 448 if (Assert.ASSERTS_ENABLED) { 449 // make sure the pointer points inside the frame 450 Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); 451 Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer"); 452 } 453 return new BasicObjectLock(result); 454 } 455 456 public int interpreterFrameMonitorSize() { 457 return BasicObjectLock.size(); 458 } 459 460 // Method 461 public Address addressOfInterpreterFrameMethod() { 462 return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET); 463 } 464 465 // Constant pool cache 466 public Address addressOfInterpreterFrameCPCache() { 467 return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET); 468 } 469 470 // Entry frames 471 public JavaCallWrapper getEntryFrameCallWrapper() { 472 return new PPC64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0)); 473 } 474 475 protected Address addressOfSavedOopResult() { 476 // offset is 2 for compiler2 and 3 for compiler1 477 return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) * 478 VM.getVM().getAddressSize()); 479 } 480 481 protected Address addressOfSavedReceiver() { 482 return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); 483 } 484 485 private void dumpStack() { 486 if (getFP() != null) { 487 for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); 488 AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize())); 489 addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { 490 System.out.println(addr + ": " + addr.getAddressAt(0)); 491 } 492 } else { 493 for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); 494 AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize())); 495 addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { 496 System.out.println(addr + ": " + addr.getAddressAt(0)); 497 } 498 } 499 } 500 }