/*
 * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "Subspace.h"

#include "AlignedMemoryAllocator.h"
#include "HeapCellType.h"
#include "MarkedSpaceInlines.h"
#include "ParallelSourceAdapter.h"
#include "SubspaceInlines.h"

namespace JSC {

Subspace::Subspace(CString name, Heap& heap)
    : m_space(heap.objectSpace())
    , m_name(name)
{
}

void Subspace::initialize(HeapCellType* heapCellType, AlignedMemoryAllocator* alignedMemoryAllocator)
{
    m_heapCellType = heapCellType;
    m_alignedMemoryAllocator = alignedMemoryAllocator;
    m_directoryForEmptyAllocation = m_alignedMemoryAllocator->firstDirectory();

    Heap& heap = m_space.heap();
    heap.objectSpace().m_subspaces.append(this);
    m_alignedMemoryAllocator->registerSubspace(this);
}

Subspace::~Subspace()
{
}

void Subspace::finishSweep(MarkedBlock::Handle& block, FreeList* freeList)
{
    m_heapCellType->finishSweep(block, freeList);
}

void Subspace::destroy(VM& vm, JSCell* cell)
{
    m_heapCellType->destroy(vm, cell);
}

void Subspace::prepareForAllocation()
{
    forEachDirectory(
        [&] (BlockDirectory& directory) {
            directory.prepareForAllocation();
        });

    m_directoryForEmptyAllocation = m_alignedMemoryAllocator->firstDirectory();
}

MarkedBlock::Handle* Subspace::findEmptyBlockToSteal()
{
    for (; m_directoryForEmptyAllocation; m_directoryForEmptyAllocation = m_directoryForEmptyAllocation->nextDirectoryInAlignedMemoryAllocator()) {
        if (MarkedBlock::Handle* block = m_directoryForEmptyAllocation->findEmptyBlockToSteal())
            return block;
    }
    return nullptr;
}

Ref<SharedTask<BlockDirectory*()>> Subspace::parallelDirectorySource()
{
    class Task final : public SharedTask<BlockDirectory*()> {
    public:
        Task(BlockDirectory* directory)
            : m_directory(directory)
        {
        }
        
        BlockDirectory* run() final
        {
            Locker locker { m_lock };
            BlockDirectory* result = m_directory;
            if (result)
                m_directory = result->nextDirectoryInSubspace();
            return result;
        }
        
    private:
        BlockDirectory* m_directory;
        Lock m_lock;
    };
    
    return adoptRef(*new Task(m_firstDirectory));
}

Ref<SharedTask<MarkedBlock::Handle*()>> Subspace::parallelNotEmptyMarkedBlockSource()
{
    return createParallelSourceAdapter<BlockDirectory*, MarkedBlock::Handle*>(
        parallelDirectorySource(),
        [] (BlockDirectory* directory) -> RefPtr<SharedTask<MarkedBlock::Handle*()>> {
            if (!directory)
                return nullptr;
            return directory->parallelNotEmptyBlockSource();
        });
}

void Subspace::sweepBlocks()
{
    forEachDirectory(
        [&] (BlockDirectory& directory) {
            directory.sweep();
        });
}

void Subspace::didResizeBits(unsigned)
{
}

void Subspace::didRemoveBlock(unsigned)
{
}

void Subspace::didBeginSweepingToFreeList(MarkedBlock::Handle*)
{
}

} // namespace JSC

