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