diff --git a/indra/develop.py b/indra/develop.py
index 1d7ac42c9ccee1a431c2a1050b3b27b81a6b1b6d..b40e81bb07c0b56e61d3d51ce6029e10de270ee7 100755
--- a/indra/develop.py
+++ b/indra/develop.py
@@ -451,9 +451,7 @@ def run_build(self, opts, targets):
             targets = ' '.join(['-target ' + repr(t) for t in targets])
         else:
             targets = ''
-        # cmd = ('xcodebuild -parallelizeTargets ' # parallelizeTargets is suspected of non-deterministic build failures. + poppy 2009-06-05
-        cmd = ('xcodebuild '
-               '-configuration %s %s %s' %
+        cmd = ('xcodebuild -configuration %s %s %s' %
                (self.build_type, ' '.join(opts), targets))
         for d in self.build_dirs():
             try:
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
index 1190d88663964a6c3dace2c291778ab676d0579e..4527b115f9ad07b6a2f9180090466c2f562112a1 100644
--- a/indra/lib/python/indra/base/llsd.py
+++ b/indra/lib/python/indra/base/llsd.py
@@ -238,7 +238,7 @@ def ARRAY(self, v):
     def MAP(self, v):
         return self.elt(
             'map',
-            ''.join(["%s%s" % (self.elt('key', key), self.generate(value))
+            ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
              for key, value in v.items()]))
 
     typeof = type
diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py
index c4c40739ec9514180d57f3c75db7259293ba679e..7e0e115d14600f29fe4b855077232a8d10529271 100644
--- a/indra/lib/python/indra/util/llsubprocess.py
+++ b/indra/lib/python/indra/util/llsubprocess.py
@@ -90,6 +90,17 @@ def run(command, args=None, data=None, timeout=None):
                     child.tochild.close()
         result = child.poll()
         if result != -1:
+            # At this point, the child process has exited and result
+            # is the return value from the process. Between the time
+            # we called select() and poll() the process may have
+            # exited so read all the data left on the child process
+            # stdout and stderr.
+            last = child.fromchild.read()
+            if last:
+                out.append(last)
+            last = child.childerr.read()
+            if last:
+                err.append(last)
             child.tochild.close()
             child.fromchild.close()
             child.childerr.close()
diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py
index 693b483f792f485d206dbac812865a6fef3d0170..5c19368240afa08b8576f3f16ec01c4b738c5f76 100644
--- a/indra/lib/python/indra/util/named_query.py
+++ b/indra/lib/python/indra/util/named_query.py
@@ -48,8 +48,8 @@
 from indra.base import config
 
 DEBUG = False
-NQ_FILE_SUFFIX = None
-NQ_FILE_SUFFIX_LEN = None
+NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
+NQ_FILE_SUFFIX_LEN  = len(NQ_FILE_SUFFIX)
 
 _g_named_manager = None
 
diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp
index 1d42298f4d395adb638efae4713af11a74e45e72..1ae0ddeea0fba8787885b6a247866c0809973a28 100644
--- a/indra/llcharacter/llkeyframestandmotion.cpp
+++ b/indra/llcharacter/llkeyframestandmotion.cpp
@@ -190,7 +190,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask)
 	if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD)
 	{
 		mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation();
-		mLastGoodPelvisRotation.normQuat();
+		mLastGoodPelvisRotation.normalize();
 		mTrackAnkles = TRUE;
 	}
 	else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD)
diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h
index 873f50a65ef8abbeb1d2fcdbd2f50025f66cf90f..7544ab1d11ffb2a3f853d1709457186689fbf828 100644
--- a/indra/llcommon/llkeythrottle.h
+++ b/indra/llcommon/llkeythrottle.h
@@ -118,6 +118,63 @@ class LLKeyThrottle
 		THROTTLE_BLOCKED,		// rate exceed, block key
 	};
 
+	F64 getActionCount(const T& id)
+	{
+		U64 now = 0;
+		if ( mIsRealtime )
+		{
+			now = LLKeyThrottleImpl<T>::getTime();
+		}
+		else
+		{
+			now = LLKeyThrottleImpl<T>::getFrame();
+		}
+
+		if (now >= (m.startTime + m.intervalLength))
+		{
+			if (now < (m.startTime + 2 * m.intervalLength))
+			{
+				// prune old data
+				delete m.prevMap;
+				m.prevMap = m.currMap;
+				m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+				m.startTime += m.intervalLength;
+			}
+			else
+			{
+				// lots of time has passed, all data is stale
+				delete m.prevMap;
+				delete m.currMap;
+				m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+				m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+				m.startTime = now;
+			}
+		}
+
+		U32 prevCount = 0;
+
+		typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
+		if (prev != m.prevMap->end())
+		{
+			prevCount = prev->second.count;
+		}
+
+		typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+
+		// curr.count is the number of keys in
+		// this current 'time slice' from the beginning of it until now
+		// prevCount is the number of keys in the previous
+		// time slice scaled to be one full time slice back from the current 
+		// (now) time.
+
+		// compute current, windowed rate
+		F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
+		F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
+		return averageCount;
+	}
+
 	// call each time the key wants use
 	State noteAction(const T& id, S32 weight = 1)
 	{
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 291b019616cd4f62558920cc34b47e3301700da9..e650f911b754b49c7446cd54897312b0887defcf 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -43,7 +43,7 @@
 
 
 // statics
-BOOL            LLPerfBlock::sStatsEnabled = FALSE;    // Flag for detailed information
+S32	            LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS;       // Control what is being recorded
 LLPerfBlock::stat_map_t    LLPerfBlock::sStatMap;    // Map full path string to LLStatTime objects, tracks all active objects
 std::string        LLPerfBlock::sCurrentStatPath = "";    // Something like "/total_time/physics/physics step"
 
@@ -129,6 +129,7 @@ bool LLStatsConfigFile::loadFile()
 
     F32 duration = 0.f;
     F32 interval = 0.f;
+	S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS;
 
     const char * w = "duration";
     if (stats_config.has(w))
@@ -140,8 +141,18 @@ bool LLStatsConfigFile::loadFile()
     {
         interval = (F32)stats_config[w].asReal();
     } 
+    w = "flags";
+    if (stats_config.has(w))
+    {
+		flags = (S32)stats_config[w].asInteger();
+		if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS &&
+			duration > 0)
+		{   // No flags passed in, but have a duration, so reset to basic stats
+			flags = LLPerfBlock::LLSTATS_BASIC_STATS;
+		}
+    } 
 
-    mStatsp->setReportPerformanceDuration( duration );
+    mStatsp->setReportPerformanceDuration( duration, flags );
     mStatsp->setReportPerformanceInterval( interval );
 
     if ( duration > 0 )
@@ -253,13 +264,14 @@ void LLPerfStats::dumpIntervalPerformanceStats()
     }
 }
 
-// Set length of performance stat recording
-void    LLPerfStats::setReportPerformanceDuration( F32 seconds )
+// Set length of performance stat recording.  
+// If turning stats on, caller must provide flags
+void    LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ )
 { 
 	if ( seconds <= 0.f )
 	{
 		mReportPerformanceStatEnd = 0.0;
-		LLPerfBlock::setStatsEnabled( FALSE );
+		LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS);		// Make sure all recording is off
 		mFrameStatsFile.close();
 		LLPerfBlock::clearDynamicStats();
 	}
@@ -268,8 +280,8 @@ void    LLPerfStats::setReportPerformanceDuration( F32 seconds )
 		mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
 		// Clear failure flag to try and create the log file once
 		mFrameStatsFileFailure = FALSE;
-		LLPerfBlock::setStatsEnabled( TRUE );
 		mSkipFirstFrameStats = TRUE;		// Skip the first report (at the end of this frame)
+		LLPerfBlock::setStatsFlags(flags);
 	}
 }
 
@@ -611,11 +623,26 @@ LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicSta
     }
 }
 
-// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
-// These are also turned on or off via the switch passed in
-LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+// Use this constructor for normal, optional LLPerfBlock time slices
+LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL)
 {
-    if (!sStatsEnabled) return;
+    if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0)
+	{	// These are off unless the base set is enabled
+		return;
+	}
+
+	initDynamicStat(key);
+}
+
+	
+// Use this constructor for dynamically created LLPerfBlock time slices
+// that are only enabled by specific control flags
+LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+{
+    if ((sStatsFlags & flags) == 0)
+	{
+		return;
+	}
 
     if (NULL == key2 || strlen(key2) == 0)
     {
@@ -629,10 +656,12 @@ LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat
     }
 }
 
