summaryrefslogtreecommitdiff
path: root/src/vm/objectlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/objectlist.cpp')
-rw-r--r--src/vm/objectlist.cpp209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/vm/objectlist.cpp b/src/vm/objectlist.cpp
new file mode 100644
index 0000000000..e3500dee32
--- /dev/null
+++ b/src/vm/objectlist.cpp
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#include "common.h"
+#include "objectlist.h"
+
+#ifndef DACCESS_COMPILE
+
+ObjectList::ObjectList( void )
+: freeIndexHead_( INVALID_COMPRESSEDSTACK_INDEX ),
+ listLock_( CrstObjectList, CrstFlags(CRST_UNSAFE_SAMELEVEL | CRST_UNSAFE_ANYMODE) )
+{
+ CONTRACTL {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ } CONTRACTL_END;
+}
+
+#endif
+
+#define MAX_LOOP 2
+
+DWORD
+ObjectList::AddToList( PVOID ptr )
+{
+ CONTRACTL {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(ptr));
+ } CONTRACTL_END;
+
+
+ // sanity check that the pointer low bit is not set
+ _ASSERTE( (((DWORD)(size_t)ptr & 0x1) == 0) && "Invalid pointer" );
+
+ DWORD retval = INVALID_COMPRESSEDSTACK_INDEX;
+
+ CrstHolder ch( &listLock_ );
+
+ // If there is an entry in the free list, simply use it.
+
+ if (this->freeIndexHead_ != INVALID_COMPRESSEDSTACK_INDEX)
+ {
+ _ASSERTE( this->listLock_.OwnedByCurrentThread() );
+
+ // grab the head of the list
+ retval = (this->freeIndexHead_ >> 1);
+
+ DWORD nextFreeIndex = (DWORD)(size_t)this->allEntries_.Get( retval );
+
+ // index in use, pointer values have low bit as 0
+ _ASSERTE( ((nextFreeIndex & 0x01) == 1) && "The free list points to an index that is in use" );
+ // update the head of the list with the next free index stored in the array list
+ this->freeIndexHead_ = nextFreeIndex;
+
+ // store the pointer
+ this->allEntries_.Set( retval, ptr);
+ }
+ // Otherwise we place this new entry at that end of the list.
+ else
+ {
+ _ASSERTE( this->listLock_.OwnedByCurrentThread() );
+ retval = this->allEntries_.GetCount();
+ IfFailThrow(this->allEntries_.Append(ptr));
+ }
+
+ _ASSERTE( retval != INVALID_COMPRESSEDSTACK_INDEX );
+
+ return retval;
+}
+
+void
+ObjectList::RemoveFromList( PVOID ptr )
+{
+ CONTRACTL {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(ptr));
+ } CONTRACTL_END;
+
+ // sanity check that the pointer low bit is not set
+ _ASSERTE( (((DWORD)(size_t)ptr & 0x1) == 0) && "Invalid pointer" );
+
+ DWORD index = INVALID_COMPRESSEDSTACK_INDEX;
+
+ CrstHolder ch( &listLock_ );
+
+ ObjectList::Iterator iter = Iterate();
+
+ while (iter.Next())
+ {
+ if (iter.GetElement() == ptr)
+ {
+ index = iter.GetIndex();
+ break;
+ }
+ }
+
+ if (index == INVALID_COMPRESSEDSTACK_INDEX)
+ {
+ _ASSERTE( FALSE && "Unable to find object" );
+ }
+ else
+ {
+ // add the index to the free list ( shift the freeIndex left and set the low bit)
+ this->allEntries_.Set( index, (PVOID)(size_t)(this->freeIndexHead_));
+ this-> freeIndexHead_ = ((index<<1) | 0x1);
+ }
+}
+
+
+
+void
+ObjectList::RemoveFromList( DWORD index, PVOID ptr )
+{
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(ptr));
+ } CONTRACTL_END;
+
+ CrstHolder ch( &listLock_ );
+
+ // sanity check that the pointer low bit is not set
+ _ASSERTE( (((DWORD)(size_t)ptr & 0x1) == 0) && "Invalid pointer" );
+
+ _ASSERTE( index < this->allEntries_.GetCount() );
+ _ASSERTE( this->allEntries_.Get( index ) == ptr && "Index tracking failed for this object" );
+
+ // add the index to the free list ( shift the freeIndex left and set the low bit)
+ this->allEntries_.Set( index, (PVOID)(size_t)(this->freeIndexHead_));
+ this-> freeIndexHead_ = ((index<<1) | 0x1);
+
+}
+
+PVOID
+ObjectList::Get( DWORD index )
+{
+ LIMITED_METHOD_CONTRACT;
+ return this->allEntries_.Get( index );
+}
+
+
+UnsynchronizedBlockAllocator::UnsynchronizedBlockAllocator( size_t blockSize )
+: blockSize_( blockSize ),
+ offset_( blockSize ),
+ index_( INVALID_COMPRESSEDSTACK_INDEX )
+{
+ LIMITED_METHOD_CONTRACT;
+ // We start off the offset at the block size to force the first
+ // allocation to create a new (first) block
+}
+
+UnsynchronizedBlockAllocator::~UnsynchronizedBlockAllocator( void )
+{
+ LIMITED_METHOD_CONTRACT;
+ ArrayList::Iterator iter = this->blockList_.Iterate();
+
+ while (iter.Next())
+ {
+ delete [] (BYTE *) iter.GetElement();
+ }
+}
+
+
+PVOID
+UnsynchronizedBlockAllocator::Allocate( size_t size )
+{
+ CONTRACTL {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ } CONTRACTL_END;
+
+ _ASSERTE( size <= this->blockSize_ );
+
+ NewHolder<BYTE> buffer;
+
+ S_SIZE_T sizecheck = S_SIZE_T(this->offset_) + S_SIZE_T(size) ;
+ if( sizecheck.IsOverflow() )
+ {
+ ThrowOutOfMemory();
+ }
+
+ if (sizecheck.Value() > this->blockSize_)
+ {
+ buffer.Assign( new BYTE[this->blockSize_] );
+ IfFailThrow(this->blockList_.Append( buffer ));
+ buffer.SuppressRelease();
+ ++this->index_;
+ this->offset_ = 0;
+ }
+ else
+ {
+ buffer.Assign( (BYTE*)this->blockList_.Get( index_ ) );
+ buffer.SuppressRelease();
+ }
+
+ void* retval = buffer.GetValue() + this->offset_;
+ this->offset_ += size;
+
+ return retval;
+}