diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index b1ece51439dee907f9c3e9b8cc6b8e4fbc714a22..5f07501983da646bc04ad1ed9604b4e334abcaf4 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3785,8 +3785,8 @@ void LLAgent::sendAgentSetAppearance()
 	if (!gAgentWearables.changeInProgress())
 	{
 		// Change is fully resolved, can close some open phases.
-		gAgentAvatarp->stopPhase("process_initial_wearables_update");
-		gAgentAvatarp->stopPhase("wear_inventory_category");
+		gAgentAvatarp->getPhases().stopPhase("process_initial_wearables_update");
+		gAgentAvatarp->getPhases().stopPhase("wear_inventory_category");
 	}
 	
 	gAgentAvatarp->sendAppearanceChangeMetrics();
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 5bfcace7072bcdafb42ee75b8b48a46495ce9228..0104d2b08888482670c36ac2932fb78a8064d1bb 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -953,7 +953,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
 	if (isAgentAvatarValid())
 	{
 		//gAgentAvatarp->clearPhases(); // reset phase timers for outfit loading.
-		gAgentAvatarp->startPhase("process_initial_wearables_update");
+		gAgentAvatarp->getPhases().startPhase("process_initial_wearables_update");
 		gAgentAvatarp->outputRezTiming("Received initial wearables update");
 	}
 
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
index 2735c7ef39d9b9470e4493dba9fd921ff8475ee1..e2417cdddb3528d17d68897dae5e8f547744e366 100644
--- a/indra/newview/llagentwearablesfetch.cpp
+++ b/indra/newview/llagentwearablesfetch.cpp
@@ -89,7 +89,7 @@ LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :
 {
 	if (isAgentAvatarValid())
 	{
-		gAgentAvatarp->startPhase("initial_wearables_fetch");
+		gAgentAvatarp->getPhases().startPhase("initial_wearables_fetch");
 		gAgentAvatarp->outputRezTiming("Initial wearables fetch started");
 	}
 }
@@ -108,7 +108,7 @@ void LLInitialWearablesFetch::done()
 	doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this));
 	if (isAgentAvatarValid())
 	{
-		gAgentAvatarp->stopPhase("initial_wearables_fetch");
+		gAgentAvatarp->getPhases().stopPhase("initial_wearables_fetch");
 		gAgentAvatarp->outputRezTiming("Initial wearables fetch done");
 	}
 }
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
old mode 100644
new mode 100755
index 3923b4510a7b8b1e74401af8545a8baf2e801542..31343ee90854f5d7f82465b17f0ef790f3afd1c8
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2706,7 +2706,10 @@ void LLStartUp::setStartupState( EStartupState state )
 	LL_INFOS("AppInit") << "Startup state changing from " <<  
 		getStartupStateString() << " to " <<  
 		startupStateToString(state) << LL_ENDL;
+
+	selfStopPhase(getStartupStateString());
 	gStartupState = state;
+	selfStartPhase(getStartupStateString());
 	postStartupState();
 }
 
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index f408d06f4cc092f7314e8193bb3395de1c748127..4c59fd037195925fe656ac3d99a5085061381173 100755
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -265,8 +265,8 @@ LLViewerAssetStats::recordAvatarStats()
 	LLVOAvatar::getNearbyRezzedStats(rez_counts);
 	mAvatarRezStates = rez_counts;
 	mPhaseStats.clear();
-	mPhaseStats["cloud"] = LLVOAvatar::getPhaseStats("cloud");
-	mPhaseStats["cloud-or-gray"] = LLVOAvatar::getPhaseStats("cloud-or-gray");
+	mPhaseStats["cloud"] = LLViewerStats::PhaseMap::getPhaseStats("cloud");
+	mPhaseStats["cloud-or-gray"] = LLViewerStats::PhaseMap::getPhaseStats("cloud-or-gray");
 }
 
 LLSD
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
index 4b278bc2a2d169117a2a9d30ff07c69da9734090..83197522306f2572ce64bec9e908354d1ab1f255 100755
--- a/indra/newview/llviewerassetstats.h
+++ b/indra/newview/llviewerassetstats.h
@@ -259,7 +259,7 @@ class LLViewerAssetStats
 
 	// Nearby avatar stats
 	std::vector<S32> mAvatarRezStates;
-	LLVOAvatar::phase_stats_t mPhaseStats;
+	LLViewerStats::phase_stats_t mPhaseStats;
 };
 
 
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
old mode 100644
new mode 100755
index c88122f22c9078efd0a46fc00a388cb5444e59cf..497e95c5e3712286b376b608cc666fac4a6df5b4
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -860,3 +860,110 @@ void send_stats()
 	LLHTTPClient::post(url, body, new ViewerStatsResponder());
 }
 
+LLFrameTimer& LLViewerStats::PhaseMap::getPhaseTimer(const std::string& phase_name)
+{
+	phase_map_t::iterator iter = mPhaseMap.find(phase_name);
+	if (iter == mPhaseMap.end())
+	{
+		LLFrameTimer timer;
+		mPhaseMap[phase_name] = timer;
+	}
+	LLFrameTimer& timer = mPhaseMap[phase_name];
+	return timer;
+}
+
+void LLViewerStats::PhaseMap::startPhase(const std::string& phase_name)
+{
+	LLFrameTimer& timer = getPhaseTimer(phase_name);
+	lldebugs << "startPhase " << phase_name << llendl;
+	timer.unpause();
+}
+
+void LLViewerStats::PhaseMap::stopPhase(const std::string& phase_name)
+{
+	phase_map_t::iterator iter = mPhaseMap.find(phase_name);
+	if (iter != mPhaseMap.end())
+	{
+		if (iter->second.getStarted())
+		{
+			// Going from started to paused state - record stats.
+			recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
+		}
+		lldebugs << "stopPhase " << phase_name << llendl;
+		iter->second.pause();
+	}
+	else
+	{
+		lldebugs << "stopPhase " << phase_name << " is not started, no-op" << llendl;
+	}
+}
+
+void LLViewerStats::PhaseMap::stopAllPhases()
+{
+	for (phase_map_t::iterator iter = mPhaseMap.begin();
+		 iter != mPhaseMap.end(); ++iter)
+	{
+		const std::string& phase_name = iter->first;
+		if (iter->second.getStarted())
+		{
+			// Going from started to paused state - record stats.
+			recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
+		}
+		lldebugs << "stopPhase (all) " << phase_name << llendl;
+		iter->second.pause();
+	}
+}
+
+void LLViewerStats::PhaseMap::clearPhases()
+{
+	lldebugs << "clearPhases" << llendl;
+
+	mPhaseMap.clear();
+}
+
+LLSD LLViewerStats::PhaseMap::dumpPhases()
+{
+	LLSD result;
+	for (phase_map_t::iterator iter = mPhaseMap.begin(); iter != mPhaseMap.end(); ++iter)
+	{
+		const std::string& phase_name = iter->first;
+		result[phase_name]["completed"] = !(iter->second.getStarted());
+		result[phase_name]["elapsed"] = iter->second.getElapsedTimeF32();
+#if 0 // global stats for each phase seem like overkill here
+		phase_stats_t::iterator stats_iter = sPhaseStats.find(phase_name);
+		if (stats_iter != sPhaseStats.end())
+		{
+			result[phase_name]["stats"] = stats_iter->second.getData();
+		}
+#endif
+	}
+	return result;
+}
+
+// static initializer
+//static
+LLViewerStats::phase_stats_t LLViewerStats::PhaseMap::sStats;
+
+LLViewerStats::PhaseMap::PhaseMap()
+{
+}
+
+// static
+LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name)
+{
+	phase_stats_t::iterator it = sStats.find(phase_name);
+	if (it == sStats.end())
+	{
+		LLViewerStats::StatsAccumulator new_stats;
+		sStats[phase_name] = new_stats;
+	}
+	return sStats[phase_name];
+}
+
+// static
+void LLViewerStats::PhaseMap::recordPhaseStat(const std::string& phase_name, F32 value)
+{
+	LLViewerStats::StatsAccumulator& stats = getPhaseStats(phase_name);
+	stats.push(value);
+}
+
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 718fabc75a99e5012ea4468dc54f8f04f3909500..750d963f69e6792310034b5c5fe85e5f4084a616 100755
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -274,7 +274,28 @@ class LLViewerStats : public LLSingleton<LLViewerStats>
 	};
 
 	StatsAccumulator mAgentPositionSnaps;
