public final class ScanThread extends Object
Threads, stacks, jni environments, and register objects have a complex interaction in terms of scanning. The operation of scanning the stack reveals not only roots inside the stack but also the state of the register objects's gprs and the JNI refs array. They are all associated via the thread object, making it natural for scanThread to be considered a single operation with the method directly accessing these objects via the thread object's fields.
One pitfall occurs when scanning the thread object (plus dependents) when not all of the objects have been copied. Then it may be that the innards of the register object has not been copied while the stack object has. The result is that an inconsistent set of slots is reported. In this case, the copied register object may not be correct if the copy occurs after the root locations are discovered but before those locations are processed. In essence, all of these objects form one logical unit but are physically separated so that sometimes only part of it has been copied causing the scan to be incorrect.
The caller of the stack scanning routine must ensure that all of these components's descendants are consistent (all copied) when this method is called.
Code locations: Identifying pointers into code objects is essential if code objects are allowed to move (and if the code objects were not otherwise kept alive, it would be necessary to ensure the liveness of the code objects). A code pointer is the only case in which we have interior pointers (pointers into the inside of objects). For such pointers, two things must occur: first the pointed to object must be kept alive, and second, if the pointed to object is moved by a copying collector, the pointer into the object must be adjusted so it now points into the newly copied object
Modifier and Type | Field and Description |
---|---|
private CompiledMethod |
compiledMethod |
private int |
compiledMethodType |
private static int |
DEFAULT_VERBOSITY |
private boolean |
failed |
private static int |
FAILURE_VERBOSITY |
private Address |
fp |
private Address |
initialIPLoc |
private Address |
ip |
private GCMapIterator |
iterator |
private GCMapIteratorGroup |
iteratorGroup |
private Address |
prevFp |
private boolean |
processCodeLocations |
private boolean |
reinstallReturnBarrier |
private RVMThread |
thread |
private Address |
topFrame |
private TraceLocal |
trace |
(package private) static boolean |
VALIDATE_REFS
quietly validates each ref reported by map iterators
|
Constructor and Description |
---|
ScanThread() |
Modifier and Type | Method and Description |
---|---|
private void |
assertImmovableInCurrentCollection()
Assert that the stack is immovable.
|
private static void |
checkReference(Address refaddr)
Check that a reference encountered during scanning is valid.
|
private void |
checkReference(Address refaddr,
int verbosity)
Check that a reference encountered during scanning is valid.
|
private void |
dumpRef(Address refaddr,
int verbosity)
Print out information associated with a reference.
|
private void |
dumpStackFrame(int verbosity)
Dump the contents of a stack frame.
|
private void |
dumpTopFrameInfo(int verbosity)
Print out the basic information associated with the top frame on
the stack.
|
private void |
getHWExceptionRegisters()
When an exception occurs, registers are saved temporarily.
|
private void |
printMethod(RVMMethod m)
Print out the name of a method
|
private void |
printMethodHeader()
Print out the method header for the method associated with the
current frame
|
private void |
processCodeLocation(ObjectReference code,
Address ipLoc)
Push a code pointer location onto the code locations deque,
optionally performing a sanity check first.
|
private void |
processFrameForCode(int verbosity)
Identify all pointers into code pointers associated with a frame.
|
private void |
pushFrameIP(ObjectReference code,
int verbosity)
Push the instruction pointer associated with this frame onto the
code locations deque.
|
private static void |
reportDelayedRootEdge(TraceLocal trace,
Address addr)
Wrapper for
TraceLocal.reportDelayedRootEdge(Address) that allows
sanity checking of the address. |
private Address |
scanFrame(int verbosity)
Scan the current stack frame.
|
private void |
scanFrameForCode(ObjectReference code)
Scan this frame for internal code pointers.
|
private void |
scanFrameForObjects(int verbosity)
Identify all the object pointers stored as local variables
associated with (though not necessarily strictly within!)
|
private static void |
scanThread(RVMThread thread,
TraceLocal trace,
boolean processCodeLocations,
Address gprs,
Address topFrame,
boolean newRootsSufficent)
A more general interface to thread scanning, which permits the
scanning of stack segments which are dislocated from the thread
structure.
|
static void |
scanThread(RVMThread thread,
TraceLocal trace,
boolean processCodeLocations,
boolean newRootsSufficient)
Scan a thread, placing the addresses of pointers into supplied buffers.
|
private void |
scanThreadInternal(Address gprs,
int verbosity,
Address sentinelFp)
The main stack scanning loop.
|
private boolean |
setUpFrame(int verbosity)
Set up to scan the current stack frame.
|
private void |
startScan(TraceLocal trace,
boolean processCodeLocations,
RVMThread thread,
Address gprs,
Address ip,
Address fp,
Address initialIPLoc,
Address topFrame,
Address sentinelFp)
Initializes a ScanThread instance, and then scans a stack
associated with a thread, and places references in deques (one for
object pointers, one for interior code pointers).
|
static final boolean VALIDATE_REFS
private static final int DEFAULT_VERBOSITY
private static final int FAILURE_VERBOSITY
private final GCMapIteratorGroup iteratorGroup
private GCMapIterator iterator
private TraceLocal trace
private boolean processCodeLocations
private Address initialIPLoc
private CompiledMethod compiledMethod
private int compiledMethodType
private boolean failed
private boolean reinstallReturnBarrier
public ScanThread()
public static void scanThread(RVMThread thread, TraceLocal trace, boolean processCodeLocations, boolean newRootsSufficient)
thread
- The thread to be scannedtrace
- The trace instance to use for reporting references.processCodeLocations
- Should code locations be processed?newRootsSufficient
- Is a partial stack scan sufficient, or must we do a full scan?private static void reportDelayedRootEdge(TraceLocal trace, Address addr)
TraceLocal.reportDelayedRootEdge(Address)
that allows
sanity checking of the address.trace
- the trace on which TraceLocal.reportDelayedRootEdge(Address)
will be calledaddr
- see JavaDoc of TraceLocal.reportDelayedRootEdge(Address)
private static void scanThread(RVMThread thread, TraceLocal trace, boolean processCodeLocations, Address gprs, Address topFrame, boolean newRootsSufficent)
thread
- The thread to be scannedtrace
- The trace instance to use for reporting references.processCodeLocations
- Should code locations be processed?gprs
- The general purpose registers associated with the
stack being scanned (normally extracted from the thread).topFrame
- The top frame of the stack being scanned, or zero
if this is to be inferred from the thread (normally the case).newRootsSufficent
- Is a partial stack scan sufficient, or must we do a full scan?private void startScan(TraceLocal trace, boolean processCodeLocations, RVMThread thread, Address gprs, Address ip, Address fp, Address initialIPLoc, Address topFrame, Address sentinelFp)
The various state associated with stack scanning is captured by instance variables of this type, which are initialized here.
trace
- The trace instance to use for reporting locations.processCodeLocations
- whether to process parts of the thread
that could point to code (e.g. exception registers).thread
- Thread for the thread whose stack is being scannedgprs
- The general purpose registers associated with the
stack being scanned (normally extracted from the thread).ip
- The instruction pointer for the top frame of the stack
we're about to scan.fp
- The frame pointer for the top frame of the stack we're
about to scan.initialIPLoc
- the address of the initial location of the instruction
pointertopFrame
- The top frame of the stack being scanned, or zero
if this is to be inferred from the thread (normally the case).sentinelFp
- The frame pointer at which the stack scan should stop.private void scanThreadInternal(Address gprs, int verbosity, Address sentinelFp)
Walk the stack one frame at a time, top (lo) to bottom (hi),
gprs
- The general purpose registers associated with the
stack being scanned (normally extracted from the thread).verbosity
- The level of verbosity to be used when
performing the scan.sentinelFp
- the frame pointer at which the stack scan should stopprivate void getHWExceptionRegisters()
Dave G: The contents of the GPRs of the exceptionRegisters are handled during normal stack scanning (@see org.jikesrvm.runtime.compilers.common.HardwareTrapCompiledMethod. It looks to me like the main goal of this method is to ensure that the method in which the trap happened isn't treated as dead code and collected (if it's been marked as obsolete, we are setting its activeOnStackFlag below).
private void processCodeLocation(ObjectReference code, Address ipLoc)
code
- The code object into which this interior pointer pointsipLoc
- The location of the pointer into this code objectprivate Address scanFrame(int verbosity)
First the various iterators are set up, then the frame is scanned for regular pointers, before scanning for code pointers. The iterators are then cleaned up, and native frames skipped if necessary.
verbosity
- The level of verbosity to be used when
performing the scan.private boolean setUpFrame(int verbosity)
verbosity
- The level of verbosity to be used when
performing the scan.private void scanFrameForObjects(int verbosity)
NOTE: Because of the callee save policy of the optimizing compiler, references associated with a given frame may be in callee stack frames (lower memory), outside the current frame. So the iterator may return locations that are outside the frame being scanned.
verbosity
- The level of verbosity to be used when
performing the scan.private void processFrameForCode(int verbosity)
FIXME: SB: Why is it that JNI frames are skipped when considering top of stack frames, while boot image frames are skipped when considering other frames. Shouldn't they both be considered in both cases?
verbosity
- The level of verbosity to be used when
performing the scan.private void pushFrameIP(ObjectReference code, int verbosity)
A stack frame represents an execution context, and thus has an instruction pointer associated with it. In the case of the top frame, the instruction pointer is captured by the IP register, which is preserved in the thread data structure at thread switch time. In the case of all non-top frames, the next instruction pointer is stored as the return address for the previous frame.
The address of the code pointer is pushed onto the code locations deque along with the address of the code object into which it points (both are required since the former is an internal pointer).
The code pointers are updated later (after stack scanning) when the code locations deque is processed. The pointer from RVMMethod to the code object is not updated until after stack scanning, so the pointer to the (uncopied) code object is available throughout the stack scanning process, which enables interior pointer offsets to be correctly computed.
code
- start address of the machine code array associated
with the methodverbosity
- The level of verbosity to be used when
performing the scan.private void scanFrameForCode(ObjectReference code)
code
- The code object associated with this frame.private void assertImmovableInCurrentCollection()
Currently we do not allow stacks to be moved within the heap. If a stack contains native stack frames, then it is impossible for us to safely move it. Prior to the implementation of JNI, Jikes RVM did allow the GC system to move thread stacks, and called a special fixup routine, thread.fixupMovedStack to adjust all of the special interior pointers (SP, FP). If we implement split C & Java stacks then we could allow the Java stacks to be moved, but we can't move the native stack.
private void dumpTopFrameInfo(int verbosity)
verbosity
- The level of verbosity to be used when
performing the scan.private void dumpRef(Address refaddr, int verbosity)
refaddr
- The address of the reference in question.verbosity
- The level of verbosity to be used when
performing the scan.private void checkReference(Address refaddr, int verbosity)
refaddr
- The address of the reference in question.verbosity
- The level of verbosity to be used when
performing the scan.private static void checkReference(Address refaddr)
refaddr
- The address of the reference in question.private void printMethod(RVMMethod m)
m
- The method to be printedprivate void printMethodHeader()
private void dumpStackFrame(int verbosity)
verbosity
- The level of verbosity to be used when
performing the scan.