Bug 1672787 - Part 9: Spew final warm up count during finalization. r=iain

Differential Revision: https://phabricator.services.mozilla.com/D98668
This commit is contained in:
Caroline Cullen 2020-12-18 23:36:26 +00:00
parent bdcd0d89be
commit 119e260dbc
6 changed files with 133 additions and 2 deletions

View File

@ -8069,6 +8069,9 @@ void GCRuntime::mergeRealms(Realm* source, Realm* target) {
#ifdef MOZ_VTUNE
MOZ_ASSERT(!sourceZone->scriptVTuneIdMap);
#endif
#ifdef JS_CACHEIR_SPEW
MOZ_ASSERT(!sourceZone->scriptFinalWarmUpCountMap);
#endif
// The source realm is now completely empty, and is the only realm in its
// compartment, which is the only compartment in its zone. Delete realm,

View File

@ -438,6 +438,10 @@ void Zone::discardJitCode(JSFreeOp* fop,
}
}
#ifdef JS_CACHEIR_SPEW
maybeUpdateWarmUpCount(script);
#endif
// Warm-up counter for scripts are reset on GC. After discarding code we
// need to let it warm back up to get information such as which
// opcodes are setting array holes or accessing getter properties.
@ -849,6 +853,19 @@ void Zone::fixupScriptMapsAfterMovingGC(JSTracer* trc) {
}
}
#endif
#ifdef JS_CACHEIR_SPEW
if (scriptFinalWarmUpCountMap) {
for (ScriptFinalWarmUpCountMap::Enum e(*scriptFinalWarmUpCountMap);
!e.empty(); e.popFront()) {
BaseScript* script = e.front().key();
if (!IsAboutToBeFinalizedUnbarriered(&script) &&
script != e.front().key()) {
e.rekeyFront(script);
}
}
}
#endif
}
#ifdef JSGC_HASH_TABLE_CHECKS
@ -896,6 +913,18 @@ void Zone::checkScriptMapsAfterMovingGC() {
}
}
# endif // MOZ_VTUNE
# ifdef JS_CACHEIR_SPEW
if (scriptFinalWarmUpCountMap) {
for (auto r = scriptFinalWarmUpCountMap->all(); !r.empty(); r.popFront()) {
BaseScript* script = r.front().key();
MOZ_ASSERT(script->zone() == this);
CheckGCThingAfterMovingGC(script);
auto ptr = scriptFinalWarmUpCountMap->lookup(script);
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
}
}
# endif // JS_CACHEIR_SPEW
}
#endif

View File

