void ObjectGroupCycleCollectorTracer::onChild(const JS::GCCellPtr& thing) { if (thing.is<JSObject>() || thing.is<JSScript>()) { // Invoke the inner cycle collector callback on this child. It will not // recurse back into TraceChildren. innerTracer->onChild(thing); return; } if (thing.is<ObjectGroup>()) { // If this group is required to be in an ObjectGroup chain, trace it // via the provided worklist rather than continuing to recurse. ObjectGroup& group = thing.as<ObjectGroup>(); if (group.maybeUnboxedLayout()) { for (size_t i = 0; i < seen.length(); i++) { if (seen[i] == &group) return; } if (seen.append(&group) && worklist.append(&group)) { return; } else { // If append fails, keep tracing normally. The worst that will // happen is we end up overrecursing. } } } TraceChildren(this, thing.asCell(), thing.kind()); }
/* * This function is called by EndVerifyBarriers for every heap edge. If the edge * already existed in the original snapshot, we "cancel it out" by overwriting * it with nullptr. EndVerifyBarriers later asserts that the remaining * non-nullptr edges (i.e., the ones from the original snapshot that must have * been modified) must point to marked objects. */ void CheckEdgeTracer::onChild(const JS::GCCellPtr& thing) { /* Avoid n^2 behavior. */ if (node->count > MAX_VERIFIER_EDGES) return; for (uint32_t i = 0; i < node->count; i++) { if (node->edges[i].thing == thing.asCell()) { MOZ_ASSERT(node->edges[i].kind == thing.kind()); node->edges[i].thing = nullptr; return; } } }
void nsScriptObjectTracer::NoteJSChild(JS::GCCellPtr aGCThing, const char* aName, void* aClosure) { nsCycleCollectionTraversalCallback* cb = static_cast<nsCycleCollectionTraversalCallback*>(aClosure); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, aName); if (aGCThing.is<JSObject>()) { cb->NoteJSObject(&aGCThing.as<JSObject>()); } else if (aGCThing.is<JSScript>()) { cb->NoteJSScript(&aGCThing.as<JSScript>()); } else { MOZ_ASSERT(!mozilla::AddToCCKind(aGCThing.kind())); } }
/* * This function builds up the heap snapshot by adding edges to the current * node. */ void VerifyPreTracer::onChild(const JS::GCCellPtr& thing) { MOZ_ASSERT(!IsInsideNursery(thing.asCell())); edgeptr += sizeof(EdgeValue); if (edgeptr >= term) { edgeptr = term; return; } VerifyNode* node = curnode; uint32_t i = node->count; node->edges[i].thing = thing.asCell(); node->edges[i].kind = thing.kind(); node->edges[i].label = contextName(); node->count++; }
Node::Node(const JS::GCCellPtr &thing) { DispatchTraceKindTyped(ConstructFunctor(), thing.asCell(), thing.kind(), this); }
Node::Node(const JS::GCCellPtr &thing) { js::gc::CallTyped(ConstructFunctor(), thing.asCell(), thing.kind(), this); }