void Runtime::markRoots()

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();
  }
}