Commits

dessie linden committed 8f72109 Merge

merge

  • Participants
  • Parent commits 5c7486d, cec4c58

Comments (0)

Files changed (536)

 1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release
 6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1
 6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 3.0.3-beta1
+586907287be581817b2422b5137971b22d54ea48 3.0.4-start
 61aa7974df089e8621fe9a4c69bcdefdb3cc208a DRTVWR-89_3.0.3-beta2
 61aa7974df089e8621fe9a4c69bcdefdb3cc208a 3.0.3-beta2
 0496d2f74043cf4e6058e76ac3db03d44cff42ce DRTVWR-84_3.0.3-release
 0496d2f74043cf4e6058e76ac3db03d44cff42ce 3.0.3-release
+92a3aa04775438226399b19deee12ac3b5a62838 3.0.5-start
+c7282e59f374ee904bd793c3c444455e3399b0c5 3.1.0-start
+dbaaef19266478a20654c46395300640163e98e3 DRTVWR-96_3.1.0-beta2
+dbaaef19266478a20654c46395300640163e98e3 3.1.0-beta2
+dbaaef19266478a20654c46395300640163e98e3 DRTVWR-96_3.1.0-beta2
+bc01ee26fd0f1866e266429e85f76340523e91f1 DRTVWR-96_3.1.0-beta2
+dbaaef19266478a20654c46395300640163e98e3 3.1.0-beta2
+bc01ee26fd0f1866e266429e85f76340523e91f1 3.1.0-beta2

File autobuild.xml

             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a7c80fd8516df3b879b669b2b220067f</string>
+              <string>1b92a69f5eba7cd8b017180659076db5</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/232420/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20110608.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/roxie_3p-llqtwebkit/rev/242182/arch/Darwin/installer/llqtwebkit-4.7.1-darwin-20111003.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>b9cc0333cc274c9cc40256ab7146b4fc</string>
+              <string>1e7f24b69b0fc751c7e86efe7c621882</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llqtwebkit/rev/232420/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20110608.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/roxie_3p-llqtwebkit/rev/242182/arch/CYGWIN/installer/llqtwebkit-4.7.1-windows-20111003.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>

File doc/contributions.txt

 	VWR-24917
 Argent Stonecutter
 	VWR-68
+ArminWeatherHax
+	STORM-1532
 Armin Weatherwax
 	VWR-8436
 ArminasX Saiman
 Ima Mechanique
 	OPEN-50
 	OPEN-61
+	OPEN-76
 	STORM-1175
 Imnotgoing Sideways
 Inma Rau
 	STORM-1276
 	STORM-1462
 	STORM-1459
+	STORM-1297
+	STORM-1522
+	STORM-1567
+	STORM-1572
+	STORM-1574
 Kadah Coba
     STORM-1060
 Jondan Lundquist

File doc/translations.txt

-#List of translators who contribute to SL Viewer 2.0+ and SL web translation by language
+#List of translators who contribute to SL Viewer 2.0+ by language
 
 	Danish
 Flemming Congrejo
+	German
+Torben Trautman
 	French
 Valerie Linden
 	Polish
 Minerva Memel
 Polo Gufler
 Xiki Luik
-Perez Linden
+Shinya Tandino
+Catwise Yoshikawa
 	Traditional Chinese
 gefeit Dufaux

File indra/cmake/OpenSSL.cmake

   if (WINDOWS)
     set(OPENSSL_LIBRARIES ssleay32 libeay32)
   else (WINDOWS)
-    set(OPENSSL_LIBRARIES ssl)
+    set(OPENSSL_LIBRARIES ssl crypto)
   endif (WINDOWS)
   set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
 endif (STANDALONE)

File indra/llaudio/llaudioengine_fmod.cpp

File contents unchanged.

File indra/llaudio/llvorbisencode.cpp

File contents unchanged.

File indra/llcharacter/llbvhloader.cpp

File contents unchanged.

File indra/llcharacter/llkeyframemotionparam.cpp

File contents unchanged.

File indra/llcharacter/llstatemachine.cpp

File contents unchanged.

File indra/llcommon/CMakeLists.txt

     indra_constants.h
     linden_common.h
     linked_lists.h
-    llaccountingquota.h
+    llaccountingcost.h
     llallocator.h
     llallocator_heap_profile.h
     llagentconstants.h
   LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}"
                           "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
+  LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")                          
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")

File indra/llcommon/llaccountingcost.h