+// Set up the result data map if dynamic stats are enabled
 void LLPerfBlock::initDynamicStat(const std::string& key)
 {
     // Early exit if dynamic stats aren't enabled.
-    if (!sStatsEnabled) return;
+    if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS) 
+		return;
 
     mLastPath = sCurrentStatPath;		// Save and restore current path
     sCurrentStatPath += "/" + key;		// Add key to current path
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
index 61aaac45bfbd552a6193a73f06175cfde6fe4b91..e2e904bb06190b1fc0b1e017556f00b7ee9297e6 100644
--- a/indra/llcommon/llstat.h
+++ b/indra/llcommon/llstat.h
@@ -192,14 +192,23 @@ class LLPerfBlock
 	// Use this constructor for pre-defined LLStatTime objects
 	LLPerfBlock(LLStatTime* stat);
 
-	// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
-	LLPerfBlock( const char* key1, const char* key2 = NULL);
+	// Use this constructor for normal, optional LLPerfBlock time slices
+	LLPerfBlock( const char* key );
 
+	// Use this constructor for dynamically created LLPerfBlock time slices
+	// that are only enabled by specific control flags
+	LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS );
 
 	~LLPerfBlock();
 
-	static void setStatsEnabled( BOOL enable )		{ sStatsEnabled = enable;	};
-	static S32  getStatsEnabled()					{ return sStatsEnabled;		};
+	enum
+	{	// Stats bitfield flags
+		LLSTATS_NO_OPTIONAL_STATS	= 0x00,		// No optional stats gathering, just pre-defined LLStatTime objects
+		LLSTATS_BASIC_STATS			= 0x01,		// Gather basic optional runtime stats
+		LLSTATS_SCRIPT_FUNCTIONS	= 0x02,		// Include LSL function calls
+	};
+	static void setStatsFlags( S32 flags )	{ sStatsFlags = flags;	};
+	static S32  getStatsFlags()				{ return sStatsFlags;	};
 
 	static void clearDynamicStats();		// Reset maps to clear out dynamic objects
 	static void addStatsToLLSDandReset( LLSD & stats,		// Get current information and clear time bin
@@ -213,7 +222,7 @@ class LLPerfBlock
 	LLStatTime * 			mPredefinedStat;		// LLStatTime object to get data
 	StatEntry *				mDynamicStat;   		// StatEntryobject to get data
 
-	static BOOL				sStatsEnabled;			// Normally FALSE
+	static S32				sStatsFlags;			// Control what is being recorded
     static stat_map_t		sStatMap;				// Map full path string to LLStatTime objects
 	static std::string		sCurrentStatPath;		// Something like "frame/physics/physics step"
 };
@@ -236,7 +245,7 @@ class LLPerfStats
     BOOL    frameStatsIsRunning()                                { return (mReportPerformanceStatEnd > 0.);        };
     F32     getReportPerformanceInterval() const                { return mReportPerformanceStatInterval;        };
     void    setReportPerformanceInterval( F32 interval )        { mReportPerformanceStatInterval = interval;    };
-    void    setReportPerformanceDuration( F32 seconds );
+    void    setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS );
     void    setProcessName(const std::string& process_name) { mProcessName = process_name; }
     void    setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
 
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 1b93c219824c5974499dc6057768458174fd36fc..900652d06d2403d773d3bafbcac0a7db3c94da1f 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -178,8 +178,8 @@ LLImageJ2C::LLImageJ2C() : 	LLImageFormatted(IMG_CODEC_J2C),
 							mMaxBytes(0),
 							mRawDiscardLevel(-1),
 							mRate(0.0f),
-							mReversible(FALSE)
-	
+							mReversible(FALSE),
+							mAreaUsedForDataSizeCalcs(0)
 {
 	//We assume here that if we wanted to create via
 	//a dynamic library that the approriate open calls were made
@@ -195,6 +195,12 @@ LLImageJ2C::LLImageJ2C() : 	LLImageFormatted(IMG_CODEC_J2C),
 	}
 
 	mImpl = j2cimpl_create_func();
+
+	// Clear data size table
+	for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
+	{	// Array size is MAX_DISCARD_LEVEL+1
+		mDataSizes[i] = 0;
+	}
 }
 
 // virtual
@@ -367,9 +373,45 @@ S32 LLImageJ2C::calcHeaderSize()
 	return calcHeaderSizeJ2C();
 }
 
+
+// calcDataSize() returns how many bytes to read 
+// to load discard_level (including header and higher discard levels)
 S32 LLImageJ2C::calcDataSize(S32 discard_level)
 {
-	return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
+	discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL);
+
+	if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth()) 
+		|| mDataSizes[0] == 0)
+	{
+		mAreaUsedForDataSizeCalcs = getHeight() * getWidth();
+		
+		S32 level = MAX_DISCARD_LEVEL;	// Start at the highest discard
+		while ( level >= 0 )
+		{
+			mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+			level--;
+		}
+
+		/* This is technically a more correct way to calculate the size required
+		   for each discard level, since they should include the size needed for
+		   lower levels.   Unfortunately, this doesn't work well and will lead to 
+		   download stalls.  The true correct way is to parse the header.  This will
+		   all go away with http textures at some point.
+
+		// Calculate the size for each discard level.   Lower levels (higher quality)
+		// contain the cumulative size of higher levels		
+		S32 total_size = calcHeaderSizeJ2C();
+
+		S32 level = MAX_DISCARD_LEVEL;	// Start at the highest discard
+		while ( level >= 0 )
+		{	// Add in this discard level and all before it
+			total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+			mDataSizes[level] = total_size;
+			level--;
+		}
+		*/
+	}
+	return mDataSizes[discard_level];
 }
 
 S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index 23f6ef5fd10b8a7a82cc4283143acd990eaf51e8..55df7f44296e537ec9cf50c796a7831ed3b48a21 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -87,6 +87,10 @@ class LLImageJ2C : public LLImageFormatted
 	void updateRawDiscardLevel();
 
 	S32 mMaxBytes; // Maximum number of bytes of data to use...
+	
+	S32 mDataSizes[MAX_DISCARD_LEVEL+1];		// Size of data required to reach a given level
+	U32 mAreaUsedForDataSizeCalcs;				// Height * width used to calculate mDataSizes
+
 	S8  mRawDiscardLevel;
 	F32 mRate;
 	BOOL mReversible;
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 328ed4588bf847a1ef29a37c47dd1f0114c47037..2a27f3fc8da4cd11487ab9016cf745db7e5fcd6b 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -277,6 +277,17 @@ BOOL LLPermissions::setOwnerAndGroup(
 	return allowed;
 }
 
+//Fix for DEV-33917, last owner isn't used much and has little impact on
+//permissions so it's reasonably safe to do this, however, for now, 
+//limiting the functionality of this routine to objects which are 
+//group owned.
+void LLPermissions::setLastOwner(const LLUUID& last_owner)
+{
+	if (isGroupOwned())
+		mLastOwner = last_owner;
+}
+
+ 
 // only call this if you know what you're doing
 // there are usually perm-bit consequences when the 
 // ownerhsip changes
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 5587f8c3c83d38c7611772a38a5e81810888c08a..9280629e0c69c626ecc06736ed1629a2b7bc4067 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -229,6 +229,10 @@ class LLPermissions : public LLReflective
 	// ownerhsip changes
 	void yesReallySetOwner(const LLUUID& owner, bool group_owned);
 
+	// Last owner doesn't have much in the way of permissions so it's 
+	//not too dangerous to do this. 
+	void setLastOwner(const LLUUID& last_owner);
+
 	// saves last owner, sets owner to uuid null, sets group
 	// owned. group_id must be the group of the object (that's who it
 	// is being deeded to) and the object must be group
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index cfd6183ec44cc3f118b16647b028fded6b811b9e..fdcc19d657b6ee0144121cdbd411fc82b22b6513 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -121,7 +121,7 @@ void	LLQuaternion::quantize16(F32 lower, F32 upper)
 	mQ[VZ] = z;
 	mQ[VS] = s;
 
