| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "RuntimeLibraryPch.h"
- namespace Js
- {
- bool DelayedFreeArrayBuffer::HasAnyItem()
- {
- return !this->listOfBuffers.Empty();
- }
- void DelayedFreeArrayBuffer::Push(ArrayBufferContentForDelayedFreeBase* item)
- {
- AssertOrFailFast(item);
- this->listOfBuffers.Push(item);
- }
- void Js::DelayedFreeArrayBuffer::ResetToNoMarkObject()
- {
- this->listOfBuffers.Map([](Js::ArrayBufferContentForDelayedFreeBase* item) {
- Assert(item != nullptr);
- item->SetMarkBit(false);
- });
- }
- void DelayedFreeArrayBuffer::ReleaseOnlyNonMarkedObject()
- {
- FOREACH_SLIST_ENTRY_EDITING(ArrayBufferContentForDelayedFreeBase*, item, &this->listOfBuffers, iter)
- {
- if (!item->IsMarked())
- {
- item->Release();
- item->ClearSelfOnly();
- iter.RemoveCurrent();
- }
- else
- {
- // Reset the mark bit
- item->SetMarkBit(false);
- }
- } NEXT_SLIST_ENTRY_EDITING
- }
- void DelayedFreeArrayBuffer::CheckAndMarkObject(void * candidate)
- {
- this->listOfBuffers.Map([&](Js::ArrayBufferContentForDelayedFreeBase* item) {
- if (!item->IsMarked() && item->IsAddressPartOfBuffer(candidate))
- {
- item->SetMarkBit(true);
- }
- });
- }
- void DelayedFreeArrayBuffer::ClearAll()
- {
- if (HasAnyItem())
- {
- this->listOfBuffers.Map([](Js::ArrayBufferContentForDelayedFreeBase* item) {
- item->Release();
- item->ClearSelfOnly();
- });
- this->listOfBuffers.Clear();
- }
- }
- void DelayedFreeArrayBuffer::ScanStack(void ** stackTop, size_t byteCount, void ** registers, size_t registersByteCount)
- {
- AssertOrFailFast(HasAnyItem());
- ResetToNoMarkObject();
- auto BufferFreeFunction = [&](void ** obj, size_t byteCount)
- {
- Assert(byteCount != 0);
- Assert(byteCount % sizeof(void *) == 0);
- void ** objEnd = obj + (byteCount / sizeof(void *));
- do
- {
- // We need to ensure that the compiler does not reintroduce reads to the object after inlining.
- // This could cause the value to change after the marking checks (e.g., the null/low address check).
- // Intrinsics avoid the expensive memory barrier on ARM (due to /volatile:ms).
- #if defined(_M_ARM64)
- void * candidate = reinterpret_cast<void *>(__iso_volatile_load64(reinterpret_cast<volatile __int64 *>(obj)));
- #elif defined(_M_ARM)
- void * candidate = reinterpret_cast<void *>(__iso_volatile_load32(reinterpret_cast<volatile __int32 *>(obj)));
- #else
- void * candidate = *(static_cast<void * volatile *>(obj));
- #endif
- CheckAndMarkObject(candidate);
- obj++;
- } while (obj != objEnd);
- };
- BufferFreeFunction(registers, registersByteCount);
- BufferFreeFunction(stackTop, byteCount);
- ReleaseOnlyNonMarkedObject();
- }
- void ArrayBufferContentForDelayedFreeBase::Release()
- {
- // this function will be called when we are releasing instance from the listOfBuffer which we have delayed.
- RefCountedBuffer *content = this->buffer;
- this->buffer = nullptr;
- long refCount = content->Release();
- if (refCount == 0)
- {
- FreeTheBuffer(content->GetBuffer());
- HeapDelete(content);
- }
- }
- bool ArrayBufferContentForDelayedFreeBase::IsAddressPartOfBuffer(void *obj)
- {
- void *start = this->buffer->GetBuffer();
- void *end = this->buffer->GetBuffer() + this->bufferLength;
- return start <= obj && obj < end;
- }
- }
|