+/** 
+ * @file llaccountingcost.h
+ * @
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_ACCOUNTINGQUOTA_H
+#define LL_ACCOUNTINGQUOTA_H
+
+struct ParcelQuota
+{
+	ParcelQuota( F32 ownerRenderCost,	 F32 ownerPhysicsCost,	  F32 ownerNetworkCost,	   F32 ownerSimulationCost,
+				 F32 groupRenderCost,	 F32 groupPhysicsCost,	  F32 groupNetworkCost,	   F32 groupSimulationCost,
+				 F32 otherRenderCost,	 F32 otherPhysicsCost,	  F32 otherNetworkCost,	   F32 otherSimulationCost,
+				 F32 tempRenderCost,	 F32 tempPhysicsCost,	  F32 tempNetworkCost,	   F32 tempSimulationCost,
+				 F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
+				 F32 parcelCapacity )
+	: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost ) 
+	, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
+	, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
+	, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
+	, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
+	, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
+	, mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost ) 
+	, mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
+	, mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost ) 
+	, mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
+	, mParcelCapacity( parcelCapacity )
+	{
+	}
+
+	ParcelQuota(){}			
+	F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
+	F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
+	F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
+	F32 mTempRenderCost,  mTempPhysicsCost,  mTempNetworkCost,  mTempSimulationCost;
+	F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
+	F32 mParcelCapacity;
+};
+
+//SelectionQuota atm does not require a id
+struct SelectionCost
+{
+	SelectionCost( /*LLTransactionID transactionId, */ F32 physicsCost, F32 networkCost, F32 simulationCost )
+	//: mTransactionId( transactionId)
+	: mPhysicsCost( physicsCost )
+	, mNetworkCost( networkCost )
+	, mSimulationCost( simulationCost )
+	{
+	}
+	SelectionCost()
+	: mPhysicsCost( 0.0f )
+	, mNetworkCost( 0.0f )
+	, mSimulationCost( 0.0f )
+	{}
+	
+	F32 mPhysicsCost, mNetworkCost, mSimulationCost;	
+	//LLTransactionID mTransactionId;
+};
+
+typedef enum { Roots = 0 , Prims } eSelectionType;
+
+#endif
+
+
+

File indra/llcommon/llaccountingquota.h

