]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/CodeBlockSet.cpp
2a818f0e1ac8bdbc99885f020ff057bb970ecd72
[apple/javascriptcore.git] / heap / CodeBlockSet.cpp
1 /*
2 * Copyright (C) 2013, 2014 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 "CodeBlockSet.h"
28
29 #include "CodeBlock.h"
30 #include "JSCInlines.h"
31 #include "SlotVisitor.h"
32 #include <wtf/CommaPrinter.h>
33
34 namespace JSC {
35
36 static const bool verbose = false;
37
38 CodeBlockSet::CodeBlockSet(BlockAllocator& blockAllocator)
39 : m_currentlyExecuting(blockAllocator)
40 {
41 }
42
43 CodeBlockSet::~CodeBlockSet()
44 {
45 for (CodeBlock* codeBlock : m_oldCodeBlocks)
46 codeBlock->deref();
47
48 for (CodeBlock* codeBlock : m_newCodeBlocks)
49 codeBlock->deref();
50 }
51
52 void CodeBlockSet::add(PassRefPtr<CodeBlock> codeBlock)
53 {
54 CodeBlock* block = codeBlock.leakRef();
55 bool isNewEntry = m_newCodeBlocks.add(block).isNewEntry;
56 ASSERT_UNUSED(isNewEntry, isNewEntry);
57 }
58
59 void CodeBlockSet::promoteYoungCodeBlocks()
60 {
61 m_oldCodeBlocks.add(m_newCodeBlocks.begin(), m_newCodeBlocks.end());
62 m_newCodeBlocks.clear();
63 }
64
65 void CodeBlockSet::clearMarksForFullCollection()
66 {
67 for (CodeBlock* codeBlock : m_oldCodeBlocks) {
68 codeBlock->m_mayBeExecuting = false;
69 codeBlock->m_visitAggregateHasBeenCalled = false;
70 }
71
72 // We promote after we clear marks on the old generation CodeBlocks because
73 // none of the young generations CodeBlocks need to be cleared.
74 promoteYoungCodeBlocks();
75 }
76
77 void CodeBlockSet::clearMarksForEdenCollection(const Vector<const JSCell*>& rememberedSet)
78 {
79 // This ensures that we will revisit CodeBlocks in remembered Executables even if they were previously marked.
80 for (const JSCell* cell : rememberedSet) {
81 ScriptExecutable* executable = const_cast<ScriptExecutable*>(jsDynamicCast<const ScriptExecutable*>(cell));
82 if (!executable)
83 continue;
84 executable->forEachCodeBlock([](CodeBlock* codeBlock) {
85 codeBlock->m_mayBeExecuting = false;
86 codeBlock->m_visitAggregateHasBeenCalled = false;
87 });
88 }
89 }
90
91 void CodeBlockSet::deleteUnmarkedAndUnreferenced(HeapOperation collectionType)
92 {
93 HashSet<CodeBlock*>& set = collectionType == EdenCollection ? m_newCodeBlocks : m_oldCodeBlocks;
94
95 // This needs to be a fixpoint because code blocks that are unmarked may
96 // refer to each other. For example, a DFG code block that is owned by
97 // the GC may refer to an FTL for-entry code block that is also owned by
98 // the GC.
99 Vector<CodeBlock*, 16> toRemove;
100 if (verbose)
101 dataLog("Fixpointing over unmarked, set size = ", set.size(), "...\n");
102 for (;;) {
103 for (CodeBlock* codeBlock : set) {
104 if (!codeBlock->hasOneRef())
105 continue;
106 if (codeBlock->m_mayBeExecuting)
107 continue;
108 codeBlock->deref();
109 toRemove.append(codeBlock);
110 }
111 if (verbose)
112 dataLog(" Removing ", toRemove.size(), " blocks.\n");
113 if (toRemove.isEmpty())
114 break;
115 for (CodeBlock* codeBlock : toRemove)
116 set.remove(codeBlock);
117 toRemove.resize(0);
118 }
119
120 // Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks.
121 if (collectionType == EdenCollection)
122 promoteYoungCodeBlocks();
123 }
124
125 void CodeBlockSet::remove(CodeBlock* codeBlock)
126 {
127 codeBlock->deref();
128 if (m_oldCodeBlocks.contains(codeBlock)) {
129 m_oldCodeBlocks.remove(codeBlock);
130 return;
131 }
132 ASSERT(m_newCodeBlocks.contains(codeBlock));
133 m_newCodeBlocks.remove(codeBlock);
134 }
135
136 void CodeBlockSet::traceMarked(SlotVisitor& visitor)
137 {
138 if (verbose)
139 dataLog("Tracing ", m_currentlyExecuting.size(), " code blocks.\n");
140 for (CodeBlock* codeBlock : m_currentlyExecuting) {
141 ASSERT(codeBlock->m_mayBeExecuting);
142 codeBlock->visitAggregate(visitor);
143 }
144 }
145
146 void CodeBlockSet::rememberCurrentlyExecutingCodeBlocks(Heap* heap)
147 {
148 #if ENABLE(GGC)
149 if (verbose)
150 dataLog("Remembering ", m_currentlyExecuting.size(), " code blocks.\n");
151 for (CodeBlock* codeBlock : m_currentlyExecuting) {
152 heap->addToRememberedSet(codeBlock->ownerExecutable());
153 ASSERT(codeBlock->m_mayBeExecuting);
154 }
155 m_currentlyExecuting.clear();
156 #else
157 UNUSED_PARAM(heap);
158 #endif // ENABLE(GGC)
159 }
160
161 void CodeBlockSet::dump(PrintStream& out) const
162 {
163 CommaPrinter comma;
164 out.print("{old = [");
165 for (CodeBlock* codeBlock : m_oldCodeBlocks)
166 out.print(comma, pointerDump(codeBlock));
167 out.print("], new = [");
168 comma = CommaPrinter();
169 for (CodeBlock* codeBlock : m_newCodeBlocks)
170 out.print(comma, pointerDump(codeBlock));
171 out.print("], currentlyExecuting = [");
172 comma = CommaPrinter();
173 for (CodeBlock* codeBlock : m_currentlyExecuting)
174 out.print(comma, pointerDump(codeBlock));
175 out.print("]}");
176 }
177
178 } // namespace JSC
179