Bug 1614622 part 3 - Remove optimization tracking from profiler backend, remove forEach API methods. r=djvj

Differential Revision: https://phabricator.services.mozilla.com/D62427

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jan de Mooij 2020-02-12 10:55:17 +00:00
Родитель 79d45d6fcb
Коммит 214eabb067
7 изменённых файлов: 0 добавлений и 489 удалений

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

@ -28,9 +28,6 @@ class ProfilingFrameIterator;
namespace JS {
struct ForEachTrackedOptimizationAttemptOp;
struct ForEachTrackedOptimizationTypeInfoOp;
// This iterator can be used to walk the stack of a thread suspended at an
// arbitrary pc. To provide accurate results, profiling must have been enabled
// (via EnableRuntimeProfilingStack) before executing the callstack being
@ -193,12 +190,6 @@ class MOZ_STACK_CLASS ProfiledFrameHandle {
void* canonicalAddress() const { return canonicalAddr_; }
JS_PUBLIC_API ProfilingFrameIterator::FrameKind frameKind() const;
JS_PUBLIC_API void forEachOptimizationAttempt(
ForEachTrackedOptimizationAttemptOp& op, JSScript** scriptOut,
jsbytecode** pcOut) const;
JS_PUBLIC_API void forEachOptimizationTypeInfo(
ForEachTrackedOptimizationTypeInfoOp& op) const;
JS_PUBLIC_API uint64_t realmID() const;
};

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

@ -202,51 +202,6 @@ JS_PUBLIC_API const char* TrackedOutcomeString(TrackedOutcome outcome);
JS_PUBLIC_API const char* TrackedTypeSiteString(TrackedTypeSite site);
struct ForEachTrackedOptimizationAttemptOp {
virtual void operator()(TrackedStrategy strategy, TrackedOutcome outcome) = 0;
};
struct ForEachTrackedOptimizationTypeInfoOp {
// Called 0+ times per entry, once for each type in the type set that Ion
// saw during MIR construction. readType is always called _before_
// operator() on the same entry.
//
// The keyedBy parameter describes how the type is keyed:
// - "primitive" for primitive types
// - "constructor" for object types tied to a scripted constructor
// function.
// - "alloc site" for object types tied to an allocation site.
// - "prototype" for object types tied neither to a constructor nor
// to an allocation site, but to a prototype.
// - "singleton" for object types which only has a single value.
// - "function" for object types referring to scripted functions.
// - "native" for object types referring to native functions.
//
// The name parameter is the string representation of the type. If the
// type is keyed by "constructor", or if the type itself refers to a
// scripted function, the name is the function's displayAtom. If the type
// is keyed by "native", this is nullptr.
//
// The location parameter is the filename if the type is keyed by
// "constructor", "alloc site", or if the type itself refers to a scripted
// function. If the type is keyed by "native", it is the offset of the
// native function, suitable for use with addr2line on Linux or atos on OS
// X. Otherwise it is nullptr.
//
// The lineno parameter is the line number if the type is keyed by
// "constructor", "alloc site", or if the type itself refers to a scripted
// function. Otherwise it is Nothing().
//
// The location parameter is the only one that may need escaping if being
// quoted.
virtual void readType(const char* keyedBy, const char* name,
const char* location,
const mozilla::Maybe<unsigned>& lineno) = 0;
// Called once per entry.
virtual void operator()(TrackedTypeSite site, const char* mirType) = 0;
};
} // namespace JS
#endif // js_TrackedOptimizationInfo_h

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

