singrdk/base/Kernel/Bartok/GCs/GCProfiler.cs

159 lines
5.4 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
/*******************************************************************/
/* WARNING */
/* This file should be identical in the Bartok and Singularity */
/* depots. Master copy resides in Bartok Depot. Changes should be */
/* made to Bartok Depot and propagated to Singularity Depot. */
/*******************************************************************/
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
namespace System.GCs
{
using Microsoft.Bartok.Runtime;
internal delegate
void ProfileRootsDelegate(NonNullReferenceVisitor visitor);
internal delegate
void ProfileObjectsDelegate(SegregatedFreeList.ObjectVisitor visitor);
// Receive notifications from the GC and deliver them to a profiler. This class
// should be subtyped and then an instance associated with the GC via
// System.GC.SetProfiler().
[CLSCompliant(false)]
public abstract class GCProfiler
{
public GCProfiler()
{
rootVisitor = new RootVisitor(this);
objectVisitor = new ObjectVisitor(this);
}
// To limit the size of the TCB, we make a strict separation between two APIs.
// The trusted API is the one between the GC and this base GCProfiler. The
// untrusted API is the one between this base GCProfiler and any subtypes of
// this profiler that actually generate useful profiles.
// Trusted API between this base and the GC
internal void NotifyShutdown()
{
Shutdown();
}
internal void NotifyPreGC(int generation)
{
PreGC(generation);
}
internal void NotifyPostGC(ProfileRootsDelegate profileRoots,
ProfileObjectsDelegate profileObjects)
{
this.profileRoots = profileRoots;
this.profileObjects = profileObjects;
PostGC();
}
internal void NotifyAllocation(UIntPtr objAddr, Type type, UIntPtr size)
{
Allocation(objAddr, type, size);
}
// Untrusted API between this base and the concrete profiler subtype. The
// concrete subtype implements this.
protected abstract void Shutdown();
protected abstract void PreGC(int generation);
protected abstract void PostGC();
protected abstract void Allocation(UIntPtr objAddr, Type type, UIntPtr size);
protected abstract void ScanOneRoot(UIntPtr objectAddress);
protected abstract void StartScanOneObject(UIntPtr objectAddress, Type type, UIntPtr size);
protected abstract void ScanOneObjectField(UIntPtr objectAddress);
protected abstract void EndScanOneObject();
// API for the concrete subtype to call back on the abstract base. We must
// not accept UIntPtrs, etc. from the untrusted subtype and operate on them
// here!
protected void ScanRoots()
{
profileRoots(rootVisitor);
}
protected void ScanObjects()
{
profileObjects(objectVisitor);
}
// And the rest is implementation detail.
private RootVisitor rootVisitor;
private ObjectVisitor objectVisitor;
private ProfileRootsDelegate profileRoots;
private ProfileObjectsDelegate profileObjects;
// For one object, visit all the references it contains
internal class OneObjectVisitor : NonNullReferenceVisitor
{
private GCProfiler profiler;
public OneObjectVisitor(GCProfiler profiler)
{
this.profiler = profiler;
}
// The NonNullReferenceVisitor contract:
internal unsafe override void Visit(UIntPtr *location)
{
profiler.ScanOneObjectField(*location);
}
}
// Visit all the roots
internal class RootVisitor : NonNullReferenceVisitor
{
private GCProfiler profiler;
public RootVisitor(GCProfiler profiler)
{
this.profiler = profiler;
}
// The NonNullReferenceVisitor contract:
internal unsafe override void Visit(UIntPtr *location)
{
profiler.ScanOneRoot(*location);
}
}
// Visit all the objects in the heap
internal class ObjectVisitor : SegregatedFreeList.ObjectVisitor
{
private GCProfiler profiler;
private OneObjectVisitor oneObjectVisitor;
public ObjectVisitor(GCProfiler profiler)
{
this.profiler = profiler;
oneObjectVisitor = new OneObjectVisitor(profiler);
}
// The ObjectVisitor contract:
// Must return the size of the visited object.
internal override UIntPtr Visit(Object obj)
{
UIntPtr size = ObjectLayout.Sizeof(obj);
UIntPtr objectAddress = Magic.addressOf(obj);
profiler.StartScanOneObject(objectAddress, obj.GetType(), size);
oneObjectVisitor.VisitReferenceFields(obj);
profiler.EndScanOneObject();
return size;
}
}
}
}