diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index 88f3c7d6f9726e2ddab6c52b82e72b26faf90574..12a1e98075b29c1724c91d6486cd21184ec4a27b 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -330,6 +330,8 @@ LLViewerOctreeEntryData::LLViewerOctreeEntryData(LLViewerOctreeEntry::eEntryData
 //virtual
 void LLViewerOctreeEntryData::setOctreeEntry(LLViewerOctreeEntry* entry)
 {
+	llassert_always(mEntry.isNull());
+
 	if(mEntry.notNull())
 	{
 		return; 
@@ -346,6 +348,15 @@ void LLViewerOctreeEntryData::setOctreeEntry(LLViewerOctreeEntry* entry)
 	mEntry->addData(this);
 }
 
+void LLViewerOctreeEntryData::removeOctreeEntry()
+{
+	if(mEntry)
+	{
+		mEntry->removeData(this);
+		mEntry = NULL;
+	}
+}
+
 void LLViewerOctreeEntryData::setSpatialExtents(const LLVector3& min, const LLVector3& max)
 { 
 	mEntry->mExtents[0].load3(min.mV); 
diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h
index 0f32e0dcc4b2f69624f1288f71966350c2f43271..219ec7e8da7c47d2d46f6a512267ca2e6fd96bb0 100644
--- a/indra/newview/llvieweroctree.h
+++ b/indra/newview/llvieweroctree.h
@@ -140,6 +140,7 @@ class LLViewerOctreeEntryData : public LLRefCount
 	LLViewerOctreeEntry* getEntry() {return mEntry;}
 	
 	virtual void setOctreeEntry(LLViewerOctreeEntry* entry);
+	void         removeOctreeEntry();
 
 	F32                  getBinRadius() const   {return mEntry->getBinRadius();}
 	const LLVector4a*    getSpatialExtents() const;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index f9689c74736a33f1a2aef6a74ccb17111b80b070..ae4306847c7530a2214b296e8b59afaaed57906c 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -806,50 +806,10 @@ void LLViewerRegion::dirtyHeights()
 	}
 }
 
-void LLViewerRegion::replaceVisibleCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry)
-{
-	//save old entry
-	old_entry->moveTo(new_entry);
-	U32 state = old_entry->getState();
-	U32 old_parent_id = old_entry->getParentID();
-
-	//kill old entry
-	killCacheEntry(old_entry);
-	
-	//parse new entry
-	U32	new_parent_id = 0;
-	LLViewerObject::unpackParentID(new_entry->getDP(), new_parent_id);
-	
-	//store new entry
-	mImpl->mCacheMap[new_entry->getLocalID()] = new_entry;	
-	
-	//process entry state
-	new_entry->setState(state);
-	if(state == LLVOCacheEntry::ACTIVE)
-	{
-		llassert(new_entry->getEntry()->hasDrawable());
-		mImpl->mActiveSet.insert(new_entry);
-	}
-	else if(state == LLVOCacheEntry::WAITING)
-	{
-		mImpl->mWaitingSet.insert(new_entry);
-	}
-	
-	//process parent info
-	if(!old_parent_id && new_parent_id > 0) //becomes a child
-	{
-		new_entry->clearChildrenList();
-	}
-	new_entry->setParentID(new_parent_id);
-
-	//update the object
-	gObjectList.processObjectUpdateFromCache(new_entry, this);
-}
-
 //physically delete the cache entry
 void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering)
 {	
-	if(!entry)
+	if(!entry || !entry->isValid())
 	{
 		return;
 	}
@@ -889,22 +849,18 @@ void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering)
 	}
 	else if(entry->getNumOfChildren() > 0)//remove children from cache if has any
 	{
-		S32 num_child = entry->getNumOfChildren();
-
-		LLVOCacheEntry* child;
-		for(S32 i = 0; i < num_child; i++)
+		LLVOCacheEntry* child = entry->getChild();
+		while(child != NULL)
 		{
-			child = entry->getChild(i);
-			if(child)
-			{
-				child->setParentID(0); //disconnect from parent
-				killCacheEntry(child, for_rendering);
-			}
+			killCacheEntry(child, for_rendering);
+			child = entry->getChild();
 		}
 	}
 
-	//remove from mCacheMap, real deletion
-	mImpl->mCacheMap.erase(entry->getLocalID());
+	//will remove it from the object cache, real deletion
+	entry->setState(LLVOCacheEntry::INACTIVE);
+	entry->removeOctreeEntry();
+	entry->setValid(FALSE);
 }
 
 //physically delete the cache entry	
@@ -924,6 +880,10 @@ void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry)
 	{
 		return;
 	}
+	if(entry->isState(LLVOCacheEntry::ACTIVE))
+	{
+		return; //already inserted.
+	}
 
 	if(entry->isState(LLVOCacheEntry::WAITING))
 	{
@@ -939,10 +899,14 @@ void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry)
 
 void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep)
 {
-	if(mDead || !entry)
+	if(mDead || !entry || !entry->isValid())
 	{
 		return;
 	}
+	if(!entry->isState(LLVOCacheEntry::ACTIVE))
+	{
+		return; //not an active entry.
+	}
 
 	//shift to the local regional space from agent space
 	if(drawablep != NULL && drawablep->getVObj().notNull())
@@ -1004,11 +968,7 @@ void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
 		return;
 	}
 
-	if(mDead || !entry || !entry->getEntry())
-	{
-		return;
-	}
-	if(entry->getGroup()) //already in octree.
+	if(mDead || !entry || !entry->getEntry() || !entry->isValid())
 	{
 		return;
 	}
@@ -1017,7 +977,14 @@ void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
 		return; //no child prim in cache octree.
 	}
 
-	llassert(!entry->getEntry()->hasDrawable());
+	if(entry->hasState(LLVOCacheEntry::IN_VO_TREE))
+	{
+		return; //already in the tree.
+	}
+	entry->setState(LLVOCacheEntry::IN_VO_TREE);
+
+	llassert_always(!entry->getGroup()); //not in octree.
+	llassert(!entry->getEntry()->hasDrawable()); //not have drawables
 
 	mImpl->mVOCachePartition->addEntry(entry->getEntry());
 }
@@ -1028,10 +995,12 @@ void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry)
 	{
 		return;
 	}
-	if(!entry->getGroup())
+	
+	if(!entry->hasState(LLVOCacheEntry::IN_VO_TREE))
 	{
-		return;
+		return; //not in the tree.
 	}
+	entry->clearState(LLVOCacheEntry::IN_VO_TREE);
 
 	mImpl->mVOCachePartition->removeEntry(entry->getEntry());	
 }
@@ -1039,7 +1008,7 @@ void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry)
 //add the visible entries
 void LLViewerRegion::addVisibleCacheEntry(LLVOCacheEntry* entry)
 {
-	if(mDead || !entry || !entry->getEntry())
+	if(mDead || !entry || !entry->getEntry() || !entry->isValid())
 	{
 		return; 
 	}
@@ -1053,7 +1022,22 @@ void LLViewerRegion::addVisibleCacheEntry(LLVOCacheEntry* entry)
 	{
 		entry->setState(LLVOCacheEntry::IN_QUEUE);
 	}
-	mImpl->mVisibleEntries.insert(entry);
+
+	if(!entry->isState(LLVOCacheEntry::ACTIVE))
+	{
+		mImpl->mVisibleEntries.insert(entry);
+	}
+
+	//add all children
+	if(entry->getNumOfChildren() > 0)
+	{
+		LLVOCacheEntry* child = entry->getChild();
+		while(child != NULL)
+		{
+			addVisibleCacheEntry(child);
+			child = entry->getChild();
+		}
+	}
 }
 
 void LLViewerRegion::updateVisibleEntries(F32 max_time)
