зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1383343 part 2 - Add a cache for Function.prototype.toString. r=anba
This commit is contained in:
Родитель
09e17362ed
Коммит
deb7d25aa4
|
@ -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()) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче