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 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.deoptHandlerBegin())) { 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 Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(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)Metadata.instantiateWrapperFor(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 // Note: The version of this operation on any platform with callee-save 563 // registers must update the register map (if not null). 564 // In order to do this correctly, the various subtypes of 565 // of frame (interpreted, compiled, glue, native), 566 // must be distinguished. There is no need on SPARC for 567 // such distinctions, because all callee-save registers are 568 // preserved for all frames via SPARC-specific mechanisms. 569 // 570 // *** HOWEVER, *** if and when we make any floating-point 571 // registers callee-saved, then we will have to copy over 572 // the RegisterMap update logic from the Intel code. 573 574 // The constructor of the sender must know whether this frame is interpreted so it can set the 575 // sender's _interpreter_sp_adjustment field. 576 if (VM.getVM().getInterpreter().contains(pc)) { 577 isInterpreted = true; 578 map.makeIntegerRegsUnsaved(); 579 map.shiftWindow(sp, youngerSP); 580 } else { 581 // Find a CodeBlob containing this frame's pc or elide the lookup and use the 582 // supplied blob which is already known to be associated with this frame. 583 cb = VM.getVM().getCodeCache().findBlob(pc); 584 if (cb != null) { 585 // Update the location of all implicitly saved registers 586 // as the address of these registers in the register save 587 // area (for %o registers we use the address of the %i 588 // register in the next younger frame) 589 map.shiftWindow(sp, youngerSP); 590 if (map.getUpdateMap()) { 591 if (cb.callerMustGCArguments()) { 592 map.setIncludeArgumentOops(true); 593 } 594 if (cb.getOopMaps() != null) { 595 OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); 596 } 597 } 598 } 599 } 600 601 return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted); 602 } 603 604 protected boolean hasSenderPD() { 605 try { 606 // FIXME: should not happen!!! 607 if (getSP() == null) { 608 return false; 609 } 610 if ( unBiasSP(getSP().getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())) == null ) { 611 return false; 612 } 613 return true; 614 } catch (RuntimeException e) { 615 if (DEBUG) { 616 System.out.println("Bad frame " + this); 617 } 618 throw e; 619 } 620 } 621 622 //-------------------------------------------------------------------------------- 623 // Return address: 624 // 625 626 public Address getSenderPC() { 627 return addressOfI7().getAddressAt(0).addOffsetTo(PC_RETURN_OFFSET); 628 } 629 630 // FIXME: currently unimplementable 631 // inline void frame::set_sender_pc(address addr) { *I7_addr() = addr - pc_return_offset; } 632 633 public Address getUnextendedSP() { 634 return getSP().addOffsetTo(interpreterSPAdjustmentOffset); 635 } 636 637 public Address getSenderSP() { 638 return getFP(); 639 } 640 641 /** Given the next-younger sp for a given frame's sp, compute the 642 frame. We need the next-younger sp, because its register save 643 area holds the flushed copy of its I7, which is the PC of the 644 frame we are interested in. */ 645 public SPARCFrame afterSave() { 646 return new SPARCFrame(biasSP(getYoungerSP()), null); 647 } 648 649 /** Accessors for the instance variables */ 650 public Address getFP() { 651 Address sp = getSP(); 652 if (sp == null) { 653 System.out.println("SPARCFrame.getFP(): sp == null"); 654 } 655 Address fpAddr = sp.addOffsetTo(SPARCRegisters.FP.spOffsetInSavedWindow()); 656 try { 657 Address fp = unBiasSP(fpAddr.getAddressAt(0)); 658 if (fp == null) { 659 System.out.println("SPARCFrame.getFP(): fp == null (&fp == " + fpAddr + ")"); 660 } 661 return fp; 662 } catch (RuntimeException e) { 663 System.out.println("SPARCFrame.getFP(): is bad (&fp == " + fpAddr + " sp = " + sp + ")"); 664 return null; 665 } 666 } 667 668 private Address addressOfFPSlot(int index) { 669 return getFP().addOffsetTo(index * VM.getVM().getAddressSize()); 670 } 671 672 // FIXME: temporarily elided 673 // // All frames 674 // 675 // intptr_t* fp_addr_at(int index) const { return &fp()[index]; } 676 // intptr_t* sp_addr_at(int index) const { return &sp()[index]; } 677 // intptr_t fp_at( int index) const { return *fp_addr_at(index); } 678 // intptr_t sp_at( int index) const { return *sp_addr_at(index); } 679 // 680 // private: 681 // inline address* I7_addr() const; 682 // inline address* O7_addr() const; 683 // 684 // inline address* I0_addr() const; 685 // inline address* O0_addr() const; 686 // 687 // public: 688 // // access to SPARC arguments and argument registers 689 // 690 // intptr_t* register_addr(Register reg) const { 691 // return sp_addr_at(reg.sp_offset_in_saved_window()); 692 // } 693 // intptr_t* memory_param_addr(int param_ix, bool is_in) const { 694 // int offset = callee_register_argument_save_area_sp_offset + param_ix; 695 // if (is_in) 696 // return fp_addr_at(offset); 697 // else 698 // return sp_addr_at(offset); 699 // } 700 // intptr_t* param_addr(int param_ix, bool is_in) const { 701 // if (param_ix >= callee_register_argument_save_area_words) 702 // return memory_param_addr(param_ix, is_in); 703 // else if (is_in) 704 // return register_addr(Argument(param_ix, true).as_register()); 705 // else { 706 // // the registers are stored in the next younger frame 707 // // %%% is this really necessary? 708 // frame next_younger = after_save(); 709 // return next_younger.register_addr(Argument(param_ix, true).as_register()); 710 // } 711 // } 712 713 //-------------------------------------------------------------------------------- 714 // Interpreter frames: 715 // 716 717 /** 2 words, also used to save float regs across calls to C */ 718 public static final int INTERPRETER_FRAME_D_SCRATCH_FP_OFFSET = -2; 719 public static final int INTERPRETER_FRAME_L_SCRATCH_FP_OFFSET = -4; 720 /** For native calls only */ 721 public static final int INTERPRETER_FRAME_PADDING_OFFSET = -5; 722 /** For native calls only */ 723 public static final int INTERPRETER_FRAME_MIRROR_OFFSET = -6; 724 /** Should be same as above, and should be zero mod 8 */ 725 public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET = -6; 726 public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET; 727 728 /** Interpreter frame set-up needs to save 2 extra words in outgoing 729 param area for class and jnienv arguments for native stubs (see 730 nativeStubGen_sparc.cpp) */ 731 public static final int INTERPRETER_FRAME_EXTRA_OUTGOING_ARGUMENT_WORDS = 2; 732 733 // FIXME: elided for now 734 // 735 // // the compiler frame has many of the same fields as the interpreter frame 736 // // %%%%% factor out declarations of the shared fields 737 // enum compiler_frame_fixed_locals { 738 // compiler_frame_d_scratch_fp_offset = -2, 739 // compiler_frame_vm_locals_fp_offset = -2, // should be same as above 740 // 741 // compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset 742 // }; 743 // 744 // private: 745 // 746 // // where LcpoolCache is saved: 747 // ConstantPoolCache** interpreter_frame_cpoolcache_addr() const { 748 // return (ConstantPoolCache**)sp_addr_at( LcpoolCache.sp_offset_in_saved_window()); 749 // } 750 // 751 // // where Lmonitors is saved: 752 // BasicObjectLock** interpreter_frame_monitors_addr() const { 753 // return (BasicObjectLock**) sp_addr_at( Lmonitors.sp_offset_in_saved_window()); 754 // } 755 // intptr_t** interpreter_frame_esp_addr() const { 756 // return (intptr_t**)sp_addr_at( Lesp.sp_offset_in_saved_window()); 757 // } 758 // 759 // inline void interpreter_frame_set_tos_address(intptr_t* x); 760 // 761 // // next two fns read and write Lmonitors value, 762 // private: 763 // BasicObjectLock* interpreter_frame_monitors() const { return *interpreter_frame_monitors_addr(); } 764 // void interpreter_frame_set_monitors(BasicObjectLock* monitors) { *interpreter_frame_monitors_addr() = monitors; } 765 // 766 //#ifndef CORE 767 //inline oop *frame::pd_compiled_argument_to_location(VMReg::Name reg, RegisterMap reg_map, int arg_size) const { 768 // COMPILER1_ONLY(return (oop *) (arg_size - 1 - reg + sp() + memory_parameter_word_sp_offset); ) 769 // COMPILER2_ONLY(return oopmapreg_to_location(reg, ®_map); ) 770 //} 771 //#endif 772 773 // FIXME: NOT FINISHED 774 public Address addressOfInterpreterFrameLocals() { 775 return getSP().addOffsetTo(SPARCRegisters.Llocals.spOffsetInSavedWindow()); 776 } 777 778 // FIXME: this is not atomic with respect to GC and is unsuitable 779 // for use in a non-debugging, or reflective, system. 780 private Address addressOfInterpreterFrameBCX() { 781 // %%%%% reinterpreting Lbcp as a bcx 782 return getSP().addOffsetTo(SPARCRegisters.Lbcp.spOffsetInSavedWindow()); 783 } 784 785 public int getInterpreterFrameBCI() { 786 // FIXME: this is not atomic with respect to GC and is unsuitable 787 // for use in a non-debugging, or reflective, system. Need to 788 // figure out how to express this. 789 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); 790 Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); 791 Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); 792 return bcpToBci(bcp, method); 793 } 794 795 public Address addressOfInterpreterFrameExpressionStack() { 796 return addressOfInterpreterFrameMonitors().addOffsetTo(-1 * VM.getVM().getAddressSize()); 797 } 798 799 public int getInterpreterFrameExpressionStackDirection() { 800 return -1; 801 } 802 803 /** Top of expression stack */ 804 public Address addressOfInterpreterFrameTOS() { 805 return getSP().getAddressAt(SPARCRegisters.Lesp.spOffsetInSavedWindow()).addOffsetTo(VM.getVM().getAddressSize()); 806 } 807 808 /** Expression stack from top down */ 809 public Address addressOfInterpreterFrameTOSAt(int slot) { 810 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); 811 } 812 813 public Address getInterpreterFrameSenderSP() { 814 if (Assert.ASSERTS_ENABLED) { 815 Assert.that(isInterpretedFrame(), "interpreted frame expected"); 816 } 817 return getFP(); 818 } 819 820 // FIXME: elided for now 821 //inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) { 822 // *interpreter_frame_esp_addr() = x - 1; 823 //} 824 825 //-------------------------------------------------------------------------------- 826 // Monitors: 827 // 828 829 private Address addressOfInterpreterFrameMonitors() { 830 return getSP().addOffsetTo(SPARCRegisters.Lmonitors.spOffsetInSavedWindow()).getAddressAt(0); 831 } 832 833 // Monitors 834 public BasicObjectLock interpreterFrameMonitorBegin() { 835 int roundedVMLocalWords = Bits.roundTo(INTERPRETER_FRAME_VM_LOCAL_WORDS, WORDS_PER_LONG); 836 return new BasicObjectLock(addressOfFPSlot(-1 * roundedVMLocalWords)); 837 } 838 839 public BasicObjectLock interpreterFrameMonitorEnd() { 840 return new BasicObjectLock(addressOfInterpreterFrameMonitors()); 841 } 842 843 public int interpreterFrameMonitorSize() { 844 return Bits.roundTo(BasicObjectLock.size(), WORDS_PER_LONG * (int) VM.getVM().getAddressSize()); 845 } 846 847 // FIXME: elided for now 848 // // monitor elements 849 // 850 // // in keeping with Intel side: end is lower in memory than begin; 851 // // and beginning element is oldest element 852 // // Also begin is one past last monitor. 853 // 854 // inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const { 855 // int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); 856 // return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words); 857 // } 858 // 859 // inline BasicObjectLock* frame::interpreter_frame_monitor_end() const { 860 // return interpreter_frame_monitors(); 861 // } 862 // 863 // 864 // inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) { 865 // interpreter_frame_set_monitors(value); 866 // } 867 // 868 // 869 // inline int frame::interpreter_frame_monitor_size() { 870 // return round_to(BasicObjectLock::size(), WordsPerLong); 871 // } 872 873 public Address addressOfInterpreterFrameMethod() { 874 return getSP().addOffsetTo(SPARCRegisters.Lmethod.spOffsetInSavedWindow()); 875 } 876 877 public Address addressOfInterpreterFrameCPCache() { 878 return getSP().addOffsetTo(SPARCRegisters.LcpoolCache.spOffsetInSavedWindow()); 879 } 880 881 //-------------------------------------------------------------------------------- 882 // Entry frames: 883 // 884 885 public JavaCallWrapper getEntryFrameCallWrapper() { 886 // Note: adjust this code if the link argument in StubGenerator::call_stub() changes! 887 SPARCArgument link = new SPARCArgument(0, false); 888 return (JavaCallWrapper) VMObjectFactory.newObject(JavaCallWrapper.class, 889 getSP().getAddressAt(link.asIn().asRegister().spOffsetInSavedWindow())); 890 } 891 892 // 893 // 894 // inline JavaCallWrapper* frame::entry_frame_call_wrapper() const { 895 // // note: adjust this code if the link argument in StubGenerator::call_stub() changes! 896 // const Argument link = Argument(0, false); 897 // return (JavaCallWrapper*)sp()[link.as_in().as_register().sp_offset_in_saved_window()]; 898 // } 899 900 //-------------------------------------------------------------------------------- 901 // Safepoints: 902 // 903 904 protected Address addressOfSavedOopResult() { 905 return addressOfO0(); 906 } 907 908 protected Address addressOfSavedReceiver() { 909 return addressOfO0(); 910 } 911 912 913 //-------------------------------------------------------------------------------- 914 // Internals only below this point 915 // 916 917 private Address addressOfI7() { 918 return getSP().addOffsetTo(SPARCRegisters.I7.spOffsetInSavedWindow()); 919 } 920 921 private Address addressOfO7() { 922 return afterSave().addressOfI7(); 923 } 924 925 private Address addressOfI0() { 926 return getSP().addOffsetTo(SPARCRegisters.I0.spOffsetInSavedWindow()); 927 } 928 929 private Address addressOfO0() { 930 return afterSave().addressOfI0(); 931 } 932 933 private static boolean addressesEqual(Address a1, Address a2) { 934 if ((a1 == null) && (a2 == null)) { 935 return true; 936 } 937 938 if ((a1 == null) || (a2 == null)) { 939 return false; 940 } 941 942 return (a1.equals(a2)); 943 } 944 945 946 private Frame senderForEntryFrame(RegisterMap regMap) { 947 SPARCRegisterMap map = (SPARCRegisterMap) regMap; 948 949 if (Assert.ASSERTS_ENABLED) { 950 Assert.that(map != null, "map must be set"); 951 } 952 // Java frame called from C; skip all C frames and return top C 953 // frame of that chunk as the sender 954 JavaCallWrapper jcw = getEntryFrameCallWrapper(); 955 if (Assert.ASSERTS_ENABLED) { 956 Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); 957 Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); 958 } 959 Address lastJavaSP = jcw.getLastJavaSP(); 960 Address lastJavaPC = jcw.getLastJavaPC(); 961 map.clear(); 962 963 map.makeIntegerRegsUnsaved(); 964 map.shiftWindow(lastJavaSP, null); 965 966 if (Assert.ASSERTS_ENABLED) { 967 Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); 968 } 969 970 if (lastJavaPC != null) { 971 return new SPARCFrame(biasSP(lastJavaSP), lastJavaPC); 972 } else { 973 Address youngerSP = getNextYoungerSP(lastJavaSP, getSP()); 974 return new SPARCFrame(biasSP(lastJavaSP), biasSP(youngerSP), false); 975 } 976 } 977 978 private static Address getNextYoungerSP(Address oldSP, Address youngSP) { 979 Address sp = getNextYoungerSPOrNull(oldSP, youngSP, null); 980 if (Assert.ASSERTS_ENABLED) { 981 Assert.that(sp != null, "missed the SP"); 982 } 983 return sp; 984 } 985 986 private static Address getNextYoungerSPOrNull(Address oldSP, Address youngSP, Address sp) { 987 if (youngSP == null) { 988 // FIXME 989 throw new RuntimeException("can not handle null youngSP in debugging system (seems to require register window flush)"); 990 } 991 992 if (sp == null) { 993 sp = youngSP; 994 } 995 996 Address previousSP = null; 997 998 /** Minimum frame size is 16 */ 999 int maxFrames = (int) (oldSP.minus(sp) / (16 * VM.getVM().getAddressSize())); 1000 1001 while(!sp.equals(oldSP) && spIsValid(oldSP, youngSP, sp)) { 1002 if (maxFrames-- <= 0) { 1003 // too many frames have gone by; invalid parameters given to this function 1004 break; 1005 } 1006 previousSP = sp; 1007 sp = unBiasSP(sp.getAddressAt(SPARCRegisters.FP.spOffsetInSavedWindow())); 1008 } 1009 1010 return (sp.equals(oldSP) ? previousSP : null); 1011 } 1012 1013 private static boolean spIsValid(Address oldSP, Address youngSP, Address sp) { 1014 long mask = VM.getVM().getAddressSize(); 1015 mask = 2 * mask - 1; 1016 return ((sp.andWithMask(mask) == null) && 1017 (sp.lessThanOrEqual(oldSP)) && 1018 (sp.greaterThanOrEqual(youngSP))); 1019 } 1020 1021 // FIXME: this is a hopefully temporary hack (not sure what is going on) 1022 public long getUContextOffset() { 1023 // FIXME: there is something I clearly don't understand about the 1024 // way the signal handler frame is laid out, because I shouldn't need this extra offset 1025 int MAJOR_HACK_OFFSET = 8; 1026 // System.out.println(" SPARCFrame.isSignalHandlerFrameDbg: I2 = " + i2 + ", fp = " + fp + ", youngerSP = " + youngerSP); 1027 return VM.getVM().getAddressSize() * (REGISTER_SAVE_WORDS + MAJOR_HACK_OFFSET); 1028 } 1029 1030 public long getMContextAreaOffsetInUContext() { 1031 // From dbx-related sources: 1032 // /* 1033 // * struct sigframe is declaredf in the kernel sources in 1034 // * .../uts/sun4c/os/machdep.c/sendsig() 1035 // * unfortunately we only get a pointer to the 'uc' passed 1036 // * to the sighandler so we need to do this stuff to get 1037 // * to 'rwin'. 1038 // * Have to do it like this to take account of alignment. 1039 // */ 1040 // static struct sigframe { 1041 // struct rwindow rwin; 1042 // ucontext_t uc; 1043 // } sf_help; 1044 1045 // From /usr/include/sys/ucontext.h: 1046 // #if !defined(_XPG4_2) || defined(__EXTENSIONS__) 1047 // struct ucontext { 1048 // #else 1049 // struct __ucontext { 1050 // #endif 1051 // uint_t uc_flags; 1052 // ucontext_t *uc_link; 1053 // sigset_t uc_sigmask; 1054 // stack_t uc_stack; 1055 // mcontext_t uc_mcontext; 1056 // #ifdef __sparcv9 1057 // long uc_filler[4]; 1058 // #else /* __sparcv9 */ 1059 // long uc_filler[23]; 1060 // #endif /* __sparcv9 */ 1061 // }; 1062 1063 // This walks to the start of the gregs in the mcontext_t 1064 // (first entry in that data structure). Really should read 1065 // this from header file. 1066 1067 // Also not sure exactly how alignment works...maybe should read these offsets from the target VM 1068 // (When you have a hammer, everything looks like a nail) 1069 long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize()); // uc_flags 1070 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // uc_link plus 1071 // doubleword alignment for structs? 1072 offset += 16 + // uc_sigmask 1073 2 * VM.getVM().getAddressSize() + 4; // uc_stack 1074 offset = VM.getVM().alignUp(offset + VM.getVM().getAddressSize(), 8); // doubleword alignment for structs? 1075 1076 // System.out.println("SPARCFrame.getMContextAreaOffsetInUContext: offset = " + offset); 1077 1078 return offset; 1079 } 1080 }