@@ -1085,53 +1069,18 @@ void LLViewerRegion::updateVisibleEntries(F32 max_time)
 	for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();)
 	{
 		LLVOCacheEntry* vo_entry = *iter;
-
-		//set a large number to force to load this object.
-		vo_entry->setSceneContribution(LARGE_SCENE_CONTRIBUTION);
-
-		if(vo_entry->getState() < LLVOCacheEntry::WAITING)
-		{			
-			mImpl->mWaitingList.insert(vo_entry);
-		}
-
-		LLVOCacheEntry* child;
-		S32 num_child = vo_entry->getNumOfChildren();
-		S32 num_done = 0;
-		for(S32 i = 0; i < num_child; i++)
-		{
-			child = vo_entry->getChild(i);
-			if(child->getState() < LLVOCacheEntry::WAITING)
-			{
-				child->setSceneContribution(LARGE_SCENE_CONTRIBUTION); //a large number to force to load the child.
-				mImpl->mWaitingList.insert(child);
-			}
-			else
-			{
-				num_done++;
-			}
-		}
-		if(num_done == num_child)
-		{
-			vo_entry->clearChildrenList();
-		}
-
-		if(!vo_entry->getNumOfChildren())
+		
+		if(vo_entry->isValid() && vo_entry->getState() < LLVOCacheEntry::WAITING)
 		{
-			if(vo_entry->getState() >= LLVOCacheEntry::WAITING)
-			{
-				LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter;
-				++next_iter;
-				mImpl->mVisibleEntries.erase(iter);
-				iter = next_iter;
-			}
-			else
-			{
-				++iter;
-			}
+			//set a large number to force to load this object.
+			vo_entry->setSceneContribution(LARGE_SCENE_CONTRIBUTION);
+			
+			mImpl->mWaitingList.insert(vo_entry);
+			++iter;
 		}
 		else
 		{
-			++iter;
+			iter = mImpl->mVisibleEntries.erase(iter);
 		}
 	}
 
@@ -1163,6 +1112,10 @@ void LLViewerRegion::updateVisibleEntries(F32 max_time)
 					//child visibility depends on its parent.
 					continue;
 				}
+				if(!vo_entry->isValid())
+				{
+					continue; //skip invalid entry.
+				}
 
 				vo_entry->calcSceneContribution(local_origin, needs_update, last_update, dist_threshold);
 				if(vo_entry->getSceneContribution() > projection_threshold)
@@ -1240,10 +1193,7 @@ void LLViewerRegion::clearCachedVisibleObjects()
 				parent->addChild(entry);
 			}
 
-			LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter;
-			++next_iter;
-			mImpl->mVisibleEntries.erase(iter);
-			iter = next_iter;
+			iter = mImpl->mVisibleEntries.erase(iter);
 		}
 		else //parent is not cache-able, leave it.
 		{
@@ -2044,8 +1994,7 @@ void LLViewerRegion::findOrphans(U32 parent_id)
 		for(S32 i = 0; i < children->size(); i++)
 		{
 			//parent is visible, so is the child.
-			LLVOCacheEntry* child = getCacheEntry((*children)[i]);
-			addVisibleCacheEntry(child);
+			addVisibleCacheEntry(getCacheEntry((*children)[i]));
 		}
 		children->clear();
 		mOrphanMap.erase(parent_id);
@@ -2059,46 +2008,50 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
 		gObjectList.processObjectUpdateFromCache(entry, this);
 		return;
 	}
+	if(!entry || !entry->isValid())
+	{
+		return;
+	}
 
-	if(entry != NULL && !entry->getEntry())
+	if(!entry->getEntry())
 	{
 		entry->setOctreeEntry(NULL);
+	}
 		
-		if(entry->getEntry()->hasDrawable()) //already in the rendering pipeline
+	if(entry->getEntry()->hasDrawable()) //already in the rendering pipeline
+	{
+		LLViewerRegion* old_regionp = ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion();
+		if(old_regionp != this && old_regionp)
 		{
-			LLViewerRegion* old_regionp = ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion();
-			if(old_regionp != this && old_regionp)
+			LLViewerObject* obj = ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj();
+			if(obj)
 			{
-				LLViewerObject* obj = ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj();
-				if(obj)
-				{
-					//remove from old region
-					old_regionp->killCacheEntry(obj->getLocalID());
+				//remove from old region
+				old_regionp->killCacheEntry(obj->getLocalID());
 
-					//change region
-					obj->setRegion(this);
-				}
+				//change region
+				obj->setRegion(this);
 			}
+		}
 
-			addActiveCacheEntry(entry);
+		addActiveCacheEntry(entry);
 		
-			//set parent id
-			U32	parent_id = 0;
-			LLViewerObject::unpackParentID(entry->getDP(), parent_id);
-			if(parent_id > 0)
-			{
-				entry->setParentID(parent_id);
-			}
-
-			//update the object
-			gObjectList.processObjectUpdateFromCache(entry, this);
-			return; //done
+		//set parent id
+		U32	parent_id = 0;
+		LLViewerObject::unpackParentID(entry->getDP(), parent_id);
+		if(parent_id != entry->getParentID())
+		{				
+			entry->setParentID(parent_id);
 		}
+
+		//update the object
+		gObjectList.processObjectUpdateFromCache(entry, this);
+		return; //done
 	}
-	else if(entry->getGroup() != NULL)
-	{
-		return; //already in octree, no post processing.
-	}	
+	
+	//must not be active.
+	llassert_always(!entry->isState(LLVOCacheEntry::ACTIVE));
+	removeFromVOCacheTree(entry); //remove from cache octree if it is in.
 
 	LLVector3 pos;
 	LLVector3 scale;
@@ -2107,27 +2060,56 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
 	//decode spatial info and parent info
 	U32 parent_id = LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot);
 	
-	if(parent_id > 0) //has parent
+	U32 old_parent_id = entry->getParentID();
+	bool same_old_parent = false;
+	if(parent_id != old_parent_id) //parent changed.
 	{
+		if(old_parent_id > 0) //has an old parent, disconnect it
+		{
+			LLVOCacheEntry* old_parent = getCacheEntry(old_parent_id);
+			if(old_parent)
+			{
+				old_parent->removeChild(entry);
+				if(!old_parent->isState(LLVOCacheEntry::INACTIVE))
+				{
+					mImpl->mVisibleEntries.erase(entry);
+					entry->setState(LLVOCacheEntry::INACTIVE);
+				}
+			}
+		}
 		entry->setParentID(parent_id);
-	
+	}
+	else
+	{
+		same_old_parent = true;
+	}
+
+	if(parent_id > 0) //has a new parent
+	{	
 		//1, find the parent in cache
 		LLVOCacheEntry* parent = getCacheEntry(parent_id);
 		
 		//2, parent is not in the cache, put into the orphan list.
 		if(!parent)
 		{
-			//check if parent is non-cacheable and already created
-			if(isNonCacheableObjectCreated(parent_id))
+			if(!same_old_parent)
 			{
-				//parent is visible, so is the child.
-				addVisibleCacheEntry(entry);
+				//check if parent is non-cacheable and already created
+				if(isNonCacheableObjectCreated(parent_id))
+				{
+					//parent is visible, so is the child.
+					addVisibleCacheEntry(entry);
+				}
+				else
+				{
+					entry->setBoundingInfo(pos, scale);
+					mOrphanMap[parent_id].push_back(entry->getLocalID());
+				}
 			}
 			else
 			{
 				entry->setBoundingInfo(pos, scale);
-				mOrphanMap[parent_id].push_back(entry->getLocalID());
-		    }
+			}
 		}
 		else //parent in cache.
 		{
@@ -2194,10 +2176,12 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerB
 	LLViewerObject::unpackU32(&dp, local_id, "LocalID");
 	LLViewerObject::unpackU32(&dp, crc, "CRC");
 
-	LLVOCacheEntry* entry = getCacheEntry(local_id);
+	LLVOCacheEntry* entry = getCacheEntry(local_id, false);
 
 	if (entry)
 	{
+		entry->setValid();
+
 		// we've seen this object before
 		if (entry->getCRC() == crc)
 		{
@@ -2205,31 +2189,15 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerB
 			entry->recordDupe();
 			result = CACHE_UPDATE_DUPE;
 		}
-		else
+		else //CRC changed
 		{
 			// Update the cache entry
-			LLPointer<LLVOCacheEntry> new_entry = new LLVOCacheEntry(local_id, crc, dp);
-			
-			//if visible, update it
-			if(!entry->isState(LLVOCacheEntry::INACTIVE))
-			{
-				replaceVisibleCacheEntry(entry, new_entry);
-			}
-			else //invisible
-			{
-				//copy some contents from old entry
-				entry->moveTo(new_entry, true);
-
-				//remove old entry
-				killCacheEntry(entry);
-				entry = new_entry;
-				
-				mImpl->mCacheMap[local_id] = entry;
-				decodeBoundingInfo(entry);
-			}
+			entry->updateEntry(crc, dp);
+
+			decodeBoundingInfo(entry);
 
 			result = CACHE_UPDATE_CHANGED;
-		}
+		}		
 	}
 	else
 	{
@@ -2268,12 +2236,15 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id)
 	return entry;
 }
 
-LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id)
+LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id, bool valid)
 {
 	LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.find(local_id);
 	if(iter != mImpl->mCacheMap.end())
 	{
-		return iter->second;
+		if(!valid || iter->second->isValid())
+		{
+			return iter->second;
+		}
 	}
 	return NULL;
 }
@@ -2323,7 +2294,7 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
 {
 	//llassert(mCacheLoaded);  This assert failes often, changing to early-out -- davep, 2010/10/18
 
-	LLVOCacheEntry* entry = getCacheEntry(local_id);
+	LLVOCacheEntry* entry = getCacheEntry(local_id, false);
 
 	if (entry)
 	{
@@ -2341,15 +2312,12 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
 				return true;
 			}
 
-			if(entry->getGroup() || !entry->isState(LLVOCacheEntry::INACTIVE)) //already probed
+			if(entry->isValid())
 			{
-				return true;
-			}
-			if(entry->getParentID() > 0) //already probed
-			{
-				return true;
+				return true; //already probed
 			}
 
+			entry->setValid();
 			decodeBoundingInfo(entry);
 			return true;
 		}
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 2085f83f32cdd2b33e42a5633a09c8b58d65e785..7ce191fe8fbbfe088dc29a83c3e416d040e4152a 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -331,7 +331,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags);
 	eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags);	
 	LLVOCacheEntry* getCacheEntryForOctree(U32 local_id);
-	LLVOCacheEntry* getCacheEntry(U32 local_id);
+	LLVOCacheEntry* getCacheEntry(U32 local_id, bool valid = true);
 	bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type);
 	void requestCacheMisses();
 	void addCacheMissFull(const U32 local_id);
@@ -384,7 +384,6 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	LLViewerObject* addNewObject(LLVOCacheEntry* entry);
 	void killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>& delete_list);	
 	void removeFromVOCacheTree(LLVOCacheEntry* entry);
-	void replaceVisibleCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry);
 	void killCacheEntry(LLVOCacheEntry* entry, bool for_rendering = false); //physically delete the cache entry	
 	void killInvisibleObjects(F32 max_time);
 	void createVisibleObjects(F32 max_time);
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 515cc003c08026dd021afe26edd80cff1d479b49..aa3594638a1a8f9566471c24d785efe5bc38c9b2 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -69,7 +69,7 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &
 	mCRCChangeCount(0),
 	mState(INACTIVE),
 	mSceneContrib(0.f),
-	mTouched(TRUE),
+	mValid(TRUE),
 	mParentID(0),
 	mBSphereRadius(-1.0f)
 {
@@ -90,7 +90,7 @@ LLVOCacheEntry::LLVOCacheEntry()
 	mBuffer(NULL),
 	mState(INACTIVE),
 	mSceneContrib(0.f),
-	mTouched(TRUE),
+	mValid(TRUE),
 	mParentID(0),
 	mBSphereRadius(-1.0f)
 {
@@ -104,7 +104,7 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
 	mUpdateFlags(-1),
 	mState(INACTIVE),
 	mSceneContrib(0.f),
-	mTouched(FALSE),
+	mValid(FALSE),
 	mParentID(0),
 	mBSphereRadius(-1.0f)
 {
@@ -169,14 +169,29 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
 		mCRCChangeCount = 0;
 		mBuffer = NULL;
 		mEntry = NULL;
-		mState = 0;
+		mState = INACTIVE;
 	}
 }
 
 LLVOCacheEntry::~LLVOCacheEntry()
 {
 	mDP.freeBuffer();
-	//llassert(mState == INACTIVE);
+}
+
+void LLVOCacheEntry::updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp)
+{
+	if(mCRC != crc)
+	{
+		mCRC = crc;
+		mCRCChangeCount++;
+	}
+
+	mDP.freeBuffer();
+
+	llassert_always(dp.getBufferSize() > 0);
+	mBuffer = new U8[dp.getBufferSize()];
+	mDP.assignBuffer(mBuffer, dp.getBufferSize());
+	mDP = dp;
 }
 
 //virtual 
