home *** CD-ROM | disk | FTP | other *** search
- // calltrac.cpp
- //
- // Created 01/18/99
- //
- // (C) Copyright 1995 - 1999 Microsoft Corporation. All rights reserved.
- //
-
- #include "project.hpp"
- #pragma hdrstop
-
- #include "calltrac.hpp"
- #include "jviewprf.hpp"
-
-
- void CallTracer::PrintStackLeader (ThreadRecord *pThread)
- {
- WriteOutputFmt("%8x ", pThread->tid);
-
- ULONG indent = pThread->tracedata.nStackFrames;
-
- // Don't let the indentation get out of hand, bloating output files.
- if (indent < g_OutputWidth)
- {
- while (indent--)
- WriteOutput(" ", 1);
- }
- }
-
-
- VOID CallTracer::SpewValue (CHAR chsig, PVOID pvalue)
- {
- INT i;
-
- switch (chsig)
- {
- case '[':
- case 'L':
- {
- ObjectID objid = *(ObjectID*)pvalue;
- if (objid == NULL)
- {
- WriteOutput("null");
- }
- else
- {
- ClassID clsid;
- HRESULT hr = m_pmon->GetVMInfoIfc()->ObjectInformation(objid, &clsid);
- if (hr == S_OK)
- {
- IJavaEventMonitorIDInfo2 *pinfo2 = m_pmon->GetVMInfoIfc2();
- if (pinfo2 != NULL)
- {
- PWSTR descr;
- hr = pinfo2->DescribeObject(objid, &descr);
- if (hr == S_OK)
- {
- WriteOutputW(descr);
-
- CoTaskMemFree(descr);
- }
- else
- {
- goto USE_CLSNAME_FOR_DESCR;
- }
- }
- else
- {
- USE_CLSNAME_FOR_DESCR:
-
- PSTR pszClassUtf8;
- hr = m_pmon->GetVMInfoIfc()->ClassInformation(clsid, &pszClassUtf8, NULL, NULL, NULL, NULL);
- if (hr == S_OK)
- {
- WriteOutputUtf8(pszClassUtf8);
-
- if ((g_ProfOptions & OPT_VERBOSE) && pszClassUtf8[0] == '[')
- {
- // TODO: spew array elements
- }
-
- CoTaskMemFree(pszClassUtf8);
- }
- }
- }
- }
- }
- break;
-
- case 'Z':
- WriteOutput(*(BOOL*)pvalue ? "true" : "false");
- break;
-
- case 'C': {
- WCHAR rgwch[2];
- rgwch[0] = *(WCHAR*)pvalue;
- rgwch[1] = L'\0';
- WriteOutputW(rgwch);
- break; }
-
- case 'J': {
- __int64 val = *(__int64*)pvalue;
- if (val < INT_MAX)
- WriteOutputFmt("%d", (int)val);
- else
- WriteOutputFmt("0x%x%08x", (int)(val >> 32), (int)val);
- break; }
-
- case 'D':
- WriteOutputFloat(0, *(double*)pvalue);
- break;
-
- case 'F':
- WriteOutputFloat(0, *(float*)pvalue);
- break;
-
- case 'B':
- i = *(BYTE*)pvalue;
- goto PRINT_INT;
-
- case 'S':
- i = *(SHORT*)pvalue;
- goto PRINT_INT;
-
- case 'I':
- i = *(INT*)pvalue;
- PRINT_INT:
- WriteOutputFmt("%d", i);
- break;
-
- case 'V':
- break;
- }
- }
-
- int NextSigElement (PCSTR *ppszsig)
- {
- int nslots = 1;
- PCSTR psznext = *ppszsig;
- CHAR chsig = *psznext;
- if (chsig == 'L')
- {
- findsigend:
- while (*++psznext != ';');
- }
- else if (chsig == '[')
- {
- while (1)
- {
- chsig = *psznext;
- if (chsig != '[')
- break;
- psznext++;
- }
- if (chsig == 'L')
- goto findsigend;
- }
- else if (chsig == 'J' || chsig == 'D')
- {
- nslots = 2;
- }
- *ppszsig = psznext+1;
- return nslots;
- }
-
-
- VOID CallTracer::SpewParams (ThreadRecord *pThread, MethodID method_id, StackID stack_id, ClassID idMethodClass, PCSTR pcszMethodName)
- {
- IJavaEventMonitorIDInfo3 *pinfo3 = m_pmon->GetVMInfoIfc3();
- if (pinfo3 != NULL)
- {
- DWORD *pparams;
- JVM_CALLING_CONVENTION callconv;
- DWORD flags;
- if (SUCCEEDED(pinfo3->GetMethodEntryParameters(&pparams, NULL, &callconv, &flags)))
- {
- if (callconv == JVM_CALL_PASCAL)
- {
- PCSTR pszsig = pcszMethodName;
- while (*pszsig++ != '(');
-
- PCSTR pszsigtmp = pszsig;
- int totalparamslots = 0;
- while (*pszsigtmp != ')')
- totalparamslots += NextSigElement(&pszsigtmp);
-
- if (totalparamslots)
- {
- PrintStackLeader(pThread);
-
- WriteOutput("parameters: ");
-
- pparams += totalparamslots;
-
- pszsigtmp = pszsig;
- do
- {
- if (pszsigtmp != pszsig)
- WriteOutput(", ");
-
- CHAR chvalsig = *pszsigtmp;
-
- pparams -= NextSigElement(&pszsigtmp);
-
- SpewValue(chvalsig, pparams);
- }
- while (*pszsigtmp != ')');
-
- WriteOutput("\n");
- }
-
- if (flags & JVM_CALL_THIS)
- {
- DWORD *pThis = pparams+totalparamslots;
-
- ObjectID idThis = *(ObjectID*)pThis;
-
- ClassID idThisClass = NULL;
-
- if ( FAILED(pinfo3->ObjectInformation(idThis, &idThisClass))
- || idThisClass != idMethodClass)
- {
- PrintStackLeader(pThread);
-
- WriteOutput("this: ");
- SpewValue('L', pThis);
- WriteOutput("\n");
- }
- }
- }
- }
- }
- }
-
-
- VOID CallTracer::SpewReturnValue ()
- {
- MethodID exiting_method_id;
- __int64 *pretval;
-
- IJavaEventMonitorIDInfo3 *pinfo3 = m_pmon->GetVMInfoIfc3();
-
- HRESULT hr = pinfo3->GetMethodExitReturnValue(&exiting_method_id, &pretval);
- if (SUCCEEDED(hr))
- {
- WriteOutput("return value: ");
- if (hr == S_FALSE)
- {
- WriteOutput("void\n");
- }
- else
- {
- PSTR pszMethodUtf8;
- hr = pinfo3->MethodInformation(exiting_method_id, &pszMethodUtf8, NULL, NULL, NULL, NULL);
- if (hr == S_OK)
- {
- PSTR retsig = pszMethodUtf8;
- while (*retsig++ != ')');
- SpewValue(*retsig, pretval);
-
- CoTaskMemFree(pszMethodUtf8);
- }
-
- WriteOutput("\n");
- }
- }
- }
-
-
- HRESULT CallTracer::Initialize (EventMonitor *pmon)
- {
- (m_pmon = pmon)->AddRef();
- return S_OK;
- }
-
- VOID CallTracer::Destruct ()
- {
- if (m_pmon)
- m_pmon->Release();
- }
-
-
- VOID CallTracer::OnEnterMethod (ThreadRecord *pThread, MethodID method_id, StackID stack_id)
- {
- if (g_ProfOptions & OPT_CALL_TRACE)
- {
- PSTR pszMethodUtf8 = NULL;
- ClassID class_id;
- JAVA_EXECUTION_MODEL jem;
- if (SUCCEEDED(m_pmon->GetVMInfoIfc()->MethodInformation(method_id, &pszMethodUtf8, &class_id, &jem, NULL, NULL)))
- {
- PCSTR pcszExecModel;
-
- switch (jem)
- {
- case JVM_EXECUTION_JIT_COMPILED:
- pcszExecModel = "JIT-compiled";
- break;
-
- case JVM_EXECUTION_NATIVE:
- pcszExecModel = "native";
- break;
-
- case JVM_EXECUTION_INTERPRETED:
- pcszExecModel = "interpreted";
- break;
-
- case JVM_EXECUTION_FAST_INTERPRETED:
- pcszExecModel = "fast interpreted";
- break;
-
- case JVM_EXECUTION_COM:
- pcszExecModel = "COM";
- break;
-
- default:
- pcszExecModel = "UNKNOWN";
- break;
- }
-
- PrintStackLeader(pThread);
-
- WriteOutputUtf8(pszMethodUtf8);
- WriteOutputFmt(" [%s]\n", pcszExecModel);
- }
-
- pThread->tracedata.nStackFrames++;
-
- if (pszMethodUtf8)
- {
- if (g_ProfOptions & OPT_CALL_TRACE_PARAMS)
- {
- SpewParams(pThread, method_id, stack_id, class_id, pszMethodUtf8);
- }
-
- CoTaskMemFree(pszMethodUtf8);
- }
- }
- }
-
- VOID CallTracer::OnMethodExit (ThreadRecord *pThread, MethodID method_id, StackID stack_id)
- {
- if (g_ProfOptions & OPT_CALL_TRACE)
- {
- PrintStackLeader(pThread);
-
- if (g_ProfOptions & OPT_CALL_TRACE_PARAMS)
- SpewReturnValue();
- else
- WriteOutput("returned\n");
-
- pThread->tracedata.nStackFrames--;
- }
- }
-
-