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