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; 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 // Tells whether the current interpreter_frame frame pointer 362 // corresponds to the old compiled/deoptimized fp 363 // The receiver used to be a top level frame 364 // public boolean interpreter_frame_equals_unpacked_fp(intptr_t* fp); 365 366 //-------------------------------------------------------------------------------- 367 // Method and constant pool cache: 368 // 369 370 /** Current method */ 371 public abstract Address addressOfInterpreterFrameMethod(); 372 373 /** Current method */ 374 public Method getInterpreterFrameMethod() { 375 return (Method)Metadata.instantiateWrapperFor(addressOfInterpreterFrameMethod().getAddressAt(0)); 376 } 377 378 /** Current method */ 379 // FIXME: not yet implementable 380 // public void setInterpreterFrameMethod(Method method); 381 382 /** Constant pool cache */ 383 public abstract Address addressOfInterpreterFrameCPCache(); 384 /** Constant pool cache */ 385 public ConstantPoolCache getInterpreterFrameCPCache() { 386 return (ConstantPoolCache) Metadata.instantiateWrapperFor(addressOfInterpreterFrameCPCache().getAddressAt(0)); 387 } 388 389 //-------------------------------------------------------------------------------- 390 // Entry frames: 391 // 392 393 public abstract JavaCallWrapper getEntryFrameCallWrapper(); 394 395 // FIXME: add 396 // inline intptr_t* entry_frame_argument_at(int offset) const; 397 398 399 /** Tells whether there is another chunk of Delta stack above */ 400 public boolean entryFrameIsFirst() { return (getEntryFrameCallWrapper().getLastJavaSP() == null); } 401 402 //-------------------------------------------------------------------------------- 403 // Safepoints: 404 // 405 406 protected abstract Address addressOfSavedOopResult(); 407 protected abstract Address addressOfSavedReceiver(); 408 409 public OopHandle getSavedOopResult() { 410 return addressOfSavedOopResult().getOopHandleAt(0); 411 } 412 413 // FIXME: not yet implementable 414 // public void setSavedOopResult(OopHandle obj); 415 416 public OopHandle getSavedReceiver() { 417 return addressOfSavedReceiver().getOopHandleAt(0); 418 } 419 420 // FIXME: not yet implementable 421 // public void setSavedReceiver(OopHandle obj); 422 423 //-------------------------------------------------------------------------------- 424 // Oop traversals: 425 // 426 427 public void oopsInterpretedArgumentsDo(Symbol signature, boolean isStatic, AddressVisitor f) { 428 ArgumentOopFinder finder = new ArgumentOopFinder(signature, isStatic, this, f); 429 finder.oopsDo(); 430 } 431 432 /** Conversion from an VMReg::Name to physical stack location */ 433 public Address oopMapRegToLocation(VMReg reg, RegisterMap regMap) { 434 VMReg stack0 = VM.getVM().getVMRegImplInfo().getStack0(); 435 if (reg.lessThan(stack0)) { 436 // If it is passed in a register, it got spilled in the stub frame. 437 return regMap.getLocation(reg); 438 } else { 439 long spOffset = VM.getVM().getAddressSize() * reg.minus(stack0); 440 return getUnextendedSP().addOffsetTo(spOffset); 441 } 442 } 443 444 public void oopsDo(AddressVisitor oopVisitor, RegisterMap map) { 445 if (isInterpretedFrame()) { 446 oopsInterpretedDo(oopVisitor, map); 447 } else if (isEntryFrame()) { 448 oopsEntryDo(oopVisitor, map); 449 } else if (VM.getVM().getCodeCache().contains(getPC())) { 450 oopsCodeBlobDo(oopVisitor, map); 451 } else { 452 Assert.that(false, "should not reach here"); 453 } 454 } 455 456 //-------------------------------------------------------------------------------- 457 // Printing code 458 // 459 460 public void printValue() { 461 printValueOn(System.out); 462 } 463 464 public void printValueOn(PrintStream tty) { 465 // FIXME; 466 } 467 468 public void print() { 469 printOn(System.out); 470 } 471 472 public void printOn(PrintStream tty) { 473 // FIXME; 474 } 475 476 public void interpreterFramePrintOn(PrintStream tty) { 477 // FIXME; 478 } 479 480 //-------------------------------------------------------------------------------- 481 // Get/set typed locals from a frame. 482 // Respects platform dependent word-ordering. 483 // 484 // FIXME: avoiding implementing this for now if possible 485 // 486 // Currently these work only for interpreted frames. 487 // Todo: make these work for compiled frames. 488 // 489 // oop get_local_object(jint slot) const; 490 // jint get_local_int (jint slot) const; 491 // jlong get_local_long (jint slot) const; 492 // jfloat get_local_float (jint slot) const; 493 // jdouble get_local_double(jint slot) const; 494 // 495 // void set_local_object(jint slot, oop obj); 496 // void set_local_int (jint slot, jint i); 497 // void set_local_long (jint slot, jlong l); 498 // void set_local_float (jint slot, jfloat f); 499 // void set_local_double(jint slot, jdouble d); 500 501 // FIXME: add safepoint code, oops_do, etc. 502 // FIXME: NOT FINISHED 503 504 505 506 507 508 //-------------------------------------------------------------------------------- 509 // Internals only below this point 510 // 511 512 // /** Helper method for better factored code in frame::sender */ 513 // private frame sender_for_entry_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); } 514 // private frame sender_for_interpreter_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); } 515 516 // 517 // Oop iteration (FIXME: NOT FINISHED) 518 // 519 520 521 private static class InterpVisitor implements OopMapVisitor { 522 private AddressVisitor addressVisitor; 523 524 public InterpVisitor(AddressVisitor oopVisitor) { 525 setAddressVisitor(oopVisitor); 526 } 527 528 public void setAddressVisitor(AddressVisitor addressVisitor) { 529 this.addressVisitor = addressVisitor; 530 } 531 532 public void visitOopLocation(Address oopAddr) { 533 addressVisitor.visitAddress(oopAddr); 534 } 535 536 public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) { 537 if (VM.getVM().isClientCompiler()) { 538 Assert.that(false, "should not reach here"); 539 } else if (VM.getVM().isServerCompiler() && 540 VM.getVM().useDerivedPointerTable()) { 541 Assert.that(false, "FIXME: add derived pointer table"); 542 } 543 } 544 545 public void visitValueLocation(Address valueAddr) { 546 } 547 548 public void visitNarrowOopLocation(Address compOopAddr) { 549 addressVisitor.visitCompOopAddress(compOopAddr); 550 } 551 } 552 553 private void oopsInterpretedDo(AddressVisitor oopVisitor, RegisterMap map) { 554 if (Assert.ASSERTS_ENABLED) { 555 Assert.that(map != null, "map must be set"); 556 } 557 Method m = getInterpreterFrameMethod(); 558 int bci = getInterpreterFrameBCI(); 559 560 // FIXME: Seeing this sometimes 561 if (VM.getVM().isDebugging()) { 562 if (bci < 0 || bci >= m.getCodeSize()) return; 563 } 564 565 if (Assert.ASSERTS_ENABLED) { 566 // Assert.that(VM.getVM().getUniverse().heap().isIn(m), "method must be valid oop"); 567 Assert.that((m.isNative() && (bci == 0)) || ((bci >= 0) && (bci < m.getCodeSize())), "invalid bci value"); 568 } 569 570 // Handle the monitor elements in the activation 571 // FIXME: monitor information not yet exposed 572 // for ( 573 // BasicObjectLock* current = interpreter_frame_monitor_end(); 574 // current < interpreter_frame_monitor_begin(); 575 // current = next_monitor_in_interpreter_frame(current) 576 // ) { 577 //#ifdef ASSERT 578 // interpreter_frame_verify_monitor(current); 579 //#endif 580 // current->oops_do(f); 581 // } 582 583 // process fixed part 584 // FIXME: these are no longer oops, so should anything be visitied? 585 // oopVisitor.visitAddress(addressOfInterpreterFrameMethod()); 586 // oopVisitor.visitAddress(addressOfInterpreterFrameCPCache()); 587 588 // FIXME: expose interpreterFrameMirrorOffset 589 // if (m.isNative() && m.isStatic()) { 590 // oopVisitor.visitAddress(getFP().addOffsetTo(interpreterFrameMirrorOffset)); 591 // } 592 593 int maxLocals = (int) (m.isNative() ? m.getSizeOfParameters() : m.getMaxLocals()); 594 InterpreterFrameClosure blk = new InterpreterFrameClosure(this, maxLocals, (int) m.getMaxStack(), oopVisitor); 595 596 // process locals & expression stack 597 OopMapCacheEntry mask = m.getMaskFor(bci); 598 mask.iterateOop(blk); 599 600 // process a callee's arguments if we are at a call site 601 // (i.e., if we are at an invoke bytecode) 602 if (map.getIncludeArgumentOops() && !m.isNative()) { 603 BytecodeInvoke call = BytecodeInvoke.atCheck(m, bci); 604 if (call != null && getInterpreterFrameExpressionStackSize() > 0) { 605 // we are at a call site & the expression stack is not empty 606 // => process callee's arguments 607 // 608 // Note: The expression stack can be empty if an exception 609 // occured during method resolution/execution. In all 610 // cases we empty the expression stack completely be- 611 // fore handling the exception (the exception handling 612 // code in the interpreter calls a blocking runtime 613 // routine which can cause this code to be executed). 614 // (was bug gri 7/27/98) 615 oopsInterpretedArgumentsDo(call.signature(), call.isInvokestatic(), oopVisitor); 616 } 617 } 618 } 619 620 private void oopsEntryDo (AddressVisitor oopVisitor, RegisterMap regMap) {} 621 private void oopsCodeBlobDo (AddressVisitor oopVisitor, RegisterMap regMap) { 622 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); 623 if (Assert.ASSERTS_ENABLED) { 624 Assert.that(cb != null, "sanity check"); 625 } 626 if (cb.getOopMaps() != null) { 627 ImmutableOopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging()); 628 629 // FIXME: add in traversal of argument oops (skipping this for 630 // now until we have the other stuff tested) 631 632 } 633 634 // FIXME: would add this in in non-debugging system 635 636 // If we see an activation belonging to a non_entrant nmethod, we mark it. 637 // if (cb->is_nmethod() && ((nmethod *)cb)->is_not_entrant()) { 638 // ((nmethod*)cb)->mark_as_seen_on_stack(); 639 // } 640 } 641 642 // FIXME: implement the above routines, plus add 643 // oops_interpreted_arguments_do and oops_compiled_arguments_do 644 } 645 646 // 647 // Only used internally, to iterate through oop slots in interpreted 648 // frames 649 // 650 class InterpreterFrameClosure implements OffsetClosure { 651 // Used for debugging this code 652 private static final boolean DEBUG = false; 653 654 private Frame fr; 655 private AddressVisitor f; 656 private int maxLocals; 657 private int maxStack; 658 659 InterpreterFrameClosure(Frame fr, int maxLocals, int maxStack, AddressVisitor f) { 660 this.fr = fr; 661 this.maxLocals = maxLocals; 662 this.maxStack = maxStack; 663 this.f = f; 664 } 665 666 public void offsetDo(int offset) { 667 if (DEBUG) { 668 System.err.println("Visiting offset " + offset + ", maxLocals = " + maxLocals + 669 " for frame " + fr + ", method " + 670 fr.getInterpreterFrameMethod().getMethodHolder().getName().asString() + 671 fr.getInterpreterFrameMethod().getName().asString()); 672 } 673 Address addr; 674 if (offset < maxLocals) { 675 addr = fr.addressOfInterpreterFrameLocal(offset); 676 if (Assert.ASSERTS_ENABLED) { 677 Assert.that(AddressOps.gte(addr, fr.getSP()), "must be inside the frame"); 678 } 679 if (DEBUG) { 680 System.err.println(" Visiting local at addr " + addr); 681 } 682 f.visitAddress(addr); 683 } else { 684 addr = fr.addressOfInterpreterFrameExpressionStackSlot(offset - maxLocals); 685 if (DEBUG) { 686 System.err.println(" Address of expression stack slot: " + addr + ", TOS = " + 687 fr.addressOfInterpreterFrameTOS()); 688 } 689 // In case of exceptions, the expression stack is invalid and the esp will be reset to express 690 // this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel). 691 boolean inStack; 692 if (fr.getInterpreterFrameExpressionStackDirection() > 0) { 693 inStack = AddressOps.lte(addr, fr.addressOfInterpreterFrameTOS()); 694 } else { 695 inStack = AddressOps.gte(addr, fr.addressOfInterpreterFrameTOS()); 696 } 697 if (inStack) { 698 if (DEBUG) { 699 System.err.println(" In stack; visiting location."); 700 } 701 f.visitAddress(addr); 702 } else if (DEBUG) { 703 System.err.println(" *** WARNING: Address is out of bounds"); 704 } 705 } 706 } 707 } 708 709 // Only used internally, to find arguments in interpreted frames 710 class ArgumentOopFinder extends SignatureInfo { 711 private AddressVisitor f; 712 private int offset; 713 private boolean isStatic; 714 private Frame fr; 715 716 protected void set(int size, int type) { 717 offset -= size; 718 if (type == BasicType.getTObject() || type == BasicType.getTArray()) oopOffsetDo(); 719 } 720 721 private void oopOffsetDo() { 722 f.visitAddress(fr.addressOfInterpreterFrameTOSAt(offset)); 723 } 724 725 public ArgumentOopFinder(Symbol signature, boolean isStatic, Frame fr, AddressVisitor f) { 726 super(signature); 727 728 // compute size of arguments 729 int argsSize = new ArgumentSizeComputer(signature).size() + (isStatic ? 0 : 1); 730 if (Assert.ASSERTS_ENABLED) { 731 Assert.that(!fr.isInterpretedFrame() || 732 argsSize <= fr.getInterpreterFrameExpressionStackSize(), "args cannot be on stack anymore"); 733 } 734 // initialize ArgumentOopFinder 735 this.f = f; 736 this.fr = fr; 737 this.offset = argsSize; 738 this.isStatic = isStatic; 739 } 740 741 public void oopsDo() { 742 if (!isStatic) { 743 --offset; 744 oopOffsetDo(); 745 } 746 iterateParameters(); 747 } 748 }