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