Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GC Pinning? #1085

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions include/Array.h
Expand Up @@ -126,6 +126,18 @@ class ArrayKeyValueIterator : public cpp::FastIterator_obj<Dynamic>

namespace hx
{
#if (HXCPP_API_LEVEL>=500)
class HXCPP_EXTERN_CLASS_ATTRIBUTES ArrayPin
{
char* ptr;
public:
ArrayPin(char* inPtr);

~ArrayPin();

char* GetBase();
};
#endif

// Also used by cpp::VirtualArray
class HXCPP_EXTERN_CLASS_ATTRIBUTES ArrayCommon : public hx::Object
Expand Down Expand Up @@ -196,6 +208,9 @@ class HXCPP_EXTERN_CLASS_ATTRIBUTES ArrayBase : public ArrayCommon
mAlloc = -1;
}

#if (HXCPP_API_LEVEL>=500)
ArrayPin* Pin();
#endif

int __GetType() const { return vtArray; }

Expand Down
4 changes: 4 additions & 0 deletions include/hx/GC.h
Expand Up @@ -187,6 +187,10 @@ void MarkConservative(int *inBottom, int *inTop,hx::MarkContext *__inCtx);
void GCAddRoot(hx::Object **inRoot);
void GCRemoveRoot(hx::Object **inRoot);

#if (HXCPP_API_LEVEL>=500)
void GCPinPtr(void* inPtr);
void GCUnpinPtr(void* inPtr);
#endif

// This is used internally in hxcpp
// It calls InternalNew, and takes care of null-terminating the result
Expand Down
26 changes: 26 additions & 0 deletions src/Array.cpp
Expand Up @@ -36,7 +36,33 @@ ArrayBase::ArrayBase(int inSize,int inReserve,int inElementSize,bool inAtomic)
inElementSize==sizeof(String) ? aciStringArray : aciObjectArray;
}

#if (HXCPP_API_LEVEL>=500)
ArrayPin::ArrayPin(char* inPtr) : ptr(inPtr)
{
hx::GCPinPtr(ptr);
}

ArrayPin::~ArrayPin()
{
hx::GCUnpinPtr(ptr);
}

char* ArrayPin::GetBase()
{
return ptr;
}

ArrayPin* ArrayBase::Pin()
{
if (!mBase)
{
return nullptr;
}

// If the array holds unmanaged data is it safe to put this in the ArrayPin if we don't know the lifetime of that pointer?
return new ArrayPin(mBase);
}
#endif

void ArrayBase::reserve(int inSize) const
{
Expand Down
64 changes: 62 additions & 2 deletions src/hx/gc/Immix.cpp
Expand Up @@ -2364,6 +2364,9 @@ static RootSet sgRootSet;
typedef hx::UnorderedMap<void *,int> OffsetRootSet;
static OffsetRootSet *sgOffsetRootSet=0;

typedef hx::UnorderedSet<void*> PinSet;
static PinSet sgPinSet;

void GCAddRoot(hx::Object **inRoot)
{
AutoLock lock(*sGCRootLock);
Expand All @@ -2376,7 +2379,6 @@ void GCRemoveRoot(hx::Object **inRoot)
sgRootSet.erase(inRoot);
}


void GcAddOffsetRoot(void *inRoot, int inOffset)
{
AutoLock lock(*sGCRootLock);
Expand Down Expand Up @@ -3184,6 +3186,14 @@ class GlobalAllocator
unsigned int *blob = ((unsigned int *)inLarge) - 2;
unsigned int size = *blob;
mLargeListLock.Lock();

if (hx::sgPinSet.count(inLarge))
{
mLargeListLock.Unlock();

return;
}

mLargeAllocated -= size;
// Could somehow keep it in the list, but mark as recycled?
mLargeList.qerase_val(blob);
Expand Down Expand Up @@ -4716,10 +4726,37 @@ class GlobalAllocator
hx::Object *obj = (hx::Object *)(ptr - offset);

if (obj)
hx::MarkObjectAlloc(obj , &mMarker );
hx::MarkObjectAlloc(obj , &mMarker);
}
} // automark

{
hx::AutoMarkPush info(&mMarker, "Pins", "pin");

for (hx::PinSet::iterator i = hx::sgPinSet.begin(); i != hx::sgPinSet.end(); ++i)
{
void* const ptr = *i;
if (!ptr)
{
continue;
}

auto ptr_i = reinterpret_cast<size_t>(ptr) - sizeof(int);
auto flags = *reinterpret_cast<unsigned int*>(ptr_i);
auto onLOH = (flags & 0xffff) == 0;

if (!onLOH)
{
BlockData* block = reinterpret_cast<BlockData*>(reinterpret_cast<size_t>(ptr) & IMMIX_BLOCK_BASE_MASK);
BlockDataInfo* info = (*gBlockInfo)[block->mId];

info->pin();
}

hx::MarkAlloc(ptr, &mMarker);
}
}

#ifdef PROFILE_COLLECT
hx::rootObjects = sObjectMarks;
hx::rootAllocs = sAllocMarks;
Expand Down Expand Up @@ -5585,6 +5622,29 @@ class GlobalAllocator

namespace hx
{
#if (HXCPP_API_LEVEL>=430)
void GCPinPtr(void* inPtr)
{
if (IsConstAlloc(inPtr))
{
return;
}

AutoLock(sGlobalAlloc->mLargeListLock);
sgPinSet.emplace(inPtr);
}

void GCUnpinPtr(void* inPtr)
{
if (IsConstAlloc(inPtr))
{
return;
}

AutoLock(sGlobalAlloc->mLargeListLock);
sgPinSet.erase(inPtr);
}
#endif

MarkChunk *MarkChunk::swapForNew()
{
Expand Down