-	
+
+	// Phase tracking (originally put in for avatar rezzing), tracking
+	// progress of active/completed phases for activities like outfit changing.
+	typedef std::map<std::string,LLFrameTimer>	phase_map_t;
+	typedef std::map<std::string,StatsAccumulator>	phase_stats_t;
+	class PhaseMap
+	{
+	private:
+		phase_map_t mPhaseMap;
+		static phase_stats_t sStats;
+	public:
+		PhaseMap();
+		LLFrameTimer& 	getPhaseTimer(const std::string& phase_name);
+		void			startPhase(const std::string& phase_name);
+		void			stopPhase(const std::string& phase_name);
+		void			stopAllPhases();
+		void			clearPhases();
+		LLSD			dumpPhases();
+		static StatsAccumulator& getPhaseStats(const std::string& phase_name);
+		static void recordPhaseStat(const std::string& phase_name, F32 value);
+	};
+
 private:
 	F64	mStats[ST_COUNT];
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 46805ec0c6de4abefac5f023a913532e9bf8e535..275c326ef67e3869676535a7310b76ed3062a853 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -637,7 +637,6 @@ F32 LLVOAvatar::sUnbakedTime = 0.f;
 F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
 F32 LLVOAvatar::sGreyTime = 0.f;
 F32 LLVOAvatar::sGreyUpdateTime = 0.f;
-LLVOAvatar::phase_stats_t LLVOAvatar::sPhaseStats;
 
 //-----------------------------------------------------------------------------
 // Helper functions
@@ -867,7 +866,7 @@ LLVOAvatar::~LLVOAvatar()
 	mAnimationSources.clear();
 	LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
 
-	clearPhases();
+	getPhases().clearPhases();
 	
 	lldebugs << "LLVOAvatar Destructor end" << llendl;
 }
@@ -951,106 +950,6 @@ S32 LLVOAvatar::getRezzedStatus() const
 	return 1; // gray
 }
 
