The allocator used to allocate memory for MarkedBlocks and LargeAllocations should...
[WebKit-https.git] / Source / JavaScriptCore / heap / Subspace.h
1 /*
2  * Copyright (C) 2017 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 "MarkedBlock.h"
29 #include "MarkedSpace.h"
30 #include <wtf/text/CString.h>
31
32 namespace JSC {
33
34 class AlignedMemoryAllocator;
35
36 // The idea of subspaces is that you can provide some custom behavior for your objects if you
37 // allocate them from a custom Subspace in which you override some of the virtual methods. This
38 // class is the baseclass of Subspaces and it provides a reasonable default implementation, where
39 // sweeping assumes immortal structure. The common ways of overriding this are:
40 //
41 // - Provide customized destructor behavior. You can change how the destructor is called. You can
42 //   also specialize the destructor call in the loop.
43 //
44 // - Use the Subspace as a quick way to iterate all of the objects in that subspace.
45 class Subspace {
46     WTF_MAKE_NONCOPYABLE(Subspace);
47     WTF_MAKE_FAST_ALLOCATED;
48 public:
49     JS_EXPORT_PRIVATE Subspace(CString name, Heap&, AllocatorAttributes, AlignedMemoryAllocator*);
50     JS_EXPORT_PRIVATE virtual ~Subspace();
51     
52     const char* name() const { return m_name.data(); }
53     MarkedSpace& space() const { return m_space; }
54     
55     const AllocatorAttributes& attributes() const { return m_attributes; }
56     AlignedMemoryAllocator* alignedMemoryAllocator() const { return m_alignedMemoryAllocator; }
57     
58     // The purpose of overriding this is to specialize the sweep for your destructors. This won't
59     // be called for no-destructor blocks. This must call MarkedBlock::finishSweepKnowingSubspace.
60     virtual void finishSweep(MarkedBlock::Handle&, FreeList*);
61     
62     // These get called for large objects.
63     virtual void destroy(VM&, JSCell*);
64     
65     MarkedAllocator* tryAllocatorFor(size_t);
66     MarkedAllocator* allocatorFor(size_t);
67     
68     JS_EXPORT_PRIVATE void* allocate(size_t);
69     JS_EXPORT_PRIVATE void* allocate(GCDeferralContext*, size_t);
70     
71     JS_EXPORT_PRIVATE void* tryAllocate(size_t);
72     JS_EXPORT_PRIVATE void* tryAllocate(GCDeferralContext*, size_t);
73     
74     void prepareForAllocation();
75     
76     void didCreateFirstAllocator(MarkedAllocator* allocator) { m_allocatorForEmptyAllocation = allocator; }
77     
78     // Finds an empty block from any Subspace that agrees to trade blocks with us.
79     MarkedBlock::Handle* findEmptyBlockToSteal();
80     
81     template<typename Func>
82     void forEachAllocator(const Func&);
83     
84     template<typename Func>
85     void forEachMarkedBlock(const Func&);
86     
87     template<typename Func>
88     void forEachNotEmptyMarkedBlock(const Func&);
89     
90     template<typename Func>
91     void forEachLargeAllocation(const Func&);
92     
93     template<typename Func>
94     void forEachMarkedCell(const Func&);
95
96     template<typename Func>
97     void forEachLiveCell(const Func&);
98     
99     static ptrdiff_t offsetOfAllocatorForSizeStep() { return OBJECT_OFFSETOF(Subspace, m_allocatorForSizeStep); }
100     
101     MarkedAllocator** allocatorForSizeStep() { return &m_allocatorForSizeStep[0]; }
102
103 private:
104     MarkedAllocator* allocatorForSlow(size_t);
105     
106     // These slow paths are concerned with large allocations and allocator creation.
107     void* allocateSlow(GCDeferralContext*, size_t);
108     void* tryAllocateSlow(GCDeferralContext*, size_t);
109     
110     void didAllocate(void*);
111     
112     MarkedSpace& m_space;
113     
114     CString m_name;
115     AllocatorAttributes m_attributes;
116     
117     AlignedMemoryAllocator* m_alignedMemoryAllocator;
118     
119     std::array<MarkedAllocator*, MarkedSpace::numSizeClasses> m_allocatorForSizeStep;
120     MarkedAllocator* m_firstAllocator { nullptr };
121     MarkedAllocator* m_allocatorForEmptyAllocation { nullptr }; // Uses the MarkedSpace linked list of blocks.
122     SentinelLinkedList<LargeAllocation, BasicRawSentinelNode<LargeAllocation>> m_largeAllocations;
123 };
124
125 ALWAYS_INLINE MarkedAllocator* Subspace::tryAllocatorFor(size_t size)
126 {
127     if (size <= MarkedSpace::largeCutoff)
128         return m_allocatorForSizeStep[MarkedSpace::sizeClassToIndex(size)];
129     return nullptr;
130 }
131
132 ALWAYS_INLINE MarkedAllocator* Subspace::allocatorFor(size_t size)
133 {
134     if (size <= MarkedSpace::largeCutoff) {
135         if (MarkedAllocator* result = m_allocatorForSizeStep[MarkedSpace::sizeClassToIndex(size)])
136             return result;
137         return allocatorForSlow(size);
138     }
139     return nullptr;
140 }
141
142 } // namespace JSC
143