@@ -197,27 +212,19 @@ void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry)
 	LLViewerOctreeEntryData::setOctreeEntry(entry);
 }
 
-void LLVOCacheEntry::moveTo(LLVOCacheEntry* new_entry, bool no_entry_move)
+void LLVOCacheEntry::setState(U32 state)
 {
-	//copy LLViewerOctreeEntry
-	if(mEntry.notNull() && !no_entry_move)
-	{
-		new_entry->setOctreeEntry(mEntry);
-		mEntry = NULL;
-	}
-
-	//copy children
-	S32 num_children = getNumOfChildren();
-	for(S32 i = 0; i < num_children; i++)
+	if(state > LOW_BITS) //special states
 	{
-		new_entry->addChild(getChild(i));
+		mState |= (HIGH_BITS & state);
+		return;
 	}
-	mChildrenList.clear();
-}
 
-void LLVOCacheEntry::setState(U32 state)
-{
-	mState = state;
+	//
+	//otherwise LOW_BITS states
+	//
+	clearState(LOW_BITS);
+	mState |= (LOW_BITS & state);
 
 	if(getState() == ACTIVE)
 	{
@@ -249,8 +256,8 @@ void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
 	{
 		return;
 	}
-
-	mChildrenList.push_back(entry);
+	
+	mChildrenList.insert(entry);
 
 	//update parent bbox
 	if(getEntry() != NULL && isState(INACTIVE))
@@ -262,24 +269,27 @@ void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
 	
 void LLVOCacheEntry::removeChild(LLVOCacheEntry* entry)
 {
-	for(S32 i = 0; i < mChildrenList.size(); i++)
+	entry->setParentID(0);
+
+	vocache_entry_set_t::iterator iter = mChildrenList.find(entry);
+	if(iter != mChildrenList.end())
 	{
-		if(mChildrenList[i] == entry)
-		{
-			entry->setParentID(0);
-			mChildrenList[i] = mChildrenList[mChildrenList.size() - 1];
-			mChildrenList.pop_back();
-		}
+		mChildrenList.erase(iter);
 	}
 }
 
-void LLVOCacheEntry::removeAllChildren()
+//remove the first child, and return it.
+LLVOCacheEntry* LLVOCacheEntry::getChild()
 {
-	for(S32 i = 0; i < mChildrenList.size(); i++)
+	LLVOCacheEntry* child = NULL;
+	vocache_entry_set_t::iterator iter = mChildrenList.begin();
+	if(iter != mChildrenList.end())
 	{
-		mChildrenList[i]->setParentID(0);
+		child = *iter;
+		mChildrenList.erase(iter);
 	}
-	mChildrenList.clear();
+
+	return child;
 }
 
 LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP()
@@ -295,7 +305,6 @@ LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP()
 
 void LLVOCacheEntry::recordHit()
 {
-	setTouched();
 	mHitCount++;
 }
 
@@ -505,9 +514,9 @@ void LLVOCacheEntry::updateParentBoundingInfo()
 		return;
 	}
 
-	for(S32 i = 0; i < mChildrenList.size(); i++)
+	for(vocache_entry_set_t::iterator iter = mChildrenList.begin(); iter != mChildrenList.end(); ++iter)
 	{
-		updateParentBoundingInfo(mChildrenList[i]);
+		updateParentBoundingInfo(*iter);
 	}
 	resetVisible();
 }
