1 /* 2 * Copyright (c) 2000, 2017, 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; 26 27 import java.io.*; 28 import java.util.*; 29 30 import sun.jvm.hotspot.code.*; 31 import sun.jvm.hotspot.compiler.*; 32 import sun.jvm.hotspot.debugger.*; 33 import sun.jvm.hotspot.interpreter.*; 34 import sun.jvm.hotspot.oops.*; 35 import sun.jvm.hotspot.types.*; 36 import sun.jvm.hotspot.utilities.*; 37 38 /** <P> A frame represents a physical stack frame (an activation). 39 Frames can be C or Java frames, and the Java frames can be 40 interpreted or compiled. In contrast, vframes represent 41 source-level activations, so that one physical frame can 42 correspond to multiple source level frames because of inlining. 43 </P> 44 45 <P> NOTE that this is not a VMObject and does not wrap an Address 46 -- this is an actual port of the VM's Frame code to Java. </P> 47 48 <P> NOTE also that this is incomplete -- just trying to get 49 reading of interpreted frames working for now, so all non-core and 50 setter methods are removed for now. (FIXME) </P> */ 51 52 public abstract class Frame implements Cloneable { 53 /** A raw stack pointer. The accessor getSP() will return a real (usable) 54 stack pointer (e.g. from Thread::last_Java_sp) */ 55 protected Address raw_sp; 56 57 /** Program counter (the next instruction after the call) */ 58 protected Address pc; 59 protected boolean deoptimized; 60 61 public Frame() { 62 deoptimized = false; 63 } 64 65 static { 66 VM.registerVMInitializedObserver(new Observer() { 67 public void update(Observable o, Object data) { 68 initialize(VM.getVM().getTypeDataBase()); 69 } 70 }); 71 } 72 73 /** Size of ConstMethod for computing BCI from BCP (FIXME: hack) */ 74 private static long ConstMethodSize; 75 76 private static int pcReturnOffset; 77 78 public static int pcReturnOffset() { 79 return pcReturnOffset; 80 } 81 82 private static synchronized void initialize(TypeDataBase db) { 83 Type ConstMethodType = db.lookupType("ConstMethod"); 84 // FIXME: not sure whether alignment here is correct or how to 85 // force it (round up to address size?) 86 ConstMethodSize = ConstMethodType.getSize(); 87 88 pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue(); 89 } 90 91 protected int bcpToBci(Address bcp, ConstMethod cm) { 92 // bcp will be null for interpreter native methods 93 // in addition depending on where we catch the system the value can 94 // be a bcp or a bci. 95 if (bcp == null) return 0; 96 long bci = bcp.minus(null); 97 if (bci >= 0 && bci < cm.getCodeSize()) return (int) bci; 98 return (int) (bcp.minus(cm.getAddress()) - ConstMethodSize); 99 } 100 101 protected int bcpToBci(Address bcp, Method m) { 102 return bcpToBci(bcp, m.getConstMethod()); 103 } 104 105 public abstract Object clone(); 106 107 // Accessors 108 109 /** pc: Returns the pc at which this frame will continue normally. 110 It must point at the beginning of the next instruction to 111 execute. */ 112 public Address getPC() { return pc; } 113 public void setPC(Address newpc) { pc = newpc; } 114 public boolean isDeoptimized() { return deoptimized; } 115 116 public CodeBlob cb() { 117 return VM.getVM().getCodeCache().findBlob(getPC()); 118 } 119 120 public abstract Address getSP(); 121 public abstract Address getID(); 122 public abstract Address getFP(); 123 124 /** testers -- platform dependent */ 125 public abstract boolean equals(Object arg); 126 127 /** type testers */ 128 public boolean isInterpretedFrame() { return VM.getVM().getInterpreter().contains(getPC()); } 129 public boolean isJavaFrame() { 130 if (isInterpretedFrame()) return true; 131 if (!VM.getVM().isCore()) { 132 if (isCompiledFrame()) return true; 133 } 134 return false; 135 } 136 137 /** Java frame called from C? */ 138 public boolean isEntryFrame() { return VM.getVM().getStubRoutines().returnsToCallStub(getPC()); } 139 public boolean isNativeFrame() { 140 if (!VM.getVM().isCore()) { 141 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); 142 return (cb != null && cb.isNativeMethod()); 143 } else { 144 return false; 145 } 146 } 147 148 public boolean isCompiledFrame() { 149 if (Assert.ASSERTS_ENABLED) { 150 Assert.that(!VM.getVM().isCore(), "noncore builds only"); 151 } 152 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); 153 return (cb != null && cb.isJavaMethod()); 154 } 155 156 public boolean isRuntimeFrame() { 157 if (Assert.ASSERTS_ENABLED) { 158 Assert.that(!VM.getVM().isCore(), "noncore builds only"); 159 } 160 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); 161 if (cb == null) { 162 return false; 163 } 164 if (cb.isRuntimeStub()) return true; 165 else return false; 166 } 167 168 /** oldest frame? (has no sender) FIXME: this is modified from the 169 C++ code to handle the debugging situation where we try to 170 traverse the stack for, for example, the signal thread, and 171 don't find any valid Java frames. Would really like to put the 172 second half of the conditional in some sort of debugging-only if 173 statement. */ 174 // *** FIXME: THE CALL TO isJavaFrame() IS WAY TOO EXPENSIVE!!!!! *** 175 public boolean isFirstFrame() { return ((isEntryFrame() && entryFrameIsFirst()) || 176 (!isJavaFrame() && !hasSenderPD())); } 177 /** same for Java frame */ 178 public boolean isFirstJavaFrame() { throw new RuntimeException("not yet implemented"); } 179 180 /** This is an addition for debugging purposes on platforms which 181 have the notion of signals. */ 182 public abstract boolean isSignalHandlerFrameDbg(); 183 184 /** If this is a signal handler frame (again, on a platform with a 185 notion of signals), get the signal number. */ 186 public abstract int getSignalNumberDbg(); 187 188 /** If this is a signal handler frame (again, on a platform with a 189 notion of signals), get the name of the signal. */ 190 public abstract String getSignalNameDbg(); 191 192 /** performs sanity checks on interpreted frames. */ 193 public abstract boolean isInterpretedFrameValid(); 194 195 /** tells whether this frame is marked for deoptimization */ 196 public boolean shouldBeDeoptimized() { throw new RuntimeException("not yet implemented"); } 197 198 /** tells whether this frame can be deoptimized */ 199 public boolean canBeDeoptimized() { throw new RuntimeException("not yet implemented"); } 200 201 /** returns the sending frame */ 202 public abstract Frame sender(RegisterMap map, CodeBlob nm); 203 204 /** equivalent to sender(map, null) */ 205 public Frame sender(RegisterMap map) { return sender(map, null); } 206 207 /** returns the sender, but skips conversion frames */ 208 public Frame realSender(RegisterMap map) { 209 if (!VM.getVM().isCore()) { 210 Frame result = sender(map); 211 while (result.isRuntimeFrame()) { 212 result = result.sender(map); 213 } 214 return result; 215 } else { 216 return sender(map); 217 } 218 } 219 220 /** Platform-dependent query indicating whether this frame has a 221 sender. Should return true if it is possible to call sender() at 222 all on this frame. (This is currently only needed for the 223 debugging system, if a stack trace is attempted for a Java 224 thread which has no Java frames, i.e., the signal thread; we 225 have to know to stop traversal at the bottom frame.) */ 226 protected abstract boolean hasSenderPD(); 227 228 //-------------------------------------------------------------------------------- 229 // All frames: 230 // A low-level interface for vframes: 231 232 /** Returns the address of the requested "slot" on the stack. Slots 233 are as wide as addresses, so are 32 bits wide on a 32-bit 234 machine and 64 bits wide on a 64-bit machine. */ 235 public Address addressOfStackSlot(int slot) { return getFP().addOffsetTo(slot * VM.getVM().getAddressSize()); } 236 237 /** Fetches the OopHandle at the requested slot */ 238 public OopHandle getOopHandleAt(int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); } 239 /** Fetches the OopHandle at the slot, adjusted for compiler frames */ 240 // FIXME: looks like this is only used for compiled frames 241 // public OopHandle getOopHandleAtAdjusted(MethodOop method, int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); } 242 // FIXME: Not yet implementable 243 // public void setOopHandleAt(int slot, OopHandle value) { addressOfStackSlot(slot).setOopHandleAt(0, value); } 244 245 /** Fetches the (Java) int at the requested slot */ 246 public int getIntAt(int slot) { return addressOfStackSlot(slot).getJIntAt(0); } 247 // FIXME: Not yet implementable 248 // public void setIntAt(int slot, int value) { addressOfStackSlot(slot).setJIntAt(0, value); } 249 250 /** returns the frame size in stack slots */ 251 public abstract long frameSize(); 252 253 /** Link (i.e., the pointer to the previous frame) */ 254 public abstract Address getLink(); 255 // public abstract void setLink(Address addr); 256 257 /** Return address */ 258 public abstract Address getSenderPC(); 259 // FIXME: currently unimplementable 260 // public abstract void setSenderPC(Address addr); 261 262 /** The frame's original SP, before any extension by an interpreted 263 callee; used for packing debug info into vframeArray objects and 264 vframeArray lookup. */ 265 public abstract Address getUnextendedSP(); 266 267 /** Returns the stack pointer of the calling frame */ 268 public abstract Address getSenderSP(); 269 270 //-------------------------------------------------------------------------------- 271 // Interpreter frames: 272 // 273 274 public abstract Address addressOfInterpreterFrameLocals(); 275 276 public Address addressOfInterpreterFrameLocal(int slot) { 277 return addressOfInterpreterFrameLocals().getAddressAt(0).addOffsetTo(-slot * VM.getVM().getAddressSize()); 278 } 279 280 // FIXME: not yet implementable 281 // void interpreter_frame_set_locals(intptr_t* locs); 282 283 // NOTE that the accessor "addressOfInterpreterFrameBCX" has 284 // necessarily been eliminated. The byte code pointer is inherently 285 // an interior pointer to a Method (the bytecodes follow the 286 // Method data structure) and therefore acquisition of it in 287 // this system can not be allowed. All accesses to interpreter frame 288 // byte codes are via the byte code index (BCI). 289 290 /** Byte code index. In the underlying frame, what is actually 291 stored is a byte code pointer (BCP), which is converted to a BCI 292 and back by the GC when methods are moved. In this system, 293 interior pointers are not allowed, so we must make the access to 294 the interpreter frame's BCI atomic with respect to GC. This may 295 mean implementation with an underlying call through native code 296 into the VM or a magic sequence in the compiler. (FIXME) */ 297 public abstract int getInterpreterFrameBCI(); 298 // FIXME: not yet implementable 299 // public abstract void setInterpreterFrameBCI(int bci); 300 301 // FIXME: elided for now 302 // public abstract Address addressOfInterpreterCalleeReceiver(Symbol signature); 303 304 /** Find receiver for an invoke when arguments are just pushed on 305 stack (i.e., callee stack-frame is not setup) */ 306 // FIXME: elided for now 307 // public OopHandle getInterpreterCalleeReceiver(SymbolOop signature) { return addressOfInterpreterCalleeReceiver(signature).getOopHandleAt(0); } 308 309 //-------------------------------------------------------------------------------- 310 // Expression stack (may go up or down, direction == 1 or -1) 311 // 312 313 public abstract Address addressOfInterpreterFrameExpressionStack(); 314 public abstract int getInterpreterFrameExpressionStackDirection(); 315 public Address addressOfInterpreterFrameExpressionStackSlot(int slot) { 316 return addressOfInterpreterFrameExpressionStack().addOffsetTo(-slot * VM.getVM().getAddressSize()); 317 } 318 319 /** Top of expression stack */ 320 public abstract Address addressOfInterpreterFrameTOS(); 321 322 /** Expression stack from top down */ 323 public abstract Address addressOfInterpreterFrameTOSAt(int slot); 324 325 /** FIXME: is this portable? */ 326 public int getInterpreterFrameExpressionStackSize() { 327 return (int) (1 + (getInterpreterFrameExpressionStackDirection() * 328 (addressOfInterpreterFrameTOS().minus(addressOfInterpreterFrameExpressionStack())))); 329 } 330 331 public abstract Address getInterpreterFrameSenderSP(); 332 // FIXME: not yet implementable 333 // public abstract void setInterpreterFrameSenderSP(Address senderSP); 334 335 //-------------------------------------------------------------------------------- 336 // BasicObjectLocks: 337 // 338 339 public abstract BasicObjectLock interpreterFrameMonitorBegin(); 340 public abstract BasicObjectLock interpreterFrameMonitorEnd(); 341 /** NOTE: this returns a size in BYTES in this system! */ 342 public abstract int interpreterFrameMonitorSize(); 343 public BasicObjectLock nextMonitorInInterpreterFrame(BasicObjectLock cur) { 344 return new BasicObjectLock(cur.address().addOffsetTo(interpreterFrameMonitorSize())); 345 } 346 public BasicObjectLock previousMonitorInInterpreterFrame(BasicObjectLock cur) { 347 return new BasicObjectLock(cur.address().addOffsetTo(-1 * interpreterFrameMonitorSize())); 348 } 349 350 // interpreter_frame_monitor_begin is higher in memory than interpreter_frame_monitor_end 351 // Interpreter_frame_monitor_begin points to one element beyond the oldest one, 352 // interpreter_frame_monitor_end points to the youngest one, or if there are none, 353 // it points to one beyond where the first element will be. 354 // interpreter_frame_monitor_size reports the allocation size of a monitor in the interpreter stack. 355 // this value is >= BasicObjectLock::size(), and may be rounded up 356 357 // FIXME: avoiding implementing this for now if possible 358 // public void interpreter_frame_set_monitor_end(BasicObjectLock* value); 359 // public void interpreter_frame_verify_monitor(BasicObjectLock* value) const; 360 //-------------------------------------------------------------------------------- 361 // Method and constant pool cache: 362 // 363 364 /** Current method */ 365 public abstract Address addressOfInterpreterFrameMethod(); 366 367 /** Current method */ 368 public Method getInterpreterFrameMethod() { 369 return (Method)Metadata.instantiateWrapperFor(addressOfInterpreterFrameMethod().getAddressAt(0)); 370 } 371 372 /** Current method */ 373 // FIXME: not yet implementable 374 // public void setInterpreterFrameMethod(Method method); 375 376 /** Constant pool cache */ 377 public abstract Address addressOfInterpreterFrameCPCache(); 378 /** Constant pool cache */ 379 public ConstantPoolCache getInterpreterFrameCPCache() { 380 return (ConstantPoolCache) Metadata.instantiateWrapperFor(addressOfInterpreterFrameCPCache().getAddressAt(0)); 381 } 382 383 //-------------------------------------------------------------------------------- 384 // Entry frames: 385 // 386 387 public abstract JavaCallWrapper getEntryFrameCallWrapper(); 388 389 // FIXME: add 390 // inline intptr_t* entry_frame_argument_at(int offset) const; 391 392 393 /** Tells whether there is another chunk of Delta stack above */ 394 public boolean entryFrameIsFirst() { return (getEntryFrameCallWrapper().getLastJavaSP() == null); } 395 396 //-------------------------------------------------------------------------------- 397 // Safepoints: 398 // 399 400 protected abstract Address addressOfSavedOopResult(); 401 protected abstract Address addressOfSavedReceiver(); 402 403 public OopHandle getSavedOopResult() { 404 return addressOfSavedOopResult().getOopHandleAt(0); 405 } 406 407 // FIXME: not yet implementable 408 // public void setSavedOopResult(OopHandle obj); 409 410 public OopHandle getSavedReceiver() { 411 return addressOfSavedReceiver().getOopHandleAt(0); 412 } 413 414 // FIXME: not yet implementable 415 // public void setSavedReceiver(OopHandle obj); 416 417 //-------------------------------------------------------------------------------- 418 // Oop traversals: 419 // 420 421 public void oopsInterpretedArgumentsDo(Symbol signature, boolean isStatic, AddressVisitor f) { 422 ArgumentOopFinder finder = new ArgumentOopFinder(signature, isStatic, this, f); 423 finder.oopsDo(); 424 } 425 426 /** Conversion from an VMReg::Name to physical stack location */ 427 public Address oopMapRegToLocation(VMReg reg, RegisterMap regMap) { 428 VMReg stack0 = VM.getVM().getVMRegImplInfo().getStack0(); 429 if (reg.lessThan(stack0)) { 430 // If it is passed in a register, it got spilled in the stub frame. 431 return regMap.getLocation(reg); 432 } else { 433 long spOffset = reg.reg2Stack() * VM.getVM().getVMRegImplInfo().getStackSlotSize(); 434 return getUnextendedSP().addOffsetTo(spOffset); 435 } 436 } 437 438 public void oopsDo(AddressVisitor oopVisitor, RegisterMap map) { 439 if (isInterpretedFrame()) { 440 oopsInterpretedDo(oopVisitor, map); 441 } else if (isEntryFrame()) { 442 oopsEntryDo(oopVisitor, map); 443 } else if (VM.getVM().getCodeCache().contains(getPC())) { 444 oopsCodeBlobDo(oopVisitor, map); 445 } else { 446 Assert.that(false, "should not reach here"); 447 } 448 } 449 450 //-------------------------------------------------------------------------------- 451 // Printing code 452 // 453 454 public void printValue() { 455 printValueOn(System.out); 456 } 457 458 public void printValueOn(PrintStream tty) { 459 // FIXME; 460 } 461 462 public void print() { 463 printOn(System.out); 464 } 465 466 public void printOn(PrintStream tty) { 467 // FIXME; 468 } 469 470 public void interpreterFramePrintOn(PrintStream tty) { 471 // FIXME; 472 } 473 474 //-------------------------------------------------------------------------------- 475 // Get/set typed locals from a frame. 476 // Respects platform dependent word-ordering. 477 // 478 // FIXME: avoiding implementing this for now if possible 479 // 480 // Currently these work only for interpreted frames. 481 // Todo: make these work for compiled frames. 482 // 483 // oop get_local_object(jint slot) const; 484 // jint get_local_int (jint slot) const; 485 // jlong get_local_long (jint slot) const; 486 // jfloat get_local_float (jint slot) const; 487 // jdouble get_local_double(jint slot) const; 488 // 489 // void set_local_object(jint slot, oop obj); 490 // void set_local_int (jint slot, jint i); 491 // void set_local_long (jint slot, jlong l); 492 // void set_local_float (jint slot, jfloat f); 493 // void set_local_double(jint slot, jdouble d); 494 495 // FIXME: add safepoint code, oops_do, etc. 496 // FIXME: NOT FINISHED 497 498 499 500 501 502 //-------------------------------------------------------------------------------- 503 // Internals only below this point 504 // 505 506 // /** Helper method for better factored code in frame::sender */ 507 // private frame sender_for_entry_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); } 508 // private frame sender_for_interpreter_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); } 509 510 // 511 // Oop iteration (FIXME: NOT FINISHED) 512 // 513 514 515 private static class InterpVisitor implements OopMapVisitor { 516 private AddressVisitor addressVisitor; 517 518 public InterpVisitor(AddressVisitor oopVisitor) { 519 setAddressVisitor(oopVisitor); 520 } 521 522 public void setAddressVisitor(AddressVisitor addressVisitor) { 523 this.addressVisitor = addressVisitor; 524 } 525 526 public void visitOopLocation(Address oopAddr) { 527 addressVisitor.visitAddress(oopAddr); 528 } 529 530 public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) { 531 if (VM.getVM().isClientCompiler()) { 532 Assert.that(false, "should not reach here"); 533 } else if (VM.getVM().isServerCompiler() && 534 VM.getVM().useDerivedPointerTable()) { 535 Assert.that(false, "FIXME: add derived pointer table"); 536 } 537 } 538 539 public void visitNarrowOopLocation(Address compOopAddr) { 540 addressVisitor.visitCompOopAddress(compOopAddr); 541 } 542 } 543 544 private void oopsInterpretedDo(AddressVisitor oopVisitor, RegisterMap map) { 545 if (Assert.ASSERTS_ENABLED) { 546 Assert.that(map != null, "map must be set"); 547 } 548 Method m = getInterpreterFrameMethod(); 549 int bci = getInterpreterFrameBCI(); 550 551 // FIXME: Seeing this sometimes 552 if (VM.getVM().isDebugging()) { 553 if (bci < 0 || bci >= m.getCodeSize()) return; 554 } 555 556 if (Assert.ASSERTS_ENABLED) { 557 // Assert.that(VM.getVM().getUniverse().heap().isIn(m), "method must be valid oop"); 558 Assert.that((m.isNative() && (bci == 0)) || ((bci >= 0) && (bci < m.getCodeSize())), "invalid bci value"); 559 } 560 561 // Handle the monitor elements in the activation 562 // FIXME: monitor information not yet exposed 563 // for ( 564 // BasicObjectLock* current = interpreter_frame_monitor_end(); 565 // current < interpreter_frame_monitor_begin(); 566 // current = next_monitor_in_interpreter_frame(current) 567 // ) { 568 //#ifdef ASSERT 569 // interpreter_frame_verify_monitor(current); 570 //#endif 571 // current->oops_do(f); 572 // } 573 574 // process fixed part 575 // FIXME: these are no longer oops, so should anything be visitied? 576 // oopVisitor.visitAddress(addressOfInterpreterFrameMethod()); 577 // oopVisitor.visitAddress(addressOfInterpreterFrameCPCache()); 578 579 // FIXME: expose interpreterFrameMirrorOffset 580 // if (m.isNative() && m.isStatic()) { 581 // oopVisitor.visitAddress(getFP().addOffsetTo(interpreterFrameMirrorOffset)); 582 // } 583 584 int maxLocals = (int) (m.isNative() ? m.getSizeOfParameters() : m.getMaxLocals()); 585 InterpreterFrameClosure blk = new InterpreterFrameClosure(this, maxLocals, (int) m.getMaxStack(), oopVisitor); 586 587 // process locals & expression stack 588 OopMapCacheEntry mask = m.getMaskFor(bci); 589 mask.iterateOop(blk); 590 591 // process a callee's arguments if we are at a call site 592 // (i.e., if we are at an invoke bytecode) 593 if (map.getIncludeArgumentOops() && !m.isNative()) { 594 BytecodeInvoke call = BytecodeInvoke.atCheck(m, bci); 595 if (call != null && getInterpreterFrameExpressionStackSize() > 0) { 596 // we are at a call site & the expression stack is not empty 597 // => process callee's arguments 598 // 599 // Note: The expression stack can be empty if an exception 600 // occured during method resolution/execution. In all 601 // cases we empty the expression stack completely be- 602 // fore handling the exception (the exception handling 603 // code in the interpreter calls a blocking runtime 604 // routine which can cause this code to be executed). 605 // (was bug gri 7/27/98) 606 oopsInterpretedArgumentsDo(call.signature(), call.isInvokestatic(), oopVisitor); 607 } 608 } 609 } 610 611 private void oopsEntryDo (AddressVisitor oopVisitor, RegisterMap regMap) {} 612 private void oopsCodeBlobDo (AddressVisitor oopVisitor, RegisterMap regMap) { 613 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); 614 if (Assert.ASSERTS_ENABLED) { 615 Assert.that(cb != null, "sanity check"); 616 } 617 if (cb.getOopMaps() != null) { 618 ImmutableOopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging()); 619 620 // FIXME: add in traversal of argument oops (skipping this for 621 // now until we have the other stuff tested) 622 623 } 624 625 // FIXME: would add this in in non-debugging system 626 627 // If we see an activation belonging to a non_entrant nmethod, we mark it. 628 // if (cb->is_nmethod() && ((nmethod *)cb)->is_not_entrant()) { 629 // ((nmethod*)cb)->mark_as_seen_on_stack(); 630 // } 631 } 632 633 // FIXME: implement the above routines, plus add 634 // oops_interpreted_arguments_do and oops_compiled_arguments_do 635 } 636 637 // 638 // Only used internally, to iterate through oop slots in interpreted 639 // frames 640 // 641 class InterpreterFrameClosure implements OffsetClosure { 642 // Used for debugging this code 643 private static final boolean DEBUG = false; 644 645 private Frame fr; 646 private AddressVisitor f; 647 private int maxLocals; 648 private int maxStack; 649 650 InterpreterFrameClosure(Frame fr, int maxLocals, int maxStack, AddressVisitor f) { 651 this.fr = fr; 652 this.maxLocals = maxLocals; 653 this.maxStack = maxStack; 654 this.f = f; 655 } 656 657 public void offsetDo(int offset) { 658 if (DEBUG) { 659 System.err.println("Visiting offset " + offset + ", maxLocals = " + maxLocals + 660 " for frame " + fr + ", method " + 661 fr.getInterpreterFrameMethod().getMethodHolder().getName().asString() + 662 fr.getInterpreterFrameMethod().getName().asString()); 663 } 664 Address addr; 665 if (offset < maxLocals) { 666 addr = fr.addressOfInterpreterFrameLocal(offset); 667 if (Assert.ASSERTS_ENABLED) { 668 Assert.that(AddressOps.gte(addr, fr.getSP()), "must be inside the frame"); 669 } 670 if (DEBUG) { 671 System.err.println(" Visiting local at addr " + addr); 672 } 673 f.visitAddress(addr); 674 } else { 675 addr = fr.addressOfInterpreterFrameExpressionStackSlot(offset - maxLocals); 676 if (DEBUG) { 677 System.err.println(" Address of expression stack slot: " + addr + ", TOS = " + 678 fr.addressOfInterpreterFrameTOS()); 679 } 680 // In case of exceptions, the expression stack is invalid and the esp will be reset to express 681 // this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel). 682 boolean inStack; 683 if (fr.getInterpreterFrameExpressionStackDirection() > 0) { 684 inStack = AddressOps.lte(addr, fr.addressOfInterpreterFrameTOS()); 685 } else { 686 inStack = AddressOps.gte(addr, fr.addressOfInterpreterFrameTOS()); 687 } 688 if (inStack) { 689 if (DEBUG) { 690 System.err.println(" In stack; visiting location."); 691 } 692 f.visitAddress(addr); 693 } else if (DEBUG) { 694 System.err.println(" *** WARNING: Address is out of bounds"); 695 } 696 } 697 } 698 } 699 700 // Only used internally, to find arguments in interpreted frames 701 class ArgumentOopFinder extends SignatureInfo { 702 private AddressVisitor f; 703 private int offset; 704 private boolean isStatic; 705 private Frame fr; 706 707 protected void set(int size, int type) { 708 offset -= size; 709 if (type == BasicType.getTObject() || type == BasicType.getTArray()) oopOffsetDo(); 710 } 711 712 private void oopOffsetDo() { 713 f.visitAddress(fr.addressOfInterpreterFrameTOSAt(offset)); 714 } 715 716 public ArgumentOopFinder(Symbol signature, boolean isStatic, Frame fr, AddressVisitor f) { 717 super(signature); 718 719 // compute size of arguments 720 int argsSize = new ArgumentSizeComputer(signature).size() + (isStatic ? 0 : 1); 721 if (Assert.ASSERTS_ENABLED) { 722 Assert.that(!fr.isInterpretedFrame() || 723 argsSize <= fr.getInterpreterFrameExpressionStackSize(), "args cannot be on stack anymore"); 724 } 725 // initialize ArgumentOopFinder 726 this.f = f; 727 this.fr = fr; 728 this.offset = argsSize; 729 this.isStatic = isStatic; 730 } 731 732 public void oopsDo() { 733 if (!isStatic) { 734 --offset; 735 oopOffsetDo(); 736 } 737 iterateParameters(); 738 } 739 }