-	normQuat();
+	normalize();
 }
 
 void	LLQuaternion::quantize8(F32 lower, F32 upper)
@@ -131,7 +131,7 @@ void	LLQuaternion::quantize8(F32 lower, F32 upper)
 	mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
 	mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
 
-	normQuat();
+	normalize();
 }
 
 // LLVector3 Magnitude and Normalization Functions
@@ -346,7 +346,7 @@ const LLQuaternion&	LLQuaternion::setQuat(const LLMatrix4 &mat)
 //    mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ);
 //#endif
 //
-//	normQuat();
+//	normalize();
 //	return (*this);
 }
 
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index 5db9c5be2ed5167b82d85db3d1847d3fb6f5d31e..0769f29f235d747a3a36ef74d34027fcb6a659e9 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -469,20 +469,30 @@ inline const LLQuaternion&	operator*=(LLQuaternion &a, const LLQuaternion &b)
 	return a;
 }
 
+const F32 ONE_PART_IN_A_MILLION = 0.000001f;
+
 inline F32	LLQuaternion::normalize()
 {
 	F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
 
 	if (mag > FP_MAG_THRESHOLD)
 	{
-		F32 oomag = 1.f/mag;
-		mQ[VX] *= oomag;
-		mQ[VY] *= oomag;
-		mQ[VZ] *= oomag;
-		mQ[VS] *= oomag;
+		// Floating point error can prevent some quaternions from achieving
+		// exact unity length.  When trying to renormalize such quaternions we
+		// can oscillate between multiple quantized states.  To prevent such
+		// drifts we only renomalize if the length is far enough from unity.
+		if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+		{
+			F32 oomag = 1.f/mag;
+			mQ[VX] *= oomag;
+			mQ[VY] *= oomag;
+			mQ[VZ] *= oomag;
+			mQ[VS] *= oomag;
+		}
 	}
 	else
 	{
+		// we were given a very bad quaternion so we set it to identity
 		mQ[VX] = 0.f;
 		mQ[VY] = 0.f;
 		mQ[VZ] = 0.f;
@@ -499,11 +509,15 @@ inline F32	LLQuaternion::normQuat()
 
 	if (mag > FP_MAG_THRESHOLD)
 	{
-		F32 oomag = 1.f/mag;
-		mQ[VX] *= oomag;
-		mQ[VY] *= oomag;
-		mQ[VZ] *= oomag;
-		mQ[VS] *= oomag;
+		if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+		{
+			// only renormalize if length not close enough to 1.0 already
+			F32 oomag = 1.f/mag;
+			mQ[VX] *= oomag;
+			mQ[VY] *= oomag;
+			mQ[VZ] *= oomag;
+			mQ[VS] *= oomag;
+		}
 	}
 	else
 	{
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 88f83ba78ef5d847e76e5186a362dc991df7c1e7..81e518cf6eee713256ef20d51ffcbf35636f0082 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -221,6 +221,7 @@ IF (NOT LINUX AND VIEWER)
       # llhttpclientadapter.cpp
       lltrustedmessageservice.cpp
       lltemplatemessagedispatcher.cpp
+      llregionpresenceverifier.cpp
       )
     LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
     
@@ -228,3 +229,4 @@ IF (NOT LINUX AND VIEWER)
     # Don't make llmessage depend on llsdmessage_test because ADD_COMM_BUILD_TEST depends on llmessage!
     # ADD_COMM_BUILD_TEST(llsdmessage "" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py")
 ENDIF (NOT LINUX AND VIEWER)
+
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 799bc83e2028bae719e38b8c2b3aa1ccbed448c7..82186fc50371f23fdb4d46c2a6df8246642dbfed 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -76,11 +76,13 @@ class LLCacheNameEntry
 	LLCacheNameEntry();
 
 public:
-	bool mIsGroup;
-	U32 mCreateTime;	// unix time_t
-	std::string mFirstName;
-	std::string mLastName;
-	std::string mGroupName;
+	bool isUnknown()			{ return (mFirstName.empty()
+										  || mFirstName == std::string("(???)"));	};
+
+	bool mIsGroup;				// true if this is a group ID/name
+	U32 mCreateTime;			// unix time_t
+	std::string mFirstName;		// Doubles as the group name
+	std::string mLastName;		// Will be "" for groups
 };
 
 LLCacheNameEntry::LLCacheNameEntry()
@@ -162,7 +164,7 @@ void ReplySender::send(const LLUUID& id,
 	mMsg->addUUIDFast(_PREHASH_ID, id);
 	if(mCurrIsGroup)
 	{
-		mMsg->addStringFast(_PREHASH_GroupName, entry.mGroupName);
+		mMsg->addStringFast(_PREHASH_GroupName, entry.mFirstName);
 	}
 	else
 	{
@@ -222,6 +224,7 @@ class LLCacheName::Impl
 	void processPendingReplies();
 	void sendRequest(const char* msg_name, const AskQueue& queue);
 	bool isRequestPending(const LLUUID& id);
+	void makeNameRequestForID(const LLUUID& id, bool isGroup, LLHost & fromHost);
 
 	// Message system callbacks.
 	void processUUIDRequest(LLMessageSystem* msg, bool isGroup);
@@ -389,6 +392,7 @@ void LLCacheName::importFile(LLFILE* fp)
 		entry->mCreateTime = create_time;
 		entry->mFirstName = firstname;
 		entry->mLastName = lastname;
+		//llinfos << "Adding entry from file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;
 		impl.mCache[id] = entry;
 
 		count++;
@@ -425,6 +429,7 @@ bool LLCacheName::importFile(std::istream& istr)
 		entry->mCreateTime = ctime;
 		entry->mFirstName = agent[FIRST].asString();
 		entry->mLastName = agent[LAST].asString();
+		//llinfos << "Adding name entry from XML file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;
 		impl.mCache[id] = entry;
 
 		++count;
@@ -445,7 +450,9 @@ bool LLCacheName::importFile(std::istream& istr)
 		LLCacheNameEntry* entry = new LLCacheNameEntry();
 		entry->mIsGroup = true;
 		entry->mCreateTime = ctime;
-		entry->mGroupName = group[NAME].asString();
+		entry->mFirstName = group[NAME].asString();
+		entry->mLastName = "";
+		//llinfos << "Adding group entry from XML file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;
 		impl.mCache[id] = entry;
 		++count;
 	}
@@ -463,32 +470,32 @@ void LLCacheName::exportFile(std::ostream& ostr)
 		// Only write entries for which we have valid data.
 		LLCacheNameEntry* entry = iter->second;
 		if(!entry
-		   || (std::string::npos != entry->mFirstName.find('?'))
-		   || (std::string::npos != entry->mGroupName.find('?')))
-		{
+		   || entry->isUnknown())
+		{	// No entry, or user or group name is unknown
 			continue;
 		}
 
 		// store it
 		LLUUID id = iter->first;
 		std::string id_str = id.asString();
-		if(!entry->mFirstName.empty() && !entry->mLastName.empty())
-		{
+		if(entry->mIsGroup)
+		{	// Save group name and ID
+			data[GROUPS][id_str][NAME] = entry->mFirstName;
+			data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime;
+		}
+		else if(!entry->mLastName.empty())
+		{	// Save user names and ID
 			data[AGENTS][id_str][FIRST] = entry->mFirstName;
 			data[AGENTS][id_str][LAST] = entry->mLastName;
 			data[AGENTS][id_str][CTIME] = (S32)entry->mCreateTime;
 		}
-		else if(entry->mIsGroup && !entry->mGroupName.empty())
-		{
-			data[GROUPS][id_str][NAME] = entry->mGroupName;
-			data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime;
-		}
 	}
 
 	LLSDSerialize::toPrettyXML(data, ostr);
 }
 
 
+// DO NOT CALL THIS FOR GROUP NAMES
 BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last)
 {
 	if(id.isNull())
@@ -511,11 +518,11 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
 		last.clear();
 		if (!impl.isRequestPending(id))
 		{
+			//llinfos << "**** adding name req for " << id << llendl;
 			impl.mAskNameQueue.insert(id);
 		}	
-		return FALSE;
 	}
