Ignore:
Timestamp:
Jan 9, 2018, 4:30:38 PM (8 years ago)
Author:
[email protected]
Message:

CodeBlocks should be in IsoSubspaces
https://bugs.webkit.org/show_bug.cgi?id=180884

Reviewed by Saam Barati.
Source/JavaScriptCore:


This moves CodeBlocks into IsoSubspaces. Doing so means that we no longer need to have the
special CodeBlockSet HashSets of new and old CodeBlocks. We also no longer use
WeakReferenceHarvester or UnconditionalFinalizer. Instead:

  • Code block sweeping is now just eager sweeping. This means that it automatically takes advantage of our unswept set, which roughly corresponds to what CodeBlockSet used to use its eden set for.


  • Those idea of Executable "weakly visiting" the CodeBlock is replaced by Executable marking a ExecutableToCodeBlockEdge object. That object being marked corresponds to what we used to call CodeBlock "having been weakly visited". This means that CodeBlockSet no longer has to clear the set of weakly visited code blocks. This also means that determining CodeBlock liveness, propagating CodeBlock transitions, and jettisoning CodeBlocks during GC are now the edge's job. The edge is also in an IsoSubspace and it has IsoCellSets to tell us which edges have output constraints (what we used to call CodeBlock's weak reference harvester) and which have unconditional finalizers.


  • CodeBlock now uses an IsoCellSet to tell if it has an unconditional finalizer.


  • CodeBlockSet still exists! It has one unified HashSet of CodeBlocks that we use to handle requests from the sampler, debugger, and other facilities. They may want to ask if some pointer corresponds to a CodeBlock during stages of execution during which the GC is unable to answer isLive() queries. The trickiest is the sampling profiler thread. There is no way that the GC's isLive could tell us of a CodeBlock that had already been allocated has now been full constructed.


  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::finishCreationCommon):
(JSC::CodeBlock::~CodeBlock):
(JSC::CodeBlock::visitChildren):
(JSC::CodeBlock::propagateTransitions):
(JSC::CodeBlock::determineLiveness):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::stronglyVisitStrongReferences):
(JSC::CodeBlock::hasInstalledVMTrapBreakpoints const):
(JSC::CodeBlock::installVMTrapBreakpoints):
(JSC::CodeBlock::dumpMathICStats):
(JSC::CodeBlock::visitWeakly): Deleted.
(JSC::CodeBlock::WeakReferenceHarvester::visitWeakReferences): Deleted.
(JSC::CodeBlock::UnconditionalFinalizer::finalizeUnconditionally): Deleted.

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::subspaceFor):
(JSC::CodeBlock::ownerEdge const):
(JSC::CodeBlock::clearVisitWeaklyHasBeenCalled): Deleted.

  • bytecode/EvalCodeBlock.h:

(JSC::EvalCodeBlock::create): Deleted.
(JSC::EvalCodeBlock::createStructure): Deleted.
(JSC::EvalCodeBlock::variable): Deleted.
(JSC::EvalCodeBlock::numVariables): Deleted.
(JSC::EvalCodeBlock::functionHoistingCandidate): Deleted.
(JSC::EvalCodeBlock::numFunctionHoistingCandidates): Deleted.
(JSC::EvalCodeBlock::EvalCodeBlock): Deleted.
(JSC::EvalCodeBlock::unlinkedEvalCodeBlock const): Deleted.

  • bytecode/ExecutableToCodeBlockEdge.cpp: Added.

(JSC::ExecutableToCodeBlockEdge::createStructure):
(JSC::ExecutableToCodeBlockEdge::create):
(JSC::ExecutableToCodeBlockEdge::visitChildren):
(JSC::ExecutableToCodeBlockEdge::visitOutputConstraints):
(JSC::ExecutableToCodeBlockEdge::finalizeUnconditionally):
(JSC::ExecutableToCodeBlockEdge::activate):
(JSC::ExecutableToCodeBlockEdge::deactivate):
(JSC::ExecutableToCodeBlockEdge::deactivateAndUnwrap):
(JSC::ExecutableToCodeBlockEdge::wrap):
(JSC::ExecutableToCodeBlockEdge::wrapAndActivate):
(JSC::ExecutableToCodeBlockEdge::ExecutableToCodeBlockEdge):
(JSC::ExecutableToCodeBlockEdge::runConstraint):

  • bytecode/ExecutableToCodeBlockEdge.h: Added.

(JSC::ExecutableToCodeBlockEdge::subspaceFor):
(JSC::ExecutableToCodeBlockEdge::codeBlock const):
(JSC::ExecutableToCodeBlockEdge::unwrap):

  • bytecode/FunctionCodeBlock.h:

(JSC::FunctionCodeBlock::subspaceFor):
(JSC::FunctionCodeBlock::createStructure):

  • bytecode/ModuleProgramCodeBlock.h:

(JSC::ModuleProgramCodeBlock::create): Deleted.
(JSC::ModuleProgramCodeBlock::createStructure): Deleted.
(JSC::ModuleProgramCodeBlock::ModuleProgramCodeBlock): Deleted.

  • bytecode/ProgramCodeBlock.h:

(JSC::ProgramCodeBlock::create): Deleted.
(JSC::ProgramCodeBlock::createStructure): Deleted.
(JSC::ProgramCodeBlock::ProgramCodeBlock): Deleted.

  • debugger/Debugger.cpp:

(JSC::Debugger::SetSteppingModeFunctor::operator() const):
(JSC::Debugger::ToggleBreakpointFunctor::operator() const):
(JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::operator() const):
(JSC::Debugger::ClearDebuggerRequestsFunctor::operator() const):

  • heap/CodeBlockSet.cpp:

(JSC::CodeBlockSet::contains):
(JSC::CodeBlockSet::dump const):
(JSC::CodeBlockSet::add):
(JSC::CodeBlockSet::remove):
(JSC::CodeBlockSet::promoteYoungCodeBlocks): Deleted.
(JSC::CodeBlockSet::clearMarksForFullCollection): Deleted.
(JSC::CodeBlockSet::lastChanceToFinalize): Deleted.
(JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced): Deleted.

  • heap/CodeBlockSet.h:
  • heap/CodeBlockSetInlines.h:

(JSC::CodeBlockSet::iterate):
(JSC::CodeBlockSet::iterateViaSubspaces):

  • heap/ConservativeRoots.cpp:

(JSC::ConservativeRoots::genericAddPointer):
(JSC::DummyMarkHook::markKnownJSCell):
(JSC::CompositeMarkHook::mark):
(JSC::CompositeMarkHook::markKnownJSCell):

  • heap/ConservativeRoots.h:
  • heap/Heap.cpp:

(JSC::Heap::lastChanceToFinalize):
(JSC::Heap::finalizeMarkedUnconditionalFinalizers):
(JSC::Heap::finalizeUnconditionalFinalizers):
(JSC::Heap::beginMarking):
(JSC::Heap::deleteUnmarkedCompiledCode):
(JSC::Heap::sweepInFinalize):
(JSC::Heap::forEachCodeBlockImpl):
(JSC::Heap::forEachCodeBlockIgnoringJITPlansImpl):
(JSC::Heap::addCoreConstraints):
(JSC::Heap::finalizeUnconditionalFinalizersInIsoSubspace): Deleted.

  • heap/Heap.h:
  • heap/HeapCell.h:
  • heap/HeapCellInlines.h:

(JSC::HeapCell::subspace const):

  • heap/HeapInlines.h:

(JSC::Heap::forEachCodeBlock):
(JSC::Heap::forEachCodeBlockIgnoringJITPlans):

  • heap/HeapUtil.h:

(JSC::HeapUtil::findGCObjectPointersForMarking):

  • heap/IsoCellSet.cpp:

(JSC::IsoCellSet::parallelNotEmptyMarkedBlockSource):

  • heap/IsoCellSet.h:
  • heap/IsoCellSetInlines.h:

(JSC::IsoCellSet::forEachMarkedCellInParallel):
(JSC::IsoCellSet::forEachLiveCell):

  • heap/LargeAllocation.h:

(JSC::LargeAllocation::subspace const):

  • heap/MarkStackMergingConstraint.cpp:

(JSC::MarkStackMergingConstraint::executeImpl):

  • heap/MarkStackMergingConstraint.h:
  • heap/MarkedAllocator.cpp:

(JSC::MarkedAllocator::parallelNotEmptyBlockSource):

  • heap/MarkedBlock.cpp:

(JSC::MarkedBlock::Handle::didAddToAllocator):
(JSC::MarkedBlock::Handle::didRemoveFromAllocator):

  • heap/MarkedBlock.h:

(JSC::MarkedBlock::subspace const):

  • heap/MarkedBlockInlines.h:

(JSC::MarkedBlock::Handle::forEachLiveCell):

  • heap/MarkedSpaceInlines.h:

(JSC::MarkedSpace::forEachLiveCell):

  • heap/MarkingConstraint.cpp:

(JSC::MarkingConstraint::execute):
(JSC::MarkingConstraint::doParallelWork):
(JSC::MarkingConstraint::finishParallelWork): Deleted.
(JSC::MarkingConstraint::doParallelWorkImpl): Deleted.
(JSC::MarkingConstraint::finishParallelWorkImpl): Deleted.

  • heap/MarkingConstraint.h:
  • heap/MarkingConstraintSet.cpp:

(JSC::MarkingConstraintSet::add):

  • heap/MarkingConstraintSet.h:

(JSC::MarkingConstraintSet::add):

  • heap/MarkingConstraintSolver.cpp:

(JSC::MarkingConstraintSolver::execute):
(JSC::MarkingConstraintSolver::addParallelTask):
(JSC::MarkingConstraintSolver::runExecutionThread):
(JSC::MarkingConstraintSolver::didExecute): Deleted.

  • heap/MarkingConstraintSolver.h:

(JSC::MarkingConstraintSolver::TaskWithConstraint::TaskWithConstraint):
(JSC::MarkingConstraintSolver::TaskWithConstraint::operator== const):

  • heap/SimpleMarkingConstraint.cpp:

(JSC::SimpleMarkingConstraint::SimpleMarkingConstraint):
(JSC::SimpleMarkingConstraint::executeImpl):

  • heap/SimpleMarkingConstraint.h:

(JSC::SimpleMarkingConstraint::SimpleMarkingConstraint):

  • heap/SlotVisitor.cpp:

(JSC::SlotVisitor::addParallelConstraintTask):

  • heap/SlotVisitor.h:
  • heap/Subspace.cpp:

(JSC::Subspace::sweep):

  • heap/Subspace.h:
  • heap/SubspaceInlines.h:

(JSC::Subspace::forEachLiveCell):

  • llint/LowLevelInterpreter.asm:
  • runtime/EvalExecutable.cpp:

(JSC::EvalExecutable::visitChildren):

  • runtime/EvalExecutable.h:

(JSC::EvalExecutable::codeBlock):

  • runtime/FunctionExecutable.cpp:

(JSC::FunctionExecutable::baselineCodeBlockFor):
(JSC::FunctionExecutable::visitChildren):

  • runtime/FunctionExecutable.h:
  • runtime/JSType.h:
  • runtime/ModuleProgramExecutable.cpp:

(JSC::ModuleProgramExecutable::visitChildren):

  • runtime/ModuleProgramExecutable.h:
  • runtime/ProgramExecutable.cpp:

(JSC::ProgramExecutable::visitChildren):

  • runtime/ProgramExecutable.h:
  • runtime/ScriptExecutable.cpp:

(JSC::ScriptExecutable::installCode):
(JSC::ScriptExecutable::newReplacementCodeBlockFor):

  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

(JSC::VM::SpaceAndFinalizerSet::SpaceAndFinalizerSet):
(JSC::VM::SpaceAndFinalizerSet::finalizerSetFor):
(JSC::VM::forEachCodeBlockSpace):

  • runtime/VMTraps.cpp:

(JSC::VMTraps::handleTraps):

  • tools/VMInspector.cpp:

(JSC::VMInspector::codeBlockForMachinePC):
(JSC::VMInspector::isValidCodeBlock):

Source/WebCore:

No new tests because no new behavior.

Adopting new parallel constraint API, so that more of the logic of doing parallel
constraint solving is shared between the DOM's output constraints and JSC's output
constraints.

  • bindings/js/DOMGCOutputConstraint.cpp:

(WebCore::DOMGCOutputConstraint::executeImpl):
(WebCore::DOMGCOutputConstraint::doParallelWorkImpl): Deleted.
(WebCore::DOMGCOutputConstraint::finishParallelWorkImpl): Deleted.

  • bindings/js/DOMGCOutputConstraint.h:

