1/*
2 * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "Subspace.h"
28
29#include "AlignedMemoryAllocator.h"
30#include "BlockDirectoryInlines.h"
31#include "HeapCellType.h"
32#include "JSCInlines.h"
33#include "MarkedBlockInlines.h"
34#include "ParallelSourceAdapter.h"
35#include "PreventCollectionScope.h"
36#include "SubspaceInlines.h"
37
38namespace JSC {
39
40Subspace::Subspace(CString name, Heap& heap)
41 : m_space(heap.objectSpace())
42 , m_name(name)
43{
44}
45
46void Subspace::initialize(HeapCellType* heapCellType, AlignedMemoryAllocator* alignedMemoryAllocator)
47{
48 m_heapCellType = heapCellType;
49 m_alignedMemoryAllocator = alignedMemoryAllocator;
50 m_directoryForEmptyAllocation = m_alignedMemoryAllocator->firstDirectory();
51
52 Heap& heap = *m_space.heap();
53 heap.objectSpace().m_subspaces.append(this);
54 m_alignedMemoryAllocator->registerSubspace(this);
55}
56
57Subspace::~Subspace()
58{
59}
60
61void Subspace::finishSweep(MarkedBlock::Handle& block, FreeList* freeList)
62{
63 m_heapCellType->finishSweep(block, freeList);
64}
65
66void Subspace::destroy(VM& vm, JSCell* cell)
67{
68 m_heapCellType->destroy(vm, cell);
69}
70
71void Subspace::prepareForAllocation()
72{
73 forEachDirectory(
74 [&] (BlockDirectory& directory) {
75 directory.prepareForAllocation();
76 });
77
78 m_directoryForEmptyAllocation = m_alignedMemoryAllocator->firstDirectory();
79}
80
81MarkedBlock::Handle* Subspace::findEmptyBlockToSteal()
82{
83 for (; m_directoryForEmptyAllocation; m_directoryForEmptyAllocation = m_directoryForEmptyAllocation->nextDirectoryInAlignedMemoryAllocator()) {
84 if (MarkedBlock::Handle* block = m_directoryForEmptyAllocation->findEmptyBlockToSteal())
85 return block;
86 }
87 return nullptr;
88}
89
90Ref<SharedTask<BlockDirectory*()>> Subspace::parallelDirectorySource()
91{
92 class Task : public SharedTask<BlockDirectory*()> {
93 public:
94 Task(BlockDirectory* directory)
95 : m_directory(directory)
96 {
97 }
98
99 BlockDirectory* run() override
100 {
101 auto locker = holdLock(m_lock);
102 BlockDirectory* result = m_directory;
103 if (result)
104 m_directory = result->nextDirectoryInSubspace();
105 return result;
106 }
107
108 private:
109 BlockDirectory* m_directory;
110 Lock m_lock;
111 };
112
113 return adoptRef(*new Task(m_firstDirectory));
114}
115
116Ref<SharedTask<MarkedBlock::Handle*()>> Subspace::parallelNotEmptyMarkedBlockSource()
117{
118 return createParallelSourceAdapter<BlockDirectory*, MarkedBlock::Handle*>(
119 parallelDirectorySource(),
120 [] (BlockDirectory* directory) -> RefPtr<SharedTask<MarkedBlock::Handle*()>> {
121 if (!directory)
122 return nullptr;
123 return directory->parallelNotEmptyBlockSource();
124 });
125}
126
127void Subspace::sweep()
128{
129 forEachDirectory(
130 [&] (BlockDirectory& directory) {
131 directory.sweep();
132 });
133}
134
135void Subspace::didResizeBits(size_t)
136{
137}
138
139void Subspace::didRemoveBlock(size_t)
140{
141}
142
143void Subspace::didBeginSweepingToFreeList(MarkedBlock::Handle*)
144{
145}
146
147} // namespace JSC
148
149