@@ -1463,7 +1472,7 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
 	
 			for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter)
 			{
-				if(!removal_enabled || iter->second->isTouched())
+				if(!removal_enabled || iter->second->isValid())
 				{
 					success = iter->second->writeToFile(&apr_file) ;
 					if(!success)
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index c32b4f8984f259aa132178667f5081b576821445..928f8c87b93864f213ac091aeb7a0e5bc3b7a0d8 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -42,12 +42,19 @@ class LLVOCacheEntry
 	public LLTrace::MemTrackable<LLVOCacheEntry, 16>
 {
 public:
-	enum //low 16-bit state
+	enum 
 	{
+		//low 16-bit state
 		INACTIVE = 0x00000000,     //not visible
 		IN_QUEUE = 0x00000001,     //in visible queue, object to be created
 		WAITING  = 0x00000002,     //object creation request sent
-		ACTIVE   = 0x00000004      //object created, and in rendering pipeline.
+		ACTIVE   = 0x00000004,      //object created, and in rendering pipeline.
+
+		//high 16-bit state
+		IN_VO_TREE = 0x00010000,    //the entry is in the object cache tree.
+
+		LOW_BITS  = 0x0000ffff,
+		HIGH_BITS = 0xffff0000
 	};
 
 	struct CompareVOCacheEntry
@@ -79,11 +86,13 @@ class LLVOCacheEntry
 	LLVOCacheEntry(LLAPRFile* apr_file);
 	LLVOCacheEntry();	
 
-	void setState(U32 state);
-	//void clearState(U32 state) {mState &= ~state;}
-	bool isState(U32 state)    {return mState == state;}
-	bool hasState(U32 state)   {return mState & state;}
-	U32  getState() const      {return mState;}
+	void updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp);
+
+	void clearState(U32 state) {mState &= ~state;}
+	bool hasState(U32 state)   {return mState & state;}	
+	void setState(U32 state);	
+	bool isState(U32 state)    {return (mState & LOW_BITS) == state;}	
+	U32  getState() const      {return mState & LOW_BITS;}
 	
 	bool isAnyVisible(const LLVector4a& camera_origin, const LLVector4a& local_camera_origin, F32 dist_threshold);
 
@@ -102,7 +111,6 @@ class LLVOCacheEntry
 	void recordHit();
 	void recordDupe() { mDupeCount++; }
 	
-	void moveTo(LLVOCacheEntry* new_entry, bool no_entry_move = false); //copy variables 
 	/*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry);
 
 	void setParentID(U32 id) {mParentID = id;}
@@ -110,17 +118,15 @@ class LLVOCacheEntry
 
 	void addChild(LLVOCacheEntry* entry);
 	void removeChild(LLVOCacheEntry* entry);
-	void removeAllChildren();
-	LLVOCacheEntry* getChild(S32 i) {return mChildrenList[i];}
-	S32  getNumOfChildren()         {return mChildrenList.size();}
-	void clearChildrenList()        {mChildrenList.clear();}
+	LLVOCacheEntry* getChild(); //remove the first child, and return it.
+	S32  getNumOfChildren() const  {return mChildrenList.size();}
 	
 	void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); //called from processing object update message	
 	void updateParentBoundingInfo();
 	void saveBoundingSphere();
 
-	void setTouched(BOOL touched = TRUE) {mTouched = touched;}
-	BOOL isTouched() const {return mTouched;}
+	void setValid(BOOL valid = TRUE) {mValid = valid;}
+	BOOL isValid() const {return mValid;}
 
 	void setUpdateFlags(U32 flags) {mUpdateFlags = flags;}
 	U32  getUpdateFlags() const    {return mUpdateFlags;}
@@ -150,9 +156,9 @@ class LLVOCacheEntry
 
 	F32                         mSceneContrib; //projected scene contributuion of this object.
 	U32                         mState; //high 16 bits reserved for special use.
-	std::vector<LLVOCacheEntry*> mChildrenList; //children entries in a linked set.
+	vocache_entry_set_t         mChildrenList; //children entries in a linked set.
 
-	BOOL                        mTouched; //if set, this entry is valid, otherwise it is invalid.
+	BOOL                        mValid; //if set, this entry is valid, otherwise it is invalid and will be removed.
 
 	LLVector4a                  mBSphereCenter; //bounding sphere center
 	F32                         mBSphereRadius; //bounding sphere radius