-LLFrameTimer& LLVOAvatar::getPhaseTimer(const std::string& phase_name)
-{
-	phase_map_t::iterator iter = mPhases.find(phase_name);
-	if (iter == mPhases.end())
-	{
-		LLFrameTimer timer;
-		mPhases[phase_name] = timer;
-	}
-	LLFrameTimer& timer = mPhases[phase_name];
-	return timer;
-}
-
-void LLVOAvatar::startPhase(const std::string& phase_name)
-{
-	LLFrameTimer& timer = getPhaseTimer(phase_name);
-	lldebugs << "startPhase " << phase_name << llendl;
-	timer.unpause();
-}
-
-void LLVOAvatar::stopPhase(const std::string& phase_name)
-{
-	phase_map_t::iterator iter = mPhases.find(phase_name);
-	if (iter != mPhases.end())
-	{
-		if (iter->second.getStarted())
-		{
-			// Going from started to paused state - record stats.
-			recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
-		}
-		lldebugs << "stopPhase " << phase_name << llendl;
-		iter->second.pause();
-	}
-	else
-	{
-		lldebugs << "stopPhase " << phase_name << " is not started, no-op" << llendl;
-	}
-}
-
-void LLVOAvatar::stopAllPhases()
-{
-	for (phase_map_t::iterator iter = mPhases.begin();
-		 iter != mPhases.end(); ++iter)
-	{
-		const std::string& phase_name = iter->first;
-		if (iter->second.getStarted())
-		{
-			// Going from started to paused state - record stats.
-			recordPhaseStat(phase_name,iter->second.getElapsedTimeF32());
-		}
-		lldebugs << "stopPhase (all) " << phase_name << llendl;
-		iter->second.pause();
-	}
-}
-
-void LLVOAvatar::clearPhases()
-{
-	lldebugs << "clearPhases" << llendl;
-
-	mPhases.clear();
-	mLastRezzedStatus = -1;
-}
-
-LLSD LLVOAvatar::dumpPhases()
-{
-	LLSD result;
-	for (phase_map_t::iterator iter = mPhases.begin(); iter != mPhases.end(); ++iter)
-	{
-		const std::string& phase_name = iter->first;
-		result[phase_name]["completed"] = !(iter->second.getStarted());
-		result[phase_name]["elapsed"] = iter->second.getElapsedTimeF32();
-#if 0 // global stats for each phase seem like overkill here
-		phase_stats_t::iterator stats_iter = sPhaseStats.find(phase_name);
-		if (stats_iter != sPhaseStats.end())
-		{
-			result[phase_name]["stats"] = stats_iter->second.getData();
-		}
-#endif
-	}
-	return result;
-}
-
-// static
-LLViewerStats::StatsAccumulator& LLVOAvatar::getPhaseStats(const std::string& phase_name)
-{
-	phase_stats_t::iterator it = sPhaseStats.find(phase_name);
-	if (it == sPhaseStats.end())
-	{
-		LLViewerStats::StatsAccumulator new_stats;
-		sPhaseStats[phase_name] = new_stats;
-	}
-	return sPhaseStats[phase_name];
-}
-
-// static
-void LLVOAvatar::recordPhaseStat(const std::string& phase_name, F32 value)
-{
-	LLViewerStats::StatsAccumulator& stats = getPhaseStats(phase_name);
-	stats.push(value);
-}
-
 void LLVOAvatar::deleteLayerSetCaches(bool clearAll)
 {
 	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
@@ -6605,24 +6504,24 @@ void LLVOAvatar::updateRezzedStatusTimers()
 		if (is_cloud && !was_cloud)
 		{
 			// start cloud timer.
-			startPhase("cloud");
+			getPhases().startPhase("cloud");
 		}
 		else if (was_cloud && !is_cloud)
 		{
 			// stop cloud timer, which will capture stats.
-			stopPhase("cloud");
+			getPhases().stopPhase("cloud");
 		}
 
 		// Non-cloud-or-gray to cloud-or-gray
 		if (is_cloud_or_gray && !was_cloud_or_gray)
 		{
 			// start cloud-or-gray timer.
-			startPhase("cloud-or-gray");
+			getPhases().startPhase("cloud-or-gray");
 		}
 		else if (was_cloud_or_gray && !is_cloud_or_gray)
 		{
 			// stop cloud-or-gray timer, which will capture stats.
-			stopPhase("cloud-or-gray");
+			getPhases().stopPhase("cloud-or-gray");
 		}
 		
 		mLastRezzedStatus = rez_status;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 8b72682040577697438e225db93542a21e9e2ab2..6334c43f8e91dbbecd50df6ddf7054d86d10f153 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -287,32 +287,10 @@ class LLVOAvatar :
 
 	S32				mLastRezzedStatus;
 
-	// Tracking progress of active/completed phases for activities like outfit changing.
-	LLFrameTimer& 	getPhaseTimer(const std::string& phase_name);
-	void			startPhase(const std::string& phase_name);
-	void			stopPhase(const std::string& phase_name);
-	void			stopAllPhases();
-	void			clearPhases();
-	LLSD			dumpPhases();
-	static LLViewerStats::StatsAccumulator& getPhaseStats(const std::string& phase_name);
-	static void			recordPhaseStat(const std::string& phase_name, F32 value);
-
-	class ScopedPhaseSetter
+	LLViewerStats::PhaseMap& getPhases()
 	{
-	public:
-		ScopedPhaseSetter(LLVOAvatar* avatar, std::string phase_name):
-			mAvatar(avatar),mPhaseName(phase_name)
-		{
-			if (mAvatar) { mAvatar->startPhase(mPhaseName); }
-		}
-		~ScopedPhaseSetter()
-		{
-			if (mAvatar) { mAvatar->stopPhase(mPhaseName); }
-		}
-	private:
-		std::string mPhaseName;
-		LLVOAvatar* mAvatar;
-	};
+		return mPhases;
+	}
 
 protected:
 	BOOL			updateIsFullyLoaded();
