in lib/VM/Runtime.cpp [433:586]
void Runtime::markRoots(
RootAndSlotAcceptorWithNames &acceptor,
bool markLongLived) {
// The body of markRoots should be sequence of blocks, each of which starts
// with the declaration of an appropriate RootSection instance.
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::Registers);
acceptor.beginRootSection(RootAcceptor::Section::Registers);
for (auto *p = registerStackStart_, *e = stackPointer_; p != e; ++p)
acceptor.accept(*p);
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(
*this, RootAcceptor::Section::RuntimeInstanceVars);
acceptor.beginRootSection(RootAcceptor::Section::RuntimeInstanceVars);
for (auto &clazz : rootClazzes_)
acceptor.accept(clazz, "rootClass");
#define RUNTIME_HV_FIELD_INSTANCE(name) acceptor.accept((name), #name);
#include "hermes/VM/RuntimeHermesValueFields.def"
#undef RUNTIME_HV_FIELD_INSTANCE
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::RuntimeModules);
acceptor.beginRootSection(RootAcceptor::Section::RuntimeModules);
#define RUNTIME_HV_FIELD_RUNTIMEMODULE(name) acceptor.accept(name);
#include "hermes/VM/RuntimeHermesValueFields.def"
#undef RUNTIME_HV_FIELD_RUNTIMEMODULE
for (auto &rm : runtimeModuleList_)
rm.markRoots(acceptor, markLongLived);
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::CharStrings);
acceptor.beginRootSection(RootAcceptor::Section::CharStrings);
if (markLongLived) {
for (auto &hv : charStrings_)
acceptor.accept(hv);
}
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(
*this, RootAcceptor::Section::StringCycleCheckVisited);
acceptor.beginRootSection(RootAcceptor::Section::StringCycleCheckVisited);
for (auto *&ptr : stringCycleCheckVisited_)
acceptor.acceptPtr(ptr);
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::Builtins);
acceptor.beginRootSection(RootAcceptor::Section::Builtins);
for (Callable *&f : builtins_)
acceptor.acceptPtr(f);
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::Jobs);
acceptor.beginRootSection(RootAcceptor::Section::Jobs);
for (Callable *&f : jobQueue_)
acceptor.acceptPtr(f);
acceptor.endRootSection();
}
#ifdef MARK
#error "Shouldn't have defined mark already"
#endif
#define MARK(field) acceptor.accept((field), #field)
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::Prototypes);
acceptor.beginRootSection(RootAcceptor::Section::Prototypes);
// Prototypes.
#define RUNTIME_HV_FIELD_PROTOTYPE(name) MARK(name);
#include "hermes/VM/RuntimeHermesValueFields.def"
#undef RUNTIME_HV_FIELD_PROTOTYPE
acceptor.acceptPtr(objectPrototypeRawPtr, "objectPrototype");
acceptor.acceptPtr(functionPrototypeRawPtr, "functionPrototype");
#undef MARK
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::IdentifierTable);
if (markLongLived) {
// Need to add nodes before the root section, and edges during the root
// section.
acceptor.provideSnapshot([this](HeapSnapshot &snap) {
identifierTable_.snapshotAddNodes(snap);
});
acceptor.beginRootSection(RootAcceptor::Section::IdentifierTable);
identifierTable_.markIdentifiers(acceptor, &getHeap());
acceptor.provideSnapshot([this](HeapSnapshot &snap) {
identifierTable_.snapshotAddEdges(snap);
});
acceptor.endRootSection();
}
}
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::GCScopes);
acceptor.beginRootSection(RootAcceptor::Section::GCScopes);
markGCScopes(acceptor);
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::SymbolRegistry);
acceptor.beginRootSection(RootAcceptor::Section::SymbolRegistry);
symbolRegistry_.markRoots(acceptor);
acceptor.endRootSection();
}
// Mark the alternative roots during the normal mark roots call.
markRootsForCompleteMarking(acceptor);
{
MarkRootsPhaseTimer timer(
*this, RootAcceptor::Section::CodeCoverageProfiler);
acceptor.beginRootSection(RootAcceptor::Section::CodeCoverageProfiler);
if (codeCoverageProfiler_) {
codeCoverageProfiler_->markRoots(acceptor);
}
#ifdef HERMESVM_PROFILER_BB
auto *&hiddenClassArray = inlineCacheProfiler_.getHiddenClassArray();
if (hiddenClassArray) {
acceptor.acceptPtr(hiddenClassArray);
}
#endif
acceptor.endRootSection();
}
{
MarkRootsPhaseTimer timer(*this, RootAcceptor::Section::Custom);
// Define nodes before the root section starts.
for (auto &fn : customSnapshotNodeFuncs_) {
acceptor.provideSnapshot(fn);
}
acceptor.beginRootSection(RootAcceptor::Section::Custom);
for (auto &fn : customMarkRootFuncs_)
fn(&getHeap(), acceptor);
// Define edges while inside the root section.
for (auto &fn : customSnapshotEdgeFuncs_) {
acceptor.provideSnapshot(fn);
}
acceptor.endRootSection();
}
}