-
+	return FALSE;
 }
 
 BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
@@ -535,7 +542,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
 	}
 
 	LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache,id);
-	if (entry && entry->mGroupName.empty())
+	if (entry && entry->mFirstName.empty())
 	{
 		// COUNTER-HACK to combat James' HACK in exportFile()...
 		// this group name was loaded from a name cache that did not
@@ -546,7 +553,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
 
 	if (entry)
 	{
-		group = entry->mGroupName;
+		group = entry->mFirstName;
 		return TRUE;
 	}
 	else 
@@ -562,7 +569,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
 
 // TODO: Make the cache name callback take a SINGLE std::string,
 // not a separate first and last name.
-void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data)
+void LLCacheName::getNameFromUUID(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data)
 {
 	if(id.isNull())
 	{
@@ -573,15 +580,8 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb
 	LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
 	if (entry)
 	{
-		// id found in map therefore we can call the callback immediately.
-		if (entry->mIsGroup)
-		{
-			callback(id, entry->mGroupName, "", entry->mIsGroup, user_data);
-		}
-		else
-		{
-			callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data);
-		}
+		// id found in map therefore we can call the callback immediately.  mLastName will be empty for groups
+		callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data);
 	}
 	else
 	{
@@ -590,13 +590,17 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb
 		{
 			if (is_group)
 			{
+				//llinfos << "Group queued for " << id << llendl;
 				impl.mAskGroupQueue.insert(id);
 			}
 			else
 			{
+				//llinfos << "Name queued for " << id << llendl;
 				impl.mAskNameQueue.insert(id);
 			}
 		}
+
+		// There may be multiple replies for the same ID request
 		impl.mReplyQueue.push_back(PendingReply(id, callback, user_data));
 	}
 }
@@ -661,7 +665,7 @@ void LLCacheName::dump()
 		{
 			llinfos
 				<< iter->first << " = (group) "
-				<< entry->mGroupName
+				<< entry->mFirstName
 				<< " @ " << entry->mCreateTime
 				<< llendl;
 		}
@@ -715,17 +719,7 @@ void LLCacheName::Impl::processPendingReplies()
 
 		if (it->mCallback)
 		{
-			if (!entry->mIsGroup)
-			{
-				(it->mCallback)(it->mID,
-					entry->mFirstName, entry->mLastName,
-					FALSE, it->mData);
-			}
-			else {
-				(it->mCallback)(it->mID,
-					entry->mGroupName, "",
-					TRUE, it->mData);
-			}
+			(it->mCallback)(it->mID, entry->mFirstName, entry->mLastName, entry->mIsGroup, it->mData);
 		}
 	}
 
@@ -768,10 +762,12 @@ void LLCacheName::Impl::sendRequest(
 		if(start_new_message)
 		{
 			start_new_message = false;
+			//llinfos << "newMessageFast : " << msg_name << llendl;
 			mMsg->newMessageFast(msg_name);
 		}
 		mMsg->nextBlockFast(_PREHASH_UUIDNameBlock);
 		mMsg->addUUIDFast(_PREHASH_ID, (*it));
+		//llinfos << " asking for ID: " << (*it) << llendl;
 
 		if(mMsg->isSendFullFast(_PREHASH_UUIDNameBlock))
 		{
@@ -837,38 +833,102 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)
 		{
 			if (isGroup != entry->mIsGroup)
 			{
-				llwarns << "LLCacheName - Asked for "
-						<< (isGroup ? "group" : "user") << " name, "
-						<< "but found "
-						<< (entry->mIsGroup ? "group" : "user")
-						<< ": " << id << llendl;
+				if (entry->isUnknown())
+				{
+					Cache::iterator doomediter = mCache.find(id);
+					if (doomediter != mCache.end())
+					{	// Kill existing unknown entry
+						llwarns << "LLCacheName - Asked for "
+								<< (isGroup ? "group" : "user") << " name, "
+								<< "but found unknown "
+								<< (entry->mIsGroup ? "group" : "user")
+								<< " entry for: " << id 
+								<< ", deleting bad entry"
+								<< llendl;
+
+						delete entry;
+						entry = NULL;
+						mCache.erase(doomediter);
+
+						// Request it with (hopefully) the correct type
+						makeNameRequestForID(id,isGroup,fromHost);
+					}
+				}
+				else if (isGroup)
+				{
+					llwarns << "LLCacheName - Asked for group name, but found user: "
+							<< id 
+							<< " named " 
+							<< entry->mFirstName << " " << entry->mLastName 
+							<< llendl;
+				}
+				else
+				{
+					llwarns << "LLCacheName - Asked for user name, but found group: "
+							<< id 
+							<< " named " 
+							<< entry->mFirstName
+							<< llendl;
+				}
 			}
 			else
 			{
 				// ...it's in the cache, so send it as the reply
 				sender.send(id, *entry, fromHost);
-			}
-		}
-		else
-		{
-			if (!isRequestPending(id))
-			{
+
+				/*
 				if (isGroup)
 				{
-					mAskGroupQueue.insert(id);
+					llinfos << "Group ID " << id 
+						<< " name " << entry->mFirstName
+						<< " was already in cache" << llendl;
 				}
 				else
 				{
-					mAskNameQueue.insert(id);
+					llinfos << "Agent ID " << id 
+						<< " name " << entry->mFirstName << " " << entry->mLastName 
+						<< " was already in cache" << llendl;
 				}
+				*/
 			}
-			
-			mReplyQueue.push_back(PendingReply(id, fromHost));
+		}
+		else
+		{	/*
+			if (isGroup)
+			{
+				llinfos << "Group ID " << id << " is not in cache" << llendl;
+			}
+			else
+			{
+				llinfos << "Agent ID " << id << " is not in cache" << llendl;
+			}
+			*/
+			makeNameRequestForID(id,isGroup,fromHost);
 		}
 	}
 }
 
 
+void LLCacheName::Impl::makeNameRequestForID(const LLUUID& id, bool isGroup, LLHost & fromHost)
+{
+	if (!isRequestPending(id))
+	{
+		if (isGroup)
+		{
+			//llinfos << "Adding group request for " << id << llendl;
+			mAskGroupQueue.insert(id);
+		}
+		else
+		{
+			//llinfos << "Adding name request for " << id << llendl;
+			mAskNameQueue.insert(id);
+		}
+	}
+	
+	// There may be multiple replys for the same ID request
+	mReplyQueue.push_back(PendingReply(id, fromHost));
+}
+
 
 void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
 {
@@ -878,35 +938,53 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
 		LLUUID id;
 		msg->getUUIDFast(_PREHASH_UUIDNameBlock, _PREHASH_ID, id, i);
 		LLCacheNameEntry* entry = get_ptr_in_map(mCache, id);
+		bool add_new_entry_to_cache = false;
 		if (!entry)
 		{
 			entry = new LLCacheNameEntry;
-			mCache[id] = entry;
+			add_new_entry_to_cache = true;
 		}
 
+		// Remove ID from pending queue
 		mPendingQueue.erase(id);
 
-		entry->mIsGroup = isGroup;
-		entry->mCreateTime = (U32)time(NULL);
-		if (!isGroup)
-		{
-			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, entry->mFirstName, i);
-			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName,  entry->mLastName, i);
+		std::string first_name;
+		std::string last_name;
+		if (isGroup)
+		{	// Group
+			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, first_name, i);
+			LLStringFn::replace_ascii_controlchars(first_name, LL_UNKNOWN_CHAR);
 		}
 		else
-		{	// is group
-			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, entry->mGroupName, i);
-			LLStringFn::replace_ascii_controlchars(entry->mGroupName, LL_UNKNOWN_CHAR);
+		{	// User
+			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, first_name, i);
+			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, last_name, i);
 		}