Source/WTF:


Deque<>::contains() is helpful for a debug ASSERT.

  • wtf/Deque.h:

(WTF::inlineCapacity>::contains):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r226556 r226667  
    5252#include "InlineCallFrame.h"
    5353#include "InterpreterInlines.h"
     54#include "IsoCellSetInlines.h"
    5455#include "JIT.h"
    5556#include "JITMathIC.h"
     
    330331    , m_reoptimizationRetryCounter(0)
    331332    , m_creationTime(MonotonicTime::now())
    332     , m_unconditionalFinalizer(makePoisonedUnique<UnconditionalFinalizer>(*this))
    333     , m_weakReferenceHarvester(makePoisonedUnique<WeakReferenceHarvester>(*this))
    334 {
    335     m_visitWeaklyHasBeenCalled = false;
    336 
     333{
    337334    ASSERT(heap()->isDeferred());
    338335    ASSERT(m_scopeRegister.isLocal());
    339336
    340337    setNumParameters(other.numParameters());
     338   
     339    vm->heap.codeBlockSet().add(this);
    341340}
    342341
     
    344343{
    345344    Base::finishCreation(vm);
     345    finishCreationCommon(vm);
    346346
    347347    optimizeAfterWarmUp();
     
    355355        m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
    356356    }
    357    
    358     heap()->m_codeBlocks->add(this);
    359357}
    360358
     
    390388    , m_reoptimizationRetryCounter(0)
    391389    , m_creationTime(MonotonicTime::now())
    392     , m_unconditionalFinalizer(makePoisonedUnique<UnconditionalFinalizer>(*this))
    393     , m_weakReferenceHarvester(makePoisonedUnique<WeakReferenceHarvester>(*this))
    394 {
    395     m_visitWeaklyHasBeenCalled = false;
    396 
     390{
    397391    ASSERT(heap()->isDeferred());
    398392    ASSERT(m_scopeRegister.isLocal());
     
    400394    ASSERT(m_source);
    401395    setNumParameters(unlinkedCodeBlock->numParameters());
     396   
     397    vm->heap.codeBlockSet().add(this);
    402398}
    403399
     
    414410{
    415411    Base::finishCreation(vm);
     412    finishCreationCommon(vm);
    416413
    417414    auto throwScope = DECLARE_THROW_SCOPE(vm);
     
    850847        dumpBytecode();
    851848
    852     heap()->m_codeBlocks->add(this);
    853849    heap()->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
    854850
     
    856852}
    857853
     854void CodeBlock::finishCreationCommon(VM& vm)
     855{
     856    m_ownerEdge.set(vm, this, ExecutableToCodeBlockEdge::create(vm, this));
     857}
     858
    858859CodeBlock::~CodeBlock()
    859860{
    860861    VM& vm = *m_poisonedVM;
     862
     863    vm.heap.codeBlockSet().remove(this);
     864   
    861865    if (UNLIKELY(vm.m_perBytecodeProfiler))
    862866        vm.m_perBytecodeProfiler->notifyDestruction(this);
    863867
    864     if (unlinkedCodeBlock()->didOptimize() == MixedTriState)
     868    if (!vm.heap.isShuttingDown() && unlinkedCodeBlock()->didOptimize() == MixedTriState)
    865869        unlinkedCodeBlock()->setDidOptimize(FalseTriState);
    866870
     
    976980}
    977981
    978 void CodeBlock::visitWeakly(SlotVisitor& visitor)
    979 {
    980     ConcurrentJSLocker locker(m_lock);
    981     if (m_visitWeaklyHasBeenCalled)
    982         return;
    983    
    984     m_visitWeaklyHasBeenCalled = true;
    985 
    986     if (Heap::isMarked(this))
    987         return;
    988 
    989     if (shouldVisitStrongly(locker)) {
    990         visitor.appendUnbarriered(this);
    991         return;
    992     }
    993    
    994     // There are two things that may use unconditional finalizers: inline cache clearing
    995     // and jettisoning. The probability of us wanting to do at least one of those things
    996     // is probably quite close to 1. So we add one no matter what and when it runs, it
    997     // figures out whether it has any work to do.
    998     visitor.addUnconditionalFinalizer(m_unconditionalFinalizer.get());
    999 
    1000     if (!JITCode::isOptimizingJIT(jitType()))
    1001         return;
    1002 
    1003     // If we jettison ourselves we'll install our alternative, so make sure that it
    1004     // survives GC even if we don't.
    1005     visitor.append(m_alternative);
    1006    
    1007     // There are two things that we use weak reference harvesters for: DFG fixpoint for
    1008     // jettisoning, and trying to find structures that would be live based on some
    1009     // inline cache. So it makes sense to register them regardless.
    1010     visitor.addWeakReferenceHarvester(m_weakReferenceHarvester.get());
    1011 
    1012 #if ENABLE(DFG_JIT)
    1013     // We get here if we're live in the sense that our owner executable is live,
    1014     // but we're not yet live for sure in another sense: we may yet decide that this
    1015     // code block should be jettisoned based on its outgoing weak references being
    1016     // stale. Set a flag to indicate that we're still assuming that we're dead, and
    1017     // perform one round of determining if we're live. The GC may determine, based on
    1018     // either us marking additional objects, or by other objects being marked for
    1019     // other reasons, that this iteration should run again; it will notify us of this
    1020     // decision by calling harvestWeakReferences().
    1021 
    1022     m_allTransitionsHaveBeenMarked = false;
    1023     propagateTransitions(locker, visitor);
    1024 
    1025     m_jitCode->dfgCommon()->livenessHasBeenProved = false;
    1026     determineLiveness(locker, visitor);
    1027 #endif // ENABLE(DFG_JIT)
    1028 }
    1029 
    1030982size_t CodeBlock::estimatedSize(JSCell* cell)
    1031983{
     
    1042994    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    1043995    JSCell::visitChildren(thisObject, visitor);
     996    visitor.append(thisObject->m_ownerEdge);
    1044997    thisObject->visitChildren(visitor);
    1045998}
     
    10481001{
    10491002    ConcurrentJSLocker locker(m_lock);
    1050     // There are two things that may use unconditional finalizers: inline cache clearing
    1051     // and jettisoning. The probability of us wanting to do at least one of those things
    1052     // is probably quite close to 1. So we add one no matter what and when it runs, it
    1053     // figures out whether it has any work to do.
    1054     visitor.addUnconditionalFinalizer(m_unconditionalFinalizer.get());
    1055 
    10561003    if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
    10571004        visitor.appendUnbarriered(otherBlock);
     
    10721019    stronglyVisitStrongReferences(locker, visitor);
    10731020    stronglyVisitWeakReferences(locker, visitor);
    1074 
    1075     m_allTransitionsHaveBeenMarked = false;
    1076     propagateTransitions(locker, visitor);
     1021   
     1022    VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).add(this);
    10771023}
    10781024
     
    11651111    UNUSED_PARAM(visitor);
    11661112
    1167     if (m_allTransitionsHaveBeenMarked)
    1168         return;
    1169 
    11701113    VM& vm = *m_poisonedVM;
    1171     bool allAreMarkedSoFar = true;
    1172        
     1114
    11731115    if (jitType() == JITCode::InterpreterThunk) {
    11741116        const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
     
    11871129                if (Heap::isMarked(oldStructure))
    11881130                    visitor.appendUnbarriered(newStructure);
    1189                 else
    1190                     allAreMarkedSoFar = false;
    11911131                break;
    11921132            }
     
    12001140    if (JITCode::isJIT(jitType())) {
    12011141        for (auto iter = m_stubInfos.begin(); !!iter; ++iter)
    1202             allAreMarkedSoFar &= (*iter)->propagateTransitions(visitor);
     1142            (*iter)->propagateTransitions(visitor);
    12031143    }
    12041144#endif // ENABLE(JIT)
     
    12081148        DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
    12091149        for (auto& weakReference : dfgCommon->weakStructureReferences)
    1210             allAreMarkedSoFar &= weakReference->markIfCheap(visitor);
     1150            weakReference->markIfCheap(visitor);
    12111151
    12121152        for (auto& transition : dfgCommon->transitions) {
     
    12321172
    12331173                visitor.append(transition.m_to);
    1234             } else
    1235                 allAreMarkedSoFar = false;
     1174            }
    12361175        }
    12371176    }
    12381177#endif // ENABLE(DFG_JIT)
    1239    
    1240     if (allAreMarkedSoFar)
    1241         m_allTransitionsHaveBeenMarked = true;
    12421178}
    12431179
     
    12471183   
    12481184#if ENABLE(DFG_JIT)
    1249     // Check if we have any remaining work to do.
     1185    if (Heap::isMarked(this))
     1186        return;
     1187   
     1188    // In rare and weird cases, this could be called on a baseline CodeBlock. One that I found was
     1189    // that we might decide that the CodeBlock should be jettisoned due to old age, so the
     1190    // isMarked check doesn't protect us.
     1191    if (!JITCode::isOptimizingJIT(jitType()))
     1192        return;
     1193   
    12501194    DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
    1251     if (dfgCommon->livenessHasBeenProved)
    1252         return;
    1253    
    12541195    // Now check all of our weak references. If all of them are live, then we
    12551196    // have proved liveness and so we scan our strong references. If at end of
     
    12801221    // All weak references are live. Record this information so we don't
    12811222    // come back here again, and scan the strong references.
    1282     dfgCommon->livenessHasBeenProved = true;
    12831223    visitor.appendUnbarriered(this);
    12841224#endif // ENABLE(DFG_JIT)
    1285 }
    1286 
    1287 void CodeBlock::WeakReferenceHarvester::visitWeakReferences(SlotVisitor& visitor)
    1288 {
    1289     codeBlock.propagateTransitions(NoLockingNecessary, visitor);
    1290     codeBlock.determineLiveness(NoLockingNecessary, visitor);
    12911225}
    12921226
     
    14221356}
    14231357
    1424 void CodeBlock::UnconditionalFinalizer::finalizeUnconditionally()
    1425 {
    1426     codeBlock.updateAllPredictions();
    1427    
    1428     if (!Heap::isMarked(&codeBlock)) {
    1429         if (codeBlock.shouldJettisonDueToWeakReference())
    1430             codeBlock.jettison(Profiler::JettisonDueToWeakReference);
    1431         else
    1432             codeBlock.jettison(Profiler::JettisonDueToOldAge);
    1433         return;
    1434     }
    1435 
    1436     if (JITCode::couldBeInterpreted(codeBlock.jitType()))
    1437         codeBlock.finalizeLLIntInlineCaches();
     1358void CodeBlock::finalizeUnconditionally(VM&)
     1359{
     1360    updateAllPredictions();
     1361   
     1362    if (JITCode::couldBeInterpreted(jitType()))
     1363        finalizeLLIntInlineCaches();
    14381364
    14391365#if ENABLE(JIT)
    1440     if (!!codeBlock.jitCode())
    1441         codeBlock.finalizeBaselineJITInlineCaches();
    1442 #endif
     1366    if (!!jitCode())
     1367        finalizeBaselineJITInlineCaches();
     1368#endif
     1369
     1370    VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).remove(this);
    14431371}
    14441372
     
    15941522   
    15951523    visitor.append(m_globalObject);
    1596     visitor.append(m_ownerExecutable);
     1524    visitor.append(m_ownerExecutable); // This is extra important since it causes the ExecutableToCodeBlockEdge to be marked.
    15971525    visitor.append(m_unlinkedCode);
    15981526    if (m_rareData)
     
    31333061{
    31343062#if ENABLE(SIGNAL_BASED_VM_TRAPS)
    3135    
    31363063    // This function may be called from a signal handler. We need to be
    31373064    // careful to not call anything that is not signal handler safe, e.g.
     
    31533080    if (!JITCode::isOptimizingJIT(jitType()))
    31543081        return false;
    3155     m_jitCode->dfgCommon()->installVMTrapBreakpoints(this);
     3082    auto& commonData = *m_jitCode->dfgCommon();
     3083    commonData.installVMTrapBreakpoints(this);
    31563084    return true;
    31573085#else
     
    31933121            totalSubSize += subIC->codeSize();
    31943122        }
    3195 
    3196         return false;
    31973123    };
    31983124    heap()->forEachCodeBlock(countICs);
Note: See TracChangeset for help on using the changeset viewer.