зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1439014) for failing chrome failures and test verify tests on tools/profiler/tests/chrome/test_profile_with_trackopts.htm on a CLOSED TREE
Backed out changeset f01eb749b3f9 (bug 1439014) Backed out changeset 6d264bbb2669 (bug 1439014)
This commit is contained in:
Родитель
6985844d11
Коммит
bfec308dac
|
@ -32,8 +32,7 @@
|
|||
"restyle",
|
||||
"stackwalk",
|
||||
"tasktracer",
|
||||
"threads",
|
||||
"trackopts"
|
||||
"threads"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
|
@ -7260,9 +7260,6 @@ JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t v
|
|||
}
|
||||
jit::JitOptions.jumpThreshold = value;
|
||||
break;
|
||||
case JSJITCOMPILER_TRACK_OPTIMIZATIONS:
|
||||
jit::JitOptions.disableOptimizationTracking = !value;
|
||||
break;
|
||||
case JSJITCOMPILER_SPECTRE_INDEX_MASKING:
|
||||
jit::JitOptions.spectreIndexMasking = !!value;
|
||||
break;
|
||||
|
|
|
@ -5867,7 +5867,6 @@ JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled);
|
|||
Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
|
||||
Register(FULL_DEBUG_CHECKS, "jit.full-debug-checks") \
|
||||
Register(JUMP_THRESHOLD, "jump-threshold") \
|
||||
Register(TRACK_OPTIMIZATIONS, "jit.track-optimizations") \
|
||||
Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt") \
|
||||
Register(SPECTRE_INDEX_MASKING, "spectre.index-masking") \
|
||||
Register(SPECTRE_OBJECT_MITIGATIONS_BARRIERS, "spectre.object-mitigations.barriers") \
|
||||
|
|
|
@ -15,7 +15,6 @@ RegisteredThread::RegisteredThread(ThreadInfo* aInfo, nsIEventTarget* aThread,
|
|||
, mThread(aThread)
|
||||
, mContext(nullptr)
|
||||
, mJSSampling(INACTIVE)
|
||||
, mJSTrackOptimizations(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RegisteredThread);
|
||||
|
||||
|
|
|
@ -197,14 +197,13 @@ public:
|
|||
// Request that this thread start JS sampling. JS sampling won't actually
|
||||
// start until a subsequent PollJSSampling() call occurs *and* mContext has
|
||||
// been set.
|
||||
void StartJSSampling(bool aTrackOptimizations)
|
||||
void StartJSSampling()
|
||||
{
|
||||
// This function runs on-thread or off-thread.
|
||||
|
||||
MOZ_RELEASE_ASSERT(mJSSampling == INACTIVE ||
|
||||
mJSSampling == INACTIVE_REQUESTED);
|
||||
mJSSampling = ACTIVE_REQUESTED;
|
||||
mJSTrackOptimizations = aTrackOptimizations;
|
||||
}
|
||||
|
||||
// Request that this thread stop JS sampling. JS sampling won't actually stop
|
||||
|
@ -237,8 +236,6 @@ public:
|
|||
if (mJSSampling == ACTIVE_REQUESTED) {
|
||||
mJSSampling = ACTIVE;
|
||||
js::EnableContextProfilingStack(mContext, true);
|
||||
JS_SetGlobalJitCompilerOption(mContext, JSJITCOMPILER_TRACK_OPTIMIZATIONS,
|
||||
mJSTrackOptimizations);
|
||||
js::RegisterContextProfilingEventMarker(mContext, profiler_add_marker);
|
||||
|
||||
} else if (mJSSampling == INACTIVE_REQUESTED) {
|
||||
|
@ -307,8 +304,6 @@ private:
|
|||
ACTIVE = 2,
|
||||
INACTIVE_REQUESTED = 3,
|
||||
} mJSSampling;
|
||||
|
||||
bool mJSTrackOptimizations;
|
||||
};
|
||||
|
||||
#endif // RegisteredThread_h
|
||||
|
|
|
@ -2253,8 +2253,7 @@ locked_register_thread(PSLockRef aLock, const char* aName, void* aStackTop)
|
|||
if (ActivePS::FeatureJS(aLock)) {
|
||||
// This StartJSSampling() call is on-thread, so we can poll manually to
|
||||
// start JS sampling immediately.
|
||||
registeredThread->StartJSSampling(
|
||||
ActivePS::FeatureTrackOptimizations(aLock));
|
||||
registeredThread->StartJSSampling();
|
||||
registeredThread->PollJSSampling();
|
||||
if (registeredThread->GetJSContext()) {
|
||||
profiledThreadData->NotifyReceivedJSContext(ActivePS::Buffer(aLock).mRangeEnd);
|
||||
|
@ -2853,8 +2852,7 @@ locked_profiler_start(PSLockRef aLock, uint32_t aEntries, double aInterval,
|
|||
ActivePS::AddLiveProfiledThread(aLock, registeredThread.get(),
|
||||
MakeUnique<ProfiledThreadData>(info, eventTarget));
|
||||
if (ActivePS::FeatureJS(aLock)) {
|
||||
registeredThread->StartJSSampling(
|
||||
ActivePS::FeatureTrackOptimizations(aLock));
|
||||
registeredThread->StartJSSampling();
|
||||
if (info->ThreadId() == tid) {
|
||||
// We can manually poll the current thread so it starts sampling
|
||||
// immediately.
|
||||
|
@ -3482,8 +3480,7 @@ profiler_clear_js_context()
|
|||
|
||||
// Tell the thread that we'd like to have JS sampling on this
|
||||
// thread again, once it gets a new JSContext (if ever).
|
||||
registeredThread->StartJSSampling(
|
||||
ActivePS::FeatureTrackOptimizations(lock));
|
||||
registeredThread->StartJSSampling();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,10 +128,7 @@ class TimeStamp;
|
|||
macro(8, "tasktracer", TaskTracer) \
|
||||
\
|
||||
/* Profile the registered secondary threads. */ \
|
||||
macro(9, "threads", Threads) \
|
||||
\
|
||||
/* Have the JavaScript engine track JIT optimizations. */ \
|
||||
macro(10, "trackopts", TrackOptimizations)
|
||||
macro(9, "threads", Threads)
|
||||
|
||||
struct ProfilerFeature
|
||||
{
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[DEFAULT]
|
||||
support-files=profiler_test_utils.js
|
||||
|
||||
[test_profile_with_trackopts.html]
|
||||
[test_profile_worker_bug_1428076.html]
|
||||
[test_profile_worker.html]
|
||||
|
|
|
@ -42,38 +42,12 @@ function end(error) {
|
|||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function getBufferInfo() {
|
||||
let position = {}, totalSize = {}, generation = {};
|
||||
Services.profiler.GetBufferInfo(position, totalSize, generation);
|
||||
return {
|
||||
position: position.value,
|
||||
totalSize: totalSize.value,
|
||||
generation: generation.value
|
||||
};
|
||||
}
|
||||
|
||||
async function runTest(settings, workload,
|
||||
checkProfileCallback = function(profile) {}) {
|
||||
async function runTest(settings, workload) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
try {
|
||||
await startProfiler(settings);
|
||||
|
||||
// Run workload() one or more times until at least one sample has been taken.
|
||||
const bufferInfoAtStart = getBufferInfo();
|
||||
while (true) {
|
||||
await workload();
|
||||
const bufferInfoAfterWorkload = getBufferInfo();
|
||||
if (bufferInfoAfterWorkload.generation > bufferInfoAtStart.generation ||
|
||||
bufferInfoAfterWorkload.position > bufferInfoAtStart.position) {
|
||||
// The buffer position advanced, so we've either added a marker or a
|
||||
// sample. It would be better to have conclusive evidence that we
|
||||
// actually have a sample...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const profile = await getProfile();
|
||||
await checkProfileCallback(profile);
|
||||
await getProfile();
|
||||
await stopProfiler();
|
||||
await end();
|
||||
} catch (e) {
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1439014
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1439014</title>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1439014">Mozilla Bug 1439014</a>
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="profiler_test_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
/* globals runTest */
|
||||
|
||||
"use strict";
|
||||
|
||||
const settings = {
|
||||
entries: 1000000, // 9MB
|
||||
interval: 1, // ms
|
||||
features: ["js", "threads", "trackopts"],
|
||||
threads: ["GeckoMain"]
|
||||
};
|
||||
|
||||
function innerFunction(x) {
|
||||
return x * 0.7; // This is line 30.
|
||||
}
|
||||
|
||||
function middleFunction(x) {
|
||||
return innerFunction(x) * 1.4;
|
||||
}
|
||||
|
||||
function outerFunction() {
|
||||
let k = 0;
|
||||
for (let i = 0; i < 1000000; i++) {
|
||||
k += middleFunction(i); // This is line 40.
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
function workload() {
|
||||
let m = 0;
|
||||
for (let i = 0; i < 20; i++) {
|
||||
m += outerFunction();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
runTest(settings, workload, profile => {
|
||||
const thisThread = profile.threads[0];
|
||||
const { frameTable, stringTable } = thisThread;
|
||||
|
||||
function prettifyOptimizationSites(optimizationSites) {
|
||||
return optimizationSites.map(optimizationSite => {
|
||||
const result = {};
|
||||
if (optimizationSite.site) {
|
||||
result.site = stringTable[optimizationSite.site];
|
||||
}
|
||||
if (optimizationSite.mirType) {
|
||||
result.mirType = stringTable[optimizationSite.mirType];
|
||||
}
|
||||
if (optimizationSite.typeset) {
|
||||
result.typeset = optimizationSite.typeset.map(({ keyedBy, name }) => ({
|
||||
keyedBy: stringTable[keyedBy],
|
||||
name: stringTable[name],
|
||||
}));
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
function prettifyAttempts(attempts) {
|
||||
const { strategy, outcome } = attempts.schema;
|
||||
return attempts.data.map(data => ({
|
||||
strategy: stringTable[data[strategy]],
|
||||
outcome: stringTable[data[outcome]],
|
||||
}));
|
||||
}
|
||||
function prettifyOptimizations(optimizations) {
|
||||
if (!optimizations) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
types: prettifyOptimizationSites(optimizations.types),
|
||||
attempts: prettifyAttempts(optimizations.attempts),
|
||||
line: optimizations.line,
|
||||
column: optimizations.column,
|
||||
};
|
||||
}
|
||||
function framesForFunc(functionName) {
|
||||
const { location, implementation, optimizations, line } = frameTable.schema;
|
||||
return frameTable.data.filter(data => {
|
||||
return stringTable[data[location]].startsWith(functionName + " ");
|
||||
}).map(data => ({
|
||||
implementation: stringTable[data[implementation]],
|
||||
optimizations: prettifyOptimizations(data[optimizations]),
|
||||
line: data[line],
|
||||
}));
|
||||
}
|
||||
|
||||
const outerFunctionFrames = framesForFunc("outerFunction");
|
||||
const innerFunctionFrames = framesForFunc("innerFunction");
|
||||
|
||||
// console.log("outerFunction:", outerFunctionFrames);
|
||||
// console.log("innerFunction:", innerFunctionFrames);
|
||||
//
|
||||
// Example output:
|
||||
//
|
||||
// console.log: "outerFunction:" [
|
||||
// {
|
||||
// implementation: "baseline",
|
||||
// optimizations: undefined,
|
||||
// line: undefined
|
||||
// },
|
||||
// {
|
||||
// implementation: "ion",
|
||||
// optimizations: undefined,
|
||||
// line: undefined
|
||||
// },
|
||||
// {
|
||||
// implementation: "ion",
|
||||
// optimizations: {
|
||||
// types: [
|
||||
// {
|
||||
// site: "Operand",
|
||||
// mirType: "Double",
|
||||
// typeset: [
|
||||
// { keyedBy: "primitive", name: "int" },
|
||||
// { keyedBy: "primitive", name: "float" }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// site: "Operand",
|
||||
// mirType: "Double"
|
||||
// }
|
||||
// ],
|
||||
// attempts: [
|
||||
// {
|
||||
// strategy: "BinaryArith_Concat",
|
||||
// outcome: "OperandNotString"
|
||||
// },
|
||||
// {
|
||||
// strategy: "BinaryArith_SpecializedTypes",
|
||||
// outcome: "GenericSuccess"
|
||||
// }
|
||||
// ],
|
||||
// line:40,
|
||||
// column:9
|
||||
// },
|
||||
// line: undefined
|
||||
// },
|
||||
// {
|
||||
// implementation: "ion",
|
||||
// optimizations: undefined,
|
||||
// line: undefined
|
||||
// }
|
||||
// ]
|
||||
// console.log: "innerFunction:" [
|
||||
// {
|
||||
// implementation: "ion",
|
||||
// optimizations: {
|
||||
// types: [
|
||||
// {
|
||||
// site: "Operand",
|
||||
// mirType: "Int32",
|
||||
// typeset: [
|
||||
// { keyedBy: "primitive", name: "int" }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// site: "Operand",
|
||||
// mirType: "Double"
|
||||
// }
|
||||
// ],
|
||||
// attempts: [
|
||||
// {
|
||||
// strategy: "BinaryArith_SpecializedTypes",
|
||||
// outcome: "GenericSuccess"
|
||||
// }
|
||||
// ],
|
||||
// line: 30,
|
||||
// column: 2
|
||||
// },
|
||||
// line: undefined
|
||||
// }
|
||||
// ]
|
||||
|
||||
ok(outerFunctionFrames.length > 0, "should have sampled at least one frame of outerFunction() running");
|
||||
const outerFunctionIonFrames = outerFunctionFrames.filter(frame => frame.implementation === "ion");
|
||||
ok(outerFunctionIonFrames.length > 0, "should have observed outerFunction() running in ion");
|
||||
const outerFunctionIonFramesWithOptimizations = outerFunctionIonFrames.filter(frame => frame.optimizations !== undefined);
|
||||
ok(outerFunctionIonFramesWithOptimizations.length > 0, "should have optimizations info for some frames of outerFunction()");
|
||||
|
||||
// Try to check for one specific optimization. If the JS engine changes, this
|
||||
// test may need changing. In this test we only care about the fact that we
|
||||
// get useful optimization information, we don't care about how exactly this
|
||||
// JS code was optimized.
|
||||
ok(outerFunctionIonFramesWithOptimizations.some(frame => {
|
||||
return frame.optimizations.line === 40 && frame.optimizations.attempts.some(attempt => {
|
||||
return attempt.strategy === "BinaryArith_SpecializedTypes" &&
|
||||
attempt.outcome === "GenericSuccess";
|
||||
}) && frame.types.some(optimizationSite => {
|
||||
return optimizationSite.site === "Operand" &&
|
||||
optimizationSite.mirType === "Double";
|
||||
});
|
||||
}), "should find a successful arithmetic specialization for the += operation on line 40");
|
||||
|
||||
ok(innerFunctionFrames.some(frame => {
|
||||
return frame.implementation === "ion" &&
|
||||
frame.optimizations !== undefined &&
|
||||
frame.optimizations.line === 30;
|
||||
}), "should find a piece of optimization info about innerFunction for line 30");
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче