diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index f40359790aae1e5e125307a6342d48fb088bdb10..2d0363d188efab6b2d12a9e2a948cfa173bba1ca 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -276,6 +276,7 @@ LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(lldependencies "" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}")
+LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 192d79b27ddb2658c4fda32c1fdc1d83d8502588..f52cf33fd8df6898651e967f3d4770169c637720 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -45,10 +45,12 @@
 #include "llsingleton.h"
 #include "lldependencies.h"
 
+/*==========================================================================*|
 // override this to allow binding free functions with more parameters
 #ifndef LLEVENTS_LISTENER_ARITY
 #define LLEVENTS_LISTENER_ARITY 10
 #endif
+|*==========================================================================*/
 
 // hack for testing
 #ifndef testable
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index ea50acbbc5e08008c241eb34d188ba9cbc0a1280..039d68faef8a5b9eb2277f1d08ec136ba9716dac 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -38,22 +38,53 @@
 
 #include "string_table.h"
 #include <boost/utility.hpp>
-
-// This mix-in class adds support for tracking all instances of the specified class parameter T
-// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
-// If KEY is not provided, then instances are stored in a simple set
-// *NOTE: see explicit specialization below for default KEY==T* case
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+
+/// This mix-in class adds support for tracking all instances of the specified class parameter T
+/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
+/// If KEY is not provided, then instances are stored in a simple set
+/// @NOTE: see explicit specialization below for default KEY==T* case
 template<typename T, typename KEY = T*>
 class LLInstanceTracker : boost::noncopyable
 {
+	typedef typename std::map<KEY, T*> InstanceMap;
+	typedef boost::function<const KEY&(typename InstanceMap::value_type&)> KeyGetter;
+	typedef boost::function<T*(typename InstanceMap::value_type&)> InstancePtrGetter;
 public:
-	typedef typename std::map<KEY, T*>::iterator instance_iter;
-	typedef typename std::map<KEY, T*>::const_iterator instance_const_iter;
-
-	static T* getInstance(const KEY& k) { instance_iter found = getMap().find(k); return (found == getMap().end()) ? NULL : found->second; }
+	/// Dereferencing key_iter gives you a const KEY&
+	typedef boost::transform_iterator<KeyGetter, typename InstanceMap::iterator> key_iter;
+	/// Dereferencing instance_iter gives you a T&
+	typedef boost::indirect_iterator< boost::transform_iterator<InstancePtrGetter, typename InstanceMap::iterator> > instance_iter;
+
+	static T* getInstance(const KEY& k)
+	{
+		typename InstanceMap::const_iterator found = getMap().find(k);
+		return (found == getMap().end()) ? NULL : found->second;
+	}
 
-	static instance_iter beginInstances() { return getMap().begin(); }
-	static instance_iter endInstances() { return getMap().end(); }
+	static key_iter beginKeys()
+	{
+		return boost::make_transform_iterator(getMap().begin(),
+											  boost::bind(&InstanceMap::value_type::first, _1));
+	}
+	static key_iter endKeys()
+	{
+		return boost::make_transform_iterator(getMap().end(),
+											  boost::bind(&InstanceMap::value_type::first, _1));
+	}
+	static instance_iter beginInstances()
+	{
+		return instance_iter(boost::make_transform_iterator(getMap().begin(),
+															boost::bind(&InstanceMap::value_type::second, _1)));
+	}
+	static instance_iter endInstances()
+	{
+		return instance_iter(boost::make_transform_iterator(getMap().end(),
+															boost::bind(&InstanceMap::value_type::second, _1)));
+	}
 	static S32 instanceCount() { return getMap().size(); }
 protected:
 	LLInstanceTracker(KEY key) { add(key); }
@@ -69,11 +100,11 @@ class LLInstanceTracker : boost::noncopyable
 	}
 	void remove() { getMap().erase(mKey); }
 
-    static std::map<KEY, T*>& getMap()
+    static InstanceMap& getMap()
     {
         if (! sInstances)
         {
-            sInstances = new std::map<KEY, T*>;
+            sInstances = new InstanceMap;
         }
         return *sInstances;
     }
@@ -81,20 +112,27 @@ class LLInstanceTracker : boost::noncopyable
 private:
 
 	KEY mKey;
-	static std::map<KEY, T*>* sInstances;
+	static InstanceMap* sInstances;
 };
 
