95591c306ff6c1de377a8c5c466576e8f6d4a7bc
[WebKit-https.git] / Source / JavaScriptCore / heap / SlotVisitorInlines.h
1 /*
2  * Copyright (C) 2012-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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "SlotVisitor.h"
29 #include "Weak.h"
30 #include "WeakInlines.h"
31
32 namespace JSC {
33
34 ALWAYS_INLINE void SlotVisitor::appendUnbarriered(JSValue* slot, size_t count)
35 {
36     for (size_t i = count; i--;)
37         appendUnbarriered(slot[i]);
38 }
39
40 ALWAYS_INLINE void SlotVisitor::appendUnbarriered(JSCell* cell)
41 {
42     // This needs to be written in a very specific way to ensure that it gets inlined
43     // properly. In particular, it appears that using templates here breaks ALWAYS_INLINE.
44     
45     if (!cell)
46         return;
47     
48     Dependency dependency;
49     if (UNLIKELY(cell->isLargeAllocation())) {
50         dependency = nullDependency();
51         if (LIKELY(cell->largeAllocation().isMarked())) {
52             if (LIKELY(!m_heapSnapshotBuilder))
53                 return;
54         }
55     } else {
56         MarkedBlock& block = cell->markedBlock();
57         dependency = block.aboutToMark(m_markingVersion);
58         if (LIKELY(block.isMarked(cell, dependency))) {
59             if (LIKELY(!m_heapSnapshotBuilder))
60                 return;
61         }
62     }
63     
64     appendSlow(cell, dependency);
65 }
66
67 ALWAYS_INLINE void SlotVisitor::appendUnbarriered(JSValue value)
68 {
69     if (value.isCell())
70         appendUnbarriered(value.asCell());
71 }
72
73 ALWAYS_INLINE void SlotVisitor::appendHiddenUnbarriered(JSValue value)
74 {
75     if (value.isCell())
76         appendHiddenUnbarriered(value.asCell());
77 }
78
79 ALWAYS_INLINE void SlotVisitor::appendHiddenUnbarriered(JSCell* cell)
80 {
81     // This needs to be written in a very specific way to ensure that it gets inlined
82     // properly. In particular, it appears that using templates here breaks ALWAYS_INLINE.
83     
84     if (!cell)
85         return;
86     
87     Dependency dependency;
88     if (UNLIKELY(cell->isLargeAllocation())) {
89         dependency = nullDependency();
90         if (LIKELY(cell->largeAllocation().isMarked()))
91             return;
92     } else {
93         MarkedBlock& block = cell->markedBlock();
94         dependency = block.aboutToMark(m_markingVersion);
95         if (LIKELY(block.isMarked(cell, dependency)))
96             return;
97     }
98     
99     appendHiddenSlow(cell, dependency);
100 }
101
102 template<typename T>
103 ALWAYS_INLINE void SlotVisitor::append(const Weak<T>& weak)
104 {
105     appendUnbarriered(weak.get());
106 }
107
108 template<typename T>
109 ALWAYS_INLINE void SlotVisitor::append(const WriteBarrierBase<T>& slot)
110 {
111     appendUnbarriered(slot.get());
112 }
113
114 template<typename T>
115 ALWAYS_INLINE void SlotVisitor::appendHidden(const WriteBarrierBase<T>& slot)
116 {
117     appendHiddenUnbarriered(slot.get());
118 }
119
120 template<typename Iterator>
121 ALWAYS_INLINE void SlotVisitor::append(Iterator begin, Iterator end)
122 {
123     for (auto it = begin; it != end; ++it)
124         append(*it);
125 }
126
127 ALWAYS_INLINE void SlotVisitor::appendValues(const WriteBarrierBase<Unknown>* barriers, size_t count)
128 {
129     for (size_t i = 0; i < count; ++i)
130         append(barriers[i]);
131 }
132
133 ALWAYS_INLINE void SlotVisitor::appendValuesHidden(const WriteBarrierBase<Unknown>* barriers, size_t count)
134 {
135     for (size_t i = 0; i < count; ++i)
136         appendHidden(barriers[i]);
137 }
138
139 inline void SlotVisitor::reportExtraMemoryVisited(size_t size)
140 {
141     if (m_isFirstVisit) {
142         heap()->reportExtraMemoryVisited(size);
143         m_nonCellVisitCount += size;
144     }
145 }
146
147 #if ENABLE(RESOURCE_USAGE)
148 inline void SlotVisitor::reportExternalMemoryVisited(size_t size)
149 {
150     if (m_isFirstVisit)
151         heap()->reportExternalMemoryVisited(size);
152 }
153 #endif
154
155 inline Heap* SlotVisitor::heap() const
156 {
157     return &m_heap;
158 }
159
160 inline VM& SlotVisitor::vm()
161 {
162     return *m_heap.m_vm;
163 }
164
165 inline const VM& SlotVisitor::vm() const
166 {
167     return *m_heap.m_vm;
168 }
169
170 template<typename Func>
171 IterationStatus SlotVisitor::forEachMarkStack(const Func& func)
172 {
173     if (func(m_collectorStack) == IterationStatus::Done)
174         return IterationStatus::Done;
175     if (func(m_mutatorStack) == IterationStatus::Done)
176         return IterationStatus::Done;
177     return IterationStatus::Continue;
178 }
179
180 } // namespace JSC