@ -223,6 +223,9 @@ class Zone : public js::ZoneAllocator, public js::gc::GraphNodeBase<JS::Zone> {
#ifdef MOZ_VTUNE
js::UniquePtr<js::ScriptVTuneIdMap> scriptVTuneIdMap;
#endif
#ifdef JS_CACHEIR_SPEW
js::UniquePtr<js::ScriptFinalWarmUpCountMap> scriptFinalWarmUpCountMap;
#endif
js::ZoneData<js::StringStats> previousGCStringStats;
js::ZoneData<js::StringStats> stringStats;

View File

@ -9,6 +9,7 @@
# include "mozilla/Maybe.h"
# include "gc/Zone.h"
# include "jit/JitScript.h"
using namespace js;
@ -151,6 +152,35 @@ void CacheIRHealth::spewScriptFinalWarmUpCount(JSContext* cx,
spew->property("finalWarmUpCount", warmUpCount);
}
static void addScriptToFinalWarmUpCountMap(JSContext* cx, HandleScript script) {
// Create Zone::scriptFilenameMap if necessary.
JS::Zone* zone = script->zone();
if (!zone->scriptFinalWarmUpCountMap) {
auto map = MakeUnique<ScriptFinalWarmUpCountMap>();
if (!map) {
ReportOutOfMemory(cx);
return;
}
zone->scriptFinalWarmUpCountMap = std::move(map);
}
auto* filename = js_pod_malloc<char>(strlen(script->filename()) + 1);
if (!filename) {
ReportOutOfMemory(cx);
return;
}
strcpy(filename, script->filename());
if (!zone->scriptFinalWarmUpCountMap->put(
script, mozilla::MakeTuple(uint32_t(0), filename))) {
ReportOutOfMemory(cx);
return;
}
script->setNeedsFinalWarmUpCount();
}
void CacheIRHealth::rateIC(JSContext* cx, ICEntry* entry, HandleScript script,
SpewContext context) {
AutoStructuredSpewer spew(cx, SpewChannel::RateMyCacheIR, script);
@ -158,7 +188,7 @@ void CacheIRHealth::rateIC(JSContext* cx, ICEntry* entry, HandleScript script,
return;
}
script->setNeedsFinalWarmUpCount();
addScriptToFinalWarmUpCountMap(cx, script);
spew->property("spewContext", uint8_t(context));
jsbytecode* op = entry->pc(script);
@ -180,7 +210,7 @@ void CacheIRHealth::rateScript(JSContext* cx, HandleScript script,
return;
}
script->setNeedsFinalWarmUpCount();
addScriptToFinalWarmUpCountMap(cx, script);
spew->property("spewContext", uint8_t(context));
jsbytecode* next = script->code();

View File

@ -39,6 +39,7 @@
#include "frontend/StencilXdr.h" // frontend::StencilXdr::SharedData
#include "gc/FreeOp.h"
#include "jit/BaselineJIT.h"
#include "jit/CacheIRHealth.h"
#include "jit/Invalidation.h"
#include "jit/Ion.h"
#include "jit/IonScript.h"
@ -646,9 +647,18 @@ void js::BaseScript::finalize(JSFreeOp* fop) {
if (warmUpData_.isJitScript()) {
JSScript* script = this->asJSScript();
#ifdef JS_CACHEIR_SPEW
maybeUpdateWarmUpCount(script);
#endif
script->releaseJitScriptOnFinalize(fop);
}
#ifdef JS_CACHEIR_SPEW
if (hasBytecode()) {
maybeSpewScriptFinalWarmUpCount(this->asJSScript());
}
#endif
if (data_) {
// We don't need to triger any barriers here, just free the memory.
size_t size = data_->allocationSize();
@ -4210,6 +4220,51 @@ JS_FRIEND_API unsigned js::GetScriptLineExtent(JSScript* script) {
return 1 + maxLineNo - script->lineno();
}
#ifdef JS_CACHEIR_SPEW
void js::maybeUpdateWarmUpCount(JSScript* script) {
if (script->needsFinalWarmUpCount()) {
ScriptFinalWarmUpCountMap* map =
script->zone()->scriptFinalWarmUpCountMap.get();
// If needsFinalWarmUpCount is true, ScriptFinalWarmUpCountMap must have
// already been created and thus must be asserted.
MOZ_ASSERT(map);
ScriptFinalWarmUpCountMap::Ptr p = map->lookup(script);
MOZ_ASSERT(p);
mozilla::Get<0>(p->value()) += script->jitScript()->warmUpCount();
}
}
void js::maybeSpewScriptFinalWarmUpCount(JSScript* script) {
if (script->needsFinalWarmUpCount()) {
ScriptFinalWarmUpCountMap* map =
script->zone()->scriptFinalWarmUpCountMap.get();
// If needsFinalWarmUpCount is true, ScriptFinalWarmUpCountMap must have
// already been created and thus must be asserted.
MOZ_ASSERT(map);
ScriptFinalWarmUpCountMap::Ptr p = map->lookup(script);
MOZ_ASSERT(p);
uint32_t warmUpCount;
const char* scriptName;
mozilla::Tie(warmUpCount, scriptName) = p->value();
JSContext* cx = TlsContext.get();
cx->spewer().enableSpewing();
// In the case that we care about a script's final warmup count but the
// spewer is not enabled, AutoSpewChannel automatically sets and unsets
// the proper channel for the duration of spewing a health report's warm
// up count.
AutoSpewChannel channel(cx, SpewChannel::RateMyCacheIR, script);
jit::CacheIRHealth cih;
cih.spewScriptFinalWarmUpCount(cx, scriptName, script, warmUpCount);
script->zone()->scriptFinalWarmUpCountMap->remove(script);
script->setNeedsFinalWarmUpCount(false);
}
}
#endif
void js::DescribeScriptedCallerForDirectEval(JSContext* cx, HandleScript script,
jsbytecode* pc, const char** file,
unsigned* linenop,

View File

@ -174,6 +174,12 @@ using ScriptLCovMap = HashMap<BaseScript*, ScriptLCovEntry,
using ScriptVTuneIdMap = HashMap<BaseScript*, uint32_t,
DefaultHasher<BaseScript*>, SystemAllocPolicy>;
#endif
#ifdef JS_CACHEIR_SPEW
using ScriptFinalWarmUpCountEntry = mozilla::Tuple<uint32_t, char*>;
using ScriptFinalWarmUpCountMap =
HashMap<BaseScript*, ScriptFinalWarmUpCountEntry,
DefaultHasher<BaseScript*>, SystemAllocPolicy>;
#endif
using UniqueDebugScript = js::UniquePtr<DebugScript, JS::FreePolicy>;
using DebugScriptMap = HashMap<BaseScript*, UniqueDebugScript,
@ -2436,6 +2442,11 @@ extern jsbytecode* LineNumberToPC(JSScript* script, unsigned lineno);
extern JS_FRIEND_API unsigned GetScriptLineExtent(JSScript* script);
#ifdef JS_CACHEIR_SPEW
void maybeUpdateWarmUpCount(JSScript* script);
void maybeSpewScriptFinalWarmUpCount(JSScript* script);
#endif
} /* namespace js */
namespace js {