mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1350760 part 6 - Add a Zone cache for recently atomized strings. r=jonco
This commit is contained in:
parent
35bd8c0bf9
commit
1ad92e7cc7
@ -199,6 +199,10 @@ class HashMap
|
||||
// using the finish() method.
|
||||
void clear() { impl.clear(); }
|
||||
|
||||
// Remove all entries. Unlike clear() this method tries to shrink the table.
|
||||
// Unlike finish() it does not require the map to be initialized again.
|
||||
void clearAndShrink() { impl.clearAndShrink(); }
|
||||
|
||||
// Remove all the entries and release all internal buffers. The map must
|
||||
// be initialized again before any use.
|
||||
void finish() { impl.finish(); }
|
||||
@ -442,6 +446,10 @@ class HashSet
|
||||
// using the finish() method.
|
||||
void clear() { impl.clear(); }
|
||||
|
||||
// Remove all entries. Unlike clear() this method tries to shrink the table.
|
||||
// Unlike finish() it does not require the set to be initialized again.
|
||||
void clearAndShrink() { impl.clearAndShrink(); }
|
||||
|
||||
// Remove all the entries and release all internal buffers. The set must
|
||||
// be initialized again before any use.
|
||||
void finish() { impl.finish(); }
|
||||
@ -1676,6 +1684,12 @@ class HashTable : private AllocPolicy
|
||||
#endif
|
||||
}
|
||||
|
||||
void clearAndShrink()
|
||||
{
|
||||
clear();
|
||||
compactIfUnderloaded();
|
||||
}
|
||||
|
||||
void finish()
|
||||
{
|
||||
#ifdef JS_DEBUG
|
||||
|
@ -41,6 +41,7 @@ JS::Zone::Zone(JSRuntime* rt, ZoneGroup* group)
|
||||
hasDeadProxies_(group),
|
||||
typeDescrObjects_(group, this, SystemAllocPolicy()),
|
||||
markedAtoms_(group),
|
||||
atomCache_(group),
|
||||
usage(&rt->gc.usage),
|
||||
threshold(),
|
||||
gcDelayBytes(0),
|
||||
@ -93,7 +94,8 @@ bool Zone::init(bool isSystemArg)
|
||||
gcSweepGroupEdges().init() &&
|
||||
gcWeakKeys().init() &&
|
||||
typeDescrObjects().init() &&
|
||||
markedAtoms().init();
|
||||
markedAtoms().init() &&
|
||||
atomCache().init();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -434,9 +434,15 @@ struct Zone : public JS::shadow::Zone,
|
||||
private:
|
||||
// Bitmap of atoms marked by this zone.
|
||||
js::ZoneGroupOrGCTaskData<js::SparseBitmap> markedAtoms_;
|
||||
|
||||
// Set of atoms recently used by this Zone. Purged on GC.
|
||||
js::ZoneGroupOrGCTaskData<js::AtomSet> atomCache_;
|
||||
|
||||
public:
|
||||
js::SparseBitmap& markedAtoms() { return markedAtoms_.ref(); }
|
||||
|
||||
js::AtomSet& atomCache() { return atomCache_.ref(); }
|
||||
|
||||
// Track heap usage under this Zone.
|
||||
js::gc::HeapUsage usage;
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -304,10 +305,28 @@ static JSAtom*
|
||||
AtomizeAndCopyChars(JSContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin)
|
||||
{
|
||||
if (JSAtom* s = cx->staticStrings().lookup(tbchars, length))
|
||||
return s;
|
||||
return s;
|
||||
|
||||
AtomHasher::Lookup lookup(tbchars, length);
|
||||
|
||||
// Try the per-Zone cache first. If we find the atom there we can avoid the
|
||||
// atoms lock, the markAtom call, and the multiple HashSet lookups below.
|
||||
// We don't use the per-Zone cache if we want a pinned atom: handling that
|
||||
// is more complicated and pinning atoms is relatively uncommon.
|
||||
Zone* zone = cx->zone();
|
||||
Maybe<AtomSet::AddPtr> zonePtr;
|
||||
if (MOZ_LIKELY(zone && pin == DoNotPinAtom)) {
|
||||
zonePtr.emplace(zone->atomCache().lookupForAdd(lookup));
|
||||
if (zonePtr.ref()) {
|
||||
// The cache is purged on GC so if we're in the middle of an
|
||||
// incremental GC we should have barriered the atom when we put
|
||||
// it in the cache.
|
||||
JSAtom* atom = zonePtr.ref()->asPtrUnbarriered();
|
||||
MOZ_ASSERT(AtomIsMarked(zone, atom));
|
||||
return atom;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: when this function is called while the permanent atoms table is
|
||||
// being initialized (in initializeAtoms()), |permanentAtoms| is not yet
|
||||
// initialized so this lookup is always skipped. Only once
|
||||
@ -315,8 +334,12 @@ AtomizeAndCopyChars(JSContext* cx, const CharT* tbchars, size_t length, PinningB
|
||||
// initialized and then this lookup will go ahead.
|
||||
if (cx->isPermanentAtomsInitialized()) {
|
||||
AtomSet::Ptr pp = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
|
||||
if (pp)
|
||||
return pp->asPtr(cx);
|
||||
if (pp) {
|
||||
JSAtom* atom = pp->asPtr(cx);
|
||||
if (zonePtr)
|
||||
mozilla::Unused << zone->atomCache().add(*zonePtr, AtomStateEntry(atom, false));
|
||||
return atom;
|
||||
}
|
||||
}
|
||||
|
||||
AutoLockForExclusiveAccess lock(cx);
|
||||
@ -327,6 +350,8 @@ AtomizeAndCopyChars(JSContext* cx, const CharT* tbchars, size_t length, PinningB
|
||||
JSAtom* atom = p->asPtr(cx);
|
||||
p->setPinned(bool(pin));
|
||||
cx->atomMarking().inlinedMarkAtom(cx, atom);
|
||||
if (zonePtr)
|
||||
mozilla::Unused << zone->atomCache().add(*zonePtr, AtomStateEntry(atom, false));
|
||||
return atom;
|
||||
}
|
||||
|
||||
@ -359,6 +384,8 @@ AtomizeAndCopyChars(JSContext* cx, const CharT* tbchars, size_t length, PinningB
|
||||
}
|
||||
|
||||
cx->atomMarking().inlinedMarkAtom(cx, atom);
|
||||
if (zonePtr)
|
||||
mozilla::Unused << zone->atomCache().add(*zonePtr, AtomStateEntry(atom, false));
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
@ -3635,6 +3635,9 @@ GCRuntime::purgeRuntime(AutoLockForExclusiveAccess& lock)
|
||||
for (GCCompartmentsIter comp(rt); !comp.done(); comp.next())
|
||||
comp->purge();
|
||||
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next())
|
||||
zone->atomCache().clearAndShrink();
|
||||
|
||||
for (const CooperatingContext& target : rt->cooperatingContexts()) {
|
||||
freeUnusedLifoBlocksAfterSweeping(&target.context()->tempLifoAlloc());
|
||||
target.context()->interpreterStack().purge(rt);
|
||||
|
Loading…
Reference in New Issue
Block a user