-
-		if (!isGroup)
-		{
-			notifyObservers(id, entry->mFirstName, entry->mLastName, FALSE);
+	
+		if (!add_new_entry_to_cache &&
+			(entry->mFirstName != first_name ||
+				entry->mLastName != last_name ||
+				entry->mIsGroup != isGroup))
+		{	// Hmmm, we already had an different entry for this ID.  Let's see what happened...
+			llwarns << "Replacing existing entry in name cache for id " << id
+				<< " first name was " << entry->mFirstName << ", now " << first_name
+				<< " last name was " << entry->mLastName << ", now " << last_name
+				<< " group flag was " << (S32) entry->mIsGroup << ", now " << (S32) isGroup
+				<< llendl;
 		}
-		else
+
+		entry->mFirstName = first_name;
+		entry->mLastName = last_name;
+		entry->mIsGroup = isGroup;
+		entry->mCreateTime = (U32)time(NULL);
+
+		if (add_new_entry_to_cache)
 		{
-			notifyObservers(id, entry->mGroupName, "", TRUE);
+			//llinfos << "Adding entry for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;
+			mCache[id] = entry;
 		}
+
+		notifyObservers(id, entry->mFirstName, entry->mLastName, isGroup);
 	}
 }
 
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 2757b86a7c3468f99fe15cbe955bfb3575a95174..bfa116ad4a6baff44e25a9951625be30fee1fa92 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -89,12 +89,8 @@ class LLCacheName
 	// If the data is currently available, may call the callback immediatly
 	// otherwise, will request the data, and will call the callback when
 	// available.  There is no garuntee the callback will ever be called.
-	void get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL);
+	void getNameFromUUID(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL);
 	
-	// LEGACY
-	void getName(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL)
-			{ get(id, FALSE, callback, user_data); }
-
 	// This method needs to be called from time to time to send out
 	// requests.
 	void processPending();
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index bbb56960df8e4846d3544916571508a3dcbf3a0c..5236a52164e18973fbd5c4a357a276b9b65f9ecd 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientadapter.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index d5f3aeaf2cf06bdeab1137b6a15447e2248a3d8f..c489dca32d4feb57138eac62dede1d4c6a7062d0 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientadepter.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 1f13d46447cedde8117e02f1046426d1a71c8cb1..61826cc4b4dba66fea42792a9e482b0388e78560 100644
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientinterface.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
index 40826663398cc84d608a60de143aa867ea48432d..d98d891563ed61f4df24441f847eaa94dd6769d7 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llmessagesenderinterface.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
index 552cf4cbdb68ccf8c7652e51d7d373a35c4d0372..08c12f90dac6169a9c64e79a3995a76dc1409123 100644
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llregionpresenceverifier.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -25,11 +25,40 @@
 #include "net.h"
 #include "message.h"
 
+namespace boost
+{
+	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
+	{
+		++p->mReferenceCount;
+	}
+	
+	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
+	{
+		if(p && 0 == --p->mReferenceCount)
+		{
+			delete p;
+		}
+	}
+};
 
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+LLRegionPresenceVerifier::Response::~Response()
 {
 }
 
+LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
+														   uri,
+														   ResponsePtr data,
+														   S32 retry_count) :
+	mUri(uri),
+	mSharedData(data),
+	mRetryCount(retry_count)
+{
+}
+
+//virtual
+LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
+{
+}
 
 void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
 {
@@ -42,26 +71,32 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
 
 	std::stringstream uri;
 	uri << "http://" << destination.getString() << "/state/basic/";
-	mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content));
+	mSharedData->getHttpClient().get(
+		uri.str(),
+		new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
 }
 
-void LLRegionPresenceVerifier::RegionResponder::completed(
-	U32 status,
-	const std::string& reason,
-	const LLSD& content)
+void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
+													 const std::string& reason)
 {
-	LLHTTPClient::Responder::completed(status, reason, content);
-	
-	mSharedData->onCompletedRegionRequest();
+	// TODO: babbage: distinguish between region presence service and
+	// region verification errors?
+	mSharedData->onRegionVerificationFailed();
 }
 
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content)
+LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
+	S32 retry_count):
+	mUri(uri),
+	mSharedData(data),
+	mContent(content),
+	mRetryCount(retry_count) 
 {
 }
 
-
-
+//virtual
+LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
+{
+}
 
 void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
 {
@@ -76,13 +111,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD&
 	{
 		mSharedData->onRegionVerified(mContent);
 	}
-	else if (mSharedData->shouldRetry())
+	else if (mRetryCount > 0)
 	{
 		retry();
 	}
 	else
 	{
-		llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl;
+		llwarns << "Simulator verification failed. Region: " << mUri << llendl;
+		mSharedData->onRegionVerificationFailed();
 	}
 }
 
@@ -90,13 +126,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
 {
 	LLSD headers;
 	headers["Cache-Control"] = "no-cache, max-age=0";
-	llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl;
-	mSharedData->decrementRetries();
-	mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers);
+	llinfos << "Requesting region information, get uncached for region "
+			<< mUri << llendl;
+	--mRetryCount;
+	mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
 }
 
 void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
 {
-	retry();
+	if(mRetryCount > 0)
+	{
+		retry();
+	}
+	else
+	{
+		llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl;
+		mSharedData->onRegionVerificationFailed();
+	}
 }
-
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
index d1de608ec6098b8ad6ec22e4309667cafa7fd321..f11eeef50ca1cff21b428753e9f94d2e40cfa9d2 100644
--- a/indra/llmessage/llregionpresenceverifier.h
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llregionpresenceverifier.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -26,7 +26,7 @@
 #include "llhttpclient.h"
 #include <string>
 #include "llsd.h"
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
 
 class LLHTTPClientInterface;
 
@@ -36,48 +36,57 @@ class LLRegionPresenceVerifier
 	class Response
 	{
 	public:
-		virtual ~Response() {}
+		virtual ~Response() = 0;
 
 		virtual bool checkValidity(const LLSD& content) const = 0;
 		virtual void onRegionVerified(const LLSD& region_details) = 0;
-
-		virtual void decrementRetries() = 0;
+		virtual void onRegionVerificationFailed() = 0;
 
 		virtual LLHTTPClientInterface& getHttpClient() = 0;
-		virtual std::string getRegionUri() const = 0;
-		virtual bool shouldRetry() const = 0;
 
-		virtual void onCompletedRegionRequest() {}
+	public: /* but not really -- don't touch this */
+		U32 mReferenceCount;		
 	};
 
-	typedef boost::shared_ptr<Response> ResponsePtr;
+	typedef boost::intrusive_ptr<Response> ResponsePtr;
 
 	class RegionResponder : public LLHTTPClient::Responder
 	{
 	public:
-		RegionResponder(ResponsePtr data);
+		RegionResponder(const std::string& uri, ResponsePtr data,
+						S32 retry_count);
+		virtual ~RegionResponder(); 
 		virtual void result(const LLSD& content);
-		virtual void completed(
-			U32 status,
-			const std::string& reason,
-			const LLSD& content);
+		virtual void error(U32 status, const std::string& reason);
 
 	private:
 		ResponsePtr mSharedData;
+		std::string mUri;
+		S32 mRetryCount;
 	};
 
 	class VerifiedDestinationResponder : public LLHTTPClient::Responder
 	{
 	public:
-		VerifiedDestinationResponder(ResponsePtr data, const LLSD& content);
+		VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
+									 const LLSD& content, S32 retry_count);
+		virtual ~VerifiedDestinationResponder();
 		virtual void result(const LLSD& content);
 		virtual void error(U32 status, const std::string& reason);
+		
 	private:
 		void retry();
 		ResponsePtr mSharedData;
 		LLSD mContent;
+		std::string mUri;
+		S32 mRetryCount;
 	};
 };
 
+namespace boost
+{
+	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
+	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
+};
 
 #endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
index 615eff405d4e61d05da495fbc9855bc697f4e198..da6d1c84a84837b5ffa724619ff314e3727dd335 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llstoredmessage.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index e817f19bd2c68c8bf97a063f8e7b5b5b896474f7..6a27698b038427cae7306a15cb7ea7a064e46796 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llstoredmessage.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp
index 70279a3c62d033ab8eab74103eac4d93bf548bdf..0872efba508ff8d427f557881356de7bf4320fc6 100644
--- a/indra/llmessage/llthrottle.cpp
+++ b/indra/llmessage/llthrottle.cpp
@@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
 	return changed;
 }
 
+// Return bits available in the channel
+S32		LLThrottleGroup::getAvailable(S32 throttle_cat)
+{
+	S32 retval = 0;
+
+	F32 category_bps = mCurrentBPS[throttle_cat];
+	F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+	// use a temporary bits_available
+	// since we don't want to change mBitsAvailable every time
+	F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
+	F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
+
+	if (bits_available >= lookahead_bits)
+	{
+		retval = (S32) gThrottleMaximumBPS[throttle_cat];
+	}
+	else 
+	{
+		retval = (S32) bits_available;
+	}
+	
+	return retval;
+}
+
 
 BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
 {
diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h
index 7d1679beb232ead9c23259f0bab6799fdca3d9f8..47a7c653b23b1679a73d845c9da4a4ec73172468 100644
--- a/indra/llmessage/llthrottle.h
+++ b/indra/llmessage/llthrottle.h
@@ -84,6 +84,8 @@ class LLThrottleGroup
 	BOOL	dynamicAdjust();		// Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred
 	BOOL	setNominalBPS(F32* throttle_vec);				// TRUE if any value was different, resets adjustment system if was different
 
+	S32		getAvailable(S32 throttle_cat);					// Return bits available in the channel
+
 	void packThrottle(LLDataPacker &dp) const;
 	void unpackThrottle(LLDataPacker &dp);
 public:
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 3ab8057abb0951576a5f4d1dea241e404c65e4c3..81b7761ed5fdec3b2263ab3c6c6da23d2f471f31 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
  * String constants
  */
 const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
+const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
 
 
 static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
@@ -247,7 +248,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	//llinfos << "LLURLRequest::process_impl()" << llendl;
-	if(!buffer) return STATUS_ERROR;
+	if (!buffer) return STATUS_ERROR;
+	
+	// we're still waiting or prcessing, check how many
+	// bytes we have accumulated.
+	const S32 MIN_ACCUMULATION = 100000;
+	if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
+	{
+		 // This is a pretty sloppy calculation, but this
+		 // tries to make the gross assumption that if data
+		 // is coming in at 56kb/s, then this transfer will
+		 // probably succeed. So, if we're accumlated
+		 // 100,000 bytes (MIN_ACCUMULATION) then let's
+		 // give this client another 2s to complete.
+		 const F32 TIMEOUT_ADJUSTMENT = 2.0f;
+		 mDetail->mByteAccumulator = 0;
+		 pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
+		 lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl;
+		 if (mState == STATE_INITIALIZED)
+		 {
+			  llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl;
+		 }
+	}
+
 	switch(mState)
 	{
 	case STATE_INITIALIZED:
@@ -286,27 +309,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 			bool newmsg = mDetail->mCurlRequest->getResult(&result);
 			if(!newmsg)
 			{
-				// we're still waiting or prcessing, check how many
-				// bytes we have accumulated.
-				const S32 MIN_ACCUMULATION = 100000;
-				if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
-				{
-					// This is a pretty sloppy calculation, but this
-					// tries to make the gross assumption that if data
-					// is coming in at 56kb/s, then this transfer will
-					// probably succeed. So, if we're accumlated
-					// 100,000 bytes (MIN_ACCUMULATION) then let's
-					// give this client another 2s to complete.
-					const F32 TIMEOUT_ADJUSTMENT = 2.0f;
-					mDetail->mByteAccumulator = 0;
-					pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
-				}
-
 				// keep processing
 				break;
 			}
 
 			mState = STATE_HAVE_RESPONSE;
+			context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+			context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+			lldebugs << this << "Setting context to " << context << llendl;
 			switch(result)
 			{
 				case CURLE_OK:
@@ -353,10 +363,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 		// we already stuffed everything into channel in in the curl
 		// callback, so we are done.
 		eos = true;
+		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+		lldebugs << this << "Setting context to " << context << llendl;
 		return STATUS_DONE;
 
 	default:
 		PUMP_DEBUG;
+		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+		lldebugs << this << "Setting context to " << context << llendl;
 		return STATUS_ERROR;
 	}
 }
@@ -369,6 +385,8 @@ void LLURLRequest::initialize()
 	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
 	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
 	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
+	mRequestTransferedBytes = 0;
+	mResponseTransferedBytes = 0;
 }
 
 bool LLURLRequest::configure()
@@ -471,6 +489,7 @@ size_t LLURLRequest::downCallback(
 		req->mDetail->mChannels.out(),
 		(U8*)data,
 		bytes);
+	req->mResponseTransferedBytes += bytes;
 	req->mDetail->mByteAccumulator += bytes;
 	return bytes;
 }
@@ -494,6 +513,7 @@ size_t LLURLRequest::upCallback(
 		req->mDetail->mLastRead,
 		(U8*)data,
 		bytes);
+	req->mRequestTransferedBytes += bytes;
 	return bytes;
 }
 
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 86ef71f085b7048386f68a9c086681987d9d5b21..cb3c46644062cbb26530cc4fbc4e13c90a99309e 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -45,6 +45,12 @@
 #include "llchainio.h"
 #include "llerror.h"
 
+
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_DEST_URI_SD_LABEL;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_TRANSFERED_BYTES;
+
 class LLURLRequestDetail;
 
 class LLURLRequestComplete;
@@ -208,6 +214,8 @@ class LLURLRequest : public LLIOPipe
 	ERequestAction mAction;
 	LLURLRequestDetail* mDetail;
 	LLIOPipe::ptr_t mCompletionCallback;
+	 S32 mRequestTransferedBytes;
+	 S32 mResponseTransferedBytes;
 
 private:
 	/** 
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b7602ef15ca5dd04ae725d3e21ffb2d29449f11c
--- /dev/null
+++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
@@ -0,0 +1,111 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../test/lltut.h"
+#include "llregionpresenceverifier.h"
+#include "llcurl_stub.cpp"
+#include "llhost.cpp"
+#include "net.cpp"
+#include "lltesthttpclientadapter.cpp"
+
+class LLTestResponse : public LLRegionPresenceVerifier::Response
+{
+public:
+
+	virtual bool checkValidity(const LLSD& content) const
+	{
+		return true;
+	}
+
+	virtual void onRegionVerified(const LLSD& region_details)
+	{
+	}
+
+	virtual void onRegionVerificationFailed()
+	{
+	}
+	
+	virtual LLHTTPClientInterface& getHttpClient()
+	{
+		return mHttpInterface;
+	}
+
+	LLTestHTTPClientAdapter mHttpInterface;
+};
+
+namespace tut
+{
+	struct LLRegionPresenceVerifierData
+	{
+		LLRegionPresenceVerifierData() :
+			mResponse(new LLTestResponse()),
+			mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
+					   LLSD(), 3)
+		{
+		}
+		
+		LLTestResponse* mResponse;
+		LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
+	};
+
+	typedef test_group<LLRegionPresenceVerifierData> factory;
+	typedef factory::object object;
+}
+
+namespace
+{
+	tut::factory tf("LLRegionPresenceVerifier test");
+}
+
+namespace tut
+{
+	// Test that VerifiedDestinationResponder does retry
+    // on error when shouldRetry returns true.
+	template<> template<>
+	void object::test<1>()
+	{
+		mResponder.error(500, "Internal server error");
+		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
+	}
+
+	// Test that VerifiedDestinationResponder only retries
+	// on error until shouldRetry returns false.
+	template<> template<>
+	void object::test<2>()
+	{
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
+	}
+}
+
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index c9632ebdad8ba22d280d29422e78e1c129ebfc82..c1dde329930df272cb2ab0df78bfa3d4cbe0d129 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -386,8 +386,18 @@ void LLPrimTextureList::setSize(S32 new_size)
 		mEntryList.resize(new_size);
 		for (S32 index = current_size; index < new_size; ++index)
 		{
-			LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
-			mEntryList[index] = new_entry;
+			if (current_size > 0
+				&& mEntryList[current_size - 1])
+			{
+				// copy the last valid entry for the new one
+				mEntryList[index] = mEntryList[current_size - 1]->newCopy();
+			}
+			else
+			{
+				// no valid enries to copy, so we new one up
+				LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
+				mEntryList[index] = new_entry;
+			}
 		}
 	}
 	else if (new_size < current_size)
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index e231002a527c46f3ecedd1db901884efd1db4f23..452594c7e7af037a790f1e9327e75aac3a9cc20d 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -61,7 +61,7 @@ class LLPidLockFile
 			mSaving(FALSE), mWaiting(FALSE), 
 			mClean(TRUE), mPID(getpid())
 		{
-			mLockName = gDirUtilp->getTempDir() + "/savelock";
+			mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
 		}
 		bool requestLock(LLNameTable<void *> *name_table, bool autosave,
 						bool force_immediate=FALSE, F32 timeout=300.0);
diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h
index ba2c46bef253bf3a0fa685b7f49b8e26710159dc..a54ebd5831a122350e28e834443a8737a12ac562 100644
--- a/indra/lscript/lscript_byteformat.h
+++ b/indra/lscript/lscript_byteformat.h
@@ -556,7 +556,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
 // http_request string constants
 extern const char* URL_REQUEST_GRANTED;
 extern const char* URL_REQUEST_DENIED;
-extern const U64 LSL_HTTP_REQUEST_TIMEOUT;
+extern const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC;
 
 #endif
 
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index e291d4c6f8692301aef0172cf282a0ed4349a6f9..a15f1fee1186f235fe12d00ff25a7f028232f09f 100644
--- a/indra/lscript/lscript_compile/lscript_tree.cpp
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -631,9 +631,7 @@ static void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetTy
 		switch(targetType)
 		{
 		case LST_INTEGER:
-			//fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
-			fprintf(fp, "conv.i4\n"); // TODO replace this line with the above
-			// we the entire grid is > 1.25.1
+			fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
 			break;
 		case LST_STRING:
 			fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ToString(float32)\n");
@@ -8375,10 +8373,18 @@ void LLScriptStateChange::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp
 			chunk->addInteger(mIdentifier->mScopeEntry->mCount);
 		}
 		break;
+	case LSCP_TYPE:
+		mReturnType = basetype;
+		break;
 	case LSCP_EMIT_CIL_ASSEMBLY:
 		fprintf(fp, "ldarg.0\n");
 		fprintf(fp, "ldstr \"%s\"\n", mIdentifier->mName);
 		fprintf(fp, "call instance void class [LslUserScript]LindenLab.SecondLife.LslUserScript::ChangeState(string)\n");
+		// We are doing a state change. In the LSL interpreter, this is basically a longjmp. We emulate it
+		// here using a call to the ChangeState followed by a short cut return of the current method. To
+		// maintain type safety we need to push an arbitrary variable of the current method's return type
+		// onto the stack before returning. This will be ignored and discarded.
+		print_cil_init_variable(fp, mReturnType);
 		fprintf(fp, "ret\n");
 		break;
 	default:
@@ -8793,7 +8799,8 @@ void LLScriptIf::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass p
 		}
 		break;
 	case LSCP_PRUNE:
-		prunearg = FALSE;
+		prunearg = TRUE;
+		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 		break;
 	case LSCP_TYPE:
 		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
@@ -8979,7 +8986,8 @@ void LLScriptFor::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass
 		}
 		break;
 	case LSCP_PRUNE:
-		prunearg = FALSE;
+		prunearg = TRUE;
+		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 		break;
 	case LSCP_TYPE:
 		if(mSequence)
@@ -9083,7 +9091,8 @@ void LLScriptDoWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompileP
 		}
 		break;
 	case LSCP_PRUNE:
-		prunearg = FALSE;
+		prunearg = TRUE;
+		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 		break;
 	case LSCP_TYPE:
 		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
@@ -9159,7 +9168,8 @@ void LLScriptWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas
 		}
 		break;
 	case LSCP_PRUNE:
-		prunearg = FALSE;
+		prunearg = TRUE;
+		mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 		break;
 	case LSCP_TYPE:
 		mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
@@ -10127,7 +10137,10 @@ void LLScriptGlobalFunctions::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT
 			mStatements->recurse(fp, tabs, tabsize, pass, LSPRUNE_GLOBAL_NON_VOIDS, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
 			if (!prunearg)
 			{
-				gErrorToText.writeError(fp, this, LSERROR_NO_RETURN);
+				if (!gErrorToText.getErrors()) // Hide this error when a state change has been made in a global function
+				{
+					gErrorToText.writeError(fp, this, LSERROR_NO_RETURN);
+				}
 			}
 		}
 		else
diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h
index 12c16908af2b6aab5313e63014dbd0b9b6979702..a667e1eb5b796fbbea67a1dd34793a7e06df6f54 100644
--- a/indra/lscript/lscript_compile/lscript_tree.h
+++ b/indra/lscript/lscript_compile/lscript_tree.h
@@ -1888,6 +1888,7 @@ class LLScriptStateChange : public LLScriptStatement
 	S32 getSize();
 
 	LLScriptIdentifier *mIdentifier;
+	LSCRIPTType mReturnType;
 };
 
 class LLScriptJump : public LLScriptStatement
diff --git a/indra/lscript/lscript_execute.h b/indra/lscript/lscript_execute.h
index 9a631c4c8f0f999b826f1806eaf0535f9931d9e4..8549482299fd0017fc4b1d19249eeff3ee971192 100644
--- a/indra/lscript/lscript_execute.h
+++ b/indra/lscript/lscript_execute.h
@@ -369,8 +369,7 @@ class LLScriptExecute
 {
 public:
 	LLScriptExecute();
-	virtual ~LLScriptExecute() {;}
-
+	virtual ~LLScriptExecute()  = 0;
 	virtual S32 getVersion() const = 0;
 	virtual void deleteAllEvents() = 0;
 	virtual void addEvent(LLScriptDataCollection* event) = 0;
diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp
index 05fee9a4194235f71d1b4ab1b92258a323f868f0..1f908eb675d1d693a57b32dba84fe6d083ba4ff3 100644
--- a/indra/lscript/lscript_execute/lscript_execute.cpp
+++ b/indra/lscript/lscript_execute/lscript_execute.cpp
@@ -41,6 +41,8 @@
 #include "lscript_library.h"
 #include "lscript_heapruntime.h"
 #include "lscript_alloc.h"
+#include "llstat.h"
+
 
 // Static
 const	S32	DEFAULT_SCRIPT_TIMER_CHECK_SKIP = 4;
@@ -72,7 +74,7 @@ const char* URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED";
 const char* URL_REQUEST_DENIED = "URL_REQUEST_DENIED";
 
 // HTTP Requests to LSL scripts will time out after 25 seconds.
-const U64 LSL_HTTP_REQUEST_TIMEOUT = 25 * USEC_PER_SEC; 
+const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC = 25 * USEC_PER_SEC; 
 
 LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)
 {
@@ -110,6 +112,7 @@ LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)
 	init();
 }
 
+LLScriptExecute::~LLScriptExecute() {}
 LLScriptExecuteLSL2::~LLScriptExecuteLSL2()
 {
 	delete[] mBuffer;
@@ -4234,19 +4237,16 @@ S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer)
 	return 4;
 }
 
-BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+
+// Shared code for run_calllib() and run_calllib_two_byte()
+BOOL run_calllib_common(U8 *buffer, S32 &offset, const LLUUID &id, U16 arg)
 {
-	if (b_print)
-		printf("[0x%X]\tCALLLIB ", offset);
-	offset++;
-	U8 arg = safe_instruction_bytestream2byte(buffer, offset);
 	if (arg >= gScriptLibrary.mNextNumber)
 	{
 		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
 		return FALSE;
 	}
-	if (b_print)
-		printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg]->mName);
+	LLScriptLibraryFunction *function = gScriptLibrary.mFunctions[arg];
 
 	// pull out the arguments and the return values
 	LLScriptLibData	*arguments = NULL;
@@ -4254,14 +4254,14 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 
 	S32 i, number;
 
-	if (gScriptLibrary.mFunctions[arg]->mReturnType)
+	if (function->mReturnType)
 	{
 		returnvalue = new LLScriptLibData;
 	}
 
-	if (gScriptLibrary.mFunctions[arg]->mArgs)
+	if (function->mArgs)
 	{
-		number = (S32)strlen(gScriptLibrary.mFunctions[arg]->mArgs);		/*Flawfinder: ignore*/
+		number = (S32)strlen(function->mArgs);		//Flawfinder: ignore
 		arguments = new LLScriptLibData[number];
 	}
 	else
@@ -4271,24 +4271,18 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 
 	for (i = number - 1; i >= 0; i--)
 	{
-		lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg]->mArgs[i]);
+		lscript_pop_variable(&arguments[i], buffer, function->mArgs[i]);
 	}
 
