CompleteSubspace.cpp [plain text]
#include "config.h"
#include "Subspace.h"
#include "AlignedMemoryAllocator.h"
#include "AllocatorInlines.h"
#include "BlockDirectoryInlines.h"
#include "JSCInlines.h"
#include "LocalAllocatorInlines.h"
#include "MarkedBlockInlines.h"
#include "PreventCollectionScope.h"
#include "SubspaceInlines.h"
namespace JSC {
CompleteSubspace::CompleteSubspace(CString name, Heap& heap, HeapCellType* heapCellType, AlignedMemoryAllocator* alignedMemoryAllocator)
: Subspace(name, heap)
{
initialize(heapCellType, alignedMemoryAllocator);
}
CompleteSubspace::~CompleteSubspace()
{
}
Allocator CompleteSubspace::allocatorFor(size_t size, AllocatorForMode mode)
{
return allocatorForNonVirtual(size, mode);
}
void* CompleteSubspace::allocate(VM& vm, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
{
return allocateNonVirtual(vm, size, deferralContext, failureMode);
}
Allocator CompleteSubspace::allocatorForSlow(size_t size)
{
size_t index = MarkedSpace::sizeClassToIndex(size);
size_t sizeClass = MarkedSpace::s_sizeClassForSizeStep[index];
if (!sizeClass)
return Allocator();
auto locker = holdLock(m_space.directoryLock());
if (Allocator allocator = m_allocatorForSizeStep[index])
return allocator;
if (false)
dataLog("Creating BlockDirectory/LocalAllocator for ", m_name, ", ", m_attributes, ", ", sizeClass, ".\n");
std::unique_ptr<BlockDirectory> uniqueDirectory =
std::make_unique<BlockDirectory>(m_space.heap(), sizeClass);
BlockDirectory* directory = uniqueDirectory.get();
m_directories.append(WTFMove(uniqueDirectory));
directory->setSubspace(this);
m_space.addBlockDirectory(locker, directory);
std::unique_ptr<LocalAllocator> uniqueLocalAllocator =
std::make_unique<LocalAllocator>(directory);
LocalAllocator* localAllocator = uniqueLocalAllocator.get();
m_localAllocators.append(WTFMove(uniqueLocalAllocator));
Allocator allocator(localAllocator);
index = MarkedSpace::sizeClassToIndex(sizeClass);
for (;;) {
if (MarkedSpace::s_sizeClassForSizeStep[index] != sizeClass)
break;
m_allocatorForSizeStep[index] = allocator;
if (!index--)
break;
}
directory->setNextDirectoryInSubspace(m_firstDirectory);
m_alignedMemoryAllocator->registerDirectory(directory);
WTF::storeStoreFence();
m_firstDirectory = directory;
return allocator;
}
void* CompleteSubspace::allocateSlow(VM& vm, size_t size, GCDeferralContext* deferralContext, AllocationFailureMode failureMode)
{
void* result = tryAllocateSlow(vm, size, deferralContext);
if (failureMode == AllocationFailureMode::Assert)
RELEASE_ASSERT(result);
return result;
}
void* CompleteSubspace::tryAllocateSlow(VM& vm, size_t size, GCDeferralContext* deferralContext)
{
sanitizeStackForVM(&vm);
if (Allocator allocator = allocatorFor(size, AllocatorForMode::EnsureAllocator))
return allocator.allocate(deferralContext, AllocationFailureMode::ReturnNull);
if (size <= Options::largeAllocationCutoff()
&& size <= MarkedSpace::largeCutoff) {
dataLog("FATAL: attampting to allocate small object using large allocation.\n");
dataLog("Requested allocation size: ", size, "\n");
RELEASE_ASSERT_NOT_REACHED();
}
vm.heap.collectIfNecessaryOrDefer(deferralContext);
size = WTF::roundUpToMultipleOf<MarkedSpace::sizeStep>(size);
LargeAllocation* allocation = LargeAllocation::tryCreate(vm.heap, size, this);
if (!allocation)
return nullptr;
m_space.m_largeAllocations.append(allocation);
vm.heap.didAllocate(size);
m_space.m_capacity += size;
m_largeAllocations.append(allocation);
return allocation->cell();
}
}