home *** CD-ROM | disk | FTP | other *** search
- // hpmonmgr.hpp
- //
- // Created 10/04/98
- //
- // (C)Copyright 1998-1999 Microsoft Corporation, All rights reserved.
- //
-
- #ifndef __HPMONMGR_HPP__
- #define __HPMONMGR_HPP__
-
- #include "rootrefs.hpp"
- #include "gcinfo.hpp"
- #include "obsearch.hpp"
-
-
- #define WC_HEAPMONITOR "JavaHeapMonitorClass"
-
- #define IDC_STATUS 50
-
- #define IDM_WINDOW_FIRSTCHILD 100
-
-
- enum HeapMonitorManagerMessages
- {
- HMM_WM_FIRST = WM_USER,
-
- HMM_WM_ACTIVATE,
-
- HMM_WM_START_PROGRESS_INDICATOR,
-
- HMM_WM_STOP_PROGRESS_INDICATOR,
-
- HMM_WM_DESTROY_NOW,
-
- HMM_WM_LAST,
- };
-
-
- enum HeapMonitorManagerFlags
- {
- // VM has fully initialized
- HMM_FL_VM_INITIALIZED = 0x00000001,
-
- // "Stop!" was pressed
- HMM_FL_STOP = 0x00000002,
-
- // Execution was suspended by the user.
- HMM_FL_STOPPED = 0x00000004,
-
- // "Go!" was pressed
- HMM_FL_GO = 0x00000008,
-
- // heap exploration is in progress
- HMM_FL_EXPLORING_HEAP = 0x00000010,
-
- // heap was fully explored (heap dump was not aborted and C_END was received)
- HMM_FL_HEAP_EXPLORED = 0x00000020,
-
- // object aging was enabled
- HMM_FL_OBJECT_AGING = 0x00000040,
-
- // an allocation callback is active
- HMM_FL_OBJECT_ALLOCS = 0x00000080,
-
- // something went wrong during heap enumeration, information may not be
- // accurate. This is a per-gc indicator.
- HMM_FL_INACCURATE = 0x00000100,
-
- HMM_FL_ADDED_TRAY_ICON = 0x00000200,
-
- // A progress indicator is in the first part of the status window.
- HMM_FL_PROGRESS_INDICATOR = 0x00000400,
-
- // The main window was closed.
- HMM_FL_CLOSED = 0x00000800,
-
- // A HMM_WM_DESTROY_NOW message was posted.
- HMM_FL_DESTRUCTION_PENDING = 0x00001000,
- };
-
-
- // Main MDI frame. Also implements the event monitor callbacks and collects
- // basic statistics. Various events are pre-processed and dispatched to the
- // client windows.
-
- class HeapMonitorManager : private IJavaEventMonitor2,
- private IHeapInfoCallback
- {
- static CRITICAL_SECTION s_mgrlistcs;
- static HeapMonitorManager *s_mgrlist;
- HeapMonitorManager *m_next;
-
- ULONG m_RefCount;
-
- // Used to serialize access to HeapMonitorManager and IDWrapper fields
- CRITICAL_SECTION m_cs;
- #ifdef DEBUG
- DWORD m_tidCriticalSectionOwner;
- ULONG m_CriticalSectionEnterCount;
- #endif // DEBUG
-
- // bitmask of HeapMonitorManagerFlags
- DWORD m_flags;
-
- // reset while stopped, set while running
- HANDLE m_hresumeevt;
-
- IJavaEventMonitorIDInfo2 *m_vminfo;
- IJavaHeapMonitor *m_vmheapmon;
- IJavaHeapMonitor2 *m_vmheapmon2;
-
- // IHeapInfoCallback state
- CONTAINER_TYPE m_lastroottype;
- UniqueID m_lastrootvmid1;
- UniqueID m_lastrootvmid2;
- ID m_lastrootid;
- THREADID m_lastthreadid;
-
- RootReferencesRecorder m_rootrefs;
-
- // Current gc number, and information about the current gc.
- // PerGCInformation contains a 'next' link, which leads to information
- // about previous gc's.
- ULONG m_iGC;
- PerGCInformation m_gcinfo;
-
-
- //------------------------------------------------------------------------
- // Event client management
-
- public:
-
- static
- DWORD GetInfoNeededForEvents (DWORD EventMask)
- {
- DWORD InfoMask = 0;
-
- if (EventMask & HMC_ROOT_EVENTS)
- InfoMask |= (HMC_INFO_HEAP_ROOTS | HMC_INFO_HEAP_ROOT_REFS);
-
- if (EventMask & HMC_OBJECT_EVENTS)
- InfoMask |= (HMC_INFO_HEAP_OBJECTS | HMC_INFO_HEAP_OBJECT_REFS);
-
- if (EventMask & HMC_HEAP_EVENTS)
- InfoMask |= (HMC_INFO_HEAP_ROOTS | HMC_INFO_HEAP_OBJECTS);
-
- return InfoMask;
- }
-
- BOOL RegisterClient (IHeapMonitorClient *newclient, HeapMonitorClientRegistrationInfo *pinfo);
-
- VOID UnregisterClient (IHeapMonitorClient *deadclient);
-
- private:
-
- // Information about each client window, and list of active client windows
- struct ClientRecord
- {
- ULONG refcount;
- IHeapMonitorClient *client;
- DWORD EventMask;
- DWORD InfoMask;
- DWORD StoppedEventMask;
- DWORD StoppedInfoMask;
- ClientRecord *next;
- };
- ClientRecord *m_clients;
-
- // Union of events required by all clients.
- DWORD m_EventMaskUnion;
- DWORD m_StoppedEventMaskUnion;
- // Union of information required by all clients.
- DWORD m_InfoMaskUnion;
- DWORD m_StoppedInfoMaskUnion;
-
- // m_InfoMaskUnion [and m_StoppedInfoMaskUnion] at start of heap dump
- DWORD m_HeapInfoNeeded;
-
- BOOL IsEventRequested (DWORD mask)
- {
- return (m_EventMaskUnion & mask)
- || (m_flags & HMM_FL_STOPPED) && (m_StoppedEventMaskUnion & mask);
- }
-
- typedef VOID CLIENTITERFN (IHeapMonitorClient *client, PVOID token);
-
- VOID IterateClients (DWORD mask, CLIENTITERFN *cb, PVOID token);
-
-
- //------------------------------------------------------------------------
- // UI stuff
-
- public:
-
- #ifdef DEBUG
- BOOL CanSendUIMessages ()
- {
- // Sending a synchronous message to the UI thread while inside our
- // critical section can deadlock. The UI thread may block on the
- // critical section, while this thread blocks waiting for the UI
- // thread to process the message.
- return GetCurrentThreadId() == m_tid
- || !Entered();
- }
- #endif
-
- VOID IncProgressIndicator ()
- {
- m_ProgressIndicator++;
- }
-
- private:
-
- // message pump thread
- HANDLE m_hthd;
- DWORD m_tid;
-
- static DWORD WINAPI HeapMonitorManagerMessagePumpThread (PVOID token);
-
- // UI elements of the main frame
- HINSTANCE m_hinst;
- HWND m_hwnd;
- HMENU m_hmnu;
- HMENU m_hmnuWindow;
- HWND m_mdi;
- HWND m_status;
-
- BOOL InitializeUI ();
-
- VOID DestroyNow ();
-
- VOID RedrawMenuBar ();
- BOOL GrayMenu (UINT idm);
- BOOL ChangeMenuTextAndUngray (UINT idm, PCSTR text);
-
- VOID StopOrGo ();
- VOID IndicateStopped ();
- VOID IndicateRunning ();
-
- static
- VOID CALLBACK HeapMonitorManager::UpdateProgressIndicator(
- HWND hwnd, // handle to window
- UINT uMsg, // WM_TIMER message
- UINT idEvent, // timer identifier
- DWORD dwTime // current system time
- );
-
- // Status bar state. While a heap dump is in progress, the status bar is
- // segmented. The first segment is drawn with a bitmap from this list.
- HIMAGELIST m_ProgressIndicatorImages;
- UINT m_ProgressIndicatorTimer;
- UINT m_iProgressIndicatorImage;
-
- // Places that do useful work during a heap dump increment this counter.
- ULONG m_ProgressIndicator;
-
- // Snapshots of the object count from m_gcinfo and the last progress
- // counter, at the time the last bitmap was drawn.
- ULONG m_LastProgressIndicator;
- ULONG m_LastObjectCount;
-
- BOOL StartHeapDumpProgressIndicatorWorker ();
- VOID StopHeapDumpProgressIndicatorWorker ();
- BOOL StartHeapDumpProgressIndicator ();
- VOID StopHeapDumpProgressIndicator ();
-
- VOID SetStatusText (PCSTR text);
-
- static HICON s_htrayicon;
-
- BOOL AddTrayIcon ();
- BOOL RemoveTrayIconWorker ();
- BOOL RemoveTrayIcon ();
-
- VOID OnCreateWindow (HWND wnd, LPCREATESTRUCT pcs);
-
- VOID CreateNewHeapViewer ();
- VOID CreateNewClassViewer ();
- VOID CreateNewGCHistoryViewer ();
- VOID CreateNewTrackedObjectListViewer ();
- VOID CreateNewTaggedObjectListViewer ();
-
- static LRESULT CALLBACK WndProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
-
- //------------------------------------------------------------------------
- // ID management and UniqueID information caching
-
- public:
-
- ID LookupID (UniqueID vmid)
- {
- return m_idmap.LookupID(vmid);
- }
-
- PKGID LookupPackage (PKGID parentpkgid, PCWSTR pcszPackageName);
-
- CLASSID LookupClass (ClassID vmid);
-
- OBJID LookupObject (ObjectID vmid);
-
- THREADID LookupThread (ThreadID vmid);
-
- typedef int IDITERFN (ID id, PVOID cbtoken);
-
- int IterateIDs (IDITERFN *cb, PVOID cbtoken = NULL);
-
- int IterateIDs_Safe (IDITERFN *cb, PVOID cbtoken = NULL)
- {
- ASSERT(Entered() || GetCurrentThreadId() == m_HeapDumpThreadId);
-
- IDIterState state;
- state.cb = cb;
- state.cbtoken = cbtoken;
-
- return m_idmap.IterateIDs(&IterateIDsCBAdaptor, &state);
- }
-
- typedef int IterateRootReferencesProc (ID rootid, ObjectID refid, PVOID token);
-
- int IterateKnownRootReferences (IterateRootReferencesProc *cb, PVOID token)
- {
- ASSERT(CanSendUIMessages());
-
- int result;
-
- result = m_rootrefs.Iterate(cb, token);
-
- return result;
- }
-
- private:
-
- // Maps UniqueIDs from the VM to IDWrappers
- UniqueIDMap m_idmap;
- ULONG m_IDMapChangeCount;
-
- BOOL AddID (UniqueID vmid, ID id)
- {
- ASSERT(Entered());
- BOOL ret = m_idmap.AddID(vmid, id);
- if (ret)
- m_IDMapChangeCount++;
- return ret;
- }
-
- VOID DeleteID (ID id)
- {
- // IDs are not deleted in this fashion when execution is
- // resumed....they are UniqueIDMap::Filter'd.
- ASSERT(Entered());
- m_idmap.DeleteID(id->vmid);
- m_IDMapChangeCount++;
- }
-
- struct IDIterState
- {
- IDITERFN *cb;
- PVOID cbtoken;
- };
-
- static int IterateIDsCBAdaptor (PCVOID key, PVOID value, PVOID token)
- {
- IDIterState *state = (IDIterState*)token;
- return (*state->cb)((ID)value, state->cbtoken);
- }
-
- static int DeleteTransientIDs (PCVOID key, PVOID value, PVOID token);
-
- static int ResetPerGCIDInfo (PCVOID key, PVOID val, PVOID token);
-
- // Maps package name to PKGID
- struct PkgTokenEntry {
- PWSTR name;
- PKGID id;
- };
- DWORD m_npkgents;
- PkgTokenEntry *m_pkgents;
-
- PkgTokenEntry *GetPackageEntry (PCWSTR pkgname);
-
- BOOL FetchClassInfo (CLASSID id);
-
- static int FetchClassInfoCB (ID id, PVOID cbtoken);
-
- // CONTAINER_TYPE descriptions, filled in by FetchContainerName
- PSTR *m_rgpszContainerDescriptions;
- PSTR *m_rgpszVerboseContainerDescriptions;
-
- PCSTR FetchContainerName (PSTR **prgpszDescr, CONTAINER_TYPE type, BOOL fVerbose);
-
-
- //------------------------------------------------------------------------
- // Heap graph navigation
-
- public:
-
- // Returns <0 on failure, 0 to stop, or >0 to continue.
- typedef int ExpandObjectAddObjectIDReferenceProc (ObjectID vmidref, PVOID token);
- typedef int ExpandObjectAddOBJIDReferenceProc (OBJID idref, PVOID token);
-
- enum ExpandObjectResults
- {
- EOR_FAILED,
- EOR_EXPANDED,
- EOR_NO_REFERENCES,
- };
-
- // Explores the outgoing edges of an object.
- ExpandObjectResults ExpandObject (
- ObjectID vmid, OBJID *pid,
- ExpandObjectAddObjectIDReferenceProc *vmidcb,
- ExpandObjectAddOBJIDReferenceProc *idcb,
- PVOID token);
-
- BOOL FindObjectReferences (ObjectID vmid, SearchProc *cb, PVOID token);
- BOOL FindClassInstances (CLASSID cls, SearchProc *cb, PVOID token);
-
- private:
-
- #ifdef DEBUG
- DWORD m_HeapDumpThreadId;
- #endif // DEBUG
-
- OBJID CreateOBJID (ObjectID vmid);
-
- // Records an incoming edge to an object.
- OBJID DiscoveredObject (ObjectID vmid);
-
- ID DiscoveredRoot (CONTAINER_TYPE type, UniqueID vmid, UniqueID extraid);
-
- SearchHeapInfoCallback *m_searchcb;
-
- // Requests a search operation. The operation will be performed when any
- // currently running heap dump completes.
- BOOL RegisterSearchOperation (SearchOperation *searchitem);
-
- struct PendingHeapWalk
- {
- IWalkHeapCallback *cb;
- DWORD HeapWalkFlags;
- PendingHeapWalk *next;
- };
-
- PendingHeapWalk *m_heapwalks;
-
- public:
-
- // Requests a full heap dump. The operation will be performed when any
- // currently running heap dump completes.
- BOOL RegisterHeapWalk (IWalkHeapCallback *cb, DWORD HeapWalkFlags = 0);
-
- #ifdef DEBUG
- BOOL OnHeapDumpThread ()
- {
- return GetCurrentThreadId() == m_HeapDumpThreadId;
- }
- #endif // DEBUG
-
-
- //------------------------------------------------------------------------
- // OBJID operations
-
- public:
-
- BOOL ToggleObjectTracking (OBJID obj, ObjectID vmid);
-
- BOOL SetObjectTag (OBJID obj, PCSTR newtag);
-
- PCSTR GetObjectTag (OBJID obj);
-
- ClassID GetClassOfDeadObject (OBJID obj)
- {
- ASSERT(obj->flags & OID_FL_DEAD);
- TrackedObjectList *trkent = *FindTrackedObjectEntry(obj);
- return trkent->vmclsid;
- }
-
- typedef int SPECIALOBJITERFN (OBJID obj, PVOID token);
-
- // Iterates objects that are "special" to the user - tagged or tracked.
- int IterateSpecialObjects (SPECIALOBJITERFN *cb, PVOID token);
-
- private:
-
- struct TrackedObjectList
- {
- OBJID obj;
- TrackedObjectList *next;
-
- ObjectHandleID vmhid;
- PSTR tag;
- ClassID vmclsid;
-
- BOOL fStatusChanged;
- };
-
- TrackedObjectList *m_trackedobjs;
-
- TrackedObjectList **FindTrackedObjectEntry (OBJID obj);
-
- TrackedObjectList *CreateTrackedObjectEntry (OBJID obj);
-
- VOID DestroyTrackedObjectEntry (TrackedObjectList **ptrkent);
-
-
- //------------------------------------------------------------------------
- // VM event handlers
-
- private:
-
- static VOID StoppedExecutionCB (IHeapMonitorClient *client, PVOID token);
- VOID SendSuspendedEvent ();
-
- static VOID ResumeExecutionCB (IHeapMonitorClient *client, PVOID token);
- VOID SendResumingEvent ();
-
- static VOID SendClosingEventCB (IHeapMonitorClient *client, PVOID token);
- VOID SendClosingEvent ();
-
- static VOID SendThreadCreatedEventCB (IHeapMonitorClient *client, PVOID token);
- VOID SendThreadCreatedEvent (THREADID thd);
-
- static VOID SendDestroyThreadEventCB (IHeapMonitorClient *client, PVOID token);
- VOID SendDestroyThreadEvent (THREADID thd);
-
- static VOID SendPackageCreatedEventCB (IHeapMonitorClient *client, PVOID token);
- VOID SendPackageCreatedEvent (PKGID newpkgid);
-
- static VOID SendClassLoadedEventCB (IHeapMonitorClient *client, PVOID token);
- VOID SendClassLoadedEvent (CLASSID newclsid);
-
- static VOID SendUnloadClassEventCB (IHeapMonitorClient *client, PVOID token);
- VOID SendUnloadClassEvent (CLASSID cls);
-
- static VOID RootReferencedCB (IHeapMonitorClient *client, PVOID token);
- VOID SendRootReferencesEvent (RootReferencesEventInfo *pinfo);
-
- static VOID ObjectStatusChangedCB (IHeapMonitorClient *client, PVOID token);
- VOID SendObjectStatusChanged (OBJID obj);
-
- static VOID RootDiscoveryCompleteCB (IHeapMonitorClient *client, PVOID token);
- VOID SendRootDiscoveryComplete ();
-
- static VOID ObjectDiscoveryCompleteCB (IHeapMonitorClient *client, PVOID token);
- VOID SendObjectDiscoveryComplete ();
-
- VOID Stopped ();
-
- CLASSID ClassLoaded (ClassID vmid, PWSTR name);
- CLASSID ClassLoaded (ClassID vmid);
- VOID ClassUnloaded (ClassID vmid);
-
- THREADID ThreadCreated (ThreadID vmid, BOOL ghost);
- HRESULT ThreadNameChanged (ThreadID vmid, PWSTR newname);
- VOID ThreadDestroyed (ThreadID vmid);
-
- static int MarkEmptyRootsCB (ID id, PVOID token);
- static int ReportEmptyRootsCB (ID id, PVOID token);
- static int ResetEmptyRootsCB (ID id, PVOID token);
-
-
- //------------------------------------------------------------------------
- // Implemented interfaces
-
- private:
-
- // IJavaEventMonitor methods
-
- STDMETHODIMP Initialize (LPCSTR pclass_file_name, IJavaEventMonitorIDInfo *pmonitor_info, DWORD java_flags, DWORD *prequested_events);
- STDMETHODIMP NotifyEvent (JVM_EVENT_TYPE event, UniqueID event_id);
- STDMETHODIMP MethodEntry (MethodID method_id, StackID stack_id);
- STDMETHODIMP MethodExit (StackID stack_id);
- STDMETHODIMP ExecuteByteCode (MethodID method_id, BYTE_CODE *pbyte_code, DWORD byte_code_offset);
- STDMETHODIMP ExecuteSourceLine (MethodID method_id, DWORD line_number);
-
- // IJavaEventMonitor2 methods
-
- STDMETHODIMP NotifyEvent2 (JVM_EVENT_TYPE2 event2, UniqueID first_event_id, UniqueID second_event_id);
- STDMETHODIMP MethodExit2 (MethodID method_id, StackID stack_id);
- STDMETHODIMP GetPossibleEventCategories (DWORD *ppossible_events);
-
- // IHeapInfoCallback
-
- STDMETHODIMP BeginContainer (CONTAINER_TYPE type, UniqueID id1, UniqueID id2);
- STDMETHODIMP RootReferences (const ObjectID *prefs, unsigned nrefs, const DWORD *pflags);
- STDMETHODIMP ObjectReferences (ObjectID vmid, DWORD flags, const ObjectID *prefs, unsigned nrefs, const DWORD *pflags);
-
-
- //------------------------------------------------------------------------
-
- public:
-
- HeapMonitorManager ();
- ~HeapMonitorManager ();
-
- BOOL Initialize (HINSTANCE hInstance);
-
-
- static VOID OnProcessAttach (HINSTANCE hinst);
- static VOID OnProcessDetach (HINSTANCE hinst);
-
-
- VOID Enter ()
- {
- EnterCriticalSection(&m_cs);
- #ifdef DEBUG
- m_tidCriticalSectionOwner = GetCurrentThreadId();
- m_CriticalSectionEnterCount++;
- #endif // DEBUG
- }
-
- VOID Leave ()
- {
- #ifdef DEBUG
- ASSERT(m_CriticalSectionEnterCount);
- ULONG NewEnterCount = --m_CriticalSectionEnterCount;
- if (!NewEnterCount)
- m_tidCriticalSectionOwner = INVALID_THREAD_ID;
- #endif // DEBUG
- LeaveCriticalSection(&m_cs);
- }
-
- #ifdef DEBUG
- BOOL Entered ()
- {
- return m_tidCriticalSectionOwner == GetCurrentThreadId();
- }
- #endif // DEBUG
-
-
- HWND GetMDIClientWindow ()
- {
- return m_mdi;
- }
-
- HINSTANCE GetInstance ()
- {
- return m_hinst;
- }
-
- IJavaEventMonitorIDInfo2 *GetVMInfoInterface ()
- {
- m_vminfo->AddRef();
- return m_vminfo;
- }
-
-
- PCSTR GetContainerName (CONTAINER_TYPE type)
- {
- return FetchContainerName(&m_rgpszContainerDescriptions, type, FALSE);
- }
-
- PCSTR GetVerboseContainerName (CONTAINER_TYPE type)
- {
- return FetchContainerName(&m_rgpszVerboseContainerDescriptions, type, TRUE);
- }
-
- PerGCInformation *GetCurrentGCInfo ()
- {
- return m_gcinfo.next;
- }
-
-
- BOOL IsExecutionSuspended_Safe ()
- {
- ASSERT(Entered());
- return !(m_flags & (HMM_FL_EXPLORING_HEAP | HMM_FL_HEAP_EXPLORED));
- }
-
- BOOL IsExecutionSuspended ()
- {
- BOOL ret;
- Enter();
- {
- ret = IsExecutionSuspended_Safe();
- }
- Leave();
- return ret;
- }
-
- BOOL IsRunning_Safe ()
- {
- ASSERT(Entered());
- return !(m_flags & HMM_FL_STOPPED);
- }
-
- BOOL IsRunning ()
- {
- BOOL ret;
- Enter();
- {
- ret = IsRunning_Safe();
- }
- Leave();
- return ret;
- }
-
- BOOL IsStopped_Safe ()
- {
- return !IsRunning_Safe();
- }
-
- BOOL IsStopped ()
- {
- return !IsRunning();
- }
-
-
- BOOL SupportsObjectAging ()
- {
- return (m_flags & HMM_FL_OBJECT_AGING);
- }
-
- BOOL SupportsAllocatedSize ()
- {
- return (m_flags & HMM_FL_OBJECT_ALLOCS);
- }
-
-
- //------------------------------------------------------------------------
- // ID information
-
- PSTR FetchIDFriendlyName (ID id);
-
-
- //------------------------------------------------------------------------
-
- // IUnknown methods
-
- ULONG STDMETHODCALLTYPE AddRef (VOID);
- ULONG STDMETHODCALLTYPE Release (VOID);
- STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppvObj);
- };
-
-
- #endif /* __HPMONMGR_HPP__ */
-
-