diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp index 1f7d0432a..240f2c61a 100644 --- a/indra/llcommon/llfasttimer_class.cpp +++ b/indra/llcommon/llfasttimer_class.cpp @@ -57,7 +57,6 @@ S32 LLFastTimer::sLastFrameIndex = -1; U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64(); bool LLFastTimer::sPauseHistory = 0; bool LLFastTimer::sResetHistory = 0; -LLFastTimer::CurTimerData LLFastTimer::sCurTimerData; BOOL LLFastTimer::sLog = FALSE; std::string LLFastTimer::sLogName = ""; BOOL LLFastTimer::sMetricLog = FALSE; @@ -72,7 +71,6 @@ U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution #endif -std::vector* LLFastTimer::sTimerInfos = NULL; U64 LLFastTimer::sTimerCycles = 0; U32 LLFastTimer::sTimerCalls = 0; @@ -235,7 +233,8 @@ void LLFastTimer::DeclareTimer::updateCachedPointers() } // also update frame states of timers on stack - LLFastTimer* cur_timerp = LLFastTimer::sCurTimerData.mCurTimer; + static LLFastTimer::CurTimerData& static_cur_data = LLFastTimer::CurTimerData::get(); + LLFastTimer* cur_timerp = static_cur_data.mCurTimer; while(cur_timerp->mLastTimerData.mCurTimer != cur_timerp) { cur_timerp->mFrameState = &cur_timerp->mFrameState->mTimer->getFrameState(); @@ -462,10 +461,12 @@ void LLFastTimer::NamedTimer::accumulateTimings() { U32 cur_time = getCPUClockCount32(); + static LLFastTimer::CurTimerData& static_cur_data = LLFastTimer::CurTimerData::get(); + // walk up stack of active timers and accumulate current time while leaving timing structures active - LLFastTimer* cur_timer = sCurTimerData.mCurTimer; + LLFastTimer* cur_timer = static_cur_data.mCurTimer; // root defined by parent pointing to self - CurTimerData* cur_data = &sCurTimerData; + CurTimerData* cur_data = &static_cur_data; while(cur_timer->mLastTimerData.mCurTimer != cur_timer) { U32 cumulative_time_delta = cur_time - cur_timer->mStartTime; @@ -614,8 +615,10 @@ void LLFastTimer::NamedTimer::reset() // effectively zeroing out any accumulated time U32 cur_time = getCPUClockCount32(); + static LLFastTimer::CurTimerData& static_cur_data = LLFastTimer::CurTimerData::get(); + // root defined by parent pointing to self - CurTimerData* cur_data = &sCurTimerData; + CurTimerData* cur_data = &static_cur_data; LLFastTimer* cur_timer = cur_data->mCurTimer; while(cur_timer->mLastTimerData.mCurTimer != cur_timer) { @@ -649,12 +652,13 @@ void LLFastTimer::NamedTimer::reset() //static LLFastTimer::info_list_t& LLFastTimer::getFrameStateList() -{ - if (!sTimerInfos) - { - sTimerInfos = new info_list_t(); - } - return *sTimerInfos; +{ + //Static local varaible to avoid static initialization order fiasco. + //NamedTimerFactory ctor uses this object, and is called during static initialization... + //often before llfasttimer_class.cpp's translation unit. + //'leak' is harmless and intended to ensure it out-scopes NamedTimerFactory. + static info_list_t* timer_infos = new info_list_t(); + return *timer_infos; } @@ -787,10 +791,11 @@ LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state) U32 start_time = getCPUClockCount32(); mStartTime = start_time; mFrameState->mActiveCount++; - LLFastTimer::sCurTimerData.mCurTimer = this; - LLFastTimer::sCurTimerData.mFrameState = mFrameState; - LLFastTimer::sCurTimerData.mChildTime = 0; - mLastTimerData = LLFastTimer::sCurTimerData; + static LLFastTimer::CurTimerData& static_cur_data = LLFastTimer::CurTimerData::get(); + static_cur_data.mCurTimer = this; + static_cur_data.mFrameState = mFrameState; + static_cur_data.mChildTime = 0; + mLastTimerData = static_cur_data; } diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h index 27db83c28..9a547dd69 100644 --- a/indra/llcommon/llfasttimer_class.h +++ b/indra/llcommon/llfasttimer_class.h @@ -169,11 +169,11 @@ public: // keep current parent as long as it is active when we are frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); - LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData; - mLastTimerData = *cur_timer_data; - cur_timer_data->mCurTimer = this; - cur_timer_data->mFrameState = frame_state; - cur_timer_data->mChildTime = 0; + static LLFastTimer::CurTimerData& static_cur_data = LLFastTimer::CurTimerData::get(); + mLastTimerData = static_cur_data; + static_cur_data.mCurTimer = this; + static_cur_data.mFrameState = frame_state; + static_cur_data.mChildTime = 0; #endif #if TIME_FAST_TIMERS U64 timer_end = getCPUClockCount64(); @@ -195,7 +195,9 @@ public: LLFastTimer::FrameState* frame_state = mFrameState; U32 total_time = getCPUClockCount32() - mStartTime; - frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime; + static LLFastTimer::CurTimerData& static_cur_data = LLFastTimer::CurTimerData::get(); + + frame_state->mSelfTimeCounter += total_time - static_cur_data.mChildTime; frame_state->mActiveCount--; // store last caller to bootstrap tree creation @@ -205,7 +207,7 @@ public: // we are only tracking self time, so subtract our total time delta from parents mLastTimerData.mChildTime += total_time; - LLFastTimer::sCurTimerData = mLastTimerData; + static_cur_data = mLastTimerData; #endif #if TIME_FAST_TIMERS U64 timer_end = getCPUClockCount64(); @@ -252,8 +254,16 @@ public: LLFastTimer* mCurTimer; FrameState* mFrameState; U32 mChildTime; + static CurTimerData& get() + { + //Static local varaible to avoid static initialization order fiasco. + //NamedTimerFactory ctor uses this object, and is called during static initialization... + //often before llfasttimer_class.cpp's translation unit. + //'leak' is harmless and intended to ensure it out-scopes NamedTimerFactory. + static CurTimerData* timer_data = new CurTimerData(); + return *timer_data; + } }; - static CurTimerData sCurTimerData; static std::string sClockType; public: @@ -265,7 +275,6 @@ private: static S32 sCurFrameIndex; static S32 sLastFrameIndex; static U64 sLastFrameTime; - static info_list_t* sTimerInfos; U32 mStartTime; LLFastTimer::FrameState* mFrameState;