@ -358,11 +358,6 @@ class JitcodeGlobalEntry {
mozilla::Maybe<uint8_t> trackedOptimizationIndexAtAddr(
void* ptr, uint32_t* entryOffsetOut);
void forEachOptimizationAttempt(
uint8_t index, JS::ForEachTrackedOptimizationAttemptOp& op);
void forEachOptimizationTypeInfo(
uint8_t index, IonTrackedOptimizationsTypeInfo::ForEachOpAdapter& op);
template <class ShouldTraceProvider>
bool trace(JSTracer* trc);
void sweepChildren();
@ -789,47 +784,6 @@ class JitcodeGlobalEntry {
return mozilla::Nothing();
}
void forEachOptimizationAttempt(JSRuntime* rt, uint8_t index,
JS::ForEachTrackedOptimizationAttemptOp& op) {
switch (kind()) {
case Ion:
ionEntry().forEachOptimizationAttempt(index, op);
return;
case Baseline:
case Dummy:
break;
default:
MOZ_CRASH("Invalid JitcodeGlobalEntry kind.");
}
}
void forEachOptimizationTypeInfo(
JSRuntime* rt, uint8_t index,
IonTrackedOptimizationsTypeInfo::ForEachOpAdapter& op) {
switch (kind()) {
case Ion:
ionEntry().forEachOptimizationTypeInfo(index, op);
return;
case Baseline:
case Dummy:
break;
default:
MOZ_CRASH("Invalid JitcodeGlobalEntry kind.");
}
}
IonTrackedOptimizationsAttempts trackedOptimizationAttempts(uint8_t index) {
return ionEntry().trackedOptimizationAttempts(index);
}
IonTrackedOptimizationsTypeInfo trackedOptimizationTypeInfo(uint8_t index) {
return ionEntry().trackedOptimizationTypeInfo(index);
}
const IonTrackedTypeVector* allTrackedTypes() {
return ionEntry().allTrackedTypes();
}
Zone* zone() { return baseEntry().jitcode()->zone(); }
template <class ShouldTraceProvider>

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

@ -23,8 +23,6 @@ using mozilla::Maybe;
using mozilla::Nothing;
using mozilla::Some;
using JS::ForEachTrackedOptimizationAttemptOp;
using JS::ForEachTrackedOptimizationTypeInfoOp;
using JS::TrackedOutcome;
using JS::TrackedStrategy;
using JS::TrackedTypeSite;
@ -419,49 +417,6 @@ Maybe<uint8_t> JitcodeGlobalEntry::IonEntry::trackedOptimizationIndexAtAddr(
return region->findIndex(ptrOffset, entryOffsetOut);
}
void JitcodeGlobalEntry::IonEntry::forEachOptimizationAttempt(
uint8_t index, ForEachTrackedOptimizationAttemptOp& op) {
trackedOptimizationAttempts(index).forEach(op);
}
void JitcodeGlobalEntry::IonEntry::forEachOptimizationTypeInfo(
uint8_t index, IonTrackedOptimizationsTypeInfo::ForEachOpAdapter& op) {
trackedOptimizationTypeInfo(index).forEach(op, allTrackedTypes());
}
void IonTrackedOptimizationsAttempts::forEach(
ForEachTrackedOptimizationAttemptOp& op) {
CompactBufferReader reader(start_, end_);
const uint8_t* cur = start_;
while (cur != end_) {
TrackedStrategy strategy = TrackedStrategy(reader.readUnsigned());
TrackedOutcome outcome = TrackedOutcome(reader.readUnsigned());
MOZ_ASSERT(strategy < TrackedStrategy::Count);
MOZ_ASSERT(outcome < TrackedOutcome::Count);
op(strategy, outcome);
cur = reader.currentPosition();
MOZ_ASSERT(cur <= end_);
}
}
void IonTrackedOptimizationsTypeInfo::forEach(
ForEachOp& op, const IonTrackedTypeVector* allTypes) {
CompactBufferReader reader(start_, end_);
const uint8_t* cur = start_;
while (cur != end_) {
TrackedTypeSite site = JS::TrackedTypeSite(reader.readUnsigned());
MOZ_ASSERT(site < JS::TrackedTypeSite::Count);
MIRType mirType = MIRType(reader.readUnsigned());
uint32_t length = reader.readUnsigned();
for (uint32_t i = 0; i < length; i++) {
op.readType((*allTypes)[reader.readByte()]);
}
op(site, mirType);
cur = reader.currentPosition();
MOZ_ASSERT(cur <= end_);
}
}
Maybe<uint8_t> IonTrackedOptimizationsRegion::findIndex(
uint32_t offset, uint32_t* entryOffsetOut) const {
if (offset <= startOffset_ || offset > endOffset_) {
@ -1131,91 +1086,6 @@ static JSFunction* FunctionFromTrackedType(
return ty.group()->maybeInterpretedFunction();
}
void IonTrackedOptimizationsTypeInfo::ForEachOpAdapter::readType(
const IonTrackedTypeWithAddendum& tracked) {
TypeSet::Type ty = tracked.type;
if (ty.isPrimitive() || ty.isUnknown() || ty.isAnyObject()) {
op_.readType("primitive", TypeSet::NonObjectTypeString(ty), nullptr,
Nothing());
return;
}
char buf[512];
const uint32_t bufsize = mozilla::ArrayLength(buf);
if (JSFunction* fun = FunctionFromTrackedType(tracked)) {
// The displayAtom is useful for identifying both native and
// interpreted functions.
char* name = nullptr;
if (fun->displayAtom()) {
PutEscapedString(buf, bufsize, fun->displayAtom(), 0);
name = buf;
}
if (fun->isNative()) {
//
// Try printing out the displayAtom of the native function and the
// absolute address of the native function pointer.
//
// Note that this address is not usable without knowing the
// starting address at which our shared library is loaded. Shared
// library information is exposed by the profiler. If this address
// needs to be symbolicated manually (e.g., when it is gotten via
// debug spewing of all optimization information), it needs to be
// converted to an offset from the beginning of the shared library
// for use with utilities like `addr2line` on Linux and `atos` on
// OS X. Converting to an offset may be done via dladdr():
//
// void* addr = JS_FUNC_TO_DATA_PTR(void*, fun->native());
// uintptr_t offset;
// Dl_info info;
// if (dladdr(addr, &info) != 0) {
// offset = uintptr_t(addr) - uintptr_t(info.dli_fbase);
// }
//
char locationBuf[20];
if (!name) {
uintptr_t addr = JS_FUNC_TO_DATA_PTR(uintptr_t, fun->native());
snprintf(locationBuf, mozilla::ArrayLength(locationBuf), "%" PRIxPTR,
addr);
}
op_.readType("native", name, name ? nullptr : locationBuf, Nothing());
return;
}
const char* filename;
Maybe<unsigned> lineno;
InterpretedFunctionFilenameAndLineNumber(fun, &filename, &lineno);
op_.readType(tracked.hasConstructor() ? "constructor" : "function", name,
filename, lineno);
return;
}
const char* className = ty.objectKey()->clasp()->name;
snprintf(buf, bufsize, "[object %s]", className);
if (tracked.hasAllocationSite()) {
JSScript* script = tracked.script;
op_.readType(
"alloc site", buf, script->maybeForwardedScriptSource()->filename(),
Some(PCToLineNumber(script, script->offsetToPC(tracked.offset))));
return;
}
if (ty.isGroup()) {
op_.readType("prototype", buf, nullptr, Nothing());
return;
}
op_.readType("singleton", buf, nullptr, Nothing());
}
void IonTrackedOptimizationsTypeInfo::ForEachOpAdapter::operator()(
JS::TrackedTypeSite site, MIRType mirType) {
op_(site, StringFromMIRType(mirType));
}
typedef JS::ProfiledFrameHandle FrameHandle;
void FrameHandle::updateHasTrackedOptimizations() {
@ -1236,18 +1106,3 @@ void FrameHandle::updateHasTrackedOptimizations() {
(void*)(((uint8_t*)entry_.nativeStartAddr()) + entryOffset);
}
}
JS_PUBLIC_API void FrameHandle::forEachOptimizationAttempt(
ForEachTrackedOptimizationAttemptOp& op, JSScript** scriptOut,
jsbytecode** pcOut) const {
MOZ_ASSERT(optsIndex_.isSome());
entry_.forEachOptimizationAttempt(rt_, *optsIndex_, op);
entry_.youngestFrameLocationAtAddr(rt_, addr_, scriptOut, pcOut);
}
JS_PUBLIC_API void FrameHandle::forEachOptimizationTypeInfo(
ForEachTrackedOptimizationTypeInfoOp& op) const {
MOZ_ASSERT(optsIndex_.isSome());
IonTrackedOptimizationsTypeInfo::ForEachOpAdapter adapter(op);
entry_.forEachOptimizationTypeInfo(rt_, *optsIndex_, adapter);
}

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

@ -427,8 +427,6 @@ class IonTrackedOptimizationsAttempts {
// Cannot be empty.
MOZ_ASSERT(start < end);
}
void forEach(JS::ForEachTrackedOptimizationAttemptOp& op);
};
struct IonTrackedTypeWithAddendum {
@ -479,30 +477,6 @@ class IonTrackedOptimizationsTypeInfo {
}
bool empty() const { return start_ == end_; }
// Unlike IonTrackedOptimizationAttempts,
// JS::ForEachTrackedOptimizationTypeInfoOp cannot be used directly. The
// internal API needs to deal with engine-internal data structures (e.g.,
// TypeSet::Type) directly.
//
// An adapter is provided below.
struct ForEachOp {
virtual void readType(const IonTrackedTypeWithAddendum& tracked) = 0;
virtual void operator()(JS::TrackedTypeSite site, MIRType mirType) = 0;
};
class ForEachOpAdapter : public ForEachOp {
JS::ForEachTrackedOptimizationTypeInfoOp& op_;
public:
explicit ForEachOpAdapter(JS::ForEachTrackedOptimizationTypeInfoOp& op)
: op_(op) {}
void readType(const IonTrackedTypeWithAddendum& tracked) override;
void operator()(JS::TrackedTypeSite site, MIRType mirType) override;
};
void forEach(ForEachOp& op, const IonTrackedTypeVector* allTypes);
};
template <class Entry>

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

@ -959,61 +959,6 @@ bool CodeGeneratorShared::generateCompactTrackedOptimizationsMap(
return true;
}
#ifdef DEBUG
class ReadTempAttemptsVectorOp
: public JS::ForEachTrackedOptimizationAttemptOp {
TempOptimizationAttemptsVector* attempts_;
bool oom_;
public:
explicit ReadTempAttemptsVectorOp(TempOptimizationAttemptsVector* attempts)
: attempts_(attempts), oom_(false) {}
bool oom() { return oom_; }
void operator()(JS::TrackedStrategy strategy,
JS::TrackedOutcome outcome) override {
if (!attempts_->append(OptimizationAttempt(strategy, outcome))) {
oom_ = true;
}
}
};
struct ReadTempTypeInfoVectorOp
: public IonTrackedOptimizationsTypeInfo::ForEachOp {
TempAllocator& alloc_;
TempOptimizationTypeInfoVector* types_;
TempTypeList accTypes_;
bool oom_;
public:
ReadTempTypeInfoVectorOp(TempAllocator& alloc,
TempOptimizationTypeInfoVector* types)
: alloc_(alloc), types_(types), accTypes_(alloc), oom_(false) {}
bool oom() { return oom_; }
void readType(const IonTrackedTypeWithAddendum& tracked) override {
if (!accTypes_.append(tracked.type)) {
oom_ = true;
}
}
void operator()(JS::TrackedTypeSite site, MIRType mirType) override {
OptimizationTypeInfo ty(alloc_, site, mirType);
for (uint32_t i = 0; i < accTypes_.length(); i++) {
if (!ty.trackType(accTypes_[i])) {
oom_ = true;
}
}
if (!types_->append(std::move(ty))) {
oom_ = true;
}
accTypes_.clear();
}
};
#endif // DEBUG
void CodeGeneratorShared::verifyCompactTrackedOptimizationsMap(
JitCode* code, uint32_t numRegions,
const UniqueTrackedOptimizations& unique,
@ -1082,16 +1027,10 @@ void CodeGeneratorShared::verifyCompactTrackedOptimizationsMap(
if (!rt->gc.storeBuffer().cancelIonCompilations()) {
IonTrackedOptimizationsTypeInfo typeInfo = typesTable->entry(index);
TempOptimizationTypeInfoVector tvec(alloc());
ReadTempTypeInfoVectorOp top(alloc(), &tvec);
typeInfo.forEach(top, allTypes);
MOZ_ASSERT_IF(!top.oom(), entry.optimizations->matchTypes(tvec));
}
IonTrackedOptimizationsAttempts attempts = attemptsTable->entry(index);
TempOptimizationAttemptsVector avec(alloc());
ReadTempAttemptsVectorOp aop(&avec);
attempts.forEach(aop);
MOZ_ASSERT_IF(!aop.oom(), entry.optimizations->matchAttempts(avec));
}
}
#endif

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

@ -116,44 +116,6 @@ struct TypeInfo {
Maybe<unsigned> mLineNumber;
};
template <typename LambdaT>
class ForEachTrackedOptimizationTypeInfoLambdaOp
: public JS::ForEachTrackedOptimizationTypeInfoOp {
public:
// aLambda needs to be a function with the following signature:
// void lambda(JS::TrackedTypeSite site, const char* mirType,
// const nsTArray<TypeInfo>& typeset)
// aLambda will be called once per entry.
explicit ForEachTrackedOptimizationTypeInfoLambdaOp(LambdaT&& aLambda)
: mLambda(aLambda) {}
// This is called 0 or more times per entry, *before* operator() is called
// for that entry.
void readType(const char* keyedBy, const char* name, const char* location,
const Maybe<unsigned>& lineno) override {
TypeInfo info = {keyedBy ? Some(nsCString(keyedBy)) : Nothing(),
name ? Some(nsCString(name)) : Nothing(),
location ? Some(nsCString(location)) : Nothing(), lineno};
mTypesetForUpcomingEntry.AppendElement(std::move(info));
}
void operator()(JS::TrackedTypeSite site, const char* mirType) override {
nsTArray<TypeInfo> typeset(std::move(mTypesetForUpcomingEntry));
mLambda(site, mirType, typeset);
}
private:
nsTArray<TypeInfo> mTypesetForUpcomingEntry;
LambdaT mLambda;
};
template <typename LambdaT>
ForEachTrackedOptimizationTypeInfoLambdaOp<LambdaT>
MakeForEachTrackedOptimizationTypeInfoLambdaOp(LambdaT&& aLambda) {
return ForEachTrackedOptimizationTypeInfoLambdaOp<LambdaT>(
std::forward<LambdaT>(aLambda));
}
// As mentioned in ProfileBufferEntry.h, the JSON format contains many
// arrays whose elements are laid out according to various schemas to help
// de-duplication. This RAII class helps write these arrays by keeping track of
@ -243,28 +205,6 @@ class MOZ_RAII AutoArraySchemaWriter {
uint32_t mNextFreeIndex;
};
template <typename LambdaT>
class ForEachTrackedOptimizationAttemptsLambdaOp
: public JS::ForEachTrackedOptimizationAttemptOp {
public:
explicit ForEachTrackedOptimizationAttemptsLambdaOp(LambdaT&& aLambda)
: mLambda(std::move(aLambda)) {}
void operator()(JS::TrackedStrategy aStrategy,
JS::TrackedOutcome aOutcome) override {
mLambda(aStrategy, aOutcome);
}
private:
LambdaT mLambda;
};
template <typename LambdaT>
ForEachTrackedOptimizationAttemptsLambdaOp<LambdaT>
MakeForEachTrackedOptimizationAttemptsLambdaOp(LambdaT&& aLambda) {
return ForEachTrackedOptimizationAttemptsLambdaOp<LambdaT>(
std::move(aLambda));
}
UniqueJSONStrings::UniqueJSONStrings() { mStringTableWriter.StartBareList(); }
UniqueJSONStrings::UniqueJSONStrings(const UniqueJSONStrings& aOther) {
@ -496,94 +436,6 @@ void UniqueStacks::StreamNonJITFrame(const FrameKey& aFrame) {
}
}
static void StreamJITFrameOptimizations(
SpliceableJSONWriter& aWriter, UniqueJSONStrings& aUniqueStrings,
JSContext* aContext, const JS::ProfiledFrameHandle& aJITFrame) {
aWriter.StartObjectElement();
{
aWriter.StartArrayProperty("types");
{
auto op = MakeForEachTrackedOptimizationTypeInfoLambdaOp(
[&](JS::TrackedTypeSite site, const char* mirType,
const nsTArray<TypeInfo>& typeset) {
aWriter.StartObjectElement();
{
aUniqueStrings.WriteProperty(aWriter, "site",
JS::TrackedTypeSiteString(site));
aUniqueStrings.WriteProperty(aWriter, "mirType", mirType);
if (!typeset.IsEmpty()) {
aWriter.StartArrayProperty("typeset");
for (const TypeInfo& typeInfo : typeset) {
aWriter.StartObjectElement();
{
aUniqueStrings.WriteProperty(aWriter, "keyedBy",
typeInfo.mKeyedBy->get());
if (typeInfo.mName) {
aUniqueStrings.WriteProperty(aWriter, "name",
typeInfo.mName->get());
}
if (typeInfo.mLocation) {
aUniqueStrings.WriteProperty(aWriter, "location",
typeInfo.mLocation->get());
}
if (typeInfo.mLineNumber.isSome()) {
aWriter.IntProperty("line", *typeInfo.mLineNumber);
}
}
aWriter.EndObject();
}
aWriter.EndArray();
}
}
aWriter.EndObject();
});
aJITFrame.forEachOptimizationTypeInfo(op);
}
aWriter.EndArray();
JS::Rooted<JSScript*> script(aContext);
jsbytecode* pc;
aWriter.StartObjectProperty("attempts");
{
{
JSONSchemaWriter schema(aWriter);
schema.WriteField("strategy");
schema.WriteField("outcome");
}
aWriter.StartArrayProperty("data");
{
auto op = MakeForEachTrackedOptimizationAttemptsLambdaOp(
[&](JS::TrackedStrategy strategy, JS::TrackedOutcome outcome) {
enum Schema : uint32_t { STRATEGY = 0, OUTCOME = 1 };
AutoArraySchemaWriter writer(aWriter, aUniqueStrings);
writer.StringElement(STRATEGY,
JS::TrackedStrategyString(strategy));
writer.StringElement(OUTCOME, JS::TrackedOutcomeString(outcome));
});
aJITFrame.forEachOptimizationAttempt(op, script.address(), &pc);
}
aWriter.EndArray();
}
aWriter.EndObject();
if (JSAtom* name = js::GetPropertyNameFromPC(script, pc)) {
char buf[512];
JS_PutEscapedLinearString(buf, ArrayLength(buf),
js::AtomToLinearString(name), 0);
aUniqueStrings.WriteProperty(aWriter, "propertyName", buf);
}
unsigned line, column;
line = JS_PCToLineNumber(script, pc, &column);
aWriter.IntProperty("line", line);
aWriter.IntProperty("column", column);
}
aWriter.EndObject();
}
static void StreamJITFrame(JSContext* aContext, SpliceableJSONWriter& aWriter,
UniqueJSONStrings& aUniqueStrings,
const JS::ProfiledFrameHandle& aJITFrame) {
@ -616,15 +468,6 @@ static void StreamJITFrame(JSContext* aContext, SpliceableJSONWriter& aWriter,
IMPLEMENTATION,
frameKind == JS::ProfilingFrameIterator::Frame_Ion ? "ion" : "baseline");
if (aJITFrame.hasTrackedOptimizations()) {
writer.FreeFormElement(
OPTIMIZATIONS,
[&](SpliceableJSONWriter& aWriter, UniqueJSONStrings& aUniqueStrings) {
StreamJITFrameOptimizations(aWriter, aUniqueStrings, aContext,
aJITFrame);
});
}
const JS::ProfilingCategoryPairInfo& info =
JS::GetProfilingCategoryPairInfo(JS::ProfilingCategoryPair::JS);
writer.IntElement(CATEGORY, uint32_t(info.mCategory));