Unreviewed, rolling out r190522.
https://bugs.webkit.org/show_bug.cgi?id=149787
Caused a lot of leaks (Requested by ap on #webkit).
Reverted changeset:
"Unreviewed, rolling back in r190450"
https://bugs.webkit.org/show_bug.cgi?id=149727
http://trac.webkit.org/changeset/190522
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@190546 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/heap/CodeBlockSet.cpp b/Source/JavaScriptCore/heap/CodeBlockSet.cpp
index cfeb81f..3eda521 100644
--- a/Source/JavaScriptCore/heap/CodeBlockSet.cpp
+++ b/Source/JavaScriptCore/heap/CodeBlockSet.cpp
@@ -41,11 +41,17 @@
CodeBlockSet::~CodeBlockSet()
{
+ for (CodeBlock* codeBlock : m_oldCodeBlocks)
+ codeBlock->deref();
+
+ for (CodeBlock* codeBlock : m_newCodeBlocks)
+ codeBlock->deref();
}
-void CodeBlockSet::add(CodeBlock* codeBlock)
+void CodeBlockSet::add(PassRefPtr<CodeBlock> codeBlock)
{
- bool isNewEntry = m_newCodeBlocks.add(codeBlock).isNewEntry;
+ CodeBlock* block = codeBlock.leakRef();
+ bool isNewEntry = m_newCodeBlocks.add(block).isNewEntry;
ASSERT_UNUSED(isNewEntry, isNewEntry);
}
@@ -58,26 +64,52 @@
void CodeBlockSet::clearMarksForFullCollection()
{
for (CodeBlock* codeBlock : m_oldCodeBlocks)
- codeBlock->clearVisitWeaklyHasBeenCalled();
+ codeBlock->clearMarks();
// We promote after we clear marks on the old generation CodeBlocks because
// none of the young generations CodeBlocks need to be cleared.
promoteYoungCodeBlocks();
}
+void CodeBlockSet::clearMarksForEdenCollection(const Vector<const JSCell*>& rememberedSet)
+{
+ // This ensures that we will revisit CodeBlocks in remembered Executables even if they were previously marked.
+ for (const JSCell* cell : rememberedSet) {
+ ScriptExecutable* executable = const_cast<ScriptExecutable*>(jsDynamicCast<const ScriptExecutable*>(cell));
+ if (!executable)
+ continue;
+ executable->forEachCodeBlock([this](CodeBlock* codeBlock) {
+ codeBlock->clearMarks();
+ m_remembered.add(codeBlock);
+ });
+ }
+}
+
void CodeBlockSet::deleteUnmarkedAndUnreferenced(HeapOperation collectionType)
{
HashSet<CodeBlock*>& set = collectionType == EdenCollection ? m_newCodeBlocks : m_oldCodeBlocks;
- Vector<CodeBlock*> unmarked;
- for (CodeBlock* codeBlock : set) {
- if (Heap::isMarked(codeBlock))
- continue;
- unmarked.append(codeBlock);
- }
- for (CodeBlock* codeBlock : unmarked) {
- codeBlock->classInfo()->methodTable.destroy(codeBlock);
- set.remove(codeBlock);
+ // This needs to be a fixpoint because code blocks that are unmarked may
+ // refer to each other. For example, a DFG code block that is owned by
+ // the GC may refer to an FTL for-entry code block that is also owned by
+ // the GC.
+ Vector<CodeBlock*, 16> toRemove;
+ if (verbose)
+ dataLog("Fixpointing over unmarked, set size = ", set.size(), "...\n");
+ for (;;) {
+ for (CodeBlock* codeBlock : set) {
+ if (!codeBlock->hasOneRef())
+ continue;
+ codeBlock->deref();
+ toRemove.append(codeBlock);
+ }
+ if (verbose)
+ dataLog(" Removing ", toRemove.size(), " blocks.\n");
+ if (toRemove.isEmpty())
+ break;
+ for (CodeBlock* codeBlock : toRemove)
+ set.remove(codeBlock);
+ toRemove.resize(0);
}
// Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks.
@@ -87,6 +119,7 @@
void CodeBlockSet::remove(CodeBlock* codeBlock)
{
+ codeBlock->deref();
if (m_oldCodeBlocks.contains(codeBlock)) {
m_oldCodeBlocks.remove(codeBlock);
return;
@@ -95,13 +128,35 @@
m_newCodeBlocks.remove(codeBlock);
}
+void CodeBlockSet::traceMarked(SlotVisitor& visitor)
+{
+ if (verbose)
+ dataLog("Tracing ", m_currentlyExecuting.size(), " code blocks.\n");
+
+ // We strongly visit the currently executing set because jettisoning code
+ // is not valuable once it's on the stack. We're past the point where
+ // jettisoning would avoid the cost of OSR exit.
+ for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+ codeBlock->visitStrongly(visitor);
+
+ // We strongly visit the remembered set because jettisoning old code during
+ // Eden GC is unsound. There might be an old object with a strong reference
+ // to the code.
+ for (const RefPtr<CodeBlock>& codeBlock : m_remembered)
+ codeBlock->visitStrongly(visitor);
+}
+
void CodeBlockSet::rememberCurrentlyExecutingCodeBlocks(Heap* heap)
{
if (verbose)
dataLog("Remembering ", m_currentlyExecuting.size(), " code blocks.\n");
- for (CodeBlock* codeBlock : m_currentlyExecuting)
- heap->addToRememberedSet(codeBlock);
+ for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+ heap->addToRememberedSet(codeBlock->ownerExecutable());
+
+ // It's safe to clear these RefPtr sets because we won't delete the CodeBlocks
+ // in them until the next GC, and we'll recompute them at that time.
m_currentlyExecuting.clear();
+ m_remembered.clear();
}
void CodeBlockSet::dump(PrintStream& out) const
@@ -116,8 +171,8 @@
out.print(comma, pointerDump(codeBlock));
out.print("], currentlyExecuting = [");
comma = CommaPrinter();
- for (CodeBlock* codeBlock : m_currentlyExecuting)
- out.print(comma, pointerDump(codeBlock));
+ for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+ out.print(comma, pointerDump(codeBlock.get()));
out.print("]}");
}