Bug 1383343 part 2 - Add a cache for Function.prototype.toString. r=anba

This commit is contained in:
Jan de Mooij 2017-07-25 14:58:17 +02:00
Родитель 09e17362ed
Коммит deb7d25aa4
4 изменённых файлов: 64 добавлений и 3 удалений

Просмотреть файл

@ -43,6 +43,7 @@ JS::Zone::Zone(JSRuntime* rt, ZoneGroup* group)
markedAtoms_(group),
atomCache_(group),
externalStringCache_(group),
functionToStringCache_(group),
usage(&rt->gc.usage),
threshold(),
gcDelayBytes(0),

Просмотреть файл

@ -107,6 +107,31 @@ class MOZ_NON_TEMPORARY_CLASS ExternalStringCache
MOZ_ALWAYS_INLINE void put(JSString* s);
};
class MOZ_NON_TEMPORARY_CLASS FunctionToStringCache
{
struct Entry {
JSScript* script;
JSString* string;
void set(JSScript* scriptArg, JSString* stringArg) {
script = scriptArg;
string = stringArg;
}
};
static const size_t NumEntries = 2;
mozilla::Array<Entry, NumEntries> entries_;
FunctionToStringCache(const FunctionToStringCache&) = delete;
void operator=(const FunctionToStringCache&) = delete;
public:
FunctionToStringCache() { purge(); }
void purge() { mozilla::PodArrayZero(entries_); }
MOZ_ALWAYS_INLINE JSString* lookup(JSScript* script) const;
MOZ_ALWAYS_INLINE void put(JSScript* script, JSString* string);
};
} // namespace js
namespace JS {
@ -445,6 +470,9 @@ struct Zone : public JS::shadow::Zone,
// Cache storing allocated external strings. Purged on GC.
js::ZoneGroupOrGCTaskData<js::ExternalStringCache> externalStringCache_;
// Cache for Function.prototype.toString. Purged on GC.
js::ZoneGroupOrGCTaskData<js::FunctionToStringCache> functionToStringCache_;
public:
js::SparseBitmap& markedAtoms() { return markedAtoms_.ref(); }
@ -452,6 +480,8 @@ struct Zone : public JS::shadow::Zone,
js::ExternalStringCache& externalStringCache() { return externalStringCache_.ref(); };
js::FunctionToStringCache& functionToStringCache() { return functionToStringCache_.ref(); }
// Track heap usage under this Zone.
js::gc::HeapUsage usage;

Просмотреть файл

@ -990,6 +990,25 @@ const Class JSFunction::class_ = {
const Class* const js::FunctionClassPtr = &JSFunction::class_;
JSString*
js::FunctionToStringCache::lookup(JSScript* script) const
{
for (size_t i = 0; i < NumEntries; i++) {
if (entries_[i].script == script)
return entries_[i].string;
}
return nullptr;
}
void
js::FunctionToStringCache::put(JSScript* script, JSString* string)
{
for (size_t i = NumEntries - 1; i > 0; i--)
entries_[i] = entries_[i - 1];
entries_[0].set(script, string);
}
JSString*
js::FunctionToString(JSContext* cx, HandleFunction fun, bool isToSource)
{
@ -1037,10 +1056,19 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool isToSource)
// Fast path for the common case, to avoid StringBuffer overhead.
if (!addParentheses && haveSource) {
FunctionToStringCache& cache = cx->zone()->functionToStringCache();
if (JSString* str = cache.lookup(script))
return str;
size_t start = script->toStringStart(), end = script->toStringEnd();
if (end - start <= ScriptSource::SourceDeflateLimit)
return script->scriptSource()->substring(cx, start, end);
return script->scriptSource()->substringDontDeflate(cx, start, end);
JSString* str = (end - start <= ScriptSource::SourceDeflateLimit)
? script->scriptSource()->substring(cx, start, end)
: script->scriptSource()->substringDontDeflate(cx, start, end);
if (!str)
return nullptr;
cache.put(script, str);
return str;
}
StringBuffer out(cx);

Просмотреть файл

@ -2589,6 +2589,7 @@ GCRuntime::updateZonePointersToRelocatedCells(Zone* zone, AutoLockForExclusiveAc
comp->fixupAfterMovingGC();
zone->externalStringCache().purge();
zone->functionToStringCache().purge();
// Iterate through all cells that can contain relocatable pointers to update
// them. Since updating each cell is independent we try to parallelize this
@ -3708,6 +3709,7 @@ GCRuntime::purgeRuntime(AutoLockForExclusiveAccess& lock)
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
zone->atomCache().clearAndShrink();
zone->externalStringCache().purge();
zone->functionToStringCache().purge();
}
for (const CooperatingContext& target : rt->cooperatingContexts()) {