Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 194081 | Differences between
and this patch

Collapse All | Expand All

(-)src-native/src/BaseProf/ProfEnv.cpp (-6 / +574 lines)
Lines 11-16 Link Here
11
 *
11
 *
12
 * $Id: ProfEnv.cpp,v 1.31 2008/12/08 13:37:37 jkubasta Exp $ 
12
 * $Id: ProfEnv.cpp,v 1.31 2008/12/08 13:37:37 jkubasta Exp $ 
13
 ************************************************************************/
13
 ************************************************************************/
14
#ifndef LIN
15
#pragma warning(disable:4786) // Add for bug 194081 to disable VC compiler warning when use STL
16
#endif
14
17
15
#include "ProfEnv.h"
18
#include "ProfEnv.h"
16
#include "log.h"
19
#include "log.h"
Lines 19-24 Link Here
19
using namespace Martini::MPI;
22
using namespace Martini::MPI;
20
using namespace Martini::OSA;
23
using namespace Martini::OSA;
21
using namespace Martini::JPIAgent;
24
using namespace Martini::JPIAgent;
25
using namespace std;  // Add for bug 194081
22
26
23
CProfEnv::CProfEnv(){
27
CProfEnv::CProfEnv(){
24
    m_pClassSData = 0;
28
    m_pClassSData = 0;
Lines 61-66 Link Here
61
    m_pAggStorage->Destroy(); 
65
    m_pAggStorage->Destroy(); 
62
    m_pSSMethodLeaveData_LockObject->Destroy(); 
66
    m_pSSMethodLeaveData_LockObject->Destroy(); 
63
    lockGetThreadInfoObject->Destroy(); 
67
    lockGetThreadInfoObject->Destroy(); 
68
    
69
    // Add for bug 194081
70
    m_pShadowStackTracker = NULL;
71
    // Add for bug 194081
64
}
72
}
65
73
66
void 
74
void 
Lines 101-106 Link Here
101
        delete m_pMethodSData;
109
        delete m_pMethodSData;
102
    }
110
    }
103
    m_pMethodSDataLockObject->Leave();
111
    m_pMethodSDataLockObject->Leave();
112
    
113
    // Add for bug 194081
114
    if (m_pShadowStackTracker)
115
    {
116
        delete m_pShadowStackTracker;
117
        m_pShadowStackTracker = NULL;
118
    }
119
    // Add for bug 194081
104
}
120
}
105
121
106
/*
122
/*
Lines 124-129 Link Here
124
    }
140
    }
125
    libraryLoader->Destroy();
141
    libraryLoader->Destroy();
126
    (*ecpEnv)(profName, &ec_env);
142
    (*ecpEnv)(profName, &ec_env);
143
    
144
    // Add for bug 194081
145
	m_pShadowStackTracker = new CCGShadowStackTracker(*this);
146
	if ( (NULL == m_pShadowStackTracker) ||
147
	    !(m_pShadowStackTracker->ValidateCGShadowStackTracker()) )
148
	{
149
	    return MRTE_ERROR_FAIL;
150
	}
151
	// Add for bug 194081
152
	
127
    return MRTE_RESULT_OSA_PLACE_HOLDER;
153
    return MRTE_RESULT_OSA_PLACE_HOLDER;
128
}
154
}
129
155
Lines 209-214 Link Here
209
    return ret;
235
    return ret;
210
}
236
}
211
237
238
// Add for bug 194081
239
void 
240
CProfEnv::DeleteMethodsData()
241
{
242
    if (m_pMethodSData) 
243
    {
244
        delete m_pMethodSData;
245
        m_pMethodSData = NULL;
246
    }
247
}
248
// Add for bug 194081
249
212
void 
250
void 
213
CProfEnv::AddNewMethodData(SMethodInfo* pSMethodInfo, TId methodId, bool isPrinted)
251
CProfEnv::AddNewMethodData(SMethodInfo* pSMethodInfo, TId methodId, bool isPrinted)
214
{
252
{
Lines 366-374 Link Here
366
    lockObjectCheckObject->Leave();
404
    lockObjectCheckObject->Leave();
367
}
405
}
368
406
407
// Add for bug 194081. Filter additional data referring to CanInstrumentClass
408
bool CProfEnv::IsExcludedClass(const char* szClassName)
409
{
410
    static char* ExcludedClassPatterns[] = 
411
    {
412
        "org.eclipse.tptp.martini.",
413
        "com.ibm.crypto",
414
        "sun.reflect.Generated",
415
        "jrockit.",
416
        "com.Intel.VTune.VTuneAPI",
417
        "org.eclipse.hyades.collection.profiler",
418
        "java.lang.",
419
        "java.security.",
420
        "java.awt.",
421
        "java.io.",
422
        "javax.swing."
423
        "com.ibm.jvm.",
424
        "com.ibm.misc.",
425
        "com.ibm.oti.",
426
        "sun.nio.",
427
        "CGLIB$$"
428
    };
429
430
    // Check if the class appear in the excluded class patterns list
431
    unsigned int patternArraySize = 
432
        sizeof(ExcludedClassPatterns)/sizeof(*ExcludedClassPatterns);
433
    
434
    for (unsigned int i = 0; i < patternArraySize; ++i)
435
    {
436
        char *szExcludedPattern = ExcludedClassPatterns[i];
437
        if (strstr(szClassName, szExcludedPattern) != NULL)
438
        {
439
            return true;
440
        }
441
    }
442
443
    return false;
444
}
445
// Add for bug 194081. Filter additional data referring to CanInstrumentClass
369
446
370
void 
447
void 
371
CProfEnv::CheckMethodId(TId methodId) {
448
CProfEnv::CheckMethodId(TId methodId) {
449
    // Add for bug 194081 to filter additional data after reattach
450
    SMethodInfo methodClassInfo = {0};
451
    TResult iRes = m_pMpiApi->GetMethodInfo(m_clientId, 
452
        methodId, DR_CLASS_NAME, &methodClassInfo);
453
    LOG_ASSERT(iRes == MRTE_RESULT_OK);
454
    LOG_ASSERT((methodClassInfo.validData & DR_CLASS_NAME) != 0);
455
456
    if (IsExcludedClass(methodClassInfo.szClassName))
457
    {
458
        return;
459
    }
460
    // Add for bug 194081  to filter additional data after reattach
461
    
372
    bool isPrint = false;
462
    bool isPrint = false;
373
463
374
    m_pMethodSDataLockObject->Enter();
464
    m_pMethodSDataLockObject->Enter();
Lines 381-387 Link Here
381
    methodInfo->managedToSrcLineMap.uiSize = 1;
471
    methodInfo->managedToSrcLineMap.uiSize = 1;
382
    methodInfo->managedToSrcLineMap.entries = (SLineNumberTableEntry*)malloc(sizeof(SLineNumberTableEntry) * 1);
472
    methodInfo->managedToSrcLineMap.entries = (SLineNumberTableEntry*)malloc(sizeof(SLineNumberTableEntry) * 1);
383
    
473
    
384
    TResult iRes = m_pMpiApi->GetMethodInfo(m_clientId, methodId,
474
    iRes = m_pMpiApi->GetMethodInfo(m_clientId, methodId,
385
        DR_JAVA_NATIVE_METHOD_NAME | DR_JAVA_NATIVE_METHOD_SIGNATURE | DR_METHOD_NAME | DR_METHOD_SIGNATURE | 
475
        DR_JAVA_NATIVE_METHOD_NAME | DR_JAVA_NATIVE_METHOD_SIGNATURE | DR_METHOD_NAME | DR_METHOD_SIGNATURE | 
386
        DR_JAVA_NATIVE_CLASS_NAME | DR_CLASS_NAME | DR_METHOD_LINE_NUMBERS | DR_CLASS_ID | DR_MANAGED_TO_SRC_LINE_MAP, methodInfo);
476
        DR_JAVA_NATIVE_CLASS_NAME | DR_CLASS_NAME | DR_METHOD_LINE_NUMBERS | DR_CLASS_ID | DR_MANAGED_TO_SRC_LINE_MAP, methodInfo);
387
    if (iRes == MRTE_ERROR_BUFFER_TOO_SHORT) {
477
    if (iRes == MRTE_ERROR_BUFFER_TOO_SHORT) {
Lines 541-546 Link Here
541
    int size = 0;
631
    int size = 0;
542
    int maxDepth = ec_env->getMaxStackDepth();
632
    int maxDepth = ec_env->getMaxStackDepth();
543
    TResult retVal;
633
    TResult retVal;
634
    
544
    do {
635
    do {
545
    	if(maxDepth >= 0){
636
    	if(maxDepth >= 0){
546
    		size = maxDepth;
637
    		size = maxDepth;
Lines 574-582 Link Here
574
    for (unsigned int i = 0; i < stackTrace->uiSize; i++) {
665
    for (unsigned int i = 0; i < stackTrace->uiSize; i++) {
575
        stackTrace->pStackEntries[i].methodId = threadInfo.vmOffsetStack.pStackEntries[i].methodId;
666
        stackTrace->pStackEntries[i].methodId = threadInfo.vmOffsetStack.pStackEntries[i].methodId;
576
        SMethodInfo* methodInfo = GetMethodData(stackTrace->pStackEntries[i].methodId);
667
        SMethodInfo* methodInfo = GetMethodData(stackTrace->pStackEntries[i].methodId);
577
        stackTrace->pStackEntries[i].methodName = (char*)malloc(strlen(methodInfo->szMethodName) + strlen(methodInfo->szMethodSig) + strlen(methodInfo->szClassName) + 3);
668
        if (NULL != methodInfo)
578
        sprintf(stackTrace->pStackEntries[i].methodName, "%s.%s %s", methodInfo->szClassName, methodInfo->szMethodName, methodInfo->szMethodSig);
669
        {
579
        stackTrace->pStackEntries[i].lineNumber = GetLineNumber(threadInfo.vmOffsetStack.pStackEntries[i].location, &(methodInfo->managedToSrcLineMap));
670
            stackTrace->pStackEntries[i].methodName = 
671
            	(char*)malloc(strlen(methodInfo->szMethodName) + 
672
            	strlen(methodInfo->szMethodSig) + 
673
            	strlen(methodInfo->szClassName) + 3);
674
            
675
            sprintf(stackTrace->pStackEntries[i].methodName, "%s.%s %s", 
676
            	methodInfo->szClassName, methodInfo->szMethodName, methodInfo->szMethodSig);
677
            
678
            stackTrace->pStackEntries[i].lineNumber = 
679
            	GetLineNumber(threadInfo.vmOffsetStack.pStackEntries[i].location, 
680
            	                &(methodInfo->managedToSrcLineMap));
681
        }
682
        
580
    }
683
    }
581
    free(threadInfo.vmOffsetStack.pStackEntries);
684
    free(threadInfo.vmOffsetStack.pStackEntries);
582
}
685
}
Lines 598-610 Link Here
598
void 
701
void 
599
CProfEnv::FreeStackTrace(SStackTrace_* stackTrace)
702
CProfEnv::FreeStackTrace(SStackTrace_* stackTrace)
600
{
703
{
601
    if (stackTrace->pStackEntries == 0) {
704
    if (NULL == stackTrace || stackTrace->pStackEntries == NULL) {
602
        return;
705
        return;
603
    }
706
    }
604
    for (unsigned int i = 0; i < stackTrace->uiSize; i++) {
707
    for (unsigned int i = 0; i < stackTrace->uiSize; i++) {
605
        free(stackTrace->pStackEntries[i].methodName);
708
    	if (NULL != stackTrace->pStackEntries[i].methodName)
709
    	{
710
    	    free(stackTrace->pStackEntries[i].methodName);
711
    	    stackTrace->pStackEntries[i].methodName = NULL;
712
    	}
606
    }
713
    }
607
    free(stackTrace->pStackEntries);
714
    free(stackTrace->pStackEntries);
715
    stackTrace->pStackEntries = NULL;
716
    stackTrace->uiSize = 0;
608
}
717
}
609
718
610
//==================================================================================
719
//==================================================================================
Lines 791-793 Link Here
791
    return MRTE_RESULT_OK;
900
    return MRTE_RESULT_OK;
792
}
901
}
793
902
903
//==================================================================
904
// Add for bug 194081
905
CCGShadowStackTracker::CCGShadowStackTracker(CProfEnv& profEnv)
906
    : m_refProfEnv(profEnv)
907
{
908
    m_lockVMStackDataMap = CreateThreadSync();
909
}
910
911
CCGShadowStackTracker::~CCGShadowStackTracker()
912
{
913
    if (m_lockVMStackDataMap)
914
    {
915
        m_lockVMStackDataMap->Destroy();
916
    }
917
}
918
919
bool CCGShadowStackTracker::isNeedTrack()
920
{
921
    return ( 
922
            ((m_refProfEnv.ec_env)->isCGExecDetails()) &&
923
            !((m_refProfEnv.ec_env)->isStandAlone()) 
924
           );
925
}
926
927
bool CCGShadowStackTracker::ValidateCGShadowStackTracker()
928
{
929
    if (!isNeedTrack())
930
    {
931
        return true;
932
    }
933
    
934
    // You can add additional validate condition in this function
935
    return (NULL != m_lockVMStackDataMap);
936
}
937
938
void CCGShadowStackTracker::TrackVMShutdown()
939
{
940
    if (!(m_refProfEnv.IsSupportedEG(EG_CALL_GRAPH)))
941
    {// For profilers' common events, just handle for call graph
942
        return;
943
    }
944
    
945
    if (!isNeedTrack())
946
    {
947
        return;
948
    }
949
    
950
    ReportLeftStackTrackDataMethodsLeave();
951
}
952
953
TResult CCGShadowStackTracker::InitNewThreadInfoArray(
954
    SThreadInfoArray& threadInfoArray, 
955
    int MAX_THREADS, int MAX_FRAMES)
956
{
957
    DestroyThreadInfoArray(threadInfoArray);
958
            
959
    threadInfoArray.pEntries = 
960
   	(SThreadInfoArrayEntry*)malloc(sizeof(SThreadInfoArrayEntry) * MAX_THREADS);
961
    if (NULL == threadInfoArray.pEntries)
962
    { 
963
        return MRTE_ERROR_OUT_OF_MEMORY;
964
    }
965
966
    threadInfoArray.uiSize = MAX_THREADS;
967
    memset(threadInfoArray.pEntries, 0, sizeof(SThreadInfoArrayEntry) * MAX_THREADS);
968
    
969
    unsigned int i = 0;
970
    for (i = 0; i < MAX_THREADS; i++)
971
    {
972
        threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.uiSize = MAX_FRAMES;
973
        threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries = new SStackEntry[MAX_FRAMES];
974
975
        if (NULL == threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries)
976
        {
977
            DestroyThreadInfoArray(threadInfoArray);
978
            return MRTE_ERROR_OUT_OF_MEMORY;
979
        }
980
981
        memset(threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries, 0, 
982
              	sizeof(SStackEntry) * MAX_FRAMES);
983
    }
984
985
    return MRTE_RESULT_OK;
986
}
987
988
void CCGShadowStackTracker::DestroyThreadInfoArray(
989
    SThreadInfoArray& threadInfoArray)
990
{
991
    if (NULL != threadInfoArray.pEntries)
992
    {
993
        for (unsigned int i = 0; i < threadInfoArray.uiSize; i++)
994
        {
995
            if (NULL != threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries)
996
            {
997
                delete [](threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries);
998
            }
999
        }
1000
1001
        free(threadInfoArray.pEntries);
1002
    }
1003
            
1004
    threadInfoArray.uiSize = 0;
1005
    threadInfoArray.uiActualSize = 0;
1006
}
1007
1008
TResult CCGShadowStackTracker::GetInitialShadowStackTraces(
1009
    SThreadInfoArray& threadInfoArray)
1010
{
1011
    // Suspend all VM threads and Get all threads stack traces
1012
    TResult res = (m_refProfEnv.m_pMpiApi)->SuspendVM();
1013
    if (MRTE_FAILED(res))
1014
    {
1015
        LOG_ERROR("Can not suspend VM when try to get shadow stack sanpshot")
1016
        return res;
1017
    } 
1018
    
1019
    // TODO: This fixed thread num and frame num is a limit, referring to original AttachEvent.cpp
1020
    int MAX_THREADS = 100;
1021
    int MAX_FRAMES = 100;
1022
        
1023
    res = InitNewThreadInfoArray(threadInfoArray, MAX_THREADS, MAX_FRAMES);
1024
    if (MRTE_FAILED(res))
1025
    {
1026
        (m_refProfEnv.m_pMpiApi)->ResumeVM();
1027
        return res;
1028
    }
1029
1030
    res = (m_refProfEnv.m_pMpiApi)->GetAllThreadsInfo(m_refProfEnv.m_clientId, MAX_FRAMES, 
1031
        DR_VM_RELATIVE_STACK_TRACE, &threadInfoArray);
1032
    if (MRTE_FAILED(res))
1033
    {
1034
        (m_refProfEnv.m_pMpiApi)->ResumeVM();
1035
        DestroyThreadInfoArray(threadInfoArray);
1036
    }
1037
    
1038
    return res;
1039
}
1040
1041
void CCGShadowStackTracker::ReportThreadsStart(SThreadInfoArray& threadInfoArray)
1042
{    
1043
    for (unsigned int threadIdx = 0; threadIdx < threadInfoArray.uiActualSize; threadIdx++)
1044
    {
1045
        SThreadInfoArrayEntry* pThread = &(threadInfoArray.pEntries[threadIdx]);
1046
        
1047
        // Clear outdated data
1048
        m_refProfEnv.m_Tickets.ReleaseTicket(pThread->threadId);
1049
        m_refProfEnv.m_Tickets.DeleteThread(pThread->threadId);
1050
        
1051
        // Add new data info
1052
        m_refProfEnv.m_Tickets.AddNewThread(pThread->threadId);
1053
                
1054
        m_refProfEnv.GetThreadInfo(m_refProfEnv.m_clientId, pThread->threadId, 
1055
            DR_THREAD_INFO | DR_THREAD_ELAPSED_TIME | DR_THREAD_CPU_TIME, &(pThread->threadInfo));
1056
        
1057
        if (m_refProfEnv.m_profilerIsActive)
1058
        {
1059
            (m_refProfEnv.ec_env)->PrintThreadStartElement(pThread->threadId, 0, 
1060
                &(pThread->threadInfo));
1061
        }
1062
        else
1063
        {
1064
            m_refProfEnv.StoreThreadEvent(pThread->threadId, THREAD_START_EVENT, 
1065
                &(pThread->threadInfo), 0);            
1066
        }
1067
    }
1068
}
1069
1070
void CCGShadowStackTracker::ReportMethodEnter(TId threadId, SThreadInfo* pThreadInfo, TId methodId)
1071
{
1072
    // Get classId according to methodId
1073
    SMethodInfo methodInfo = {0};
1074
    TResult iRes = (m_refProfEnv.m_pMpiApi)->GetMethodInfo(m_refProfEnv.m_clientId, 
1075
        methodId, DR_CLASS_ID | DR_CLASS_NAME, &methodInfo);
1076
    LOG_ASSERT(iRes == MRTE_RESULT_OK);
1077
    LOG_ASSERT((methodInfo.validData & DR_CLASS_ID) != 0);
1078
    LOG_ASSERT((methodInfo.validData & DR_CLASS_NAME) != 0);
1079
1080
    if (m_refProfEnv.IsExcludedClass(methodInfo.szClassName))
1081
    {
1082
        return;
1083
    }
1084
            
1085
    // Just for Exec Details
1086
    m_refProfEnv.CheckMethodId(methodId);
1087
            
1088
    if (m_refProfEnv.m_profilerIsActive)
1089
    {// Profiler is in run mode
1090
        unsigned long ticket = m_refProfEnv.m_Tickets.GetNewTicket(threadId, 
1091
            pThreadInfo->uiCpuNanos, true);
1092
        unsigned long stackDepth = m_refProfEnv.m_Tickets.GetStackDepth(threadId);
1093
        (m_refProfEnv.ec_env)->PrintMethodEntryElement(threadId, methodId, 
1094
                methodInfo.classId, ticket, stackDepth);
1095
    }
1096
    else
1097
    {// Profiler is in pause mode
1098
        m_refProfEnv.m_Tickets.AddMethodEnterData(threadId, methodId, 
1099
            methodInfo.classId, pThreadInfo->uiCpuNanos);
1100
    }
1101
}
1102
1103
void CCGShadowStackTracker::ReportMethodsEnter(SThreadInfoArray& threadInfoArray)
1104
{    
1105
    for (unsigned int threadIdx = 0; threadIdx < threadInfoArray.uiActualSize; threadIdx++)
1106
    {
1107
        TId threadId = threadInfoArray.pEntries[threadIdx].threadId;
1108
        SThreadInfo* pThreadInfo = &(threadInfoArray.pEntries[threadIdx].threadInfo);
1109
        
1110
        for (int stackTraceIdx = (pThreadInfo->vmOffsetStack).uiActualSize - 1; stackTraceIdx >= 0 ; 
1111
            stackTraceIdx--)
1112
        {
1113
            // Get methodId from stack trace info
1114
            SStackEntry* pStackEntry = &(pThreadInfo->vmOffsetStack.pStackEntries[stackTraceIdx]);
1115
            
1116
            ReportMethodEnter(threadId, pThreadInfo, pStackEntry->methodId);
1117
        }
1118
    }
1119
}
1120
1121
void CCGShadowStackTracker::SaveAllShadowStacksMethods(SThreadInfoArray& threadInfoArray)
1122
{
1123
    for (unsigned int threadIdx = 0; threadIdx < threadInfoArray.uiActualSize; threadIdx++)
1124
    {
1125
        SThreadInfoArrayEntry* pThread = &(threadInfoArray.pEntries[threadIdx]);
1126
        CVMStackTrackData vmStacks;
1127
        vmStacks.threadId = pThread->threadId;
1128
        unsigned int stackTraceSize = 
1129
            (pThread->threadInfo).vmOffsetStack.uiActualSize;
1130
1131
        for (int stackTraceIdx = stackTraceSize - 1; stackTraceIdx >= 0; stackTraceIdx--)
1132
        {
1133
            vmStacks.shadowStack.push(
1134
                (pThread->threadInfo).vmOffsetStack.pStackEntries[stackTraceIdx].methodId);
1135
        }
1136
1137
        m_VMStacktraceDataMap.insert(
1138
          std::pair<MPI::TId, CVMStackTrackData>(vmStacks.threadId, vmStacks));
1139
    }
1140
}
1141
1142
void CCGShadowStackTracker::TrackECAttach()
1143
{
1144
    if (!(m_refProfEnv.IsSupportedEG(EG_CALL_GRAPH)))
1145
    {// For profilers' common events, just handle for call graph
1146
        return;
1147
    }
1148
    
1149
    if (!isNeedTrack())
1150
    {
1151
        return;
1152
    }
1153
    
1154
    SThreadInfoArray threadInfoArray = {0};
1155
    TResult res = GetInitialShadowStackTraces(threadInfoArray);
1156
    if (MRTE_FAILED(res))
1157
    {
1158
        LOG_ERROR("Can not get VM thread stack traces info.")
1159
        return;
1160
    }
1161
    
1162
    // Report related events and get initial shadow stacks
1163
    ReportThreadsStart(threadInfoArray);
1164
1165
    ReportMethodsEnter(threadInfoArray);
1166
    
1167
    SaveAllShadowStacksMethods(threadInfoArray);
1168
    
1169
    DestroyThreadInfoArray(threadInfoArray);
1170
    (m_refProfEnv.m_pMpiApi)->ResumeVM();
1171
}
1172
1173
void CCGShadowStackTracker::TrackECDetach()
1174
{
1175
    if (!(m_refProfEnv.IsSupportedEG(EG_CALL_GRAPH)))
1176
    {// For profilers' common events, just handle for call graph
1177
        return;
1178
    }
1179
    
1180
    if (!isNeedTrack())
1181
    {
1182
        return;
1183
    }
1184
    
1185
    ReportLeftStackTrackDataMethodsLeave();
1186
}
1187
1188
void CCGShadowStackTracker::ReportMethodLeave(TId threadId, TId methodId, 
1189
    TTimeStamp uiCpuNanos)
1190
{
1191
    SMethodInfo methodInfo;
1192
    TResult iRes = (m_refProfEnv.m_pMpiApi)->GetMethodInfo(m_refProfEnv.m_clientId, 
1193
        methodId, DR_CLASS_ID | DR_CLASS_NAME, &methodInfo);
1194
    LOG_ASSERT(iRes == MRTE_RESULT_OK);
1195
    LOG_ASSERT((methodInfo.validData & DR_CLASS_ID) != 0);
1196
    LOG_ASSERT((methodInfo.validData & DR_CLASS_NAME) != 0);
1197
1198
    if (m_refProfEnv.IsExcludedClass(methodInfo.szClassName))
1199
    {
1200
        return;
1201
    }
1202
    
1203
    // Just for Exec Details
1204
    U64 cpuTime = uiCpuNanos - m_refProfEnv.m_Tickets.GetCpuTime(threadId);
1205
    unsigned long ticket = m_refProfEnv.m_Tickets.ReleaseTicket(threadId);
1206
            
1207
    if (m_refProfEnv.m_profilerIsActive) 
1208
    {
1209
        (m_refProfEnv.ec_env)->PrintMethodExitElement(threadId, methodId, 
1210
            methodInfo.classId, ticket, cpuTime); 
1211
    }
1212
    else if (ticket != -1)
1213
    {
1214
        m_refProfEnv.AddMethodLeaveData(threadId, methodId, methodInfo.classId, 
1215
            ticket, cpuTime);    
1216
    }
1217
}
1218
1219
void CCGShadowStackTracker::UpdateShadowStack(stack< TId >& tmpShadowStack,
1220
    stack< TId >& shadowStack, const SMethodEnterEventData& data)
1221
{ 
1222
    // Because normal stack is empty now, the tmpShadowStack must less or equal shadowStack
1223
    while (tmpShadowStack.size() < shadowStack.size())
1224
    {// Geneate method leave events for shadow stack method
1225
        TId methodId = shadowStack.top();
1226
        shadowStack.pop();
1227
        ReportMethodLeave(data.threadId, methodId, data.uiCpuNanos);
1228
    }
1229
}
1230
1231
void CCGShadowStackTracker::TrackMethodEnter(SMethodEnterEventData &data)
1232
{
1233
    if (!isNeedTrack())
1234
    {
1235
        return;
1236
    }
1237
    
1238
    m_lockVMStackDataMap->Enter();
1239
    map< MPI::TId, CVMStackTrackData >::iterator pos = m_VMStacktraceDataMap.find(data.threadId);
1240
    
1241
    if (pos == m_VMStacktraceDataMap.end())
1242
    {// Enter a new thread after attach, it has no shadow stack record and can be handled normally
1243
        m_lockVMStackDataMap->Leave();
1244
        return;
1245
    }
1246
    
1247
    CVMStackTrackData& refVmStacks = pos->second;
1248
    
1249
    if (refVmStacks.normalStack.empty())
1250
    {
1251
        SStackTrace_ stackTrace = {0};
1252
        
1253
        m_refProfEnv.GetStackTrace(data.threadId, &stackTrace);
1254
        
1255
        std::stack< MPI::TId > tmpShadowStack;
1256
        // Ignore the new entered method, CGProxy.EarlyMethodEnter and CGProxy.MethodEnter on the stack top
1257
        const int ignoredMethodNum = 3;
1258
        for (int stackTraceIdx = stackTrace.uiSize - 1; stackTraceIdx > ignoredMethodNum - 1; stackTraceIdx--)
1259
        {
1260
            tmpShadowStack.push(stackTrace.pStackEntries[stackTraceIdx].methodId);
1261
        }
1262
        
1263
        UpdateShadowStack(tmpShadowStack, refVmStacks.shadowStack, data);
1264
1265
        if (NULL != stackTrace.pStackEntries)
1266
        {
1267
            stackTrace.uiSize = 0;
1268
            free(stackTrace.pStackEntries);
1269
        }
1270
    }
1271
    
1272
    refVmStacks.normalStack.push(data.methodId);
1273
    m_lockVMStackDataMap->Leave();
1274
}
1275
1276
// return value: If continue to handle the MethodLeave events
1277
bool CCGShadowStackTracker::TrackMethodLeave(SMethodLeaveEventData &data)
1278
{
1279
    if (!isNeedTrack())
1280
    {
1281
        return true;
1282
    }   
1283
    
1284
    m_lockVMStackDataMap->Enter();
1285
    map< MPI::TId, CVMStackTrackData >::iterator pos = m_VMStacktraceDataMap.find(data.threadId);
1286
    
1287
    if (pos == m_VMStacktraceDataMap.end())
1288
    {// Enter a new thread after attach, it has no shadow stack record and can be handled normally
1289
        m_lockVMStackDataMap->Leave();
1290
        return true;
1291
    }
1292
    
1293
    CVMStackTrackData& refVmStacks = pos->second;
1294
    
1295
    if (refVmStacks.normalStack.empty())
1296
    {// Method leave notification is generated by instrumet before reattach, ignore it
1297
        m_lockVMStackDataMap->Leave();
1298
        return false;
1299
    }
1300
    else
1301
    {
1302
        refVmStacks.normalStack.pop();
1303
        m_lockVMStackDataMap->Leave();
1304
        return true;
1305
    }
1306
}
1307
1308
void CCGShadowStackTracker::TrackThreadEnd(SThreadEventData &data)
1309
{
1310
    if (!isNeedTrack())
1311
    {
1312
        return;
1313
    }
1314
1315
    m_lockVMStackDataMap->Enter();
1316
    map< MPI::TId, CVMStackTrackData >::iterator pos = m_VMStacktraceDataMap.find(data.threadId);
1317
    
1318
    if (pos == m_VMStacktraceDataMap.end())
1319
    {// Enter a new thread after attach, it has no shadow stack record and can be handled normally
1320
        m_lockVMStackDataMap->Leave();
1321
        return;
1322
    }
1323
    
1324
    CVMStackTrackData& refVmStacks = pos->second;
1325
    
1326
    // refVmStacks.shadowStack report method leave events
1327
    while (!refVmStacks.shadowStack.empty())
1328
    {
1329
        TId methodId = refVmStacks.shadowStack.top();
1330
        refVmStacks.shadowStack.pop();
1331
        ReportMethodLeave(data.threadId, methodId, m_refProfEnv.m_Tickets.GetCpuTime(data.threadId));
1332
    }
1333
    m_lockVMStackDataMap->Leave();
1334
}
1335
1336
void CCGShadowStackTracker::ReportLeftStackTrackDataMethodsLeave()
1337
{
1338
    m_lockVMStackDataMap->Enter();
1339
    
1340
    map< MPI::TId, CVMStackTrackData >::iterator pos = m_VMStacktraceDataMap.begin();
1341
    for(; pos != m_VMStacktraceDataMap.end(); pos++)
1342
    {
1343
        CVMStackTrackData& refVmStacks = pos->second;
1344
        
1345
        while (!refVmStacks.normalStack.empty())
1346
        {
1347
            TId methodId = refVmStacks.normalStack.top();
1348
            refVmStacks.normalStack.pop();
1349
            ReportMethodLeave(pos->first, methodId, m_refProfEnv.m_Tickets.GetCpuTime(pos->first));
1350
        }
1351
        
1352
        while (!refVmStacks.shadowStack.empty())
1353
        {
1354
            TId methodId = refVmStacks.shadowStack.top();
1355
            refVmStacks.shadowStack.pop();
1356
            ReportMethodLeave(pos->first, methodId, m_refProfEnv.m_Tickets.GetCpuTime(pos->first));
1357
        }
1358
    }
1359
    m_lockVMStackDataMap->Leave();
1360
}
1361
// Add for bug 194081
(-)src-native/src/BaseProf/DetachEvent.cpp (-1 / +4 lines)
Lines 40-46 Link Here
40
    if (!m_pProfEnv->m_bVMInitDone) {
40
    if (!m_pProfEnv->m_bVMInitDone) {
41
        return;
41
        return;
42
    }
42
    }
43
    m_pProfEnv->ec_env->SetProfileOption("EXECDETAILS", "false");
43
    // Modify for bug 194081
44
    // m_pProfEnv->ec_env->SetProfileOption("EXECDETAILS", "false");
45
    m_pProfEnv->m_pShadowStackTracker->TrackECDetach();
46
    // Modify for bug 194081
44
    if (!m_pProfEnv->IsSupportedEG(EG_CALL_GRAPH) && !m_pProfEnv->IsSupportedEG(EG_HEAP)) {
47
    if (!m_pProfEnv->IsSupportedEG(EG_CALL_GRAPH) && !m_pProfEnv->IsSupportedEG(EG_HEAP)) {
45
        return;
48
        return;
46
    }
49
    }
(-)src-native/src/BaseProf/ProfEnv.h (+86 lines)
Lines 15-20 Link Here
15
#ifndef _PROF_ENV_H_
15
#ifndef _PROF_ENV_H_
16
#define _PROF_ENV_H_
16
#define _PROF_ENV_H_
17
17
18
// Add for bug 194081
19
#include <stack>
20
#include <map>
21
// Add for bug 194081
22
18
#include "MpiAPI.h"
23
#include "MpiAPI.h"
19
#include "OSA.h"
24
#include "OSA.h"
20
25
Lines 50-55 Link Here
50
        MPI::SThreadInfo threadInfo; //For THREAD_START_EVENT only
55
        MPI::SThreadInfo threadInfo; //For THREAD_START_EVENT only
51
        MPI::TId objectId; //For THREAD_START_EVENT only
56
        MPI::TId objectId; //For THREAD_START_EVENT only
52
    };
57
    };
58
    
59
    // Add for bug 194081
60
    class CCGShadowStackTracker
61
    {
62
        class CVMStackTrackData
63
        {
64
        public:
65
            MPI::TId threadId;
66
            std::stack< MPI::TId > shadowStack;
67
            std::stack< MPI::TId > normalStack;
68
        };
69
70
    public:
71
    	CCGShadowStackTracker(CProfEnv& profEnv);
72
    	~CCGShadowStackTracker();
73
74
        // Assure init process is successful, called by CProfEnv init
75
    	bool ValidateCGShadowStackTracker();
76
    	
77
    	//---------------------------------------------------------------------
78
        // Common profiler events need to be tracked, except for VMInit, ECStart and ECStop event
79
    	void TrackVMShutdown();
80
81
    	void TrackECAttach();
82
    	void TrackECDetach();
83
    	
84
    	//---------------------------------------------------------------------
85
    	// Call Graph profiler specialized events, except for NewMethod and ThreadStart
86
        void TrackMethodEnter(MPI::SMethodEnterEventData& data);
87
        
88
        // TrackMethodLeave return bool to avoid handle MethodLeave events before reattach
89
        bool TrackMethodLeave(MPI::SMethodLeaveEventData& data);
90
        
91
        void TrackThreadEnd(MPI::SThreadEventData &data);
92
93
    private:
94
        // Functions for deciding whether to track corresponding events 
95
        bool isNeedTrack();
96
        
97
        // Used by ECAttach tracker
98
        TResult InitNewThreadInfoArray(MPI::SThreadInfoArray& threadInfoArray, 
99
            int MAX_THREADS, int MAX_FRAMES);
100
        void DestroyThreadInfoArray(MPI::SThreadInfoArray& threadInfoArray);
101
        
102
        TResult GetInitialShadowStackTraces(MPI::SThreadInfoArray& threadInfoArray);
103
        void ReportThreadsStart(MPI::SThreadInfoArray& threadInfoArray);  // Refer to CGProf ThreadStartHandler
104
        
105
        void ReportMethodEnter(MPI::TId threadId, MPI::SThreadInfo* pThreadInfo, MPI::TId methodId);
106
        void ReportMethodsEnter(MPI::SThreadInfoArray& threadInfoArray);
107
        
108
        void SaveAllShadowStacksMethods(MPI::SThreadInfoArray& threadInfoArray);
109
        
110
        // Used by MethodEnter and ThreadEnd trackers, ReportLeftStackTrackDataMethodsLeave
111
        void ReportMethodLeave(MPI::TId threadId, MPI::TId methodId, MPI::TTimeStamp uiCpuNanos);
112
        
113
        // Used by MethodEnter tracker 
114
        void UpdateShadowStack(std::stack< MPI::TId >&, std::stack< MPI::TId >&, 
115
            const MPI::SMethodEnterEventData&);
116
            
117
        // Used by VMShutdown and Detach trackers
118
        // Generate method leave events for each left methods in track stack
119
        void ReportLeftStackTrackDataMethodsLeave();
120
121
    private:
122
    	CProfEnv& m_refProfEnv;
123
124
        OSA::IThreadSync* m_lockVMStackDataMap;
125
        std::map< MPI::TId, CVMStackTrackData > m_VMStacktraceDataMap;
126
    };
127
    // Add for bug 194081
53
128
54
    class CProfEnv
129
    class CProfEnv
55
    {
130
    {
Lines 82-87 Link Here
82
        bool IsObjectStored(MPI::TId objectId);
157
        bool IsObjectStored(MPI::TId objectId);
83
        //
158
        //
84
//        void AddNewMethodData(MPI::SMethodInfo* pSMethodInfo, MPI::TId methodId);
159
//        void AddNewMethodData(MPI::SMethodInfo* pSMethodInfo, MPI::TId methodId);
160
        // Add for bug 194081
161
        void DeleteMethodsData();
162
        // Add for bug 194081
85
        void AddNewMethodData(MPI::SMethodInfo* pSMethodInfo, MPI::TId methodId, bool isPrinted);
163
        void AddNewMethodData(MPI::SMethodInfo* pSMethodInfo, MPI::TId methodId, bool isPrinted);
86
        //
164
        //
87
        MPI::SMethodInfo* GetMethodData(MPI::TId methodId);
165
        MPI::SMethodInfo* GetMethodData(MPI::TId methodId);
Lines 151-156 Link Here
151
        MPI::TId m_clientId;
229
        MPI::TId m_clientId;
152
        // Profiler library name
230
        // Profiler library name
153
        char* profName;
231
        char* profName;
232
        
233
        // Add for bug 194081
234
        CCGShadowStackTracker* m_pShadowStackTracker;
235
        
236
    	// Filter some additional classes after reattach
237
    	bool IsExcludedClass(const char* szClassName);
238
        // Add for bug 194081
239
        
154
    private:
240
    private:
155
        CClassDefDataSet* m_pClassSData;
241
        CClassDefDataSet* m_pClassSData;
156
        OSA::IThreadSync* m_pClassSDataLockObject;
242
        OSA::IThreadSync* m_pClassSDataLockObject;
(-)src-native/src/BaseProf/BaseProfiler.h (-1 / +1 lines)
Lines 35-41 Link Here
35
        // Constructor
35
        // Constructor
36
        CBaseProfiler();
36
        CBaseProfiler();
37
        // Destructor
37
        // Destructor
38
        ~CBaseProfiler();
38
        virtual ~CBaseProfiler();
39
        // Initialization
39
        // Initialization
40
		TResult Init(MPI::IMpi *pMpiApi, MPI::TId clientId, const char *szOptions);
40
		TResult Init(MPI::IMpi *pMpiApi, MPI::TId clientId, const char *szOptions);
41
41
(-)src-native/src/BaseProf/AttachEvent.cpp (-2 / +25 lines)
Lines 41-50 Link Here
41
    if (!m_pProfEnv->m_bVMInitDone) {
41
    if (!m_pProfEnv->m_bVMInitDone) {
42
        return;
42
        return;
43
    }
43
    }
44
44
    
45
    m_pProfEnv->DeleteAggCallGraphData();
45
    m_pProfEnv->DeleteAggCallGraphData();
46
    m_pProfEnv->DeleteStoredThreadEvents();
46
    m_pProfEnv->DeleteStoredThreadEvents();
47
47
48
    // Add for bug 194081
49
    if (m_pProfEnv->ec_env->isCGExecDetails())
50
    {
51
        m_pProfEnv->DeleteMethodsData();
52
        m_pProfEnv->m_pShadowStackTracker->TrackECAttach();
53
    
54
        TResult res = m_pProfEnv->EnableSupportedEG();
55
        if (MRTE_FAILED(res))
56
        {
57
            if (MRTE_ERROR_PHASE_FAILURE == res) 
58
            {
59
                LOG_DIE("Attach failed (too early)");
60
            } 
61
            else
62
            {
63
                LOG_DIE("Attach failed");
64
            }
65
        }
66
        
67
        return;
68
    }
69
    // Add for bug 194081
70
48
    const int MAX_THREADS = 100;
71
    const int MAX_THREADS = 100;
49
    const int MAX_FRAMES = 100;
72
    const int MAX_FRAMES = 100;
50
    TResult res; 
73
    TResult res; 
Lines 161-167 Link Here
161
            }
184
            }
162
        }
185
        }
163
        for (i = 0; i < MAX_THREADS; i++) {
186
        for (i = 0; i < MAX_THREADS; i++) {
164
            delete threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries;
187
            delete [](threadInfoArray.pEntries[i].threadInfo.vmOffsetStack.pStackEntries);
165
        }
188
        }
166
    } else {
189
    } else {
167
        res = m_pProfEnv->m_pMpiApi->GetAllThreadsInfo(m_pProfEnv->m_clientId, 0, DR_THREAD_INFO, &threadInfoArray);
190
        res = m_pProfEnv->m_pMpiApi->GetAllThreadsInfo(m_pProfEnv->m_clientId, 0, DR_THREAD_INFO, &threadInfoArray);
(-)src-native/src/BaseProf/VMShutdownEvent.cpp (-1 / +11 lines)
Lines 41-46 Link Here
41
    if (!m_pProfEnv->m_profilerIsActive) {
41
    if (!m_pProfEnv->m_profilerIsActive) {
42
        return;
42
        return;
43
    }
43
    }
44
    m_pProfEnv->PrintAggCallGraph();
44
    // Modified for bug 194081
45
    if (m_pProfEnv->ec_env->isCGExecDetails())
46
    {
47
        m_pProfEnv->m_pShadowStackTracker->TrackVMShutdown();
48
    }
49
    else
50
    {
51
        m_pProfEnv->PrintAggCallGraph();
52
    }
53
    // Modified for bug 194081
54
    
45
    m_pProfEnv->ec_env->PrintRuntimeShutdownElement();
55
    m_pProfEnv->ec_env->PrintRuntimeShutdownElement();
46
}
56
}
(-)src-native/src/HeapProf/ObjAllocEvent.cpp (-1 / +3 lines)
Lines 45-51 Link Here
45
        LOG_ASSERT((data.validData & DR_METHOD_ID) != 0);
45
        LOG_ASSERT((data.validData & DR_METHOD_ID) != 0);
46
        LOG_ASSERT((data.validData & DR_ALLOC_VM_INSTRUCTION_OFFSET) != 0);
46
        LOG_ASSERT((data.validData & DR_ALLOC_VM_INSTRUCTION_OFFSET) != 0);
47
    }
47
    }
48
    if (!m_pProfEnv->m_profilerIsActive) {
48
	// Modified for bug 275321
49
    //if (!m_pProfEnv->m_profilerIsActive) {
50
	if (!m_pProfEnv->m_profilerIsActive || NULL == data.pObjectInfo) {
49
        return;
51
        return;
50
    }
52
    }
51
    m_pProfEnv->CheckClassId(data.pObjectInfo->classId);
53
    m_pProfEnv->CheckClassId(data.pObjectInfo->classId);
(-)src-native/src/CGProf/ThreadEndEvent.cpp (+4 lines)
Lines 40-45 Link Here
40
{
40
{
41
    if ((data.validData & DR_THREAD_ID) != 0)
41
    if ((data.validData & DR_THREAD_ID) != 0)
42
    {
42
    {
43
        // Add for bug 194081
44
        m_pProfEnv->m_pShadowStackTracker->TrackThreadEnd(data);
45
        // Add for bug 194081
46
        
43
        m_pProfEnv->m_Tickets.DeleteThread(data.threadId);
47
        m_pProfEnv->m_Tickets.DeleteThread(data.threadId);
44
        if (!m_pProfEnv->m_profilerIsActive) {
48
        if (!m_pProfEnv->m_profilerIsActive) {
45
            m_pProfEnv->StoreThreadEvent(data.threadId, THREAD_END_EVENT, &data, 0);
49
            m_pProfEnv->StoreThreadEvent(data.threadId, THREAD_END_EVENT, &data, 0);
(-)src-native/src/CGProf/MethodEnterEvent.cpp (+4 lines)
Lines 44-49 Link Here
44
    LOG_ASSERT((data.validData & DR_METHOD_ID) != 0);
44
    LOG_ASSERT((data.validData & DR_METHOD_ID) != 0);
45
    LOG_ASSERT((data.validData & DR_THREAD_ID) != 0);
45
    LOG_ASSERT((data.validData & DR_THREAD_ID) != 0);
46
    LOG_ASSERT((data.validData & DR_THREAD_CPU_TIME) != 0);
46
    LOG_ASSERT((data.validData & DR_THREAD_CPU_TIME) != 0);
47
    
48
    // Add for bug 194081
49
    m_pProfEnv->m_pShadowStackTracker->TrackMethodEnter(data);
50
    // Add for bug 194081
47
51
48
    SMethodInfo classInfo;
52
    SMethodInfo classInfo;
49
    TResult iRes = m_pProfEnv->m_pMpiApi->GetMethodInfo(m_pProfEnv->m_clientId, data.methodId, 
53
    TResult iRes = m_pProfEnv->m_pMpiApi->GetMethodInfo(m_pProfEnv->m_clientId, data.methodId, 
(-)src-native/src/CGProf/MethodLeaveEvent.cpp (+8 lines)
Lines 42-47 Link Here
42
    LOG_ASSERT((data.validData & DR_METHOD_ID) != 0);
42
    LOG_ASSERT((data.validData & DR_METHOD_ID) != 0);
43
    LOG_ASSERT((data.validData & DR_THREAD_ID) != 0);
43
    LOG_ASSERT((data.validData & DR_THREAD_ID) != 0);
44
    LOG_ASSERT((data.validData & DR_THREAD_CPU_TIME) != 0);
44
    LOG_ASSERT((data.validData & DR_THREAD_CPU_TIME) != 0);
45
    
46
    // Add for bug 194081
47
    bool isContinueHandleMethodLeave = m_pProfEnv->m_pShadowStackTracker->TrackMethodLeave(data);
48
    if (!isContinueHandleMethodLeave)
49
    {
50
        return;
51
    }
52
    // Add for bug 194081
45
53
46
    SMethodInfo classInfo;
54
    SMethodInfo classInfo;
47
    TResult iRes = m_pProfEnv->m_pMpiApi->GetMethodInfo(m_pProfEnv->m_clientId, data.methodId, 
55
    TResult iRes = m_pProfEnv->m_pMpiApi->GetMethodInfo(m_pProfEnv->m_clientId, data.methodId, 
(-)src-native/src/JPIAgent/Options.h (-1 / +4 lines)
Lines 144-150 Link Here
144
144
145
        // is CG pfofiler aggregated
145
        // is CG pfofiler aggregated
146
        bool isCGExecDetails() {
146
        bool isCGExecDetails() {
147
            return (!isEnabled()) && (m_jvmtiAgent_Options.cgExecDetails == 1); //in enabled mode we support aggregated cg profiler only
147
            // Modified for bug 194081
148
            //return (!isEnabled()) && (m_jvmtiAgent_Options.cgExecDetails == 1); //in enabled mode we support aggregated cg profiler only
149
            return (m_jvmtiAgent_Options.cgExecDetails == 1);
150
            // Modified for bug 194081
148
        }
151
        }
149
152
150
        // if cg memory should be freed after snapshot then returns true
153
        // if cg memory should be freed after snapshot then returns true

Return to bug 194081