-/** 
- * @file llaccountingquota.h
- * @
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_ACCOUNTINGQUOTA_H
-#define LL_ACCOUNTINGQUOTA_H
-
-struct ParcelQuota
-{
-	ParcelQuota( F32 ownerRenderCost,	 F32 ownerPhysicsCost,	  F32 ownerNetworkCost,	   F32 ownerSimulationCost,
-				 F32 groupRenderCost,	 F32 groupPhysicsCost,	  F32 groupNetworkCost,	   F32 groupSimulationCost,
-				 F32 otherRenderCost,	 F32 otherPhysicsCost,	  F32 otherNetworkCost,	   F32 otherSimulationCost,
-				 F32 tempRenderCost,	 F32 tempPhysicsCost,	  F32 tempNetworkCost,	   F32 tempSimulationCost,
-				 F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
-				 F32 parcelCapacity )
-	: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost ) 
-	, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
-	, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
-	, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
-	, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
-	, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
-	, mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost ) 
-	, mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
-	, mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost ) 
-	, mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
-	, mParcelCapacity( parcelCapacity )
-	{
-	}
-
-	ParcelQuota(){}			
-	F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
-	F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
-	F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
-	F32 mTempRenderCost,  mTempPhysicsCost,  mTempNetworkCost,  mTempSimulationCost;
-	F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
-	F32 mParcelCapacity;
-};
-
-struct SelectionQuota
-{
-	SelectionQuota( LLUUID localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
-	: mLocalId( localId)
-	, mRenderCost( renderCost )
-	, mPhysicsCost( physicsCost )
-	, mNetworkCost( networkCost )
-	, mSimulationCost( simulationCost )
-	{
-	}
-	SelectionQuota() {}
-	
-	F32 mRenderCost, mPhysicsCost, mNetworkCost, mSimulationCost;	
-	LLUUID mLocalId;
-};
-
-#endif
-
-
-

File indra/llcommon/llapp.cpp

File contents unchanged.

File indra/llcommon/llapr.cpp

File contents unchanged.

File indra/llcommon/llapr.h

File contents unchanged.

File indra/llcommon/llcommon.cpp

File contents unchanged.

File indra/llcommon/llcommon.h

File contents unchanged.

File indra/llcommon/llerror.cpp

File contents unchanged.

File indra/llcommon/llerror.h

File contents unchanged.

File indra/llcommon/llfasttimer_class.cpp

 
 std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
 {
+	F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond();
 	if (history_idx < 0)
 	{
-		// by default, show average number of calls
-		return llformat("%s (%d calls)", getName().c_str(), (S32)getCallAverage());
+		// by default, show average number of call
+		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage());
 	}
 	else
 	{
-		return llformat("%s (%d calls)", getName().c_str(), (S32)getHistoricalCalls(history_idx));
+		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx));
 	}
 }
 
 		llinfos << "Slow frame, fast timers inaccurate" << llendl;
 	}
 
-	if (sPauseHistory)
-	{
-		sResetHistory = true;
-	}
-	else if (sResetHistory)
-	{
-		sLastFrameIndex = 0;
-		sCurFrameIndex = 0;
-		sResetHistory = false;
-	}
-	else // not paused
+	if (!sPauseHistory)
 	{
 		NamedTimer::processTimes();
 		sLastFrameIndex = sCurFrameIndex++;

File indra/llcommon/llfasttimer_class.h

 	public:
 		~NamedTimer();
 
-		enum { HISTORY_NUM = 60 };
+		enum { HISTORY_NUM = 300 };
 
 		const std::string& getName() const { return mName; }
 		NamedTimer* getParent() const { return mParent; }

File indra/llcommon/llfixedbuffer.cpp

File contents unchanged.

File indra/llcommon/llinstancetracker.cpp

 //static 
 void * & LLInstanceTrackerBase::getInstances(std::type_info const & info)
 {
-	static std::map<std::string, void *> instances;
+	typedef std::map<std::string, void *> InstancesMap;
+	static InstancesMap instances;
 
-	std::string k = info.name();
-	if(instances.find(k) == instances.end())
-	{
-		instances[k] = NULL;
-	}
-
-	return instances[k];
+	// std::map::insert() is just what we want here. You attempt to insert a
+	// (key, value) pair. If the specified key doesn't yet exist, it inserts
+	// the pair and returns a std::pair of (iterator, true). If the specified
+	// key DOES exist, insert() simply returns (iterator, false). One lookup
+	// handles both cases.
+	return instances.insert(InstancesMap::value_type(info.name(),
+													 InstancesMap::mapped_type()))
+		.first->second;
 }
-

File indra/llcommon/llinstancetracker.h

 #define LL_LLINSTANCETRACKER_H
 
 #include <map>
+#include <typeinfo>
 
 #include "string_table.h"
 #include <boost/utility.hpp>
 #include <boost/iterator/transform_iterator.hpp>
 #include <boost/iterator/indirect_iterator.hpp>
 
+/**
+ * Base class manages "class-static" data that must actually have singleton
+ * semantics: one instance per process, rather than one instance per module as
+ * sometimes happens with data simply declared static.
+ */
 class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable
 {
-	protected:
-		static void * & getInstances(std::type_info const & info);
+protected:
+	/// Get a process-unique void* pointer slot for the specified type_info
+	static void * & getInstances(std::type_info const & info);
+
+	/// Find or create a STATICDATA instance for the specified TRACKED class.
+	/// STATICDATA must be default-constructible.
+	template<typename STATICDATA, class TRACKED>
+	static STATICDATA& getStatic()
+	{
+		void *& instances = getInstances(typeid(TRACKED));
+		if (! instances)
+		{
+			instances = new STATICDATA;
+		}
+		return *static_cast<STATICDATA*>(instances);
+	}
+
+    /// It's not essential to derive your STATICDATA (for use with
+    /// getStatic()) from StaticBase; it's just that both known
+    /// implementations do.
+    struct StaticBase
+    {
+        StaticBase():
+            sIterationNestDepth(0)
+        {}
+        S32 sIterationNestDepth;
+    };
 };
 
 /// This mix-in class adds support for tracking all instances of the specified class parameter T
 template<typename T, typename KEY = T*>
 class LLInstanceTracker : public LLInstanceTrackerBase
 {
+	typedef LLInstanceTracker<T, KEY> MyT;
 	typedef typename std::map<KEY, T*> InstanceMap;
-	typedef LLInstanceTracker<T, KEY> MyT;
+	struct StaticData: public StaticBase
+	{
+		InstanceMap sMap;
+	};
+	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
+	static InstanceMap& getMap_() { return getStatic().sMap; }
+
 public:
 	class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag>
 	{
 		instance_iter(const typename InstanceMap::iterator& it)
 		:	mIterator(it)
 		{
-			++sIterationNestDepth;
+			++getStatic().sIterationNestDepth;
 		}
 
 		~instance_iter()
 		{
-			--sIterationNestDepth;
+			--getStatic().sIterationNestDepth;
 		}
 
 
 		key_iter(typename InstanceMap::iterator it)
 			:	mIterator(it)
 		{
-			++sIterationNestDepth;
+			++getStatic().sIterationNestDepth;
 		}
 
 		key_iter(const key_iter& other)
 			:	mIterator(other.mIterator)
 		{
-			++sIterationNestDepth;
+			++getStatic().sIterationNestDepth;
 		}
 
 		~key_iter()
 		{
-			--sIterationNestDepth;
+			--getStatic().sIterationNestDepth;
 		}
 
 
 	virtual ~LLInstanceTracker() 
 	{ 
 		// it's unsafe to delete instances of this type while all instances are being iterated over.
-		llassert(sIterationNestDepth == 0);
-		remove_(); 		
+		llassert_always(getStatic().sIterationNestDepth == 0);
+		remove_();		
 	}
 	virtual void setKey(KEY key) { remove_(); add_(key); }
 	virtual const KEY& getKey() const { return mInstanceKey; }
 		getMap_().erase(mInstanceKey);
 	}
 
-    static InstanceMap& getMap_()
-    {
-		void * & instances = getInstances(typeid(MyT));
-        if (! instances)
-        {
-            instances = new InstanceMap;
-        }
-        return * static_cast<InstanceMap*>(instances);
-    }
-
 private:
-
 	KEY mInstanceKey;
-	static S32 sIterationNestDepth;
 };
 
-template <typename T, typename KEY> S32 LLInstanceTracker<T, KEY>::sIterationNestDepth = 0;
-
 /// explicit specialization for default case where KEY is T*
 /// use a simple std::set<T*>
 template<typename T>
 class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
 {
+	typedef LLInstanceTracker<T, T*> MyT;
 	typedef typename std::set<T*> InstanceSet;
-	typedef LLInstanceTracker<T, T*> MyT;
+	struct StaticData: public StaticBase
+	{
+		InstanceSet sSet;
+	};
+	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
+	static InstanceSet& getSet_() { return getStatic().sSet; }
+
 public:
 
 	/// for completeness of analogy with the generic implementation
 		instance_iter(const typename InstanceSet::iterator& it)
 		:	mIterator(it)
 		{
-			++sIterationNestDepth;
+			++getStatic().sIterationNestDepth;
 		}
 
 		instance_iter(const instance_iter& other)
 		:	mIterator(other.mIterator)
 		{
-			++sIterationNestDepth;
+			++getStatic().sIterationNestDepth;
 		}
 
 		~instance_iter()
 		{
-			--sIterationNestDepth;
+			--getStatic().sIterationNestDepth;
 		}
 
 	private:
 protected:
 	LLInstanceTracker()
 	{
-		// it's safe but unpredictable to create instances of this type while all instances are being iterated over.  I hate unpredictable.  This assert will probably be turned on early in the next development cycle.
+		// it's safe but unpredictable to create instances of this type while all instances are being iterated over.  I hate unpredictable.	 This assert will probably be turned on early in the next development cycle.
 		getSet_().insert(static_cast<T*>(this));
 	}
 	virtual ~LLInstanceTracker()
 	{
 		// it's unsafe to delete instances of this type while all instances are being iterated over.
-		llassert(sIterationNestDepth == 0);
+		llassert_always(getStatic().sIterationNestDepth == 0);
 		getSet_().erase(static_cast<T*>(this));
 	}
 
 	{
 		getSet_().insert(static_cast<T*>(this));
 	}
-
-	static InstanceSet& getSet_()
-	{
-		void * & instances = getInstances(typeid(MyT));
-		if (! instances)
-		{
-			instances = new InstanceSet;
-		}
-		return * static_cast<InstanceSet *>(instances);
-	}
-
-	static S32 sIterationNestDepth;
 };
 
-template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0;
-
 #endif

File indra/llcommon/llmemory.cpp

 
 #include "linden_common.h"
 
-#include "llmemory.h"
 
-#if MEM_TRACK_MEM
+//#if MEM_TRACK_MEM
 #include "llthread.h"
-#endif
+//#endif
 
 #if defined(LL_WINDOWS)
-# include <windows.h>
+//# include <windows.h>
 # include <psapi.h>
 #elif defined(LL_DARWIN)
 # include <sys/types.h>
 # include <unistd.h>
 #endif
 
+#include "llmemory.h"
+
+#include "llsys.h"
+#include "llframetimer.h"
 //----------------------------------------------------------------------------
 
 //static
 char* LLMemory::reserveMem = 0;
+U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ;
+U32 LLMemory::sMaxPhysicalMemInKB = 0;
+U32 LLMemory::sAllocatedMemInKB = 0;
+U32 LLMemory::sAllocatedPageSizeInKB = 0 ;
+U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ;
+BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
+
+#if __DEBUG_PRIVATE_MEM__
+LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sMemAllocationTracker;
+#endif
 
 //static
 void LLMemory::initClass()
 	reserveMem = NULL;
 }
 
+//static 
+void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure)
+{
+	sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ;
+	sEnableMemoryFailurePrevention = prevent_heap_failure ;
+}
+
+//static 
+void LLMemory::updateMemoryInfo() 
+{
+#if LL_WINDOWS	
+	HANDLE self = GetCurrentProcess();
+	PROCESS_MEMORY_COUNTERS counters;
+	
+	if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))
+	{
+		llwarns << "GetProcessMemoryInfo failed" << llendl;
+		return ;
+	}
+
+	sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
+	sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
+
+	U32 avail_phys, avail_virtual;
+	LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
+	sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
+
+	if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
+	{
+		sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
+	}
+	else
+	{
+		sAvailPhysicalMemInKB = 0 ;
+	}
+#else
+	//not valid for other systems for now.
+	sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
+	sMaxPhysicalMemInKB = U32_MAX ;
+	sAvailPhysicalMemInKB = U32_MAX ;
+#endif
+
+	return ;
+}
+
+//
+//this function is to test if there is enough space with the size in the virtual address space.
+//it does not do any real allocation
+//if success, it returns the address where the memory chunk can fit in;
+//otherwise it returns NULL.
+//
+//static 
+void* LLMemory::tryToAlloc(void* address, U32 size)
+{
+#if LL_WINDOWS
+	address = VirtualAlloc(address, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS) ;
+	if(address)
+	{
+		if(!VirtualFree(address, 0, MEM_RELEASE))
+		{
+			llerrs << "error happens when free some memory reservation." << llendl ;
+		}
+	}
+	return address ;
+#else
+	return (void*)0x01 ; //skip checking
+#endif	
+}
+
+//static 
+void LLMemory::logMemoryInfo(BOOL update)
+{
+	if(update)
+	{
+		updateMemoryInfo() ;
+	}
+
+	llinfos << "Current allocated physical memory(KB): " << sAllocatedMemInKB << llendl ;
+	llinfos << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << llendl ;
+	llinfos << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << llendl ;
+	llinfos << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << llendl ;
+
+	llinfos << "--- private pool information -- " << llendl ;
+	llinfos << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << llendl ;
+	llinfos << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << llendl ;
+}
+
+//return 0: everything is normal;
+//return 1: the memory pool is low, but not in danger;
+//return -1: the memory pool is in danger, is about to crash.
+//static 
+bool LLMemory::isMemoryPoolLow()
+{
+	static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
+	const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
+	static void* last_reserved_address = NULL ;
+
+	if(!sEnableMemoryFailurePrevention)
+	{
+		return false ; //no memory failure prevention.
+	}
+
+	if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory
+	{
+		return true ;
+	}
+
+	if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space.
+	{
+		return true ;
+	}
+
+	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || 
+		sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
+
+	//check the virtual address space fragmentation
+	if(!is_low)
+	{
+		if(!last_reserved_address)
+		{
+			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+		}
+		else
+		{
+			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+			if(!last_reserved_address) //failed, try once more
+			{
+				last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+			}
+		}
+
+		is_low = !last_reserved_address ; //allocation failed
+	}
+
+	return is_low ;
+}
+
+//static 
+U32 LLMemory::getAvailableMemKB() 
+{
+	return sAvailPhysicalMemInKB ;
+}
+
+//static 
+U32 LLMemory::getMaxMemKB() 
+{
+	return sMaxPhysicalMemInKB ;
+}
+
+//static 
+U32 LLMemory::getAllocatedMemKB() 
+{
+	return sAllocatedMemInKB ;
+}
+
+void* ll_allocate (size_t size)
+{
+	if (size == 0)
+	{
+		llwarns << "Null allocation" << llendl;
+	}
+	void *p = malloc(size);
+	if (p == NULL)
+	{
+		LLMemory::freeReserve();
+		llerrs << "Out of memory Error" << llendl;
+	}
+	return p;
+}
 
 //----------------------------------------------------------------------------
 
 
 U32 LLMemory::getWorkingSetSize()
 {
-	return 0 ;
+	return 0;
 }
 
 #endif
 	mDrawnIndex = 0 ;
 	mPaused = FALSE ;
 
