diff options
Diffstat (limited to 'devtools/client/performance/test/browser_perf-options-show-jit-optimizations.js')
-rw-r--r-- | devtools/client/performance/test/browser_perf-options-show-jit-optimizations.js | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/devtools/client/performance/test/browser_perf-options-show-jit-optimizations.js b/devtools/client/performance/test/browser_perf-options-show-jit-optimizations.js new file mode 100644 index 000000000..fd0bbc663 --- /dev/null +++ b/devtools/client/performance/test/browser_perf-options-show-jit-optimizations.js @@ -0,0 +1,260 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; +/* eslint-disable */ +// Bug 1235788, increase time out of this test +requestLongerTimeout(2); + +/** + * Tests that the JIT Optimizations view renders optimization data + * if on, and displays selected frames on focus. + */ + const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils"); +Services.prefs.setBoolPref(INVERT_PREF, false); + +function* spawnTest() { + let { panel } = yield initPerformance(SIMPLE_URL); + let { EVENTS, $, $$, window, PerformanceController } = panel.panelWin; + let { OverviewView, DetailsView, OptimizationsListView, JsCallTreeView } = panel.panelWin; + + let profilerData = { threads: [gThread] }; + + is(Services.prefs.getBoolPref(JIT_PREF), false, "record JIT Optimizations pref off by default"); + Services.prefs.setBoolPref(JIT_PREF, true); + is(Services.prefs.getBoolPref(JIT_PREF), true, "toggle on record JIT Optimizations"); + + // Make two recordings, so we have one to switch to later, as the + // second one will have fake sample data + yield startRecording(panel); + yield stopRecording(panel); + + yield startRecording(panel); + yield stopRecording(panel); + + yield DetailsView.selectView("js-calltree"); + + yield injectAndRenderProfilerData(); + + is($("#jit-optimizations-view").classList.contains("hidden"), true, + "JIT Optimizations should be hidden when pref is on, but no frame selected"); + + // A is never a leaf, so it's optimizations should not be shown. + yield checkFrame(1); + + // gRawSite2 and gRawSite3 are both optimizations on B, so they'll have + // indices in descending order of # of samples. + yield checkFrame(2, true); + + // Leaf node (C) with no optimizations should not display any opts. + yield checkFrame(3); + + // Select the node with optimizations and change to a new recording + // to ensure the opts view is cleared + let rendered = once(JsCallTreeView, "focus"); + mousedown(window, $$(".call-tree-item")[2]); + yield rendered; + let isHidden = $("#jit-optimizations-view").classList.contains("hidden"); + ok(!isHidden, "opts view should be visible when selecting a frame with opts"); + + let select = once(PerformanceController, EVENTS.RECORDING_SELECTED); + rendered = once(JsCallTreeView, EVENTS.UI_JS_CALL_TREE_RENDERED); + setSelectedRecording(panel, 0); + yield Promise.all([select, rendered]); + + isHidden = $("#jit-optimizations-view").classList.contains("hidden"); + ok(isHidden, "opts view is hidden when switching recordings"); + + rendered = once(JsCallTreeView, EVENTS.UI_JS_CALL_TREE_RENDERED); + setSelectedRecording(panel, 1); + yield rendered; + + rendered = once(JsCallTreeView, "focus"); + mousedown(window, $$(".call-tree-item")[2]); + yield rendered; + isHidden = $("#jit-optimizations-view").classList.contains("hidden"); + ok(!isHidden, "opts view should be visible when selecting a frame with opts"); + + rendered = once(JsCallTreeView, EVENTS.UI_JS_CALL_TREE_RENDERED); + Services.prefs.setBoolPref(JIT_PREF, false); + yield rendered; + ok(true, "call tree rerendered when JIT pref changes"); + isHidden = $("#jit-optimizations-view").classList.contains("hidden"); + ok(isHidden, "opts view hidden when toggling off jit pref"); + + rendered = once(JsCallTreeView, "focus"); + mousedown(window, $$(".call-tree-item")[2]); + yield rendered; + isHidden = $("#jit-optimizations-view").classList.contains("hidden"); + ok(isHidden, "opts view hidden when jit pref off and selecting a frame with opts"); + + yield teardown(panel); + finish(); + + function* injectAndRenderProfilerData() { + // Get current recording and inject our mock data + info("Injecting mock profile data"); + let recording = PerformanceController.getCurrentRecording(); + recording._profile = profilerData; + + // Force a rerender + let rendered = once(JsCallTreeView, EVENTS.UI_JS_CALL_TREE_RENDERED); + JsCallTreeView.render(OverviewView.getTimeInterval()); + yield rendered; + } + + function* checkFrame(frameIndex, hasOpts) { + info(`Checking frame ${frameIndex}`); + // Click the frame + let rendered = once(JsCallTreeView, "focus"); + mousedown(window, $$(".call-tree-item")[frameIndex]); + yield rendered; + + let isHidden = $("#jit-optimizations-view").classList.contains("hidden"); + if (hasOpts) { + ok(!isHidden, "JIT Optimizations view is not hidden if current frame has opts."); + } else { + ok(isHidden, "JIT Optimizations view is hidden if current frame does not have opts"); + } + } +} + +var gUniqueStacks = new RecordingUtils.UniqueStacks(); + +function uniqStr(s) { + return gUniqueStacks.getOrAddStringIndex(s); +} + +// Since deflateThread doesn't handle deflating optimization info, use +// placeholder names A_O1, B_O2, and B_O3, which will be used to manually +// splice deduped opts into the profile. +var gThread = RecordingUtils.deflateThread({ + samples: [{ + time: 0, + frames: [ + { location: "(root)" } + ] + }, { + time: 5, + frames: [ + { location: "(root)" }, + { location: "A_O1" }, + { location: "B_O2" }, + { location: "C (http://foo/bar/baz:56)" } + ] + }, { + time: 5 + 1, + frames: [ + { location: "(root)" }, + { location: "A (http://foo/bar/baz:12)" }, + { location: "B_O2" }, + ] + }, { + time: 5 + 1 + 2, + frames: [ + { location: "(root)" }, + { location: "A_O1" }, + { location: "B_O3" }, + ] + }, { + time: 5 + 1 + 2 + 7, + frames: [ + { location: "(root)" }, + { location: "A_O1" }, + { location: "E (http://foo/bar/baz:90)" }, + { location: "F (http://foo/bar/baz:99)" } + ] + }], + markers: [] +}, gUniqueStacks); + +// 3 RawOptimizationSites +var gRawSite1 = { + _testFrameInfo: { name: "A", line: "12", file: "@baz" }, + line: 12, + column: 2, + types: [{ + mirType: uniqStr("Object"), + site: uniqStr("A (http://foo/bar/bar:12)"), + typeset: [{ + keyedBy: uniqStr("constructor"), + name: uniqStr("Foo"), + location: uniqStr("A (http://foo/bar/baz:12)") + }, { + keyedBy: uniqStr("primitive"), + location: uniqStr("self-hosted") + }] + }], + attempts: { + schema: { + outcome: 0, + strategy: 1 + }, + data: [ + [uniqStr("Failure1"), uniqStr("SomeGetter1")], + [uniqStr("Failure2"), uniqStr("SomeGetter2")], + [uniqStr("Failure3"), uniqStr("SomeGetter3")] + ] + } +}; + +var gRawSite2 = { + _testFrameInfo: { name: "B", line: "10", file: "@boo" }, + line: 40, + types: [{ + mirType: uniqStr("Int32"), + site: uniqStr("Receiver") + }], + attempts: { + schema: { + outcome: 0, + strategy: 1 + }, + data: [ + [uniqStr("Failure1"), uniqStr("SomeGetter1")], + [uniqStr("Failure2"), uniqStr("SomeGetter2")], + [uniqStr("Inlined"), uniqStr("SomeGetter3")] + ] + } +}; + +var gRawSite3 = { + _testFrameInfo: { name: "B", line: "10", file: "@boo" }, + line: 34, + types: [{ + mirType: uniqStr("Int32"), + site: uniqStr("Receiver") + }], + attempts: { + schema: { + outcome: 0, + strategy: 1 + }, + data: [ + [uniqStr("Failure1"), uniqStr("SomeGetter1")], + [uniqStr("Failure2"), uniqStr("SomeGetter2")], + [uniqStr("Failure3"), uniqStr("SomeGetter3")] + ] + } +}; + +gThread.frameTable.data.forEach((frame) => { + const LOCATION_SLOT = gThread.frameTable.schema.location; + const OPTIMIZATIONS_SLOT = gThread.frameTable.schema.optimizations; + + let l = gThread.stringTable[frame[LOCATION_SLOT]]; + switch (l) { + case "A_O1": + frame[LOCATION_SLOT] = uniqStr("A (http://foo/bar/baz:12)"); + frame[OPTIMIZATIONS_SLOT] = gRawSite1; + break; + case "B_O2": + frame[LOCATION_SLOT] = uniqStr("B (http://foo/bar/boo:10)"); + frame[OPTIMIZATIONS_SLOT] = gRawSite2; + break; + case "B_O3": + frame[LOCATION_SLOT] = uniqStr("B (http://foo/bar/boo:10)"); + frame[OPTIMIZATIONS_SLOT] = gRawSite3; + break; + } +}); +/* eslint-enable */ |