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#pragma once
27
28#include "AllocationFailureMode.h"
29#include "AllocatorForMode.h"
30#include "Allocator.h"
31#include "MarkedBlock.h"
32#include "MarkedSpace.h"
33#include <wtf/text/CString.h>
34
35namespace JSC {
36
37class AlignedMemoryAllocator;
38class HeapCellType;
39
40// The idea of subspaces is that you can provide some custom behavior for your objects if you
41// allocate them from a custom Subspace in which you override some of the virtual methods. This
42// class is the baseclass of Subspaces. Usually you will use either Subspace or FixedSizeSubspace.
43class Subspace {
44 WTF_MAKE_NONCOPYABLE(Subspace);
45 WTF_MAKE_FAST_ALLOCATED;
46public:
47 JS_EXPORT_PRIVATE Subspace(CString name, Heap&);
48 JS_EXPORT_PRIVATE virtual ~Subspace();
49
50 const char* name() const { return m_name.data(); }
51 MarkedSpace& space() const { return m_space; }
52
53 const CellAttributes& attributes() const;
54 HeapCellType* heapCellType() const { return m_heapCellType; }
55 AlignedMemoryAllocator* alignedMemoryAllocator() const { return m_alignedMemoryAllocator; }
56
57 void finishSweep(MarkedBlock::Handle&, FreeList*);
58 void destroy(VM&, JSCell*);
59
60 virtual Allocator allocatorFor(size_t, AllocatorForMode) = 0;
61 virtual void* allocate(VM&, size_t, GCDeferralContext*, AllocationFailureMode) = 0;
62
63 void prepareForAllocation();
64
65 void didCreateFirstDirectory(BlockDirectory* directory) { m_directoryForEmptyAllocation = directory; }
66
67 // Finds an empty block from any Subspace that agrees to trade blocks with us.
68 MarkedBlock::Handle* findEmptyBlockToSteal();
69
70 template<typename Func>
71 void forEachDirectory(const Func&);
72
73 Ref<SharedTask<BlockDirectory*()>> parallelDirectorySource();
74
75 template<typename Func>
76 void forEachMarkedBlock(const Func&);
77
78 template<typename Func>
79 void forEachNotEmptyMarkedBlock(const Func&);
80
81 JS_EXPORT_PRIVATE Ref<SharedTask<MarkedBlock::Handle*()>> parallelNotEmptyMarkedBlockSource();
82
83 template<typename Func>
84 void forEachLargeAllocation(const Func&);
85
86 template<typename Func>
87 void forEachMarkedCell(const Func&);
88
89 template<typename Func>
90 Ref<SharedTask<void(SlotVisitor&)>> forEachMarkedCellInParallel(const Func&);
91
92 template<typename Func>
93 void forEachLiveCell(const Func&);
94
95 void sweep();
96
97 Subspace* nextSubspaceInAlignedMemoryAllocator() const { return m_nextSubspaceInAlignedMemoryAllocator; }
98 void setNextSubspaceInAlignedMemoryAllocator(Subspace* subspace) { m_nextSubspaceInAlignedMemoryAllocator = subspace; }
99
100 virtual void didResizeBits(size_t newSize);
101 virtual void didRemoveBlock(size_t blockIndex);
102 virtual void didBeginSweepingToFreeList(MarkedBlock::Handle*);
103
104protected:
105 void initialize(HeapCellType*, AlignedMemoryAllocator*);
106
107 MarkedSpace& m_space;
108
109 HeapCellType* m_heapCellType { nullptr };
110 AlignedMemoryAllocator* m_alignedMemoryAllocator { nullptr };
111
112 BlockDirectory* m_firstDirectory { nullptr };
113 BlockDirectory* m_directoryForEmptyAllocation { nullptr }; // Uses the MarkedSpace linked list of blocks.
114 SentinelLinkedList<LargeAllocation, BasicRawSentinelNode<LargeAllocation>> m_largeAllocations;
115 Subspace* m_nextSubspaceInAlignedMemoryAllocator { nullptr };
116
117 CString m_name;
118};
119
120} // namespace JSC
121
122