// Process a value within the stack. PolyWord ScanAddress::ScanStackAddress(PolyWord val, StackSpace *stack, bool isCode) { PolyWord *base = stack->bottom; PolyWord *end = stack->top; // If isCode is set we definitely have a code address. It may have the // bottom bit set or it may be word aligned. if (isCode || val.IsCodePtr()) { /* Find the start of the code segment */ PolyObject *oldObject = ObjCodePtrToPtr(val.AsCodePtr()); // Calculate the byte offset of this value within the code object. POLYUNSIGNED offset = val.AsCodePtr() - (byte*)oldObject; PolyObject *newObject = ScanObjectAddress(oldObject); return PolyWord::FromCodePtr((byte*)newObject + offset); } else if (val.IsTagged() || val == PolyWord::FromUnsigned(0) || (val.AsAddress() > base && val.AsAddress() <= end)) /* We don't need to process tagged integers (now we've checked it isn't a code address) and we don't need to process addresses within the current stack. */ /* N.B. We have "<= end" rather than "< end" because it is possible for the stack to be completely empty on a terminated thread. */ return val; else { ASSERT(val.IsDataPtr()); return ScanObjectAddress(val.AsObjPtr()); } }
// Process the value at a given location and update it as necessary. POLYUNSIGNED ScanAddress::ScanAddressAt(PolyWord *pt) { PolyWord val = *pt; PolyWord newVal = val; if (IS_INT(val) || val == PolyWord::FromUnsigned(0)) { // We can get zeros in the constant area if we garbage collect // while compiling some code. */ } else if (val.IsCodePtr()) { // We can get code pointers either in the stack as return addresses or // handler pointers or in constants in code segments as the addresses of // exception handlers. // Find the start of the code segment PolyObject *oldObject = ObjCodePtrToPtr(val.AsCodePtr()); // Calculate the byte offset of this value within the code object. POLYUNSIGNED offset = val.AsCodePtr() - (byte*)oldObject; // Mustn't use ScanAddressAt here. That's only valid if the value points // into the area being updated. PolyObject *newObject = ScanObjectAddress(oldObject); newVal = PolyWord::FromCodePtr((byte*)newObject + offset); } else { ASSERT(OBJ_IS_DATAPTR(val)); // Database pointer, local pointer or IO pointer. // We need to include IO area pointers when we produce an object module. newVal = ScanObjectAddress(val.AsObjPtr()); } if (newVal != val) // Only update if we need to. *pt = newVal; return 0; }
void ScanAddress::ScanRuntimeWord(PolyWord *w) { if (w->IsTagged()) {} // Don't need to do anything else if (w->IsCodePtr()) { // We can have code pointers in set_code_address. // Find the start of the code segment PolyObject *obj = ObjCodePtrToPtr(w->AsCodePtr()); // Calculate the byte offset of this value within the code object. POLYUNSIGNED offset = w->AsCodePtr() - (byte*)obj; obj = ScanObjectAddress(obj); *w = PolyWord::FromCodePtr((byte*)obj + offset); } else { ASSERT(w->IsDataPtr()); *w = ScanObjectAddress(w->AsObjPtr()); } }
// These functions are only called with pointers held by the runtime system. // Weak references can occur in the runtime system, eg. streams and windows. // Weak references are not marked and so unreferenced streams and windows // can be detected and closed. void MTGCProcessMarkPointers::ScanRuntimeAddress(PolyObject **pt, RtsStrength weak) { if (weak == STRENGTH_WEAK) return; *pt = ScanObjectAddress(*pt); CheckPointer (*pt); // Check it after any forwarding pointers have been followed. }