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