diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 99cb79aa54c553733964832adaf450e5e8cf6bfe..595bb914110246743f8b9c9ad3e91b7863e051d3 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -30,6 +30,7 @@
 #define LL_LLSDUTIL_H
 
 #include "llsd.h"
+#include <boost/functional/hash.hpp>
 
 // U32
 LL_COMMON_API LLSD ll_sd_from_U32(const U32);
@@ -419,4 +420,68 @@ class inMap
 
 } // namespace llsd
 
+
+// Specialization for generating a hash value from an LLSD block. 
+template <>
+struct boost::hash<LLSD>
+{
+    typedef LLSD argument_type;
+    typedef std::size_t result_type;
+    result_type operator()(argument_type const& s) const 
+    {
+        result_type seed(0);
+
+        LLSD::Type stype = s.type();
+        boost::hash_combine(seed, (S32)stype);
+
+        switch (stype)
+        {
+        case LLSD::TypeBoolean:
+            boost::hash_combine(seed, s.asBoolean());
+            break;
+        case LLSD::TypeInteger:
+            boost::hash_combine(seed, s.asInteger());
+            break;
+        case LLSD::TypeReal:
+            boost::hash_combine(seed, s.asReal());
+            break;
+        case LLSD::TypeURI:
+        case LLSD::TypeString:
+            boost::hash_combine(seed, s.asString());
+            break;
+        case LLSD::TypeUUID:
+            boost::hash_combine(seed, s.asUUID());
+            break;
+        case LLSD::TypeDate:
+            boost::hash_combine(seed, s.asDate().secondsSinceEpoch());
+            break;
+        case LLSD::TypeBinary:
+        {
+            const LLSD::Binary &b(s.asBinary());
+            boost::hash_range(seed, b.begin(), b.end());
+            break;
+        }
+        case LLSD::TypeMap:
+        {
+            for (LLSD::map_const_iterator itm = s.beginMap(); itm != s.endMap(); ++itm)
+            {
+                boost::hash_combine(seed, (*itm).first);
+                boost::hash_combine(seed, (*itm).second);
+            }
+            break;
+        }
+        case LLSD::TypeArray:
+            for (LLSD::array_const_iterator ita = s.beginArray(); ita != s.endArray(); ++ita)
+            {
+                boost::hash_combine(seed, (*ita));
+            }
+            break;
+        case LLSD::TypeUndefined:
+            break;
+        }
+
+        return seed;
+    }
+};
+
 #endif // LL_LLSDUTIL_H
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index dd8660a3c8dbc1275a5ae04724124b3becf7e593..fe7482ba29f82c70598a1497da8e04f4fa1f5faa 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -31,6 +31,7 @@
 #include <vector>
 #include "stdtypes.h"
 #include "llpreprocessor.h"
+#include <boost/functional/hash.hpp>
 
 class LLMutex;
 
@@ -164,6 +165,25 @@ class LL_COMMON_API LLTransactionID : public LLUUID
 	LLAssetID makeAssetID(const LLUUID& session) const;
 };
 
+// Generate a hash of an LLUUID object using the boost hash templates. 
+template <>
+struct boost::hash<LLUUID>
+{
+    typedef LLUUID argument_type;
+    typedef std::size_t result_type;
+    result_type operator()(argument_type const& s) const
+    {
+        result_type seed(0);
+
+        for (S32 i = 0; i < UUID_BYTES; ++i)
+        {
+            boost::hash_combine(seed, s.mData[i]);
+        }
+
+        return seed;
+    }
+};
+
 #endif
 
 
diff --git a/indra/newview/llsettingsbase.cpp b/indra/newview/llsettingsbase.cpp
index 904d0dd07c12c85f8ca31506060a903d10700959..e36c6d4a84dd01886c7468cab3bec5c24291d414 100644
--- a/indra/newview/llsettingsbase.cpp
+++ b/indra/newview/llsettingsbase.cpp
@@ -48,13 +48,15 @@ const F32Seconds LLSettingsBlender::DEFAULT_THRESHOLD(0.01);
 //=========================================================================
 LLSettingsBase::LLSettingsBase():
     mSettings(LLSD::emptyMap()),
-    mDirty(true)
+    mDirty(true),
+    mHashValue(0)
 {
 }
 
 LLSettingsBase::LLSettingsBase(const LLSD setting) :
     mSettings(setting),
-    mDirty(true)
+    mDirty(true),
+    mHashValue(0)
 {
 }
 
diff --git a/indra/newview/llsettingsbase.h b/indra/newview/llsettingsbase.h
index d32fcb26e88f42b09ef351103e310cf34894844a..d304b8702ae7239cc7444cfc7c801d2082cb79ec 100644
--- a/indra/newview/llsettingsbase.h
+++ b/indra/newview/llsettingsbase.h
@@ -67,6 +67,11 @@ class LLSettingsBase :
     inline bool isDirty() const { return mDirty; }
     inline void setDirtyFlag(bool dirty) { mDirty = dirty; }
 
+    inline size_t getHash() const
+    {
+        return boost::hash<LLSD>{}(mSettings);
+    }
+
     inline LLUUID getId() const
     {
         return getValue(SETTING_ID).asUUID();
@@ -227,6 +232,7 @@ class LLSettingsBase :
 
 private:
     bool    mDirty;
+    size_t  mHashValue;
 
     LLSD    combineSDMaps(const LLSD &first, const LLSD &other) const;
 
diff --git a/indra/test/llsdutil_tut.cpp b/indra/test/llsdutil_tut.cpp
index 140f4b832b295cbe133ef7c8f77086f01004e45a..6fce53f335143b5e57eec287a14dbed3684aa716 100644
--- a/indra/test/llsdutil_tut.cpp
+++ b/indra/test/llsdutil_tut.cpp
@@ -386,4 +386,49 @@ namespace tut
         lmap["Seattle"] = 72;
         ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap));
     }
+
+    template<> template<> 
+    void llsdutil_object::test<10>()
+    {
+        set_test_name("llsd_hashing");
+
+        {
+            LLSD data_s1 = LLSD::String("The quick brown aardvark jumped over the lazy lemming.");
+            LLSD data_s2 = LLSD::String("The quick brown aardvark jumped over the lazy lemming.");
+
+            ensure("hash: Identical string hashes match.", boost::hash<LLSD>{}(data_s1) == boost::hash<LLSD>{}(data_s2));
+        }
+        {
+            LLSD data_r1 = LLSD::Real(3.0f);
+            LLSD data_i1 = LLSD::Integer(3);
+            ensure("hash: equivalent values but different types do not match.", boost::hash<LLSD>{}(data_r1) != boost::hash<LLSD>{}(data_i1));
+        }
+        {
+            LLSD data_a1 = LLSDArray("A")("B")("C");
+            LLSD data_a2 = LLSDArray("A")("B")("C");
+
+            ensure("hash: identical arrays produce identical results", boost::hash<LLSD>{}(data_a1) == boost::hash<LLSD>{}(data_a2));
+
+            data_a2.append(LLSDArray(1)(2));
+
+            ensure("hash: changing the array changes the hash.", boost::hash<LLSD>{}(data_a1) != boost::hash<LLSD>{}(data_a2));
+
+            data_a1.append(LLSDArray(1)(2));
+            ensure("hash: identical arrays produce identical results with nested arrays", boost::hash<LLSD>{}(data_a1) == boost::hash<LLSD>{}(data_a2));
+        }
+        {
+            LLSD data_m1 = LLSDMap("key1", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3));
+            LLSD data_m2 = LLSDMap("key1", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3));
+
+            ensure("hash: identical maps produce identical results", boost::hash<LLSD>{}(data_m1) == boost::hash<LLSD>{}(data_m2));
+
+            LLSD data_m3 = LLSDMap("key1", LLSD::Real(5.0))("key2", "value2")("key3", LLSDArray(1)(2)(3));
+            ensure("hash: Different values in the map produce different hashes.", boost::hash<LLSD>{}(data_m1) != boost::hash<LLSD>{}(data_m3));
+
+            LLSD data_m4 = LLSDMap("keyA", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3));
+            ensure("hash: Different keys in the map produce different hashes.", boost::hash<LLSD>{}(data_m1) != boost::hash<LLSD>{}(data_m4));
+
+        }
+    }
+
 }