-	if (b_print)
-	{
-		printf("%s\n", gScriptLibrary.mFunctions[arg]->mDesc);
-	}
+	// Actually execute the function call
+	function->mExecFunc(returnvalue, arguments, id);
 
-	{
-		// LLFastTimer time_in_libraries1(LLFastTimer::FTM_TEMP7);
-		gScriptLibrary.mFunctions[arg]->mExecFunc(returnvalue, arguments, id);
-	}
-	add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg]->mEnergyUse);
-	add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg]->mSleepTime);
+	add_register_fp(buffer, LREG_ESR, -(function->mEnergyUse));
+	add_register_fp(buffer, LREG_SLR, function->mSleepTime);
 
 	if (returnvalue)
 	{
-		returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg]->mReturnType);
+		returnvalue->mType = char2type(*function->mReturnType);
 		lscript_push_return_variable(returnvalue, buffer);
 	}
 
@@ -4305,72 +4299,32 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 }
 
 
-BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 {
-	if (b_print)
-		printf("[0x%X]\tCALLLIB ", offset);
 	offset++;
-	U16 arg = safe_instruction_bytestream2u16(buffer, offset);
-	if (arg >= gScriptLibrary.mNextNumber)
-	{
-		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
-		return FALSE;
-	}
-	if (b_print)
-		printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg]->mName);
-
-	// pull out the arguments and the return values
-	LLScriptLibData	*arguments = NULL;
-	LLScriptLibData	*returnvalue = NULL;
-
-	S32 i, number;
-
-	if (gScriptLibrary.mFunctions[arg]->mReturnType)
-	{
-		returnvalue = new LLScriptLibData;
-	}
-
-	if (gScriptLibrary.mFunctions[arg]->mArgs)
+	U16 arg = (U16) safe_instruction_bytestream2byte(buffer, offset);
+	if (b_print &&
+		arg < gScriptLibrary.mNextNumber)
 	{
-		number = (S32)strlen(gScriptLibrary.mFunctions[arg]->mArgs);		/*Flawfinder: ignore*/
-		arguments = new LLScriptLibData[number];
-	}
-	else
-	{
-		number = 0;
-	}
-
-	for (i = number - 1; i >= 0; i--)
-	{
-		lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg]->mArgs[i]);
-	}
-
-	if (b_print)
-	{
-		printf("%s\n", gScriptLibrary.mFunctions[arg]->mDesc);
-	}
-
-	{
-		// LLFastTimer time_in_libraries2(LLFastTimer::FTM_TEMP8);
-		gScriptLibrary.mFunctions[arg]->mExecFunc(returnvalue, arguments, id);
+		printf("[0x%X]\tCALLLIB ", offset);
+		LLScriptLibraryFunction *function = gScriptLibrary.mFunctions[arg];
+		printf("%d (%s)\n", (U32)arg, function->mName);
+		printf("%s\n", function->mDesc);
 	}
-	add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg]->mEnergyUse);
-	add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg]->mSleepTime);
+	return run_calllib_common(buffer, offset, id, arg);
+}
 
-	if (returnvalue)
+BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+{
+	offset++;
+	U16 arg = safe_instruction_bytestream2u16(buffer, offset);
+	if (b_print &&
+		arg < gScriptLibrary.mNextNumber)
 	{
-		returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg]->mReturnType);
-		lscript_push_return_variable(returnvalue, buffer);
+		printf("[0x%X]\tCALLLIB ", (offset-1));
+		LLScriptLibraryFunction *function = gScriptLibrary.mFunctions[arg];
+		printf("%d (%s)\n", (U32)arg, function->mName);
+		printf("%s\n", function->mDesc);
 	}
-
-	delete [] arguments;
-	delete returnvalue;
-
-	// reset the BP after calling the library files
-	S32 bp = lscript_pop_int(buffer);
-	set_bp(buffer, bp);
-
-	// pop off the spot for the instruction pointer
-	lscript_poparg(buffer, 4);
-	return FALSE;
+	return run_calllib_common(buffer, offset, id, arg);
 }
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 06c1b2c12b51a7edfd2af48285778cf80e93d399..9d6c26d83478132c8545d9114178ddde59a095e8 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -3063,7 +3063,7 @@ bool LLDispatchEstateUpdateInfo::operator()(
 	regionp->setOwner(owner_id);
 	// Update estate owner name in UI
 	const BOOL is_group = FALSE;
-	gCacheName->get(owner_id, is_group, LLPanelEstateInfo::callbackCacheName);
+	gCacheName->getNameFromUUID(owner_id, is_group, LLPanelEstateInfo::callbackCacheName);
 
 	U32 estate_id = strtoul(strings[2].c_str(), NULL, 10);
 	panel->setEstateID(estate_id);
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index a90ea3926580650a9a5eafdc90d97b4d8a6a659d..5b3f3952c9729f44a30ecf8dcd06ad4d75329163 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -932,7 +932,8 @@ void LLIMMgr::inviteToSession(
 	{
 		if (caller_name.empty())
 		{
-			gCacheName->getName(caller_id, onInviteNameLookup, new LLSD(payload));
+			BOOL is_group = FALSE;		// Inviter must be a person
+			gCacheName->getNameFromUUID(caller_id, is_group, onInviteNameLookup, new LLSD(payload));
 		}
 		else
 		{
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 40b1c641460629484abe06d96492868b33ccfaca..a840b591403c60e44cd92102ca9d955eac39dc17 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -566,7 +566,7 @@ BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason, co
 			else
 			{
 				// not in cache, lookup name from cache
-				gCacheName->get(agent_id, FALSE, notify_automute_callback, (void *)reason);
+				gCacheName->getNameFromUUID(agent_id, FALSE, notify_automute_callback, (void *)reason);
 			}
 		}
 		else
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index bbfd480e0bbf5ab51916ace4eaec5ba3b87409b7..7664d7ee07bffe175b35159755d3081e765ed2a0 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1040,7 +1040,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 	// * we can't build two messages at once.
 	if (2 == button)
 	{
-		gCacheName->get(mFromID, mFromGroup, inventory_offer_mute_callback, this);
+		gCacheName->getNameFromUUID(mFromID, mFromGroup, inventory_offer_mute_callback, this);
 	}
 
 	LLMessageSystem* msg = gMessageSystem;
@@ -4428,7 +4428,7 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use
 			LLMeanCollisionData *mcd = new LLMeanCollisionData(gAgentID, perp, time, type, mag);
 			gMeanCollisionList.push_front(mcd);
 			const BOOL is_group = FALSE;
-			gCacheName->get(perp, is_group, mean_name_callback);
+			gCacheName->getNameFromUUID(perp, is_group, mean_name_callback);
 		}
 	}
 }
@@ -5375,7 +5375,7 @@ void process_load_url(LLMessageSystem* msg, void**)
 	// Add to list of pending name lookups
 	gLoadUrlList.push_back(payload);
 
-	gCacheName->get(owner_id, owner_is_group, callback_load_url_name);
+	gCacheName->getNameFromUUID(owner_id, owner_is_group, callback_load_url_name);
 }
 
 
@@ -5469,7 +5469,9 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
 	LLPanelLandCovenant::updateLastModified(last_modified);
 	LLFloaterBuyLand::updateLastModified(last_modified);
 
-	gCacheName->getName(estate_owner_id, callbackCacheEstateOwnerName);
+	// Estates can't be owned by groups
+	BOOL is_group = FALSE;
+	gCacheName->getNameFromUUID(estate_owner_id, is_group, callbackCacheEstateOwnerName);
 	
 	// load the actual covenant asset data
 	const BOOL high_priority = TRUE;
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 94407ed08ceb23c905efb54cbb2f9c8ccdfa11ed..232885b3f6ead70a7b5c164a71ba45675a940252 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -6901,7 +6901,8 @@ void LLVoiceClient::notifyFriendObservers()
 
 void LLVoiceClient::lookupName(const LLUUID &id)
 {
-	gCacheName->getName(id, onAvatarNameLookup);
+	BOOL is_group = FALSE;
+	gCacheName->getNameFromUUID(id, is_group, onAvatarNameLookup);
 }
 
 //static