1 /* 2 * Copyright 2000-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.runtime.sparc; 26 27 import java.util.*; 28 29 import sun.jvm.hotspot.asm.sparc.*; 30 import sun.jvm.hotspot.code.*; 31 import sun.jvm.hotspot.compiler.*; 32 import sun.jvm.hotspot.debugger.*; 33 import sun.jvm.hotspot.debugger.cdbg.*; 34 import sun.jvm.hotspot.oops.*; 35 import sun.jvm.hotspot.runtime.*; 36 import sun.jvm.hotspot.runtime.posix.*; 37 import sun.jvm.hotspot.types.*; 38 import sun.jvm.hotspot.utilities.*; 39 40 /** Specialization of and implementation of abstract methods of the 41 Frame class for the SPARC CPU. (FIXME: this is as quick a port as 42 possible to get things running; will have to do a better job right 43 away.) */ 44 45 public class SPARCFrame extends Frame { 46 // The pc value is the raw return address, plus 8 (pcReturnOffset()). 47 // the value of sp and youngerSP that is stored in this object 48 // is always, always, always the value that would be found in the 49 // register (or window save area) while the target VM was executing. 50 // The caller of the constructor will alwasy know if has a biased or 51 // unbiased version of the stack pointer and can convert real (unbiased) 52 // value via a helper routine we supply. 53 // Whenever we return sp or youngerSP values we do not return the internal 54 // value but the real (unbiased) pointers since these are the true, usable 55 // memory addresses. The outlier case is that of the null pointer. The current 56 // mechanism makes null pointers always look null whether biased or not. 57 // This seems to cause no problems. In theory null real pointers could be biased 58 // just like other values however this has impact on things like addOffsetTo() 59 // to be able to take an Address that represents null and add an offset to it. 60 // This doesn't seem worth the bother and the impact on the rest of the code 61 // when the biasSP and unbiasSP can make this invisible. 62 // 63 // The general rule in this code is that when we have a variable like FP, youngerSP, SP 64 // that these are real (i.e. unbiased) addresses. The instance variables in a Frame are 65 // always raw values. The other rule is that it except for the frame constructors and 66 // the unBiasSP helper all methods accept parameters that are real addresses. 67 // 68 69 /** Optional next-younger SP (used to locate O7, the PC) */ 70 private Address raw_youngerSP; 71 72 /** Intepreter adjusts the stack pointer to make all locals contiguous */ 73 private long interpreterSPAdjustmentOffset; 74 75 /** Number of stack entries for longs */ 76 private static final int WORDS_PER_LONG = 2; 77 78 /** Normal SPARC return is 2 words past PC */ 79 public static final int PC_RETURN_OFFSET = 8; 80 81 /** Size of each block, in order of increasing address */ 82 public static final int REGISTER_SAVE_WORDS = 16; 83 // FIXME: read these from the remote process 84 //#ifdef _LP64 85 // callee_aggregate_return_pointer_words = 0, 86 //#else 87 // callee_aggregate_return_pointer_words = 1, 88 //#endif 89 public static final int CALLEE_AGGREGATE_RETURN_POINTER_WORDS = 1; 90 public static final int CALLEE_REGISTER_ARGUMENT_SAVE_AREA_WORDS = 6; 91 92 // offset of each block, in order of increasing address: 93 public static final int REGISTER_SAVE_WORDS_SP_OFFSET = 0; 94 public static final int CALLEE_AGGREGATE_RETURN_POINTER_SP_OFFSET = REGISTER_SAVE_WORDS_SP_OFFSET + REGISTER_SAVE_WORDS; 95 public static final int CALLEE_REGISTER_ARGUMENT_SAVE_AREA_SP_OFFSET = (CALLEE_AGGREGATE_RETURN_POINTER_SP_OFFSET + 96 CALLEE_AGGREGATE_RETURN_POINTER_WORDS); 97 public static final int MEMORY_PARAMETER_WORD_SP_OFFSET = (CALLEE_REGISTER_ARGUMENT_SAVE_AREA_SP_OFFSET + 98 CALLEE_REGISTER_ARGUMENT_SAVE_AREA_WORDS); 99 public static final int VARARGS_OFFSET = MEMORY_PARAMETER_WORD_SP_OFFSET; 100 101 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.sparc.SPARCFrame.DEBUG") != null; 102 103 public static Address unBiasSP(Address raw_sp) { 104 if (raw_sp != null) { 105 return raw_sp.addOffsetTo(VM.getVM().getStackBias()); 106 } else { 107 return null; 108 } 109 } 110 111 public static Address biasSP(Address real_sp) { 112 if (real_sp != null) { 113 if (DEBUG) { 114 System.out.println("biasing realsp: " + real_sp + " biased: " + real_sp.addOffsetTo(-VM.getVM().getStackBias()) ); 115 } 116 return real_sp.addOffsetTo(-VM.getVM().getStackBias()); 117 } else { 118 if (DEBUG) { 119 System.out.println("biasing null realsp"); 120 } 121 return null; 122 } 123 } 124 // 125 // This is used to find the younger sp for a thread thatn has stopped but hasn't 126 // conveniently told us the information where we can find the pc or the frame 127 // containing the pc that corresponds to last_java_sp. This method will walk 128 // the frames trying to find the frame which we contains the data we need. 129 // 130 public static Address findYoungerSP(Address top, Address find) { 131 // top and find are unBiased sp values 132 // we return an unBiased value 133 Address findRaw = biasSP(find); 134 if (top == null || find == null || findRaw == null) { 135 throw new RuntimeException("bad values for findYoungerSP top: " + top + " find: " + find); 136 } 137 // It would be unusual to find more than 20 native frames before we find the java frame 138 // we are looking for. 139 final int maxFrames = 20; 140 int count = 0; 141 Address search = top; 142 Address next; 143 Address pc; 144 if (DEBUG) { 145 System.out.println("findYoungerSP top: " + top + " find: " + find + " findRaw: " + findRaw); 146 } 147 while ( count != maxFrames && search != null) { 148 next = search.getAddressAt(SPARCRegisters.I6.spOffsetInSavedWindow()); 149 pc = search.getAddressAt(SPARCRegisters.I7.spOffsetInSavedWindow()); 150 if (DEBUG) { 151 System.out.println("findYoungerSP next: " + next + " pc: " + pc); 152 } 153 if (next.equals(findRaw)) { 154 return search; 155 } 156 search = unBiasSP(next); 157 } 158 if (DEBUG) { 159 System.out.println("findYoungerSP: never found younger, top: " + top + " find: " + find); 160 } 161 return null; 162 } 163 164 public Address getSP() { 165 if (DEBUG) { 166 System.out.println("getSP raw: " + raw_sp + " unbiased: " + unBiasSP(raw_sp)); 167 } 168 return unBiasSP(raw_sp); 169 } 170 171 public Address getID() { 172 return getSP(); 173 } 174 175 public Address getYoungerSP() { 176 if (DEBUG) { 177 System.out.println("getYoungerSP: " + raw_youngerSP + " unbiased: " + unBiasSP(raw_youngerSP)); 178 } 179 return unBiasSP(raw_youngerSP); 180 } 181 182 /** This constructor relies on the fact that the creator of a frame 183 has flushed register windows which the frame will refer to, and 184 that those register windows will not be reloaded until the frame 185 is done reading and writing the stack. Moreover, if the 186 "younger_pc" argument points into the register save area of the 187 next younger frame (though it need not), the register window for 188 that next younger frame must also stay flushed. (The caller is 189 responsible for ensuring this.) */ 190 public SPARCFrame(Address raw_sp, Address raw_youngerSP, boolean youngerFrameIsInterpreted) { 191 super(); 192 if (DEBUG) { 193 System.out.println("Constructing frame(1) raw_sp: " + raw_sp + " raw_youngerSP: " + raw_youngerSP); 194 } 195 if (Assert.ASSERTS_ENABLED) { 196 Assert.that((unBiasSP(raw_sp).andWithMask(VM.getVM().getAddressSize() - 1) == null), 197 "Expected raw sp likely got real sp, value was " + raw_sp); 198 if (raw_youngerSP != null) { 199 Assert.that((unBiasSP(raw_youngerSP).andWithMask(VM.getVM().getAddressSize() - 1) == null), 200 "Expected raw youngerSP likely got real youngerSP, value was " + raw_youngerSP); 201 } 202 } 203 this.raw_sp = raw_sp; 204 this.raw_youngerSP = raw_youngerSP; 205 if (raw_youngerSP == null) { 206 // make a deficient frame which doesn't know where its PC is 207 pc = null; 208 } else { 209 Address youngerSP = unBiasSP(raw_youngerSP); 210 pc = youngerSP.getAddressAt(SPARCRegisters.I7.spOffsetInSavedWindow()).addOffsetTo(PC_RETURN_OFFSET); 211 212 if (Assert.ASSERTS_ENABLED) { 213 Assert.that(youngerSP.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow()). 214 equals(raw_sp), 215 "youngerSP must be valid"); 216 } 217 } 218 219 if (youngerFrameIsInterpreted) { 220 long IsavedSP = SPARCRegisters.IsavedSP.spOffsetInSavedWindow(); 221 // compute adjustment to this frame's SP made by its interpreted callee 222 interpreterSPAdjustmentOffset = 0; 223 Address savedSP = unBiasSP(getYoungerSP().getAddressAt(IsavedSP)); 224 if (savedSP == null) { 225 if ( DEBUG) { 226 System.out.println("WARNING: IsavedSP was null for frame " + this); 227 } 228 } else { 229 interpreterSPAdjustmentOffset = savedSP.minus(getSP()); 230 } 231 } else { 232 interpreterSPAdjustmentOffset = 0; 233 } 234 if ( pc != null) { 235 // Look for a deopt pc and if it is deopted convert to original pc 236 CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); 237 if (cb != null && cb.isJavaMethod()) { 238 NMethod nm = (NMethod) cb; 239 if (pc.equals(nm.deoptBegin())) { 240 // adjust pc if frame is deoptimized. 241 pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); 242 deoptimized = true; 243 } 244 } 245 } 246 } 247 248 /** Make a deficient frame which doesn't know where its PC is (note 249 no youngerSP argument) */ 250 public SPARCFrame(Address raw_sp, Address pc) { 251 super(); 252 if (DEBUG) { 253 System.out.println("Constructing frame(2) raw_sp: " + raw_sp ); 254 } 255 this.raw_sp = raw_sp; 256 if (Assert.ASSERTS_ENABLED) { 257 Assert.that((unBiasSP(raw_sp).andWithMask(VM.getVM().getAddressSize() - 1) == null), 258 "Expected raw sp likely got real sp, value was " + raw_sp); 259 } 260 raw_youngerSP = null; 261 this.pc = pc; 262 interpreterSPAdjustmentOffset = 0; 263 } 264 265 /** Only used internally */ 266 private SPARCFrame() { 267 } 268 269 public Object clone() { 270 SPARCFrame frame = new SPARCFrame(); 271 frame.raw_sp = raw_sp; 272 frame.pc = pc; 273 frame.raw_youngerSP = raw_youngerSP; 274 frame.interpreterSPAdjustmentOffset = interpreterSPAdjustmentOffset; 275 frame.deoptimized = deoptimized; 276 return frame; 277 } 278 279 public boolean equals(Object arg) { 280 if (arg == null) { 281 return false; 282 } 283 284 if (!(arg instanceof SPARCFrame)) { 285 return false; 286 } 287 288 SPARCFrame other = (SPARCFrame) arg; 289 290 return (AddressOps.equal(getSP(), other.getSP()) && 291 AddressOps.equal(getFP(), other.getFP()) && 292 AddressOps.equal(getPC(), other.getPC())); 293 } 294 295 public int hashCode() { 296 if (raw_sp == null) { 297 return 0; 298 } 299 300 return raw_sp.hashCode(); 301 } 302 303 public String toString() { 304 Address fp = getFP(); 305 Address sp = getSP(); 306 Address youngerSP = getYoungerSP(); 307 308 return "sp: " + (sp == null? "null" : sp.toString()) + 309 ", younger_sp: " + (youngerSP == null? "null" : youngerSP.toString()) + 310 ", fp: " + (fp == null? "null" : fp.toString()) + 311 ", pc: " + (pc == null? "null" : pc.toString()); 312 } 313 314 /** <P> Identifies a signal handler frame on the stack. </P> 315 316 <P> There are a few different algorithms for doing this, and 317 they vary from platform to platform. For example, based on a 318 conversation with Dave Dice, Solaris/x86 will be substantially 319 simpler to handle than Solaris/SPARC because the signal handler 320 frame can be identified because of a program counter == -1. </P> 321 322 <P> The dbx group provided code and advice on these topics; the 323 code below evolved from theirs, but is not correct/robust. 324 Without going into too many details, it seems that looking for 325 the incoming argument to the sigacthandler frame (which is what 326 this code identifies) is not guaranteed to be stable across 327 versions of Solaris, since that function is supplied by 328 libthread and is not guaranteed not to clobber I2 before it 329 calls __sighndlr later. From discussions, it sounds like a 330 robust algorithm which wouldn't require traversal of the 331 ucontext chain (used by dbx, but which Dave Dice thinks isn't 332 robust in the face of libthread -- need to follow up) would be 333 to be able to properly identify the __sighndlr frame, then get 334 I2 and treat that as a ucontext. To identify __sighndlr we would 335 need to look up that symbol in the remote process and look for a 336 program counter within a certain (small) distance. </P> 337 338 <P> If the underlying Debugger supports CDebugger interface, we 339 take the approach of __sighnldr symbol. This approach is more robust 340 compared to the original hueristic approach. Of course, if there 341 is no CDebugger support, we fallback to the hueristic approach. </P> 342 343 <P> The current implementation seems to work with Solaris 2.8. 344 A nice property of this system is that if we find a core file 345 this algorithm doesn't work on, we can change the code and try 346 again, so I'm putting this in as the current mechanism for 347 finding signal handler frames on Solaris/SPARC. </P> */ 348 public boolean isSignalHandlerFrameDbg() { 349 CDebugger cdbg = VM.getVM().getDebugger().getCDebugger(); 350 if (cdbg != null) { 351 LoadObject dso = cdbg.loadObjectContainingPC(getPC()); 352 if (dso != null) { 353 ClosestSymbol cs = dso.closestSymbolToPC(getPC()); 354 if (cs != null && cs.getName().equals("__sighndlr")) { 355 return true; 356 } else { 357 return false; 358 } 359 } else { 360 return false; 361 } 362 } else { 363 if (getYoungerSP() == null) { 364 // System.err.println(" SPARCFrame.isSignalHandlerFrameDbg: youngerSP = " + getYoungerSP()); 365 return false; 366 } 367 Address i2 = getSP().getAddressAt(SPARCRegisters.I2.spOffsetInSavedWindow()); 368 if (i2 == null) { 369 return false; 370 } 371 Address fp = getFP(); 372 // My (mistaken) understanding of the dbx group's code was that 373 // the signal handler frame could be identified by testing the 374 // incoming argument to see whether it was a certain distance 375 // below the frame pointer; in fact, their code did substantially 376 // more than this (traversal of the ucontext chain, which this 377 // code can't do because the topmost ucontext is not currently 378 // available via the proc_service APIs in dbx). The current code 379 // appears to work, but is probably not robust. 380 int MAJOR_HACK_OFFSET = 8; // Difference between expected location of the ucontext and reality 381 // System.err.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + 382 // ", fp = " + fp + ", raw_youngerSP = " + getYoungerSP()); 383 boolean res = i2.equals(fp.addOffsetTo(VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET))); 384 if (res) { 385 // Qualify this with another test (FIXME: this is a gross heuristic found while testing) 386 Address sigInfoAddr = getSP().getAddressAt(SPARCRegisters.I5.spOffsetInSavedWindow()); 387 if (sigInfoAddr == null) { 388 System.err.println("Frame with fp = " + fp + " looked like a signal handler frame but wasn't"); 389 res = false; 390 } 391 } 392 return res; 393 } 394 } 395 396 public int getSignalNumberDbg() { 397 // From looking at the stack trace in dbx, it looks like the 398 // siginfo* comes into sigacthandler in I5. It would be much more 399 // robust to look at the __sighndlr frame instead, but we can't 400 // currently identify that frame. 401 402 Address sigInfoAddr = getSP().getAddressAt(SPARCRegisters.I5.spOffsetInSavedWindow()); 403 // Read si_signo out of siginfo* 404 return (int) sigInfoAddr.getCIntegerAt(0, 4, false); 405 } 406 407 public String getSignalNameDbg() { 408 return POSIXSignals.getSignalName(getSignalNumberDbg()); 409 } 410 411 public boolean isInterpretedFrameValid() { 412 if (Assert.ASSERTS_ENABLED) { 413 Assert.that(isInterpretedFrame(), "Not an interpreted frame"); 414 } 415 // These are reasonable sanity checks 416 if (getFP() == null || (getFP().andWithMask(2 * VM.getVM().getAddressSize() - 1)) != null) { 417 return false; 418 } 419 if (getSP() == null || (getSP().andWithMask(2 * VM.getVM().getAddressSize() - 1)) != null) { 420 return false; 421 } 422 if (getFP().addOffsetTo(INTERPRETER_FRAME_VM_LOCAL_WORDS * VM.getVM().getAddressSize()).lessThan(getSP())) { 423 return false; 424 } 425 426 OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0); 427 428 if (VM.getVM().getObjectHeap().isValidMethod(methodHandle) == false) { 429 return false; 430 } 431 432 // These are hacks to keep us out of trouble. 433 // The problem with these is that they mask other problems 434 if (getFP().lessThanOrEqual(getSP())) { // this attempts to deal with unsigned comparison above 435 return false; 436 } 437 if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { // stack frames shouldn't be large. 438 return false; 439 } 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 bcx = addressOfInterpreterFrameBCX().getAddressAt(0); 444 445 Method method; 446 try { 447 method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle); 448 } catch (UnknownOopException ex) { 449 return false; 450 } 451 int bci = bcpToBci(bcx, method); 452 //validate bci 453 if (bci < 0) return false; 454 455 return true; 456 } 457 458 //-------------------------------------------------------------------------------- 459 // Accessors: 460 // 461 462 /** Accessors */ 463 464 public long frameSize() { 465 return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); 466 } 467 468 public Address getLink() { 469 return unBiasSP(getFP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); 470 } 471 472 // FIXME: not implementable yet 473 // public void setLink(Address addr) { 474 // if (Assert.ASSERTS_ENABLED) { 475 // Assert.that(getLink().equals(addr), "frame nesting is controlled by hardware"); 476 // } 477 // } 478 479 public Frame sender(RegisterMap regMap, CodeBlob cb) { 480 SPARCRegisterMap map = (SPARCRegisterMap) regMap; 481 482 if (Assert.ASSERTS_ENABLED) { 483 Assert.that(map != null, "map must be set"); 484 } 485 486 // Default is we don't have to follow them. The sender_for_xxx 487 // will update it accordingly 488 map.setIncludeArgumentOops(false); 489 490 if (isEntryFrame()) { 491 return senderForEntryFrame(map); 492 } 493 494 Address youngerSP = getSP(); 495 Address sp = getSenderSP(); 496 boolean isInterpreted = false; 497 498 // FIXME: this is a hack to get stackwalking to work in the face 499 // of a signal like a SEGV. For debugging purposes it's important 500 // that (a) we are able to traverse the stack if we take a signal 501 // and (b) that we get the correct program counter in this 502 // situation. If we are not using alternate signal stacks then (a) 503 // seems to work all the time (on SPARC), but (b) is violated for 504 // the frame just below the signal handler. 505 506 // The mechanism for finding the ucontext is not robust. In 507 // addition, we may find that we need to be able to fetch more 508 // registers from the ucontext than just the program counter, 509 // since the register windows on the stack are "stale". This will 510 // require substantial restructuring of this frame code, so has 511 // been avoided for now. 512 513 // It is difficult to find a clean solution for mixing debugging 514 // situations with VM frame traversal. One could consider 515 // implementing generic frame traversal in the dbx style and only 516 // using the VM's stack walking mechanism on a per-frame basis, 517 // for example to traverse Java-level activations in a compiled 518 // frame. However, this will probably not interact well with the 519 // mechanism for finding oops on the stack. 520 521 if (VM.getVM().isDebugging()) { 522 // If we are a signal handler frame, use a trick: make the 523 // youngerSP of the caller frame point to the top of the 524 // ucontext's contained register set. This should allow fetching 525 // of the registers for the frame just below the signal handler 526 // frame in the usual fashion. 527 if (isSignalHandlerFrameDbg()) { 528 529 if (DEBUG) { 530 System.out.println("SPARCFrame.sender: found signal handler frame"); 531 } 532 533 // Try to give a valid SP and PC for a "deficient frame" since 534 // we don't have a real register save area; making this class 535 // work by reading its information from a ucontext as well as 536 // a register save area is a major undertaking and has been 537 // deferred for now. It is very important that the PC is 538 // correct, which is why we don't just fall through to the 539 // other code (which would read the PC from the stale register 540 // window and thereby fail to get the actual location of the 541 // fault). 542 543 long offset = getMContextAreaOffsetInUContext(); 544 Address fp = sp; 545 // System.out.println(" FP: " + fp); 546 fp = fp.addOffsetTo(getUContextOffset() + getMContextAreaOffsetInUContext()); 547 // System.out.println(" start of mcontext: " + fp); 548 // FIXME: put these elsewhere. These are the register numbers 549 // in /usr/include/sys/regset.h. They might belong in 550 // SPARCReigsters.java, but we currently don't have that list 551 // of numbers in the SA code (because all of the registers are 552 // listed as instances of SPARCRegister) and it appears that 553 // our numbering of the registers and this one don't match up. 554 int PC_OFFSET_IN_GREGSET = 1; 555 int SP_OFFSET_IN_GREGSET = 17; 556 raw_sp = fp.getAddressAt(VM.getVM().getAddressSize() * SP_OFFSET_IN_GREGSET); 557 Address pc = fp.getAddressAt(VM.getVM().getAddressSize() * PC_OFFSET_IN_GREGSET); 558 return new SPARCFrame(raw_sp, pc); 559 } 560 } 561 562 if (!VM.getVM().isCore()) { 563 // Note: The version of this operation on any platform with callee-save 564 // registers must update the register map (if not null). 565 // In order to do this correctly, the various subtypes of 566 // of frame (interpreted, compiled, glue, native), 567 // must be distinguished. There is no need on SPARC for 568 // such distinctions, because all callee-save registers are 569 // preserved for all frames via SPARC-specific mechanisms. 570 // 571 // *** HOWEVER, *** if and when we make any floating-point 572 // registers callee-saved, then we will have to copy over 573 // the RegisterMap update logic from the Intel code. 574 575 576 // The constructor of the sender must know whether this frame is interpreted so it can set the 577 // sender's _interpreter_sp_adjustment field. 578 if (VM.getVM().getInterpreter().contains(pc)) { 579 isInterpreted = true; 580 map.makeIntegerRegsUnsaved(); 581 map.shiftWindow(sp, youngerSP); 582 } else { 583 // Find a CodeBlob containing this frame's pc or elide the lookup and use the 584 // supplied blob which is already known to be associated with this frame. 585 cb = VM.getVM().getCodeCache().findBlob(pc); 586 if (cb != null) { 587 588 if (cb.callerMustGCArguments(map.getThread())) { 589 map.setIncludeArgumentOops(true); 590 } 591 592 // Update the location of all implicitly saved registers 593 // as the address of these registers in the register save 594 // area (for %o registers we use the address of the %i 595 // register in the next younger frame) 596 map.shiftWindow(sp, youngerSP); 597 if (map.getUpdateMap()) { 598 if (cb.getOopMaps() != null) { 599 OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); 600 } 601 } 602 } 603 } 604 } // #ifndef CORE 605 606 return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted); 607 } 608 609 protected boolean hasSenderPD() { 610 try { 611 // FIXME: should not happen!!! 612 if (getSP() == null) { 613 return false; 614 } 615 if ( unBiasSP(getSP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())) == null ) { 616 return false; 617 } 618 return true; 619 } catch (RuntimeException e) { 620 if (DEBUG) { 621 System.out.println("Bad frame " + this); 622 } 623 throw e; 624 } 625 } 626 627 //-------------------------------------------------------------------------------- 628 // Return address: 629 // 630 631 public Address getSenderPC() { 632 return addressOfI7().getAddressAt(0).addOffsetTo(PC_RETURN_OFFSET); 633 } 634 635 // FIXME: currently unimplementable 636 // inline void frame::set_sender_pc(address addr) { *I7_addr() = addr - pc_return_offset; } 637 638 public Address getUnextendedSP() { 639 return getSP().addOffsetTo(interpreterSPAdjustmentOffset); 640 } 641 642 public Address getSenderSP() { 643 return getFP(); 644 } 645 646 /** Given the next-younger sp for a given frame's sp, compute the 647 frame. We need the next-younger sp, because its register save 648 area holds the flushed copy of its I7, which is the PC of the 649 frame we are interested in. */ 650 public SPARCFrame afterSave() { 651 return new SPARCFrame(biasSP(getYoungerSP()), null); 652 } 653 654 /** Accessors for the instance variables */ 655 public Address getFP() { 656 Address sp = getSP(); 657 if (sp == null) { 658 System.out.println("SPARCFrame.getFP(): sp == null"); 659 } 660 Address fpAddr = sp.addOffsetTo(SPARCRegisters.FP.spOffsetInSavedWindow()); 661 try { 662 Address fp = unBiasSP(fpAddr.getAddressAt(0)); 663 if (fp == null) { 664 System.out.println("SPARCFrame.getFP(): fp == null (&fp == " + fpAddr + ")"); 665 } 666 return fp; 667 } catch (RuntimeException e) { 668 System.out.println("SPARCFrame.getFP(): is bad (&fp == " + fpAddr + " sp = " + sp + ")"); 669 return null; 670 } 671 } 672 673 private Address addressOfFPSlot(int index) { 674 return getFP().addOffsetTo(index * VM.getVM().getAddressSize()); 675 } 676 677 // FIXME: temporarily elided 678 // // All frames 679 // 680 // intptr_t* fp_addr_at(int index) const { return &fp()[index]; } 681 // intptr_t* sp_addr_at(int index) const { return &sp()[index]; } 682 // intptr_t fp_at( int index) const { return *fp_addr_at(index); } 683 // intptr_t sp_at( int index) const { return *sp_addr_at(index); } 684 // 685 // private: 686 // inline address* I7_addr() const; 687 // inline address* O7_addr() const; 688 // 689 // inline address* I0_addr() const; 690 // inline address* O0_addr() const; 691 // 692 // public: 693 // // access to SPARC arguments and argument registers 694 // 695 // intptr_t* register_addr(Register reg) const { 696 // return sp_addr_at(reg.sp_offset_in_saved_window()); 697 // } 698 // intptr_t* memory_param_addr(int param_ix, bool is_in) const { 699 // int offset = callee_register_argument_save_area_sp_offset + param_ix; 700 // if (is_in) 701 // return fp_addr_at(offset); 702 // else 703 // return sp_addr_at(offset); 704 // } 705 // intptr_t* param_addr(int param_ix, bool is_in) const { 706 // if (param_ix >= callee_register_argument_save_area_words) 707 // return memory_param_addr(param_ix, is_in); 708 // else if (is_in) 709 // return register_addr(Argument(param_ix, true).as_register()); 710 // else { 711 // // the registers are stored in the next younger frame 712 // // %%% is this really necessary? 713 // frame next_younger = after_save(); 714 // return next_younger.register_addr(Argument(param_ix, true).as_register()); 715 // } 716 // } 717 718 //-------------------------------------------------------------------------------- 719 // Interpreter frames: 720 // 721 722 /** 2 words, also used to save float regs across calls to C */ 723 public static final int INTERPRETER_FRAME_D_SCRATCH_FP_OFFSET = -2; 724 public static final int INTERPRETER_FRAME_L_SCRATCH_FP_OFFSET = -4; 725 /** For native calls only */ 726 public static final int INTERPRETER_FRAME_PADDING_OFFSET = -5; 727 /** For native calls only */ 728 public static final int INTERPRETER_FRAME_MIRROR_OFFSET = -6; 729 /** Should be same as above, and should be zero mod 8 */ 730 public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET = -6; 731 public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET; 732 733 /** Interpreter frame set-up needs to save 2 extra words in outgoing 734 param area for class and jnienv arguments for native stubs (see 735 nativeStubGen_sparc.cpp) */ 736 public static final int INTERPRETER_FRAME_EXTRA_OUTGOING_ARGUMENT_WORDS = 2; 737 738 // FIXME: elided for now 739 // 740 // // the compiler frame has many of the same fields as the interpreter frame 741 // // %%%%% factor out declarations of the shared fields 742 // enum compiler_frame_fixed_locals { 743 // compiler_frame_d_scratch_fp_offset = -2, 744 // compiler_frame_vm_locals_fp_offset = -2, // should be same as above 745 // 746 // compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset 747 // }; 748 // 749 // private: 750 // 751 // // where LcpoolCache is saved: 752 // constantPoolCacheOop* interpreter_frame_cpoolcache_addr() const { 753 // return (constantPoolCacheOop*)sp_addr_at( LcpoolCache.sp_offset_in_saved_window()); 754 // } 755 // 756 // // where Lmonitors is saved: 757 // BasicObjectLock** interpreter_frame_monitors_addr() const { 758 // return (BasicObjectLock**) sp_addr_at( Lmonitors.sp_offset_in_saved_window()); 759 // } 760 // intptr_t** interpreter_frame_esp_addr() const { 761 // return (intptr_t**)sp_addr_at( Lesp.sp_offset_in_saved_window()); 762 // } 763 // 764 // inline void interpreter_frame_set_tos_address(intptr_t* x); 765 // 766 // // next two fns read and write Lmonitors value, 767 // private: 768 // BasicObjectLock* interpreter_frame_monitors() const { return *interpreter_frame_monitors_addr(); } 769 // void interpreter_frame_set_monitors(BasicObjectLock* monitors) { *interpreter_frame_monitors_addr() = monitors; } 770 // 771 //#ifndef CORE 772 //inline oop *frame::pd_compiled_argument_to_location(VMReg::Name reg, RegisterMap reg_map, int arg_size) const { 773 // COMPILER1_ONLY(return (oop *) (arg_size - 1 - reg + sp() + memory_parameter_word_sp_offset); ) 774 // COMPILER2_ONLY(return oopmapreg_to_location(reg, ®_map); ) 775 //} 776 //#endif 777 778 // FIXME: NOT FINISHED 779 public Address addressOfInterpreterFrameLocals() { 780 return getSP().addOffsetTo(SPARCRegisters.Llocals.spOffsetInSavedWindow()); 781 } 782 783 // FIXME: this is not atomic with respect to GC and is unsuitable 784 // for use in a non-debugging, or reflective, system. 785 private Address addressOfInterpreterFrameBCX() { 786 // %%%%% reinterpreting Lbcp as a bcx 787 return getSP().addOffsetTo(SPARCRegisters.Lbcp.spOffsetInSavedWindow()); 788 } 789 790 public int getInterpreterFrameBCI() { 791 // FIXME: this is not atomic with respect to GC and is unsuitable 792 // for use in a non-debugging, or reflective, system. Need to 793 // figure out how to express this. 794 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); 795 OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0); 796 Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle); 797 return bcpToBci(bcp, method); 798 } 799 800 public Address addressOfInterpreterFrameExpressionStack() { 801 return addressOfInterpreterFrameMonitors().addOffsetTo(-1 * VM.getVM().getAddressSize()); 802 } 803 804 public int getInterpreterFrameExpressionStackDirection() { 805 return -1; 806 } 807 808 /** Top of expression stack */ 809 public Address addressOfInterpreterFrameTOS() { 810 return getSP().getAddressAt(SPARCRegisters.Lesp.spOffsetInSavedWindow()).addOffsetTo(VM.getVM().getAddressSize()); 811 } 812 813 /** Expression stack from top down */ 814 public Address addressOfInterpreterFrameTOSAt(int slot) { 815 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); 816 } 817 818 public Address getInterpreterFrameSenderSP() { 819 if (Assert.ASSERTS_ENABLED) { 820 Assert.that(isInterpretedFrame(), "interpreted frame expected"); 821 } 822 return getFP(); 823 } 824 825 // FIXME: elided for now 826 //inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) { 827 // *interpreter_frame_esp_addr() = x - 1; 828 //} 829 830 //-------------------------------------------------------------------------------- 831 // Monitors: 832 // 833 834 private Address addressOfInterpreterFrameMonitors() { 835 return getSP().addOffsetTo(SPARCRegisters.Lmonitors.spOffsetInSavedWindow()).getAddressAt(0); 836 } 837 838 // Monitors 839 public BasicObjectLock interpreterFrameMonitorBegin() { 840 int roundedVMLocalWords = Bits.roundTo(INTERPRETER_FRAME_VM_LOCAL_WORDS, WORDS_PER_LONG); 841 return new BasicObjectLock(addressOfFPSlot(-1 * roundedVMLocalWords)); 842 } 843 844 public BasicObjectLock interpreterFrameMonitorEnd() { 845 return new BasicObjectLock(addressOfInterpreterFrameMonitors()); 846 } 847 848 public int interpreterFrameMonitorSize() { 849 return Bits.roundTo(BasicObjectLock.size(), WORDS_PER_LONG * (int) VM.getVM().getAddressSize()); 850 } 851 852 // FIXME: elided for now 853 // // monitor elements 854 // 855 // // in keeping with Intel side: end is lower in memory than begin; 856 // // and beginning element is oldest element 857 // // Also begin is one past last monitor. 858 // 859 // inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const { 860 // int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); 861 // return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words); 862 // } 863 // 864 // inline BasicObjectLock* frame::interpreter_frame_monitor_end() const { 865 // return interpreter_frame_monitors(); 866 // } 867 // 868 // 869 // inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) { 870 // interpreter_frame_set_monitors(value); 871 // } 872 // 873 // 874 // inline int frame::interpreter_frame_monitor_size() { 875 // return round_to(BasicObjectLock::size(), WordsPerLong); 876 // } 877 878 public Address addressOfInterpreterFrameMethod() { 879 return getSP().addOffsetTo(SPARCRegisters.Lmethod.spOffsetInSavedWindow()); 880 } 881 882 public Address addressOfInterpreterFrameCPCache() { 883 return getSP().addOffsetTo(SPARCRegisters.LcpoolCache.spOffsetInSavedWindow()); 884 } 885 886 //-------------------------------------------------------------------------------- 887 // Entry frames: 888 // 889 890 public JavaCallWrapper getEntryFrameCallWrapper() { 891 // Note: adjust this code if the link argument in StubGenerator::call_stub() changes! 892 SPARCArgument link = new SPARCArgument(0, false); 893 return (JavaCallWrapper) VMObjectFactory.newObject(JavaCallWrapper.class, 894 getSP().getAddressAt(link.asIn().asRegister().spOffsetInSavedWindow())); 895 } 896 897 // 898 // 899 // inline JavaCallWrapper* frame::entry_frame_call_wrapper() const { 900 // // note: adjust this code if the link argument in StubGenerator::call_stub() changes! 901 // const Argument link = Argument(0, false); 902 // return (JavaCallWrapper*)sp()[link.as_in().as_register().sp_offset_in_saved_window()]; 903 // } 904 905 //-------------------------------------------------------------------------------- 906 // Safepoints: 907 // 908 909 protected Address addressOfSavedOopResult() { 910 return addressOfO0(); 911 } 912 913 protected Address addressOfSavedReceiver() { 914 return addressOfO0(); 915 } 916 917 918 //-------------------------------------------------------------------------------- 919 // Internals only below this point 920 // 921 922 private Address addressOfI7() { 923 return getSP().addOffsetTo(SPARCRegisters.I7.spOffsetInSavedWindow()); 924 } 925 926 private Address addressOfO7() { 927 return afterSave().addressOfI7(); 928 } 929 930 private Address addressOfI0() { 931 return getSP().addOffsetTo(SPARCRegisters.I0.spOffsetInSavedWindow()); 932 } 933 934 private Address addressOfO0() { 935 return afterSave().addressOfI0(); 936 } 937 938 private static boolean addressesEqual(Address a1, Address a2) { 939 if ((a1 == null) && (a2 == null)) { 940 return true; 941 } 942 943 if ((a1 == null) || (a2 == null)) { 944 return false; 945 } 946 947 return (a1.equals(a2)); 948 } 949 950 951 private Frame senderForEntryFrame(RegisterMap regMap) { 952 SPARCRegisterMap map = (SPARCRegisterMap) regMap; 953 954 if (Assert.ASSERTS_ENABLED) { 955 Assert.that(map != null, "map must be set"); 956 } 957 // Java frame called from C; skip all C frames and return top C 958 // frame of that chunk as the sender 959 JavaCallWrapper jcw = getEntryFrameCallWrapper(); 960 if (Assert.ASSERTS_ENABLED) { 961 Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); 962 Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); 963 } 964 Address lastJavaSP = jcw.getLastJavaSP(); 965 Address lastJavaPC = jcw.getLastJavaPC(); 966 map.clear(); 967 968 if (!VM.getVM().isCore()) { 969 map.makeIntegerRegsUnsaved(); 970 map.shiftWindow(lastJavaSP, null); 971 } 972 973 if (Assert.ASSERTS_ENABLED) { 974 Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); 975 } 976 977 if (lastJavaPC != null) { 978 return new SPARCFrame(biasSP(lastJavaSP), lastJavaPC); 979 } else { 980 Address youngerSP = getNextYoungerSP(lastJavaSP, getSP()); 981 return new SPARCFrame(biasSP(lastJavaSP), biasSP(youngerSP), false); 982 } 983 } 984 985 private static Address getNextYoungerSP(Address oldSP, Address youngSP) { 986 Address sp = getNextYoungerSPOrNull(oldSP, youngSP, null); 987 if (Assert.ASSERTS_ENABLED) { 988 Assert.that(sp != null, "missed the SP"); 989 } 990 return sp; 991 } 992 993 private static Address getNextYoungerSPOrNull(Address oldSP, Address youngSP, Address sp) { 994 if (youngSP == null) { 995 // FIXME 996 throw new RuntimeException("can not handle null youngSP in debugging system (seems to require register window flush)"); 997 } 998 999 if (sp == null) { 1000 sp = youngSP; 1001 } 1002 1003 Address previousSP = null; 1004 1005 /** Minimum frame size is 16 */ 1006 int maxFrames = (int) (oldSP.minus(sp) / (16 * VM.getVM().getAddressSize())); 1007 1008 while(!sp.equals(oldSP) && spIsValid(oldSP, youngSP, sp)) { 1009 if (maxFrames-- <= 0) { 1010 // too many frames have gone by; invalid parameters given to this function 1011 break; 1012 } 1013 previousSP = sp; 1014 sp = unBiasSP(sp.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); 1015 } 1016 1017 return (sp.equals(oldSP) ? previousSP : null); 1018 } 1019 1020 private static boolean spIsValid(Address oldSP, Address youngSP, Address sp) { 1021 long mask = VM.getVM().getAddressSize(); 1022 mask = 2 * mask - 1; 1023 return ((sp.andWithMask(mask) == null) && 1024 (sp.lessThanOrEqual(oldSP)) && 1025 (sp.greaterThanOrEqual(youngSP))); 1026 } 1027 1028 // FIXME: this is a hopefully temporary hack (not sure what is going on) 1029 public long getUContextOffset() { 1030 // FIXME: there is something I clearly don't understand about the 1031 // way the signal handler frame is laid out, because I shouldn't need this extra offset 1032 int MAJOR_HACK_OFFSET = 8; 1033 // System.out.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + ", fp = " + fp + ", youngerSP = " + youngerSP); 1034 return VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET); 1035 } 1036 1037 public long getMContextAreaOffsetInUContext() { 1038 // From dbx-related sources: 1039 // /* 1040 // * struct sigframe is declaredf in the kernel sources in 1041 // * .../uts/sun4c/os/machdep.c/sendsig() 1042 // * unfortunately we only get a pointer to the 'uc' passed 1043 // * to the sighandler so we need to do this stuff to get 1044 // * to 'rwin'. 1045 // * Have to do it like this to take account of alignment. 1046 // */ 1047 // static struct sigframe { 1048 // struct rwindow rwin; 1049 // ucontext_t uc; 1050 // } sf_help; 1051 1052 // From /usr/include/sys/ucontext.h: 1053 // #if !defined(_XPG4_2) || defined(__EXTENSIONS__) 1054 // struct ucontext { 1055 // #else 1056 // struct __ucontext { 1057 // #endif 1058 // uint_t uc_flags; 1059 // ucontext_t *uc_link; 1060 // sigset_t uc_sigmask; 1061 // stack_t uc_stack; 1062 // mcontext_t uc_mcontext; 1063 // #ifdef __sparcv9 1064 // long uc_filler[4]; 1065 // #else /* __sparcv9 */ 1066 // long uc_filler[23]; 1067 // #endif /* __sparcv9 */ 1068 // }; 1069 1070 // This walks to the start of the gregs in the mcontext_t 1071 // (first entry in that data structure). Really should read 1072 // this from header file. 1073 1074 // Also not sure exactly how alignment works...maybe should read these offsets from the target VM 1075 // (When you have a hammer, everything looks like a nail) 1076 long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize()); // uc_flags 1077 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // uc_link plus 1078 // doubleword alignment for structs? 1079 offset += 16 + // uc_sigmask 1080 2 * VM.getVM().getAddressSize() + 4; // uc_stack 1081 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // doubleword alignment for structs? 1082 1083 // System.out.println("SPARCFrame.getMContextAreaOffsetInUContext: offset = " + offset); 1084 1085 return offset; 1086 } 1087 }