Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java
41161 views
/*1* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.runtime;2526import java.io.*;27import java.util.*;2829import sun.jvm.hotspot.code.*;30import sun.jvm.hotspot.compiler.*;31import sun.jvm.hotspot.debugger.*;32import sun.jvm.hotspot.interpreter.*;33import sun.jvm.hotspot.oops.*;34import sun.jvm.hotspot.types.*;35import sun.jvm.hotspot.utilities.*;36import sun.jvm.hotspot.utilities.Observable;37import sun.jvm.hotspot.utilities.Observer;3839/** <P> A frame represents a physical stack frame (an activation).40Frames can be C or Java frames, and the Java frames can be41interpreted or compiled. In contrast, vframes represent42source-level activations, so that one physical frame can43correspond to multiple source level frames because of inlining.44</P>4546<P> NOTE that this is not a VMObject and does not wrap an Address47-- this is an actual port of the VM's Frame code to Java. </P>4849<P> NOTE also that this is incomplete -- just trying to get50reading of interpreted frames working for now, so all non-core and51setter methods are removed for now. (FIXME) </P> */5253public abstract class Frame implements Cloneable {54/** A raw stack pointer. The accessor getSP() will return a real (usable)55stack pointer (e.g. from Thread::last_Java_sp) */56protected Address raw_sp;5758/** Program counter (the next instruction after the call) */59protected Address pc;60protected boolean deoptimized;6162public Frame() {63deoptimized = false;64}6566static {67VM.registerVMInitializedObserver(new Observer() {68public void update(Observable o, Object data) {69initialize(VM.getVM().getTypeDataBase());70}71});72}7374/** Size of ConstMethod for computing BCI from BCP (FIXME: hack) */75private static long ConstMethodSize;7677private static int pcReturnOffset;7879public static int pcReturnOffset() {80return pcReturnOffset;81}8283private static synchronized void initialize(TypeDataBase db) {84Type ConstMethodType = db.lookupType("ConstMethod");85// FIXME: not sure whether alignment here is correct or how to86// force it (round up to address size?)87ConstMethodSize = ConstMethodType.getSize();8889pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue();90}9192protected int bcpToBci(Address bcp, ConstMethod cm) {93// bcp will be null for interpreter native methods94// in addition depending on where we catch the system the value can95// be a bcp or a bci.96if (bcp == null) return 0;97long bci = bcp.minus(null);98if (bci >= 0 && bci < cm.getCodeSize()) return (int) bci;99return (int) (bcp.minus(cm.getAddress()) - ConstMethodSize);100}101102protected int bcpToBci(Address bcp, Method m) {103return bcpToBci(bcp, m.getConstMethod());104}105106public abstract Object clone();107108// Accessors109110/** pc: Returns the pc at which this frame will continue normally.111It must point at the beginning of the next instruction to112execute. */113public Address getPC() { return pc; }114public void setPC(Address newpc) { pc = newpc; }115public boolean isDeoptimized() { return deoptimized; }116117public CodeBlob cb() {118return VM.getVM().getCodeCache().findBlob(getPC());119}120121public abstract Address getSP();122public abstract Address getID();123public abstract Address getFP();124125/** testers -- platform dependent */126public abstract boolean equals(Object arg);127128/** type testers */129public boolean isInterpretedFrame() { return VM.getVM().getInterpreter().contains(getPC()); }130public boolean isJavaFrame() {131if (isInterpretedFrame()) return true;132if (!VM.getVM().isCore()) {133if (isCompiledFrame()) return true;134}135return false;136}137138/** Java frame called from C? */139public boolean isEntryFrame() { return VM.getVM().getStubRoutines().returnsToCallStub(getPC()); }140public boolean isNativeFrame() {141if (!VM.getVM().isCore()) {142CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());143return (cb != null && cb.isNativeMethod());144} else {145return false;146}147}148149public boolean isCompiledFrame() {150if (Assert.ASSERTS_ENABLED) {151Assert.that(!VM.getVM().isCore(), "noncore builds only");152}153CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());154return (cb != null && cb.isJavaMethod());155}156157public boolean isRuntimeFrame() {158if (Assert.ASSERTS_ENABLED) {159Assert.that(!VM.getVM().isCore(), "noncore builds only");160}161CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());162if (cb == null) {163return false;164}165if (cb.isRuntimeStub()) return true;166else return false;167}168169/** oldest frame? (has no sender) FIXME: this is modified from the170C++ code to handle the debugging situation where we try to171traverse the stack for, for example, the signal thread, and172don't find any valid Java frames. Would really like to put the173second half of the conditional in some sort of debugging-only if174statement. */175// *** FIXME: THE CALL TO isJavaFrame() IS WAY TOO EXPENSIVE!!!!! ***176public boolean isFirstFrame() { return ((isEntryFrame() && entryFrameIsFirst()) ||177(!isJavaFrame() && !hasSenderPD())); }178/** same for Java frame */179public boolean isFirstJavaFrame() { throw new RuntimeException("not yet implemented"); }180181/** This is an addition for debugging purposes on platforms which182have the notion of signals. */183public abstract boolean isSignalHandlerFrameDbg();184185/** If this is a signal handler frame (again, on a platform with a186notion of signals), get the signal number. */187public abstract int getSignalNumberDbg();188189/** If this is a signal handler frame (again, on a platform with a190notion of signals), get the name of the signal. */191public abstract String getSignalNameDbg();192193/** performs sanity checks on interpreted frames. */194public abstract boolean isInterpretedFrameValid();195196/** tells whether this frame is marked for deoptimization */197public boolean shouldBeDeoptimized() { throw new RuntimeException("not yet implemented"); }198199/** tells whether this frame can be deoptimized */200public boolean canBeDeoptimized() { throw new RuntimeException("not yet implemented"); }201202/** returns the sending frame */203public abstract Frame sender(RegisterMap map, CodeBlob nm);204205/** equivalent to sender(map, null) */206public Frame sender(RegisterMap map) { return sender(map, null); }207208/** returns the sender, but skips conversion frames */209public Frame realSender(RegisterMap map) {210if (!VM.getVM().isCore()) {211Frame result = sender(map);212while (result.isRuntimeFrame()) {213result = result.sender(map);214}215return result;216} else {217return sender(map);218}219}220221/** Platform-dependent query indicating whether this frame has a222sender. Should return true if it is possible to call sender() at223all on this frame. (This is currently only needed for the224debugging system, if a stack trace is attempted for a Java225thread which has no Java frames, i.e., the signal thread; we226have to know to stop traversal at the bottom frame.) */227protected abstract boolean hasSenderPD();228229//--------------------------------------------------------------------------------230// All frames:231// A low-level interface for vframes:232233/** Returns the address of the requested "slot" on the stack. Slots234are as wide as addresses, so are 32 bits wide on a 32-bit235machine and 64 bits wide on a 64-bit machine. */236public Address addressOfStackSlot(int slot) { return getFP().addOffsetTo(slot * VM.getVM().getAddressSize()); }237238/** Fetches the OopHandle at the requested slot */239public OopHandle getOopHandleAt(int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); }240/** Fetches the OopHandle at the slot, adjusted for compiler frames */241// FIXME: looks like this is only used for compiled frames242// public OopHandle getOopHandleAtAdjusted(MethodOop method, int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); }243// FIXME: Not yet implementable244// public void setOopHandleAt(int slot, OopHandle value) { addressOfStackSlot(slot).setOopHandleAt(0, value); }245246/** Fetches the (Java) int at the requested slot */247public int getIntAt(int slot) { return addressOfStackSlot(slot).getJIntAt(0); }248// FIXME: Not yet implementable249// public void setIntAt(int slot, int value) { addressOfStackSlot(slot).setJIntAt(0, value); }250251/** returns the frame size in stack slots */252public abstract long frameSize();253254/** Link (i.e., the pointer to the previous frame) */255public abstract Address getLink();256// public abstract void setLink(Address addr);257258/** Return address */259public abstract Address getSenderPC();260// FIXME: currently unimplementable261// public abstract void setSenderPC(Address addr);262263/** The frame's original SP, before any extension by an interpreted264callee; used for packing debug info into vframeArray objects and265vframeArray lookup. */266public abstract Address getUnextendedSP();267268/** Returns the stack pointer of the calling frame */269public abstract Address getSenderSP();270271//--------------------------------------------------------------------------------272// Interpreter frames:273//274275public abstract Address addressOfInterpreterFrameLocals();276277public Address addressOfInterpreterFrameLocal(int slot) {278return addressOfInterpreterFrameLocals().getAddressAt(0).addOffsetTo(-slot * VM.getVM().getAddressSize());279}280281// FIXME: not yet implementable282// void interpreter_frame_set_locals(intptr_t* locs);283284// NOTE that the accessor "addressOfInterpreterFrameBCX" has285// necessarily been eliminated. The byte code pointer is inherently286// an interior pointer to a Method (the bytecodes follow the287// Method data structure) and therefore acquisition of it in288// this system can not be allowed. All accesses to interpreter frame289// byte codes are via the byte code index (BCI).290291/** Byte code index. In the underlying frame, what is actually292stored is a byte code pointer (BCP), which is converted to a BCI293and back by the GC when methods are moved. In this system,294interior pointers are not allowed, so we must make the access to295the interpreter frame's BCI atomic with respect to GC. This may296mean implementation with an underlying call through native code297into the VM or a magic sequence in the compiler. (FIXME) */298public abstract int getInterpreterFrameBCI();299// FIXME: not yet implementable300// public abstract void setInterpreterFrameBCI(int bci);301302// FIXME: elided for now303// public abstract Address addressOfInterpreterCalleeReceiver(Symbol signature);304305/** Find receiver for an invoke when arguments are just pushed on306stack (i.e., callee stack-frame is not setup) */307// FIXME: elided for now308// public OopHandle getInterpreterCalleeReceiver(SymbolOop signature) { return addressOfInterpreterCalleeReceiver(signature).getOopHandleAt(0); }309310//--------------------------------------------------------------------------------311// Expression stack (may go up or down, direction == 1 or -1)312//313314public abstract Address addressOfInterpreterFrameExpressionStack();315public abstract int getInterpreterFrameExpressionStackDirection();316public Address addressOfInterpreterFrameExpressionStackSlot(int slot) {317return addressOfInterpreterFrameExpressionStack().addOffsetTo(-slot * VM.getVM().getAddressSize());318}319320/** Top of expression stack */321public abstract Address addressOfInterpreterFrameTOS();322323/** Expression stack from top down */324public abstract Address addressOfInterpreterFrameTOSAt(int slot);325326/** FIXME: is this portable? */327public int getInterpreterFrameExpressionStackSize() {328return (int) (1 + (getInterpreterFrameExpressionStackDirection() *329(addressOfInterpreterFrameTOS().minus(addressOfInterpreterFrameExpressionStack()))));330}331332public abstract Address getInterpreterFrameSenderSP();333// FIXME: not yet implementable334// public abstract void setInterpreterFrameSenderSP(Address senderSP);335336//--------------------------------------------------------------------------------337// BasicObjectLocks:338//339340public abstract BasicObjectLock interpreterFrameMonitorBegin();341public abstract BasicObjectLock interpreterFrameMonitorEnd();342/** NOTE: this returns a size in BYTES in this system! */343public abstract int interpreterFrameMonitorSize();344public BasicObjectLock nextMonitorInInterpreterFrame(BasicObjectLock cur) {345return new BasicObjectLock(cur.address().addOffsetTo(interpreterFrameMonitorSize()));346}347public BasicObjectLock previousMonitorInInterpreterFrame(BasicObjectLock cur) {348return new BasicObjectLock(cur.address().addOffsetTo(-1 * interpreterFrameMonitorSize()));349}350351// interpreter_frame_monitor_begin is higher in memory than interpreter_frame_monitor_end352// Interpreter_frame_monitor_begin points to one element beyond the oldest one,353// interpreter_frame_monitor_end points to the youngest one, or if there are none,354// it points to one beyond where the first element will be.355// interpreter_frame_monitor_size reports the allocation size of a monitor in the interpreter stack.356// this value is >= BasicObjectLock::size(), and may be rounded up357358// FIXME: avoiding implementing this for now if possible359// public void interpreter_frame_set_monitor_end(BasicObjectLock* value);360// public void interpreter_frame_verify_monitor(BasicObjectLock* value) const;361//--------------------------------------------------------------------------------362// Method and constant pool cache:363//364365/** Current method */366public abstract Address addressOfInterpreterFrameMethod();367368/** Current method */369public Method getInterpreterFrameMethod() {370return (Method)Metadata.instantiateWrapperFor(addressOfInterpreterFrameMethod().getAddressAt(0));371}372373/** Current method */374// FIXME: not yet implementable375// public void setInterpreterFrameMethod(Method method);376377/** Constant pool cache */378public abstract Address addressOfInterpreterFrameCPCache();379/** Constant pool cache */380public ConstantPoolCache getInterpreterFrameCPCache() {381return (ConstantPoolCache) Metadata.instantiateWrapperFor(addressOfInterpreterFrameCPCache().getAddressAt(0));382}383384//--------------------------------------------------------------------------------385// Entry frames:386//387388public abstract JavaCallWrapper getEntryFrameCallWrapper();389390// FIXME: add391// inline intptr_t* entry_frame_argument_at(int offset) const;392393394/** Tells whether there is another chunk of Delta stack above */395public boolean entryFrameIsFirst() { return (getEntryFrameCallWrapper().getLastJavaSP() == null); }396397//--------------------------------------------------------------------------------398// Safepoints:399//400401protected abstract Address addressOfSavedOopResult();402protected abstract Address addressOfSavedReceiver();403404public OopHandle getSavedOopResult() {405return addressOfSavedOopResult().getOopHandleAt(0);406}407408// FIXME: not yet implementable409// public void setSavedOopResult(OopHandle obj);410411public OopHandle getSavedReceiver() {412return addressOfSavedReceiver().getOopHandleAt(0);413}414415// FIXME: not yet implementable416// public void setSavedReceiver(OopHandle obj);417418//--------------------------------------------------------------------------------419// Oop traversals:420//421422public void oopsInterpretedArgumentsDo(Symbol signature, boolean isStatic, AddressVisitor f) {423ArgumentOopFinder finder = new ArgumentOopFinder(signature, isStatic, this, f);424finder.oopsDo();425}426427/** Conversion from an VMReg::Name to physical stack location */428public Address oopMapRegToLocation(VMReg reg, RegisterMap regMap) {429VMReg stack0 = VM.getVM().getVMRegImplInfo().getStack0();430if (reg.lessThan(stack0)) {431// If it is passed in a register, it got spilled in the stub frame.432return regMap.getLocation(reg);433} else {434long spOffset = reg.reg2Stack() * VM.getVM().getVMRegImplInfo().getStackSlotSize();435return getUnextendedSP().addOffsetTo(spOffset);436}437}438439public void oopsDo(AddressVisitor oopVisitor, RegisterMap map) {440if (isInterpretedFrame()) {441oopsInterpretedDo(oopVisitor, map);442} else if (isEntryFrame()) {443oopsEntryDo(oopVisitor, map);444} else if (VM.getVM().getCodeCache().contains(getPC())) {445oopsCodeBlobDo(oopVisitor, map);446} else {447Assert.that(false, "should not reach here");448}449}450451//--------------------------------------------------------------------------------452// Printing code453//454455public void printValue() {456printValueOn(System.out);457}458459public void printValueOn(PrintStream tty) {460// FIXME;461}462463public void print() {464printOn(System.out);465}466467public void printOn(PrintStream tty) {468// FIXME;469}470471public void interpreterFramePrintOn(PrintStream tty) {472// FIXME;473}474475//--------------------------------------------------------------------------------476// Get/set typed locals from a frame.477// Respects platform dependent word-ordering.478//479// FIXME: avoiding implementing this for now if possible480//481// Currently these work only for interpreted frames.482// Todo: make these work for compiled frames.483//484// oop get_local_object(jint slot) const;485// jint get_local_int (jint slot) const;486// jlong get_local_long (jint slot) const;487// jfloat get_local_float (jint slot) const;488// jdouble get_local_double(jint slot) const;489//490// void set_local_object(jint slot, oop obj);491// void set_local_int (jint slot, jint i);492// void set_local_long (jint slot, jlong l);493// void set_local_float (jint slot, jfloat f);494// void set_local_double(jint slot, jdouble d);495496// FIXME: add safepoint code, oops_do, etc.497// FIXME: NOT FINISHED498499500501502503//--------------------------------------------------------------------------------504// Internals only below this point505//506507// /** Helper method for better factored code in frame::sender */508// private frame sender_for_entry_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); }509// private frame sender_for_interpreter_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); }510511//512// Oop iteration (FIXME: NOT FINISHED)513//514515516private static class InterpVisitor implements OopMapVisitor {517private AddressVisitor addressVisitor;518519public InterpVisitor(AddressVisitor oopVisitor) {520setAddressVisitor(oopVisitor);521}522523public void setAddressVisitor(AddressVisitor addressVisitor) {524this.addressVisitor = addressVisitor;525}526527public void visitOopLocation(Address oopAddr) {528addressVisitor.visitAddress(oopAddr);529}530531public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {532if (VM.getVM().isClientCompiler()) {533Assert.that(false, "should not reach here");534} else if (VM.getVM().isServerCompiler() &&535VM.getVM().useDerivedPointerTable()) {536Assert.that(false, "FIXME: add derived pointer table");537}538}539540public void visitNarrowOopLocation(Address compOopAddr) {541addressVisitor.visitCompOopAddress(compOopAddr);542}543}544545private void oopsInterpretedDo(AddressVisitor oopVisitor, RegisterMap map) {546if (Assert.ASSERTS_ENABLED) {547Assert.that(map != null, "map must be set");548}549Method m = getInterpreterFrameMethod();550int bci = getInterpreterFrameBCI();551552// FIXME: Seeing this sometimes553if (VM.getVM().isDebugging()) {554if (bci < 0 || bci >= m.getCodeSize()) return;555}556557if (Assert.ASSERTS_ENABLED) {558// Assert.that(VM.getVM().getUniverse().heap().isIn(m), "method must be valid oop");559Assert.that((m.isNative() && (bci == 0)) || ((bci >= 0) && (bci < m.getCodeSize())), "invalid bci value");560}561562// Handle the monitor elements in the activation563// FIXME: monitor information not yet exposed564// for (565// BasicObjectLock* current = interpreter_frame_monitor_end();566// current < interpreter_frame_monitor_begin();567// current = next_monitor_in_interpreter_frame(current)568// ) {569//#ifdef ASSERT570// interpreter_frame_verify_monitor(current);571//#endif572// current->oops_do(f);573// }574575// process fixed part576// FIXME: these are no longer oops, so should anything be visitied?577// oopVisitor.visitAddress(addressOfInterpreterFrameMethod());578// oopVisitor.visitAddress(addressOfInterpreterFrameCPCache());579580// FIXME: expose interpreterFrameMirrorOffset581// if (m.isNative() && m.isStatic()) {582// oopVisitor.visitAddress(getFP().addOffsetTo(interpreterFrameMirrorOffset));583// }584585int maxLocals = (int) (m.isNative() ? m.getSizeOfParameters() : m.getMaxLocals());586InterpreterFrameClosure blk = new InterpreterFrameClosure(this, maxLocals, (int) m.getMaxStack(), oopVisitor);587588// process locals & expression stack589OopMapCacheEntry mask = m.getMaskFor(bci);590mask.iterateOop(blk);591592// process a callee's arguments if we are at a call site593// (i.e., if we are at an invoke bytecode)594if (map.getIncludeArgumentOops() && !m.isNative()) {595BytecodeInvoke call = BytecodeInvoke.atCheck(m, bci);596if (call != null && getInterpreterFrameExpressionStackSize() > 0) {597// we are at a call site & the expression stack is not empty598// => process callee's arguments599//600// Note: The expression stack can be empty if an exception601// occured during method resolution/execution. In all602// cases we empty the expression stack completely be-603// fore handling the exception (the exception handling604// code in the interpreter calls a blocking runtime605// routine which can cause this code to be executed).606// (was bug gri 7/27/98)607oopsInterpretedArgumentsDo(call.signature(), call.isInvokestatic(), oopVisitor);608}609}610}611612private void oopsEntryDo (AddressVisitor oopVisitor, RegisterMap regMap) {}613private void oopsCodeBlobDo (AddressVisitor oopVisitor, RegisterMap regMap) {614CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());615if (Assert.ASSERTS_ENABLED) {616Assert.that(cb != null, "sanity check");617}618if (cb.getOopMaps() != null) {619ImmutableOopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging());620621// FIXME: add in traversal of argument oops (skipping this for622// now until we have the other stuff tested)623624}625626// FIXME: would add this in in non-debugging system627628// If we see an activation belonging to a non_entrant nmethod, we mark it.629// if (cb->is_nmethod() && ((nmethod *)cb)->is_not_entrant()) {630// ((nmethod*)cb)->mark_as_seen_on_stack();631// }632}633634// FIXME: implement the above routines, plus add635// oops_interpreted_arguments_do and oops_compiled_arguments_do636}637638//639// Only used internally, to iterate through oop slots in interpreted640// frames641//642class InterpreterFrameClosure implements OffsetClosure {643// Used for debugging this code644private static final boolean DEBUG = false;645646private Frame fr;647private AddressVisitor f;648private int maxLocals;649private int maxStack;650651InterpreterFrameClosure(Frame fr, int maxLocals, int maxStack, AddressVisitor f) {652this.fr = fr;653this.maxLocals = maxLocals;654this.maxStack = maxStack;655this.f = f;656}657658public void offsetDo(int offset) {659if (DEBUG) {660System.err.println("Visiting offset " + offset + ", maxLocals = " + maxLocals +661" for frame " + fr + ", method " +662fr.getInterpreterFrameMethod().getMethodHolder().getName().asString() +663fr.getInterpreterFrameMethod().getName().asString());664}665Address addr;666if (offset < maxLocals) {667addr = fr.addressOfInterpreterFrameLocal(offset);668if (Assert.ASSERTS_ENABLED) {669Assert.that(AddressOps.gte(addr, fr.getSP()), "must be inside the frame");670}671if (DEBUG) {672System.err.println(" Visiting local at addr " + addr);673}674f.visitAddress(addr);675} else {676addr = fr.addressOfInterpreterFrameExpressionStackSlot(offset - maxLocals);677if (DEBUG) {678System.err.println(" Address of expression stack slot: " + addr + ", TOS = " +679fr.addressOfInterpreterFrameTOS());680}681// In case of exceptions, the expression stack is invalid and the esp will be reset to express682// this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel).683boolean inStack;684if (fr.getInterpreterFrameExpressionStackDirection() > 0) {685inStack = AddressOps.lte(addr, fr.addressOfInterpreterFrameTOS());686} else {687inStack = AddressOps.gte(addr, fr.addressOfInterpreterFrameTOS());688}689if (inStack) {690if (DEBUG) {691System.err.println(" In stack; visiting location.");692}693f.visitAddress(addr);694} else if (DEBUG) {695System.err.println(" *** WARNING: Address is out of bounds");696}697}698}699}700701// Only used internally, to find arguments in interpreted frames702class ArgumentOopFinder extends SignatureInfo {703private AddressVisitor f;704private int offset;705private boolean isStatic;706private Frame fr;707708protected void set(int size, int type) {709offset -= size;710if (type == BasicType.getTObject() || type == BasicType.getTArray()) oopOffsetDo();711}712713private void oopOffsetDo() {714f.visitAddress(fr.addressOfInterpreterFrameTOSAt(offset));715}716717public ArgumentOopFinder(Symbol signature, boolean isStatic, Frame fr, AddressVisitor f) {718super(signature);719720// compute size of arguments721int argsSize = new ArgumentSizeComputer(signature).size() + (isStatic ? 0 : 1);722if (Assert.ASSERTS_ENABLED) {723Assert.that(!fr.isInterpretedFrame() ||724argsSize <= fr.getInterpreterFrameExpressionStackSize(), "args cannot be on stack anymore");725}726// initialize ArgumentOopFinder727this.f = f;728this.fr = fr;729this.offset = argsSize;730this.isStatic = isStatic;731}732733public void oopsDo() {734if (!isStatic) {735--offset;736oopOffsetDo();737}738iterateParameters();739}740}741742743