-	mMutexp = new LLMutex(NULL) ;
+	mMutexp = new LLMutex() ;
 	mStringBuffer = new char*[128] ;
 	mStringBuffer[0] = new char[mCapacity * 128] ;
 	for(S32 i = 1 ; i < mCapacity ; i++)
 #endif //MEM_TRACK_MEM
 //--------------------------------------------------------------------------------------------------
 
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+//minimum slot size and minimal slot size interval
+const U32 ATOMIC_MEM_SLOT = 16 ; //bytes
+
+//minimum block sizes (page size) for small allocation, medium allocation, large allocation 
+const U32 MIN_BLOCK_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {2 << 10, 4 << 10, 16 << 10} ; //
+
+//maximum block sizes for small allocation, medium allocation, large allocation 
+const U32 MAX_BLOCK_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {64 << 10, 1 << 20, 4 << 20} ;
+
+//minimum slot sizes for small allocation, medium allocation, large allocation 
+const U32 MIN_SLOT_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION]  = {ATOMIC_MEM_SLOT, 2 << 10, 512 << 10};
+
+//maximum slot sizes for small allocation, medium allocation, large allocation 
+const U32 MAX_SLOT_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION]  = {(2 << 10) - ATOMIC_MEM_SLOT, (512 - 2) << 10, 4 << 20};
+
+//size of a block with multiple slots can not exceed CUT_OFF_SIZE
+const U32 CUT_OFF_SIZE = (64 << 10) ; //64 KB
+
+//max number of slots in a block
+const U32 MAX_NUM_SLOTS_IN_A_BLOCK = llmin(MIN_BLOCK_SIZES[0] / ATOMIC_MEM_SLOT, ATOMIC_MEM_SLOT * 8) ;
+
+//-------------------------------------------------------------
+//align val to be integer times of ATOMIC_MEM_SLOT
+U32 align(U32 val)
+{
+	U32 aligned = (val / ATOMIC_MEM_SLOT) * ATOMIC_MEM_SLOT ;
+	if(aligned < val)
+	{
+		aligned += ATOMIC_MEM_SLOT ;
+	}
+
+	return aligned ;
+}
+
+//-------------------------------------------------------------
+//class LLPrivateMemoryPool::LLMemoryBlock
+//-------------------------------------------------------------
+//
+//each memory block could fit for two page sizes: 0.75 * mSlotSize, which starts from the beginning of the memory chunk and grow towards the end of the
+//the block; another is mSlotSize, which starts from the end of the block and grows towards the beginning of the block.
+//
+LLPrivateMemoryPool::LLMemoryBlock::LLMemoryBlock()
+{
+	//empty
+}
+		
+LLPrivateMemoryPool::LLMemoryBlock::~LLMemoryBlock() 
+{
+	//empty
+}
+
+//create and initialize a memory block
+void LLPrivateMemoryPool::LLMemoryBlock::init(char* buffer, U32 buffer_size, U32 slot_size)
+{
+	mBuffer = buffer ;
+	mBufferSize = buffer_size ;
+	mSlotSize = slot_size ;
+	mTotalSlots = buffer_size / mSlotSize ;	
+	
+	llassert_always(buffer_size / mSlotSize <= MAX_NUM_SLOTS_IN_A_BLOCK) ; //max number is 128
+	
+	mAllocatedSlots = 0 ;
+	mDummySize = 0 ;
+
+	//init the bit map.
+	//mark free bits	
+	if(mTotalSlots > 32) //reserve extra space from mBuffer to store bitmap if needed.
+	{
+		mDummySize = ATOMIC_MEM_SLOT ;		
+		mTotalSlots -= (mDummySize + mSlotSize - 1) / mSlotSize ;
+		mUsageBits = 0 ;
+
+		S32 usage_bit_len = (mTotalSlots + 31) / 32 ;
+		
+		for(S32 i = 0 ; i < usage_bit_len - 1 ; i++)
+		{
+			*((U32*)mBuffer + i) = 0 ;
+		}
+		for(S32 i = usage_bit_len - 1 ; i < mDummySize / sizeof(U32) ; i++)
+		{
+			*((U32*)mBuffer + i) = 0xffffffff ;
+		}
+
+		if(mTotalSlots & 31)
+		{
+			*((U32*)mBuffer + usage_bit_len - 2) = (0xffffffff << (mTotalSlots & 31)) ;
+		}		
+	}	
+	else//no extra bitmap space reserved
+	{
+		mUsageBits = 0 ;
+		if(mTotalSlots & 31)
+		{
+			mUsageBits = (0xffffffff << (mTotalSlots & 31)) ;
+		}
+	}
+
+	mSelf = this ;
+	mNext = NULL ;
+	mPrev = NULL ;
+
+	llassert_always(mTotalSlots > 0) ;
+}
+
+//mark this block to be free with the memory [mBuffer, mBuffer + mBufferSize).
+void LLPrivateMemoryPool::LLMemoryBlock::setBuffer(char* buffer, U32 buffer_size)
+{
+	mBuffer = buffer ;
+	mBufferSize = buffer_size ;
+	mSelf = NULL ;
+	mTotalSlots = 0 ; //set the block is free.
+}
+
+//reserve a slot
+char* LLPrivateMemoryPool::LLMemoryBlock::allocate() 
+{
+	llassert_always(mAllocatedSlots < mTotalSlots) ;
+	
+	//find a free slot
+	U32* bits = NULL ;
+	U32  k = 0 ;
+	if(mUsageBits != 0xffffffff)
+	{
+		bits = &mUsageBits ;
+	}
+	else if(mDummySize > 0)//go to extra space
+	{		
+		for(S32 i = 0 ; i < mDummySize / sizeof(U32); i++)
+		{
+			if(*((U32*)mBuffer + i) != 0xffffffff)
+			{
+				bits = (U32*)mBuffer + i ;
+				k = i + 1 ;
+				break ;
+			}
+		}
+	}	
+	S32 idx = 0 ;
+	U32 tmp = *bits ;
+	for(; tmp & 1 ; tmp >>= 1, idx++) ;
+
+	//set the slot reserved
+	if(!idx)
+	{
+		*bits |= 1 ;
+	}
+	else
+	{
+		*bits |= (1 << idx) ;
+	}
+
+	mAllocatedSlots++ ;
+	
+	return mBuffer + mDummySize + (k * 32 + idx) * mSlotSize ;
+}
+
+//free a slot
+void  LLPrivateMemoryPool::LLMemoryBlock::freeMem(void* addr) 
+{
+	//bit index
+	U32 idx = ((U32)addr - (U32)mBuffer - mDummySize) / mSlotSize ;
+
+	U32* bits = &mUsageBits ;
+	if(idx >= 32)
+	{
+		bits = (U32*)mBuffer + (idx - 32) / 32 ;
+	}
+
+	//reset the bit
+	if(idx & 31)
+	{
+		*bits &= ~(1 << (idx & 31)) ;
+	}
+	else
+	{
+		*bits &= ~1 ;
+	}
+
+	mAllocatedSlots-- ;
+}
+
+//for debug use: reset the entire bitmap.
+void  LLPrivateMemoryPool::LLMemoryBlock::resetBitMap()
+{
+	for(S32 i = 0 ; i < mDummySize / sizeof(U32) ; i++)
+	{
+		*((U32*)mBuffer + i) = 0 ;
+	}
+	mUsageBits = 0 ;
+}
+//-------------------------------------------------------------------
+//class LLMemoryChunk
+//--------------------------------------------------------------------
+LLPrivateMemoryPool::LLMemoryChunk::LLMemoryChunk()
+{
+	//empty
+}
+
+LLPrivateMemoryPool::LLMemoryChunk::~LLMemoryChunk()
+{
+	//empty
+}
+
+//create and init a memory chunk
+void LLPrivateMemoryPool::LLMemoryChunk::init(char* buffer, U32 buffer_size, U32 min_slot_size, U32 max_slot_size, U32 min_block_size, U32 max_block_size) 
+{
+	mBuffer = buffer ;
+	mBufferSize = buffer_size ;
+	mAlloatedSize = 0 ;
+
+	mMetaBuffer = mBuffer + sizeof(LLMemoryChunk) ;
+
+	mMinBlockSize = min_block_size; //page size
+	mMinSlotSize = min_slot_size;
+	mMaxSlotSize = max_slot_size ;
+	mBlockLevels = mMaxSlotSize / mMinSlotSize ;
+	mPartitionLevels = max_block_size / mMinBlockSize + 1 ;
+
+	S32 max_num_blocks = (buffer_size - sizeof(LLMemoryChunk) - mBlockLevels * sizeof(LLMemoryBlock*) - mPartitionLevels * sizeof(LLMemoryBlock*)) / 
+		                 (mMinBlockSize + sizeof(LLMemoryBlock)) ;
+	//meta data space
+	mBlocks = (LLMemoryBlock*)mMetaBuffer ; //space reserved for all memory blocks.
+	mAvailBlockList = (LLMemoryBlock**)((char*)mBlocks + sizeof(LLMemoryBlock) * max_num_blocks) ; 
+	mFreeSpaceList = (LLMemoryBlock**)((char*)mAvailBlockList + sizeof(LLMemoryBlock*) * mBlockLevels) ; 
+	
+	//data buffer, which can be used for allocation
+	mDataBuffer = (char*)mFreeSpaceList + sizeof(LLMemoryBlock*) * mPartitionLevels ;
+	
+	//alignmnet
+	mDataBuffer = mBuffer + align(mDataBuffer - mBuffer) ;
+	
+	//init
+	for(U32 i = 0 ; i < mBlockLevels; i++)
+	{
+		mAvailBlockList[i] = NULL ;
+	}
+	for(U32 i = 0 ; i < mPartitionLevels ; i++)
+	{
+		mFreeSpaceList[i] = NULL ;
+	}
+
+	//assign the entire chunk to the first block
+	mBlocks[0].mPrev = NULL ;
+	mBlocks[0].mNext = NULL ;
+	mBlocks[0].setBuffer(mDataBuffer, buffer_size - (mDataBuffer - mBuffer)) ;
+	addToFreeSpace(&mBlocks[0]) ;
+
+	mNext = NULL ;
+	mPrev = NULL ;
+}
+
+//static 
+U32 LLPrivateMemoryPool::LLMemoryChunk::getMaxOverhead(U32 data_buffer_size, U32 min_slot_size, 
+													   U32 max_slot_size, U32 min_block_size, U32 max_block_size)
+{
+	//for large allocations, reserve some extra memory for meta data to avoid wasting much 
+	if(data_buffer_size / min_slot_size < 64) //large allocations
+	{
+		U32 overhead = sizeof(LLMemoryChunk) + (data_buffer_size / min_block_size) * sizeof(LLMemoryBlock) +
+			sizeof(LLMemoryBlock*) * (max_slot_size / min_slot_size) + sizeof(LLMemoryBlock*) * (max_block_size / min_block_size + 1) ;
+
+		//round to integer times of min_block_size
+		overhead = ((overhead + min_block_size - 1) / min_block_size) * min_block_size ;
+		return overhead ;
+	}
+	else
+	{
+		return 0 ; //do not reserve extra overhead if for small allocations
+	}
+}
+
+char* LLPrivateMemoryPool::LLMemoryChunk::allocate(U32 size)
+{
+	if(mMinSlotSize > size)
+	{
+		size = mMinSlotSize ;
+	}
+	if(mAlloatedSize + size  > mBufferSize - (mDataBuffer - mBuffer))
+	{
+		return NULL ; //no enough space in this chunk.
+	}
+
+	char* p = NULL ;
+	U32 blk_idx = getBlockLevel(size);
+
+	LLMemoryBlock* blk = NULL ;
+
+	//check if there is free block available
+	if(mAvailBlockList[blk_idx])
+	{
+		blk = mAvailBlockList[blk_idx] ;
+		p = blk->allocate() ;
+		
+		if(blk->isFull())
+		{
+			popAvailBlockList(blk_idx) ;
+		}
+	}
+
+	//ask for a new block
+	if(!p)
+	{
+		blk = addBlock(blk_idx) ;
+		if(blk)
+		{
+			p = blk->allocate() ;
+
+			if(blk->isFull())
+			{
+				popAvailBlockList(blk_idx) ;
+			}
+		}
+	}
+
+	//ask for space from larger blocks
+	if(!p)
+	{
+		for(S32 i = blk_idx + 1 ; i < mBlockLevels; i++)
+		{
+			if(mAvailBlockList[i])
+			{
+				blk = mAvailBlockList[i] ;
+				p = blk->allocate() ;
+
+				if(blk->isFull())
+				{
+					popAvailBlockList(i) ;
+				}
+				break ;
+			}
+		}
+	}
+
+	if(p && blk)
+	{		
+		mAlloatedSize += blk->getSlotSize() ;
+	}
+	return p ;
+}
+
+void LLPrivateMemoryPool::LLMemoryChunk::freeMem(void* addr)
+{	
+	U32 blk_idx = getPageIndex((U32)addr) ;
+	LLMemoryBlock* blk = (LLMemoryBlock*)(mMetaBuffer + blk_idx * sizeof(LLMemoryBlock)) ;
+	blk = blk->mSelf ;
+
+	bool was_full = blk->isFull() ;
+	blk->freeMem(addr) ;
+	mAlloatedSize -= blk->getSlotSize() ;
+
+	if(blk->empty())
+	{
+		removeBlock(blk) ;
+	}
+	else if(was_full)
+	{
+		addToAvailBlockList(blk) ;
+	}	
+}
+
+bool LLPrivateMemoryPool::LLMemoryChunk::empty()
+{
+	return !mAlloatedSize ;
+}
+
+bool LLPrivateMemoryPool::LLMemoryChunk::containsAddress(const char* addr) const
+{
+	return (U32)mBuffer <= (U32)addr && (U32)mBuffer + mBufferSize > (U32)addr ;
+}
+
+//debug use
+void LLPrivateMemoryPool::LLMemoryChunk::dump()
+{
+#if 0
+	//sanity check
+	//for(S32 i = 0 ; i < mBlockLevels ; i++)
+	//{
+	//	LLMemoryBlock* blk = mAvailBlockList[i] ;
+	//	while(blk)
+	//	{
+	//		blk_list.push_back(blk) ;
+	//		blk = blk->mNext ;
+	//	}
+	//}
+	for(S32 i = 0 ; i < mPartitionLevels ; i++)
+	{
+		LLMemoryBlock* blk = mFreeSpaceList[i] ;
+		while(blk)
+		{
+			blk_list.push_back(blk) ;
+			blk = blk->mNext ;
+		}
+	}
+
+	std::sort(blk_list.begin(), blk_list.end(), LLMemoryBlock::CompareAddress());
+
+	U32 total_size = blk_list[0]->getBufferSize() ;
+	for(U32 i = 1 ; i < blk_list.size(); i++)
+	{
+		total_size += blk_list[i]->getBufferSize() ;
+		if((U32)blk_list[i]->getBuffer() < (U32)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize())
+		{
+			llerrs << "buffer corrupted." << llendl ;
+		}
+	}
+
+	llassert_always(total_size + mMinBlockSize >= mBufferSize - ((U32)mDataBuffer - (U32)mBuffer)) ;
+
+	U32 blk_num = (mBufferSize - (mDataBuffer - mBuffer)) / mMinBlockSize ;
+	for(U32 i = 0 ; i < blk_num ; )
+	{
+		LLMemoryBlock* blk = &mBlocks[i] ;
+		if(blk->mSelf)
+		{
+			U32 end = blk->getBufferSize() / mMinBlockSize ;
+			for(U32 j = 0 ; j < end ; j++)
+			{
+				llassert_always(blk->mSelf == blk || !blk->mSelf) ;
+			}
+			i += end ;
+		}
+		else
+		{
+			llerrs << "gap happens" << llendl ;
+		}
+	}
+#endif
+#if 0
+	llinfos << "---------------------------" << llendl ;
+	llinfos << "Chunk buffer: " << (U32)getBuffer() << " size: " << getBufferSize() << llendl ;
+
+	llinfos << "available blocks ... " << llendl ;
+	for(S32 i = 0 ; i < mBlockLevels ; i++)
+	{
+		LLMemoryBlock* blk = mAvailBlockList[i] ;
+		while(blk)
+		{
+			llinfos << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << llendl ;
+			blk = blk->mNext ;
+		}
+	}
+
+	llinfos << "free blocks ... " << llendl ;
+	for(S32 i = 0 ; i < mPartitionLevels ; i++)
+	{
+		LLMemoryBlock* blk = mFreeSpaceList[i] ;
+		while(blk)
+		{
+			llinfos << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << llendl ;
+			blk = blk->mNext ;