@@ -419,6 +419,11 @@ class GCBase {
419419 // / Flush out heap profiler data to the callback after a new kFlushThreshold
420420 // / bytes are allocated.
421421 static constexpr uint64_t kFlushThreshold = 128 * (1 << 10 );
422+ // / This mutex protects stackMap_. Specifically does not protect enabled_,
423+ // / because enabled_ should only be changed while the GC isn't running
424+ // / anyway. Also doesn't protect fragments_ because only the allocator
425+ // / modifies fragments_.
426+ Mutex mtx_;
422427 // / Associates allocations at their current location with their stack trace
423428 // / data.
424429 llvh::DenseMap<const void *, StackTracesTreeNode *> stackMap_;
@@ -580,6 +585,11 @@ class GCBase {
580585 // / the Chrome snapshot viewer.
581586 static constexpr HeapSnapshot::NodeID kIDStep = 2 ;
582587
588+ // / This mutex protects objectIDMap_, symbolIDMap_, and numberIDMap_.
589+ // / Specifically does not protect lastID_, since there's only one allocator
590+ // / at a time, and only new allocations affect lastID_.
591+ Mutex mtx_;
592+
583593 // / The last ID assigned to a non-native object. Object IDs are not
584594 // / recycled so that snapshots don't confuse two objects with each other.
585595 // / NOTE: Reserved guarantees that this is an odd number.
@@ -747,6 +757,21 @@ class GCBase {
747757 virtual void createSnapshot (llvh::raw_ostream &os) = 0;
748758 void createSnapshot (GC *gc, llvh::raw_ostream &os);
749759
760+ // / Turn on the heap profiler, which will track when allocations are made and
761+ // / the stack trace of when they were created.
762+ virtual void enableHeapProfiler (
763+ std::function<void (
764+ uint64_t ,
765+ std::chrono::microseconds,
766+ std::vector<GCBase::AllocationLocationTracker::HeapStatsUpdate>)>
767+ fragmentCallback);
768+
769+ // / Turn off the heap profiler, which will stop tracking new allocations and
770+ // / not record any stack traces.
771+ // / Disabling will not forget any objects that are still alive. This way
772+ // / re-enabling later will still remember earlier objects.
773+ virtual void disableHeapProfiler ();
774+
750775#ifdef HERMESVM_SERIALIZE
751776 // / Serialize WeakRefs.
752777 virtual void serializeWeakRefs (Serializer &s) = 0;
@@ -1564,6 +1589,7 @@ inline bool GCBase::IDTracker::isTrackingIDs() const {
15641589}
15651590
15661591inline HeapSnapshot::NodeID GCBase::IDTracker::getObjectID (const void *cell) {
1592+ std::lock_guard<Mutex> lk{mtx_};
15671593 auto iter = objectIDMap_.find (cell);
15681594 if (iter != objectIDMap_.end ()) {
15691595 return iter->second ;
@@ -1576,12 +1602,14 @@ inline HeapSnapshot::NodeID GCBase::IDTracker::getObjectID(const void *cell) {
15761602
15771603inline HeapSnapshot::NodeID GCBase::IDTracker::getObjectIDMustExist (
15781604 const void *cell) {
1605+ std::lock_guard<Mutex> lk{mtx_};
15791606 auto iter = objectIDMap_.find (cell);
15801607 assert (iter != objectIDMap_.end () && " cell must already have an ID" );
15811608 return iter->second ;
15821609}
15831610
15841611inline HeapSnapshot::NodeID GCBase::IDTracker::getObjectID (uint32_t symIdx) {
1612+ std::lock_guard<Mutex> lk{mtx_};
15851613 auto iter = symbolIDMap_.find (symIdx);
15861614 if (iter != symbolIDMap_.end ()) {
15871615 return iter->second ;
@@ -1593,6 +1621,7 @@ inline HeapSnapshot::NodeID GCBase::IDTracker::getObjectID(uint32_t symIdx) {
15931621}
15941622
15951623inline HeapSnapshot::NodeID GCBase::IDTracker::getNativeID (const void *mem) {
1624+ std::lock_guard<Mutex> lk{mtx_};
15961625 auto iter = objectIDMap_.find (mem);
15971626 if (iter != objectIDMap_.end ()) {
15981627 return iter->second ;
@@ -1612,6 +1641,7 @@ inline void GCBase::IDTracker::moveObject(
16121641 // happen in old generations where it is compacted to the same location.
16131642 return ;
16141643 }
1644+ std::lock_guard<Mutex> lk{mtx_};
16151645 auto old = objectIDMap_.find (oldLocation);
16161646 if (old == objectIDMap_.end ()) {
16171647 // Avoid making new keys for objects that don't need to be tracked.
@@ -1627,6 +1657,7 @@ inline void GCBase::IDTracker::moveObject(
16271657}
16281658
16291659inline void GCBase::IDTracker::untrackObject (const void *cell) {
1660+ std::lock_guard<Mutex> lk{mtx_};
16301661 objectIDMap_.erase (cell);
16311662}
16321663
@@ -1642,6 +1673,7 @@ inline const GCExecTrace &GCBase::getGCExecTrace() const {
16421673
16431674template <typename F>
16441675inline void GCBase::IDTracker::forEachID (F callback) {
1676+ std::lock_guard<Mutex> lk{mtx_};
16451677 for (auto &p : objectIDMap_) {
16461678 callback (p.first , p.second );
16471679 }
0 commit comments