-// explicit specialization for default case where KEY is T*
-// use a simple std::set<T*>
+/// explicit specialization for default case where KEY is T*
+/// use a simple std::set<T*>
 template<typename T>
 class LLInstanceTracker<T, T*>
 {
+	typedef typename std::set<T*> InstanceSet;
 public:
-	typedef typename std::set<T*>::iterator instance_iter;
-	typedef typename std::set<T*>::const_iterator instance_const_iter;
-
-	static instance_iter beginInstances() { return getSet().begin(); }
-	static instance_iter endInstances() { return getSet().end(); }
+	/// Dereferencing key_iter gives you a T* (since T* is the key)
+	typedef typename InstanceSet::iterator key_iter;
+	/// Dereferencing instance_iter gives you a T&
+	typedef boost::indirect_iterator<key_iter> instance_iter;
+
+	/// for completeness of analogy with the generic implementation
+	static T* getInstance(T* k) { return k; }
+	static key_iter beginKeys() { return getSet().begin(); }
+	static key_iter endKeys()   { return getSet().end(); }
+	static instance_iter beginInstances() { return instance_iter(getSet().begin()); }
+	static instance_iter endInstances()   { return instance_iter(getSet().end()); }
 	static S32 instanceCount() { return getSet().size(); }
 
 protected:
@@ -103,19 +141,19 @@ class LLInstanceTracker<T, T*>
 
 	LLInstanceTracker(const LLInstanceTracker& other) { getSet().insert(static_cast<T*>(this)); }
 
-    static std::set<T*>& getSet()   // called after getReady() but before go()
+    static InstanceSet& getSet()   // called after getReady() but before go()
     {
         if (! sInstances)
         {
-            sInstances = new std::set<T*>;
+            sInstances = new InstanceSet;
         }
         return *sInstances;
     }
 
-	static std::set<T*>* sInstances;
+	static InstanceSet* sInstances;
 };
 
-template <typename T, typename KEY> std::map<KEY, T*>* LLInstanceTracker<T, KEY>::sInstances = NULL;
-template <typename T> std::set<T*>* LLInstanceTracker<T, T*>::sInstances = NULL;
+template <typename T, typename KEY> typename LLInstanceTracker<T, KEY>::InstanceMap* LLInstanceTracker<T, KEY>::sInstances = NULL;
+template <typename T> typename LLInstanceTracker<T, T*>::InstanceSet* LLInstanceTracker<T, T*>::sInstances = NULL;
 
 #endif
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index ea5b0c03ef18e8cadf136d85d5cfbd4d2f0d1284..ef3e8dbc946396353fa014978d3898900cba06a5 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -583,13 +583,13 @@ void LLEventTimer::updateClass()
 	std::list<LLEventTimer*> completed_timers;
 	for (instance_iter iter = beginInstances(); iter != endInstances(); ) 
 	{
-		LLEventTimer* timer = *iter++;
-		F32 et = timer->mEventTimer.getElapsedTimeF32();
-		if (timer->mEventTimer.getStarted() && et > timer->mPeriod) {
-			timer->mEventTimer.reset();
-			if ( timer->tick() )
+		LLEventTimer& timer = *iter++;
+		F32 et = timer.mEventTimer.getElapsedTimeF32();
+		if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
+			timer.mEventTimer.reset();
+			if ( timer.tick() )
 			{
-				completed_timers.push_back( timer );
+				completed_timers.push_back( &timer );
 			}
 		}
 	}
diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7415f2d33b1eb31eb27853c3abe103b781b9103b
--- /dev/null
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -0,0 +1,160 @@
+/**
+ * @file   llinstancetracker_test.cpp
+ * @author Nat Goodspeed
+ * @date   2009-11-10
+ * @brief  Test for llinstancetracker.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llinstancetracker.h"
+// STL headers
+#include <string>
+#include <vector>
+#include <set>
+#include <algorithm>                // std::sort()
+// std headers
+// external library headers
+#include <boost/scoped_ptr.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+
+struct Keyed: public LLInstanceTracker<Keyed, std::string>
+{
+    Keyed(const std::string& name):
+        LLInstanceTracker<Keyed, std::string>(name),
+        mName(name)
+    {}
+    std::string mName;
+};
+
+struct Unkeyed: public LLInstanceTracker<Unkeyed>
+{
+};
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct llinstancetracker_data
+    {
+    };
+    typedef test_group<llinstancetracker_data> llinstancetracker_group;
+    typedef llinstancetracker_group::object object;
+    llinstancetracker_group llinstancetrackergrp("llinstancetracker");
+
+    template<> template<>
+    void object::test<1>()
+    {
+        ensure_equals(Keyed::instanceCount(), 0);
+        {
+            Keyed one("one");
+            ensure_equals(Keyed::instanceCount(), 1);
+            Keyed* found = Keyed::getInstance("one");
+            ensure("couldn't find stack Keyed", found);
+            ensure_equals("found wrong Keyed instance", found, &one);
+            {
+                boost::scoped_ptr<Keyed> two(new Keyed("two"));
+                ensure_equals(Keyed::instanceCount(), 2);
+                Keyed* found = Keyed::getInstance("two");
+                ensure("couldn't find heap Keyed", found);
+                ensure_equals("found wrong Keyed instance", found, two.get());
+            }
+            ensure_equals(Keyed::instanceCount(), 1);
+        }
+        Keyed* found = Keyed::getInstance("one");
+        ensure("Keyed key lives too long", ! found);
+        ensure_equals(Keyed::instanceCount(), 0);
+    }
+
+    template<> template<>
+    void object::test<2>()
+    {
+        ensure_equals(Unkeyed::instanceCount(), 0);
+        {
+            Unkeyed one;
+            ensure_equals(Unkeyed::instanceCount(), 1);
+            Unkeyed* found = Unkeyed::getInstance(&one);
+            ensure_equals(found, &one);
+            {
+                boost::scoped_ptr<Unkeyed> two(new Unkeyed);
+                ensure_equals(Unkeyed::instanceCount(), 2);
+                Unkeyed* found = Unkeyed::getInstance(two.get());
+                ensure_equals(found, two.get());
+            }
+            ensure_equals(Unkeyed::instanceCount(), 1);
+        }
+        ensure_equals(Unkeyed::instanceCount(), 0);
+    }
+
+    template<> template<>
+    void object::test<3>()
+    {
+        Keyed one("one"), two("two"), three("three");
+        // We don't want to rely on the underlying container delivering keys
+        // in any particular order. That allows us the flexibility to
+        // reimplement LLInstanceTracker using, say, a hash map instead of a
+        // std::map. We DO insist that every key appear exactly once.
+        typedef std::vector<std::string> StringVector;
+        StringVector keys(Keyed::beginKeys(), Keyed::endKeys());
+        std::sort(keys.begin(), keys.end());
+        StringVector::const_iterator ki(keys.begin());
+        ensure_equals(*ki++, "one");
+        ensure_equals(*ki++, "three");
+        ensure_equals(*ki++, "two");
+        // Use ensure() here because ensure_equals would want to display
+        // mismatched values, and frankly that wouldn't help much.
+        ensure("didn't reach end", ki == keys.end());
+
+        // Use a somewhat different approach to order independence with
+        // beginInstances(): explicitly capture the instances we know in a
+        // set, and delete them as we iterate through.
+        typedef std::set<Keyed*> InstanceSet;
+        InstanceSet instances;
+        instances.insert(&one);
+        instances.insert(&two);
+        instances.insert(&three);
+        for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances());
+             ii != iend; ++ii)
+        {
+            Keyed& ref = *ii;
+            ensure_equals("spurious instance", instances.erase(&ref), 1);
+        }
+        ensure_equals("unreported instance", instances.size(), 0);
+    }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        Unkeyed one, two, three;
+        typedef std::set<Unkeyed*> KeySet;
+        KeySet keys;
+        keys.insert(&one);
+        keys.insert(&two);
+        keys.insert(&three);
+        for (Unkeyed::key_iter ki(Unkeyed::beginKeys()), kend(Unkeyed::endKeys());
+             ki != kend; ++ki)
+        {
+            ensure_equals("spurious key", keys.erase(*ki), 1);
+        }
+        ensure_equals("unreported key", keys.size(), 0);
+
+        KeySet instances;
+        instances.insert(&one);
+        instances.insert(&two);
+        instances.insert(&three);
+        for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances());
+             ii != iend; ++ii)
+        {
+            Unkeyed& ref = *ii;
+            ensure_equals("spurious instance", instances.erase(&ref), 1);
+        }
+        ensure_equals("unreported instance", instances.size(), 0);
+    }
+} // namespace tut
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 9399ace1f79f7c25ac23bd54108a462df2226f1c..14a6ddb7e0e8babee240e65250221f3fed77e771 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -792,8 +792,8 @@ void LLLayoutStack::calcMinExtents()
 //static 
 void LLLayoutStack::updateClass()
 {
-	for (LLInstanceTracker<LLLayoutStack>::instance_iter it = beginInstances(); it != endInstances(); ++it)
+	for (LLLayoutStack::instance_iter it = beginInstances(); it != endInstances(); ++it)
 	{
-		(*it)->updateLayout();
+		it->updateLayout();
 	}
 }
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 541db0ca6e1bb2fa02d68e11908b951bebfd9d68..9439717fb851acd4b74275b5986506bb32dfe7c2 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -323,8 +323,8 @@ void LLNameListCtrl::refreshAll(const LLUUID& id, const std::string& first,
 	LLInstanceTracker<LLNameListCtrl>::instance_iter it;
 	for (it = beginInstances(); it != endInstances(); ++it)
 	{
-		LLNameListCtrl* ctrl = *it;
-		ctrl->refresh(id, first, last, is_group);
+		LLNameListCtrl& ctrl = *it;
+		ctrl.refresh(id, first, last, is_group);
 	}
 }