diff options
Diffstat (limited to 'Source/JavaScriptCore/heap/CodeBlockSet.cpp')
-rw-r--r-- | Source/JavaScriptCore/heap/CodeBlockSet.cpp | 145 |
1 files changed, 81 insertions, 64 deletions
diff --git a/Source/JavaScriptCore/heap/CodeBlockSet.cpp b/Source/JavaScriptCore/heap/CodeBlockSet.cpp index c04cbacd6..6d305baf1 100644 --- a/Source/JavaScriptCore/heap/CodeBlockSet.cpp +++ b/Source/JavaScriptCore/heap/CodeBlockSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,94 +27,111 @@ #include "CodeBlockSet.h" #include "CodeBlock.h" -#include "SlotVisitor.h" +#include "JSCInlines.h" +#include <wtf/CommaPrinter.h> namespace JSC { -static const bool verbose = false; - -CodeBlockSet::CodeBlockSet() { } +CodeBlockSet::CodeBlockSet() +{ +} CodeBlockSet::~CodeBlockSet() { - HashSet<CodeBlock*>::iterator iter = m_set.begin(); - HashSet<CodeBlock*>::iterator end = m_set.end(); - for (; iter != end; ++iter) - (*iter)->deref(); } -void CodeBlockSet::add(PassRefPtr<CodeBlock> codeBlock) +void CodeBlockSet::add(CodeBlock* codeBlock) { - CodeBlock* block = codeBlock.leakRef(); - bool isNewEntry = m_set.add(block).isNewEntry; + LockHolder locker(&m_lock); + bool isNewEntry = m_newCodeBlocks.add(codeBlock).isNewEntry; ASSERT_UNUSED(isNewEntry, isNewEntry); } -void CodeBlockSet::clearMarks() +void CodeBlockSet::promoteYoungCodeBlocks(const LockHolder&) { - HashSet<CodeBlock*>::iterator iter = m_set.begin(); - HashSet<CodeBlock*>::iterator end = m_set.end(); - for (; iter != end; ++iter) { - CodeBlock* codeBlock = *iter; - codeBlock->m_mayBeExecuting = false; - codeBlock->m_visitAggregateHasBeenCalled = false; - } + ASSERT(m_lock.isLocked()); + m_oldCodeBlocks.add(m_newCodeBlocks.begin(), m_newCodeBlocks.end()); + m_newCodeBlocks.clear(); +} + +void CodeBlockSet::clearMarksForFullCollection() +{ + LockHolder locker(&m_lock); + for (CodeBlock* codeBlock : m_oldCodeBlocks) + codeBlock->clearVisitWeaklyHasBeenCalled(); +} + +void CodeBlockSet::lastChanceToFinalize(VM& vm) +{ + LockHolder locker(&m_lock); + for (CodeBlock* codeBlock : m_newCodeBlocks) + codeBlock->structure(vm)->classInfo()->methodTable.destroy(codeBlock); + + for (CodeBlock* codeBlock : m_oldCodeBlocks) + codeBlock->structure(vm)->classInfo()->methodTable.destroy(codeBlock); } -void CodeBlockSet::deleteUnmarkedAndUnreferenced() +void CodeBlockSet::deleteUnmarkedAndUnreferenced(VM& vm, CollectionScope scope) { - // 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 = ", m_set.size(), "...\n"); - for (;;) { - HashSet<CodeBlock*>::iterator iter = m_set.begin(); - HashSet<CodeBlock*>::iterator end = m_set.end(); - for (; iter != end; ++iter) { - CodeBlock* codeBlock = *iter; - if (!codeBlock->hasOneRef()) - continue; - if (codeBlock->m_mayBeExecuting) - continue; - codeBlock->deref(); - toRemove.append(codeBlock); + LockHolder locker(&m_lock); + Vector<CodeBlock*> unmarked; + + auto consider = [&] (HashSet<CodeBlock*>& set) { + for (CodeBlock* codeBlock : set) { + if (Heap::isMarked(codeBlock)) + continue;; + unmarked.append(codeBlock); + } + for (CodeBlock* codeBlock : unmarked) { + codeBlock->structure(vm)->classInfo()->methodTable.destroy(codeBlock); + set.remove(codeBlock); } - if (verbose) - dataLog(" Removing ", toRemove.size(), " blocks.\n"); - if (toRemove.isEmpty()) - break; - for (unsigned i = toRemove.size(); i--;) - m_set.remove(toRemove[i]); - toRemove.resize(0); + unmarked.resize(0); + }; + + switch (scope) { + case CollectionScope::Eden: + consider(m_newCodeBlocks); + break; + case CollectionScope::Full: + consider(m_oldCodeBlocks); + consider(m_newCodeBlocks); + break; } + + // Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks. + promoteYoungCodeBlocks(locker); } -void CodeBlockSet::traceMarked(SlotVisitor& visitor) +bool CodeBlockSet::contains(const LockHolder&, void* candidateCodeBlock) { - if (verbose) - dataLog("Tracing ", m_set.size(), " code blocks.\n"); - HashSet<CodeBlock*>::iterator iter = m_set.begin(); - HashSet<CodeBlock*>::iterator end = m_set.end(); - for (; iter != end; ++iter) { - CodeBlock* codeBlock = *iter; - if (!codeBlock->m_mayBeExecuting) - continue; - codeBlock->visitAggregate(visitor); - } + RELEASE_ASSERT(m_lock.isLocked()); + CodeBlock* codeBlock = static_cast<CodeBlock*>(candidateCodeBlock); + if (!HashSet<CodeBlock*>::isValidValue(codeBlock)) + return false; + return m_oldCodeBlocks.contains(codeBlock) || m_newCodeBlocks.contains(codeBlock) || m_currentlyExecuting.contains(codeBlock); } -void CodeBlockSet::rememberCurrentlyExecutingCodeBlocks(Heap* heap) +void CodeBlockSet::clearCurrentlyExecuting() { -#if ENABLE(GGC) - for (size_t i = 0; i < m_currentlyExecuting.size(); ++i) - heap->addToRememberedSet(m_currentlyExecuting[i]->ownerExecutable()); m_currentlyExecuting.clear(); -#else - UNUSED_PARAM(heap); -#endif // ENABLE(GGC) +} + +void CodeBlockSet::dump(PrintStream& out) const +{ + CommaPrinter comma; + out.print("{old = ["); + for (CodeBlock* codeBlock : m_oldCodeBlocks) + out.print(comma, pointerDump(codeBlock)); + out.print("], new = ["); + comma = CommaPrinter(); + for (CodeBlock* codeBlock : m_newCodeBlocks) + out.print(comma, pointerDump(codeBlock)); + out.print("], currentlyExecuting = ["); + comma = CommaPrinter(); + for (CodeBlock* codeBlock : m_currentlyExecuting) + out.print(comma, pointerDump(codeBlock)); + out.print("]}"); } } // namespace JSC |