| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- // TODO, this should be elsewhere
- #define RecyclerNewImplicitRoot(recycler,T,...) AllocatorNewBase(Recycler, recycler, NoThrowAllocImplicitRoot, T, __VA_ARGS__)
- // Forward reference
- class RecyclerTestObject;
- // A "Location" represents a location in memory where object references (ReccylerTestObject *s) are stored.
- // It includes a "type" that defines how the reference should be read or written.
- // This allows us to specify special handling for certain location types,
- // such as pinned roots, software write barrier locations, tagged locations for tracked objects, etc.
- class Location
- {
- private:
- enum class Type
- {
- Scanned, // For regular locations in scanned objects (or stack locations)
- Rooted, // This is a non-heap location that's explicitly rooted.
- Barrier, // Write barrier location
- Tagged, // Tagged location (used in tracked objects)
- ImplicitRoot, // Uses ImplicitRootBit to hold reference
- };
- class ImplicitRootHolder
- {
- private:
- Field(RecyclerTestObject *) reference;
- public:
- ImplicitRootHolder(RecyclerTestObject * reference)
- : reference(reference)
- {
- VerifyCondition(reference != nullptr);
- }
- RecyclerTestObject * GetReference() const
- {
- VerifyCondition(this->reference != nullptr);
- return this->reference;
- }
- };
- Location(RecyclerTestObject ** location, Type type) :
- location(location), type(type)
- {
- VerifyCondition(location != nullptr);
- }
- public:
- static Location Scanned(RecyclerTestObject ** location)
- {
- return Location(location, Type::Scanned);
- }
- static Location Rooted(RecyclerTestObject ** location)
- {
- return Location(location, Type::Rooted);
- }
- static Location Barrier(RecyclerTestObject ** location)
- {
- return Location(location, Type::Barrier);
- }
- static Location Tagged(RecyclerTestObject ** location)
- {
- return Location(location, Type::Tagged);
- }
- static Location ImplicitRoot(RecyclerTestObject ** location)
- {
- return Location(location, Type::ImplicitRoot);
- }
- RecyclerTestObject * Get()
- {
- switch (type)
- {
- case Type::Scanned:
- return *location;
- case Type::Rooted:
- return *location;
- case Type::Barrier:
- return *location;
- case Type::Tagged:
- return Untag(*location);
- case Type::ImplicitRoot:
- // The stored location actually contains a pointer to the ImplicitRootHolder
- ImplicitRootHolder * holder = (ImplicitRootHolder *)(*location);
- if (holder == nullptr)
- {
- return nullptr;
- }
- return holder->GetReference();
- }
- // Shouldn't get here
- VerifyCondition(false);
- return nullptr;
- }
- void Set(RecyclerTestObject * value)
- {
- switch (type)
- {
- case Type::Scanned:
- *location = value;
- return;
- case Type::Rooted:
- Unroot();
- *location = value;
- Root();
- return;
- case Type::Barrier:
- *location = value;
- if (value != nullptr)
- {
- RecyclerWriteBarrierManager::WriteBarrier(location);
- }
- return;
- case Type::Tagged:
- *location = Tag(value);
- return;
- case Type::ImplicitRoot:
- // The stored location actually contains a pointer to the ImplicitRootHolder
- ImplicitRootHolder * holder = (ImplicitRootHolder *)(*location);
- if (holder != nullptr)
- {
- // Free the implicit root
- // TODO: This should be better encapsulated
- RecyclerHeapObjectInfo heapObject;
- bool found = recyclerInstance->FindHeapObject(holder, FindHeapObjectFlags_VerifyFreeBitForAttribute, heapObject);
- VerifyCondition(found);
- // Zero pointers in order to eliminate false-positives
- memset(holder, 0, heapObject.GetSize());
- bool success = heapObject.ClearImplicitRootBit();
- VerifyCondition(success);
- *location = nullptr;
- }
- if (value != nullptr)
- {
- // Create new holder object
- holder = RecyclerNewImplicitRoot(recyclerInstance, ImplicitRootHolder, value);
- VerifyCondition(holder != nullptr);
- // Store holder back to the location
- *location = (RecyclerTestObject *)holder;
- }
- return;
- }
- // Shouldn't get here
- VerifyCondition(false);
- }
- static RecyclerTestObject * Tag(RecyclerTestObject * untagged)
- {
- if (untagged == nullptr)
- {
- return nullptr;
- }
- else
- {
- size_t value = (size_t)untagged;
- VerifyCondition((value & 0x1) == 0);
- value |= 0x1;
- return (RecyclerTestObject *)value;
- }
- }
- static RecyclerTestObject * Untag(RecyclerTestObject * tagged)
- {
- if (tagged == nullptr)
- {
- return nullptr;
- }
- else
- {
- size_t value = (size_t)tagged;
- VerifyCondition((value & 0x1) == 0x1);
- value &= ~(0x1);
- return (RecyclerTestObject *)value;
- }
- }
- private:
- void Unroot()
- {
- if (*location != nullptr)
- {
- recyclerInstance->RootRelease(*location);
- }
- }
- void Root()
- {
- if (*location != nullptr)
- {
- recyclerInstance->RootAddRef(*location);
- }
- }
- private:
- RecyclerTestObject ** location;
- Type type;
- };
|