@@ -329,14 +307,26 @@ class LLVOAvatar :
 	LLFrameTimer	mFullyLoadedTimer;
 	LLFrameTimer	mRuthTimer;
 
-	// TODO move all the phase stuff to its down data structure.
 public:
-	typedef std::map<std::string,LLViewerStats::StatsAccumulator>	phase_stats_t;
-	typedef std::map<std::string,LLFrameTimer>	phase_map_t;
+	class ScopedPhaseSetter
+	{
+	public:
+		ScopedPhaseSetter(LLVOAvatar *avatarp, std::string phase_name):
+			mAvatar(avatarp), mPhaseName(phase_name)
+		{
+			if (mAvatar) { mAvatar->getPhases().startPhase(mPhaseName); }
+		}
+		~ScopedPhaseSetter()
+		{
+			if (mAvatar) { mAvatar->getPhases().stopPhase(mPhaseName); }
+		}
+	private:
+		std::string mPhaseName;
+		LLVOAvatar* mAvatar;
+	};
 
 private:
-	phase_map_t		mPhases;
-	static phase_stats_t	sPhaseStats;
+	LLViewerStats::PhaseMap mPhases;
 
 protected:
 	LLFrameTimer    mInvisibleTimer;
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 66cc107a872eb95ba41fb6cfeea538d4f37d5160..aac07df2a9f3c03767feb6b5433eceec680fc1f7 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -80,7 +80,7 @@ void selfStartPhase(const std::string& phase_name)
 {
 	if (isAgentAvatarValid())
 	{
-		gAgentAvatarp->startPhase(phase_name);
+		gAgentAvatarp->getPhases().startPhase(phase_name);
 	}
 }
 
@@ -88,7 +88,7 @@ void selfStopPhase(const std::string& phase_name)
 {
 	if (isAgentAvatarValid())
 	{
-		gAgentAvatarp->stopPhase(phase_name);
+		gAgentAvatarp->getPhases().stopPhase(phase_name);
 	}
 }
 
@@ -96,7 +96,8 @@ void selfClearPhases()
 {
 	if (isAgentAvatarValid())
 	{
-		gAgentAvatarp->clearPhases();
+		gAgentAvatarp->getPhases().clearPhases();
+		gAgentAvatarp->mLastRezzedStatus = -1;
 	}
 }
 
@@ -104,7 +105,7 @@ void selfStopAllPhases()
 {
 	if (isAgentAvatarValid())
 	{
-		gAgentAvatarp->stopAllPhases();
+		gAgentAvatarp->getPhases().stopAllPhases();
 	}
 }
 
@@ -2146,7 +2147,7 @@ LLSD LLVOAvatarSelf::metricsData()
 	result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32();
 	result["timers"]["invisible"] = mInvisibleTimer.getElapsedTimeF32();
 	result["timers"]["fully_loaded"] = mFullyLoadedTimer.getElapsedTimeF32();
-	result["phases"] = dumpPhases();
+	result["phases"] = getPhases().dumpPhases();
 	
 	return result;
 }
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
index 952f0f1a6e786325ff9a43da631f40861772c3fd..f8923b986814dcd4c80692859e06b6a08d6d7f34 100755
--- a/indra/newview/tests/llviewerassetstats_test.cpp
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -45,12 +45,6 @@ void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts)
 	counts[2] = 1;
 }
 
-LLViewerStats::StatsAccumulator& LLVOAvatar::getPhaseStats(const std::string& phase_name)
-{
-	static std::map<std::string,LLViewerStats::StatsAccumulator> stats_map;
-	return stats_map[phase_name];
-}
-
 // static
 std::string LLVOAvatar::rezStatusToString(S32 rez_status)
 {
@@ -60,6 +54,13 @@ std::string LLVOAvatar::rezStatusToString(S32 rez_status)
 	return "unknown";
 }
 
+// static
+LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name)
+{
+	static LLViewerStats::StatsAccumulator junk;
+	return junk;
+}
+
 static const char * all_keys[] = 
 {
 	"duration",