Bug 1301764 - Implement JS_GC_REPORT_TENURING to report what is getting tenured, r=terrence

--HG--
extra : rebase_source : f1be2ad91b5848470fe486894ee7105fcc12c7bf
This commit is contained in:
Steve Fink 2016-09-13 14:03:40 -07:00
parent e1d35bb444
commit 62bd9194f0
4 changed files with 57 additions and 36 deletions

View File

@ -120,6 +120,7 @@ js::Nursery::Nursery(JSRuntime* rt)
, previousPromotionRate_(0)
, profileThreshold_(0)
, enableProfiling_(false)
, reportTenurings_(0)
, minorGcCount_(0)
, freeMallocedBuffersTask(nullptr)
, sweepActions_(nullptr)
@ -159,13 +160,23 @@ js::Nursery::init(uint32_t maxNurseryBytes, AutoLockGC& lock)
if (env) {
if (0 == strcmp(env, "help")) {
fprintf(stderr, "JS_GC_PROFILE_NURSERY=N\n"
"\tReport minor GC's taking more than N microseconds.\n");
"\tReport minor GC's taking at least N microseconds.\n");
exit(0);
}
enableProfiling_ = true;
profileThreshold_ = atoi(env);
}
env = getenv("JS_GC_REPORT_TENURING");
if (env) {
if (0 == strcmp(env, "help")) {
fprintf(stderr, "JS_GC_REPORT_TENURING=N\n"
"\tAfter a minor GC, report any ObjectGroups with at least N instances tenured.\n");
exit(0);
}
reportTenurings_ = atoi(env);
}
PodZero(&startTimes_);
PodZero(&profileTimes_);
PodZero(&totalTimes_);
@ -577,8 +588,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason)
uint32_t pretenureCount = 0;
if (promotionRate > 0.8 || reason == JS::gcreason::FULL_STORE_BUFFER) {
JSContext* cx = rt->contextFromMainThread();
for (size_t i = 0; i < ArrayLength(tenureCounts.entries); i++) {
const TenureCount& entry = tenureCounts.entries[i];
for (auto& entry : tenureCounts.entries) {
if (entry.count >= 3000) {
ObjectGroup* group = entry.group;
if (group->canPreTenure()) {
@ -623,6 +633,15 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason)
promotionRate * 100,
numChunks());
printProfileTimes(profileTimes_);
if (reportTenurings_) {
for (auto& entry : tenureCounts.entries) {
if (entry.count >= reportTenurings_) {
fprintf(stderr, "%d x ", entry.count);
entry.group->print();
}
}
}
}
}

View File

@ -305,10 +305,13 @@ class Nursery
/* Promotion rate for the previous minor collection. */
double previousPromotionRate_;
/* Report minor collections taking more than this many us, if enabled. */
/* Report minor collections taking at least this many us, if enabled. */
int64_t profileThreshold_;
bool enableProfiling_;
/* Report ObjectGroups with at lest this many instances tenured. */
int64_t reportTenurings_;
/* Profiling data. */
enum class ProfileKey

View File

@ -123,6 +123,33 @@ TypeSet::NonObjectTypeString(TypeSet::Type type)
return "object";
}
/* static */ const char*
TypeSet::TypeString(TypeSet::Type type)
{
if (type.isPrimitive() || type.isUnknown() || type.isAnyObject())
return NonObjectTypeString(type);
static char bufs[4][40];
static unsigned which = 0;
which = (which + 1) & 3;
if (type.isSingleton()) {
JSObject* singleton = type.singletonNoBarrier();
snprintf(bufs[which], 40, "<%s %#" PRIxPTR ">",
singleton->getClass()->name, uintptr_t(singleton));
} else {
snprintf(bufs[which], 40, "[%s * %#" PRIxPTR "]", type.groupNoBarrier()->clasp()->name, uintptr_t(type.groupNoBarrier()));
}
return bufs[which];
}
/* static */ const char*
TypeSet::ObjectGroupString(ObjectGroup* group)
{
return TypeString(TypeSet::ObjectType(group));
}
#ifdef DEBUG
static bool InferSpewActive(SpewChannel channel)
@ -195,30 +222,6 @@ js::InferSpewColor(TypeSet* types)
return colors[DefaultHasher<TypeSet*>::hash(types) % 7];
}
/* static */ const char*
TypeSet::TypeString(TypeSet::Type type)
{
if (type.isPrimitive() || type.isUnknown() || type.isAnyObject())
return NonObjectTypeString(type);
static char bufs[4][40];
static unsigned which = 0;
which = (which + 1) & 3;
if (type.isSingleton())
snprintf(bufs[which], 40, "<0x%p>", (void*) type.singletonNoBarrier());
else
snprintf(bufs[which], 40, "[0x%p]", (void*) type.groupNoBarrier());
return bufs[which];
}
/* static */ const char*
TypeSet::ObjectGroupString(ObjectGroup* group)
{
return TypeString(TypeSet::ObjectType(group));
}
void
js::InferSpew(SpewChannel channel, const char* fmt, ...)
{
@ -3045,8 +3048,8 @@ ObjectGroup::print()
fprintf(stderr, "\n newScript %d properties",
(int) newScript()->templateObject()->slotSpan());
if (newScript()->initializedGroup()) {
fprintf(stderr, " initializedGroup %p with %d properties",
newScript()->initializedGroup(), (int) newScript()->initializedShape()->slotSpan());
fprintf(stderr, " initializedGroup %#" PRIxPTR " with %d properties",
uintptr_t(newScript()->initializedGroup()), int(newScript()->initializedShape()->slotSpan()));
}
} else {
fprintf(stderr, "\n newScript unanalyzed");
@ -4469,7 +4472,8 @@ TypeScript::printTypes(JSContext* cx, HandleScript script) const
fprintf(stderr, "Eval");
else
fprintf(stderr, "Main");
fprintf(stderr, " %p %s:%" PRIuSIZE " ", script.get(), script->filename(), script->lineno());
fprintf(stderr, " %#" PRIxPTR " %s:%" PRIuSIZE " ",
uintptr_t(script.get()), script->filename(), script->lineno());
if (script->functionNonDelazifying()) {
if (JSAtom* name = script->functionNonDelazifying()->name())

View File

@ -378,13 +378,8 @@ class TypeSet
static const char* NonObjectTypeString(Type type);
#ifdef DEBUG
static const char* TypeString(Type type);
static const char* ObjectGroupString(ObjectGroup* group);
#else
static const char* TypeString(Type type) { return nullptr; }
static const char* ObjectGroupString(ObjectGroup* group) { return nullptr; }
#endif
protected:
/* Flags for this type set. */