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