Changeset 241219 in webkit


Ignore:
Timestamp:
Feb 8, 2019 4:25:46 PM (5 years ago)
Author:
commit-queue@webkit.org
Message:

Web Inspector: Import / Export Heap Snapshots
https://bugs.webkit.org/show_bug.cgi?id=194448
<rdar://problem/47928093>

Patch by Joseph Pecoraro <Joseph Pecoraro> on 2019-02-08
Reviewed by Devin Rousso.

Source/WebInspectorUI:

  • Localizations/en.lproj/localizedStrings.js:

New strings.

  • UserInterface/Proxies/HeapSnapshotProxy.js:

(WI.HeapSnapshotProxy):
(WI.HeapSnapshotProxy.deserialize):
(WI.HeapSnapshotProxy.prototype.get imported):
(WI.HeapSnapshotProxy.prototype.get snapshotStringData):
(WI.HeapSnapshotProxy.prototype.set snapshotStringData):
Include an "imported" state on the HeapSnapshot and allow for
stashing the snapshotStringData on the main thread side.

  • UserInterface/Proxies/HeapSnapshotWorkerProxy.js:

(WI.HeapSnapshotWorkerProxy.prototype.createImportedSnapshot):

  • UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js:

(HeapSnapshotWorker.prototype.clearSnapshots):
(HeapSnapshotWorker.prototype.createSnapshot):
Provide a specialized way to create an imported HeapSnapshot.
Track imported snapshots separately since they won't want to
be searched for live/dead objects due to active recording GCs.

  • UserInterface/Workers/HeapSnapshot/HeapSnapshot.js:

(HeapSnapshot):
(HeapSnapshot.updateCategoriesAndMetadata):
(HeapSnapshot.allocationBucketCounts):
(HeapSnapshot.instancesWithClassName):
(HeapSnapshot.prototype.nodeWithIdentifier):
(HeapSnapshot.prototype.dominatedNodes):
(HeapSnapshot.prototype.retainedNodes):
(HeapSnapshot.prototype.retainers):
(HeapSnapshot.prototype.updateDeadNodesAndGatherCollectionData):
(HeapSnapshot.prototype.serialize):
(HeapSnapshot.prototype.serializeNode):
(HeapSnapshot.prototype._buildPostOrderIndexes):
(HeapSnapshot.prototype._buildDominatorIndexes):
(HeapSnapshot.prototype._buildRetainedSizes):
(HeapSnapshot.prototype._gcRootPathes.visitNode):
(HeapSnapshot.prototype._gcRootPathes):
Construct a HeapSnapshot knowinng whether or not it is imported.
Imported snapshots may be the "GCDebugging" snapshot type which
differs from "Inspector" by the number of node fields. So keep
the node field count a member instead of a global constant
in order to work with both snapshot types.

  • UserInterface/Models/HeapAllocationsInstrument.js:

(WI.HeapAllocationsInstrument.prototype._takeHeapSnapshot):

  • UserInterface/Protocol/ConsoleObserver.js:

(WI.ConsoleObserver.prototype.heapSnapshot):

  • UserInterface/Protocol/HeapObserver.js:

(WI.HeapObserver.prototype.trackingStart):
(WI.HeapObserver.prototype.trackingComplete):
Stash the original string JSON data on the main thread side
where we already have the data.

  • UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js:

(WI.HeapAllocationsTimelineOverviewGraph.prototype.layout):
Don't show [S] icons for imported snapshots with no timestamp.

  • UserInterface/Views/HeapAllocationsTimelineView.js:

(WI.HeapAllocationsTimelineView):
(WI.HeapAllocationsTimelineView.prototype.get navigationItems):
(WI.HeapAllocationsTimelineView.prototype._importButtonNavigationItemClicked):
(WI.HeapAllocationsTimelineView.prototype._takeHeapSnapshotClicked):
Import button that just creates a new snapshot.

  • UserInterface/Views/HeapSnapshotContentView.js:

(WI.HeapSnapshotContentView):
(WI.HeapSnapshotContentView.prototype.get navigationItems):
(WI.HeapSnapshotContentView.prototype.get supportsSave):
(WI.HeapSnapshotContentView.prototype.get saveData):
(WI.HeapSnapshotContentView.prototype._exportSnapshot):
Export button that saves the original data.

  • UserInterface/Views/TimelineTabContentView.js:

(WI.TimelineTabContentView.displayNameForRecord):
Specialized display string for imported snapshots.

LayoutTests:

  • inspector/heap/imported-snapshot-expected.txt: Added.
  • inspector/heap/imported-snapshot.html: Added.
  • platform/mac/TestExpectations:
Location:
trunk
Files:
2 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r241209 r241219  
     12019-02-08  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Import / Export Heap Snapshots
     4        https://bugs.webkit.org/show_bug.cgi?id=194448
     5        <rdar://problem/47928093>
     6
     7        Reviewed by Devin Rousso.
     8
     9        * inspector/heap/imported-snapshot-expected.txt: Added.
     10        * inspector/heap/imported-snapshot.html: Added.
     11        * platform/mac/TestExpectations:
     12
    1132019-02-08  Nikita Vasilyev  <nvasilyev@apple.com>
    214
  • trunk/LayoutTests/platform/mac/TestExpectations

    r240829 r241219  
    10871087webkit.org/b/165582 inspector/worker/debugger-scripts.html [ Pass Failure ]
    10881088webkit.org/b/167203 inspector/worker/debugger-shared-breakpoint.html [ Pass Failure Timeout ]
     1089webkit.org/b/155607 inspector/heap/imported-snapshot.html [ Pass Timeout ]
    10891090webkit.org/b/155607 inspector/heap/snapshot.html [ Pass Timeout ]
    10901091webkit.org/b/143719 inspector/console/console-api.html [ Pass Timeout ]
  • trunk/Source/WebInspectorUI/ChangeLog

    r241216 r241219  
     12019-02-08  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Import / Export Heap Snapshots
     4        https://bugs.webkit.org/show_bug.cgi?id=194448
     5        <rdar://problem/47928093>
     6
     7        Reviewed by Devin Rousso.
     8
     9        * Localizations/en.lproj/localizedStrings.js:
     10        New strings.
     11
     12        * UserInterface/Proxies/HeapSnapshotProxy.js:
     13        (WI.HeapSnapshotProxy):
     14        (WI.HeapSnapshotProxy.deserialize):
     15        (WI.HeapSnapshotProxy.prototype.get imported):
     16        (WI.HeapSnapshotProxy.prototype.get snapshotStringData):
     17        (WI.HeapSnapshotProxy.prototype.set snapshotStringData):
     18        Include an "imported" state on the HeapSnapshot and allow for
     19        stashing the snapshotStringData on the main thread side.
     20
     21        * UserInterface/Proxies/HeapSnapshotWorkerProxy.js:
     22        (WI.HeapSnapshotWorkerProxy.prototype.createImportedSnapshot):
     23        * UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js:
     24        (HeapSnapshotWorker.prototype.clearSnapshots):
     25        (HeapSnapshotWorker.prototype.createSnapshot):
     26        Provide a specialized way to create an imported HeapSnapshot.
     27        Track imported snapshots separately since they won't want to
     28        be searched for live/dead objects due to active recording GCs.
     29
     30        * UserInterface/Workers/HeapSnapshot/HeapSnapshot.js:
     31        (HeapSnapshot):
     32        (HeapSnapshot.updateCategoriesAndMetadata):
     33        (HeapSnapshot.allocationBucketCounts):
     34        (HeapSnapshot.instancesWithClassName):
     35        (HeapSnapshot.prototype.nodeWithIdentifier):
     36        (HeapSnapshot.prototype.dominatedNodes):
     37        (HeapSnapshot.prototype.retainedNodes):
     38        (HeapSnapshot.prototype.retainers):
     39        (HeapSnapshot.prototype.updateDeadNodesAndGatherCollectionData):
     40        (HeapSnapshot.prototype.serialize):
     41        (HeapSnapshot.prototype.serializeNode):
     42        (HeapSnapshot.prototype._buildPostOrderIndexes):
     43        (HeapSnapshot.prototype._buildDominatorIndexes):
     44        (HeapSnapshot.prototype._buildRetainedSizes):
     45        (HeapSnapshot.prototype._gcRootPathes.visitNode):
     46        (HeapSnapshot.prototype._gcRootPathes):
     47        Construct a HeapSnapshot knowinng whether or not it is imported.
     48        Imported snapshots may be the "GCDebugging" snapshot type which
     49        differs from "Inspector" by the number of node fields. So keep
     50        the node field count a member instead of a global constant
     51        in order to work with both snapshot types.
     52
     53        * UserInterface/Models/HeapAllocationsInstrument.js:
     54        (WI.HeapAllocationsInstrument.prototype._takeHeapSnapshot):
     55        * UserInterface/Protocol/ConsoleObserver.js:
     56        (WI.ConsoleObserver.prototype.heapSnapshot):
     57        * UserInterface/Protocol/HeapObserver.js:
     58        (WI.HeapObserver.prototype.trackingStart):
     59        (WI.HeapObserver.prototype.trackingComplete):
     60        Stash the original string JSON data on the main thread side
     61        where we already have the data.
     62
     63        * UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js:
     64        (WI.HeapAllocationsTimelineOverviewGraph.prototype.layout):
     65        Don't show [S] icons for imported snapshots with no timestamp.
     66
     67        * UserInterface/Views/HeapAllocationsTimelineView.js:
     68        (WI.HeapAllocationsTimelineView):
     69        (WI.HeapAllocationsTimelineView.prototype.get navigationItems):
     70        (WI.HeapAllocationsTimelineView.prototype._importButtonNavigationItemClicked):
     71        (WI.HeapAllocationsTimelineView.prototype._takeHeapSnapshotClicked):
     72        Import button that just creates a new snapshot.
     73
     74        * UserInterface/Views/HeapSnapshotContentView.js:
     75        (WI.HeapSnapshotContentView):
     76        (WI.HeapSnapshotContentView.prototype.get navigationItems):
     77        (WI.HeapSnapshotContentView.prototype.get supportsSave):
     78        (WI.HeapSnapshotContentView.prototype.get saveData):
     79        (WI.HeapSnapshotContentView.prototype._exportSnapshot):
     80        Export button that saves the original data.
     81
     82        * UserInterface/Views/TimelineTabContentView.js:
     83        (WI.TimelineTabContentView.displayNameForRecord):
     84        Specialized display string for imported snapshots.
     85
    1862019-02-08  Joseph Pecoraro  <pecoraro@apple.com>
    287
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r240866 r241219  
    419419localizedStrings["Experimental"] = "Experimental";
    420420localizedStrings["Export"] = "Export";
     421localizedStrings["Export (%s)"] = "Export (%s)";
    421422localizedStrings["Export HAR"] = "Export HAR";
    422423localizedStrings["Export Result"] = "Export Result";
     
    489490localizedStrings["Headers:"] = "Headers:";
    490491localizedStrings["Heading Level"] = "Heading Level";
     492localizedStrings["Heap Snapshot %s-%s-%s at %s.%s.%s"] = "Heap Snapshot %s-%s-%s at %s.%s.%s";
    491493localizedStrings["Heap Snapshot Object (%s)"] = "Heap Snapshot Object (%s)";
    492494localizedStrings["Height"] = "Height";
     
    520522localizedStrings["Imported"] = "Imported";
    521523localizedStrings["Imported Recordings"] = "Imported Recordings";
     524localizedStrings["Imported \u2014 %s"] = "Imported \u2014 %s";
    522525localizedStrings["Incomplete"] = "Incomplete";
    523526localizedStrings["Indent width:"] = "Indent width:";
  • trunk/Source/WebInspectorUI/UserInterface/Models/HeapAllocationsInstrument.js

    r220119 r241219  
    8080            workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) => {
    8181                let snapshot = WI.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
     82                snapshot.snapshotStringData = snapshotStringData;
    8283                WI.timelineManager.heapSnapshotAdded(timestamp, snapshot);
    8384            });
  • trunk/Source/WebInspectorUI/UserInterface/Protocol/ConsoleObserver.js

    r236766 r241219  
    5454        workerProxy.createSnapshot(snapshotStringData, title || null, ({objectId, snapshot: serializedSnapshot}) => {
    5555            let snapshot = WI.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
     56            snapshot.snapshotStringData = snapshotStringData;
    5657            WI.timelineManager.heapSnapshotAdded(timestamp, snapshot);
    5758        });
  • trunk/Source/WebInspectorUI/UserInterface/Protocol/HeapObserver.js

    r220119 r241219  
    3838        workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) => {
    3939            let snapshot = WI.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
     40            snapshot.snapshotStringData = snapshotStringData;
    4041            WI.timelineManager.heapTrackingStarted(timestamp, snapshot);
    4142        });
     
    4748        workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) => {
    4849            let snapshot = WI.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
     50            snapshot.snapshotStringData = snapshotStringData;
    4951            WI.timelineManager.heapTrackingCompleted(timestamp, snapshot);
    5052        });
  • trunk/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js

    r220119 r241219  
    2626WI.HeapSnapshotProxy = class HeapSnapshotProxy extends WI.Object
    2727{
    28     constructor(snapshotObjectId, identifier, title, totalSize, totalObjectCount, liveSize, categories)
     28    constructor(snapshotObjectId, identifier, title, totalSize, totalObjectCount, liveSize, categories, imported)
    2929    {
    3030        super();
     
    3838        this._liveSize = liveSize;
    3939        this._categories = Map.fromObject(categories);
     40        this._imported = imported;
     41        this._snapshotStringData = null;
    4042
    4143        console.assert(!this.invalid);
     
    5052    static deserialize(objectId, serializedSnapshot)
    5153    {
    52         let {identifier, title, totalSize, totalObjectCount, liveSize, categories} = serializedSnapshot;
    53         return new WI.HeapSnapshotProxy(objectId, identifier, title, totalSize, totalObjectCount, liveSize, categories);
     54        let {identifier, title, totalSize, totalObjectCount, liveSize, categories, imported} = serializedSnapshot;
     55        return new WI.HeapSnapshotProxy(objectId, identifier, title, totalSize, totalObjectCount, liveSize, categories, imported);
    5456    }
    5557
     
    7476    get liveSize() { return this._liveSize; }
    7577    get categories() { return this._categories; }
     78    get imported() { return this._imported; }
    7679    get invalid() { return this._proxyObjectId === 0; }
     80
     81    get snapshotStringData()
     82    {
     83        return this._snapshotStringData;
     84    }
     85
     86    set snapshotStringData(data)
     87    {
     88        this._snapshotStringData = data;
     89    }
    7790
    7891    updateForCollectionEvent(event)
  • trunk/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js

    r220119 r241219  
    6565    {
    6666        this.performAction("createSnapshotDiff", ...arguments);
     67    }
     68
     69    createImportedSnapshot(snapshotStringData, title, callback)
     70    {
     71        const imported = true;
     72        this.performAction("createSnapshot", snapshotStringData, title, imported, callback);
    6773    }
    6874
  • trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js

    r220119 r241219  
    7474
    7575        for (let record of visibleRecords) {
     76            if (isNaN(record.timestamp))
     77                continue;
     78
    7679            const halfImageWidth = 8;
    7780            let x = xScale(record.timestamp) - halfImageWidth;
  • trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js

    r235151 r241219  
    6060        };
    6161
     62        this._importButtonNavigationItem = new WI.ButtonNavigationItem("import", WI.UIString("Import"), "Images/Import.svg", 15, 15);
     63        this._importButtonNavigationItem.toolTip = WI.UIString("Import");
     64        this._importButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
     65        this._importButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._importButtonNavigationItemClicked, this);
     66
    6267        let snapshotTooltip = WI.UIString("Take snapshot");
    6368        this._takeHeapSnapshotButtonItem = new WI.ButtonNavigationItem("take-snapshot", snapshotTooltip, "Images/Camera.svg", 16, 16);
     
    185190    {
    186191        if (this._showingSnapshotList) {
    187             let items = [this._takeHeapSnapshotButtonItem, this._compareHeapSnapshotsButtonItem];
     192            let items = [this._importButtonNavigationItem, this._takeHeapSnapshotButtonItem, this._compareHeapSnapshotsButtonItem];
    188193            if (this._selectingComparisonHeapSnapshots)
    189194                items.push(this._compareHeapSnapshotHelpTextItem);
     
    215220    }
    216221
     222    get supportsSave()
     223    {
     224        if (this._showingSnapshotList)
     225            return false;
     226
     227        if (!this._contentViewContainer.currentContentView)
     228            return false;
     229
     230        return this._contentViewContainer.currentContentView.supportsSave;
     231    }
     232
     233    get saveData()
     234    {
     235        return this._contentViewContainer.currentContentView.saveData;
     236    }
     237
    217238    selectRecord(record)
    218239    {
     
    383404    }
    384405
     406    _importButtonNavigationItemClicked()
     407    {
     408        WI.FileUtilities.importText(function(result) {
     409            let snapshotStringData = result.text;
     410            let workerProxy = WI.HeapSnapshotWorkerProxy.singleton();
     411            workerProxy.createImportedSnapshot(snapshotStringData, result.filename, ({objectId, snapshot: serializedSnapshot}) => {
     412                let snapshot = WI.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
     413                snapshot.snapshotStringData = snapshotStringData;
     414                const timestamp = NaN;
     415                WI.timelineManager.heapSnapshotAdded(timestamp, snapshot);
     416            });
     417        });
     418    }
     419
    385420    _takeHeapSnapshotClicked()
    386421    {
     
    389424            workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) => {
    390425                let snapshot = WI.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
     426                snapshot.snapshotStringData = snapshotStringData;
    391427                WI.timelineManager.heapSnapshotAdded(timestamp, snapshot);
    392428            });
  • trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js

    r220119 r241219  
    3434        this.element.classList.add("heap-snapshot");
    3535
     36        this._exportButtonNavigationItem = new WI.ButtonNavigationItem("export", WI.UIString("Export"), "Images/Export.svg", 15, 15);
     37        this._exportButtonNavigationItem.toolTip = WI.UIString("Export (%s)").format(WI.saveKeyboardShortcut.displayName);
     38        this._exportButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
     39        this._exportButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
     40        this._exportButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => { this._exportSnapshot(); });
     41
    3642        this._dataGrid = new WI.DataGrid(columns);
    3743        this._dataGrid.sortColumnIdentifier = "retainedSize";
     
    5359    // Protected
    5460
     61    get navigationItems()
     62    {
     63        if (this.representedObject instanceof WI.HeapSnapshotProxy)
     64            return [this._exportButtonNavigationItem];
     65        return [];
     66    }
     67
     68    get supportsSave()
     69    {
     70        return this.representedObject instanceof WI.HeapSnapshotProxy;
     71    }
     72
     73    get saveData()
     74    {
     75        return {customSaveHandler: () => { this._exportSnapshot(); }};
     76    }
     77
    5578    shown()
    5679    {
     
    7396
    7497    // Private
     98
     99    _exportSnapshot()
     100    {
     101        if (!this.representedObject.snapshotStringData) {
     102            InspectorFrontendHost.beep();
     103            return;
     104        }
     105
     106        let date = new Date;
     107        let values = [
     108            date.getFullYear(),
     109            Number.zeroPad(date.getMonth() + 1, 2),
     110            Number.zeroPad(date.getDate(), 2),
     111            Number.zeroPad(date.getHours(), 2),
     112            Number.zeroPad(date.getMinutes(), 2),
     113            Number.zeroPad(date.getSeconds(), 2),
     114        ];
     115        let filename = WI.UIString("Heap Snapshot %s-%s-%s at %s.%s.%s").format(...values);
     116        let url = "web-inspector:///" + encodeURI(filename) + ".json";
     117        WI.FileUtilities.save({
     118            url,
     119            content: this.representedObject.snapshotStringData,
     120            forceSaveAs: true,
     121        });
     122    }
    75123
    76124    _sortDataGrid()
  • trunk/Source/WebInspectorUI/UserInterface/Views/RecordingContentView.js

    r238198 r241219  
    148148    }
    149149
    150     // Protected
    151 
    152150    initialLayout()
    153151    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js

    r240457 r241219  
    278278            return WI.UIString("Frame %d").format(timelineRecord.frameNumber);
    279279        case WI.TimelineRecord.Type.HeapAllocations:
     280            if (timelineRecord.heapSnapshot.imported)
     281                return WI.UIString("Imported \u2014 %s").format(timelineRecord.heapSnapshot.title);
    280282            if (timelineRecord.heapSnapshot.title)
    281283                return WI.UIString("Snapshot %d \u2014 %s").format(timelineRecord.heapSnapshot.identifier, timelineRecord.heapSnapshot.title);
  • trunk/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js

    r235271 r241219  
    3737const nodeClassNameOffset = 2;
    3838const nodeInternalOffset = 3;
     39const gcDebuggingNodeFieldCount = 7;
    3940
    4041// edges
     
    7475HeapSnapshot = class HeapSnapshot
    7576{
    76     constructor(objectId, snapshotDataString, title = null)
     77    constructor(objectId, snapshotDataString, title = null, imported = false)
    7778    {
    7879        this._identifier = nextSnapshotIdentifier++;
    7980        this._objectId = objectId;
    8081        this._title = title;
     82        this._imported = imported;
    8183
    8284        let json = JSON.parse(snapshotDataString);
     
    8587        let {version, type, nodes, nodeClassNames, edges, edgeTypes, edgeNames} = json;
    8688        console.assert(version === 1, "Expect JavaScriptCore Heap Snapshot version 1");
    87         console.assert(!type || type === "Inspector", "Expect an Inspector Heap Snapshot");
     89        console.assert(!type || (type === "Inspector" || type === "GCDebugging"), "Expect an Inspector / GCDebugging Heap Snapshot");
     90
     91        this._nodeFieldCount = type === "GCDebugging" ? gcDebuggingNodeFieldCount : nodeFieldCount;
    8892
    8993        this._nodes = nodes;
    90         this._nodeCount = nodes.length / nodeFieldCount;
     94        this._nodeCount = nodes.length / this._nodeFieldCount;
    9195
    9296        this._edges = edges;
     
    100104        this._nodeIdentifierToOrdinal = new Map; // <node identifier> => nodeOrdinal
    101105        this._lastNodeIdentifier = 0;
    102         for (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex += nodeFieldCount) {
    103             let nodeOrdinal = nodeIndex / nodeFieldCount;
     106        for (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex += this._nodeFieldCount) {
     107            let nodeOrdinal = nodeIndex / this._nodeFieldCount;
    104108            let nodeIdentifier = nodes[nodeIndex + nodeIdOffset];
    105109            this._nodeIdentifierToOrdinal.set(nodeIdentifier, nodeOrdinal);
     
    152156
    153157        // Skip the <root> node.
    154         let firstNodeIndex = nodeFieldCount;
     158        let firstNodeIndex = snapshot._nodeFieldCount;
    155159        let firstNodeOrdinal = 1;
    156         for (let nodeIndex = firstNodeIndex, nodeOrdinal = firstNodeOrdinal; nodeIndex < nodes.length; nodeIndex += nodeFieldCount, nodeOrdinal++) {
     160        for (let nodeIndex = firstNodeIndex, nodeOrdinal = firstNodeOrdinal; nodeIndex < nodes.length; nodeIndex += snapshot._nodeFieldCount, nodeOrdinal++) {
    157161            if (allowNodeIdentifierCallback && !allowNodeIdentifierCallback(nodes[nodeIndex + nodeIdOffset]))
    158162                continue;
     
    192196
    193197        // Skip the <root> node.
    194         let firstNodeIndex = nodeFieldCount;
     198        let firstNodeIndex = snapshot._nodeFieldCount;
    195199
    196200    outer:
    197         for (let nodeIndex = firstNodeIndex; nodeIndex < nodes.length; nodeIndex += nodeFieldCount) {
     201        for (let nodeIndex = firstNodeIndex; nodeIndex < nodes.length; nodeIndex += snapshot._nodeFieldCount) {
    198202            if (allowNodeIdentifierCallback && !allowNodeIdentifierCallback(nodes[nodeIndex + nodeIdOffset]))
    199203                continue;
     
    220224
    221225        // Skip the <root> node.
    222         let firstNodeIndex = nodeFieldCount;
     226        let firstNodeIndex = snapshot._nodeFieldCount;
    223227        let firstNodeOrdinal = 1;
    224         for (let nodeIndex = firstNodeIndex, nodeOrdinal = firstNodeOrdinal; nodeIndex < nodes.length; nodeIndex += nodeFieldCount, nodeOrdinal++) {
     228        for (let nodeIndex = firstNodeIndex, nodeOrdinal = firstNodeOrdinal; nodeIndex < nodes.length; nodeIndex += snapshot._nodeFieldCount, nodeOrdinal++) {
    225229            if (allowNodeIdentifierCallback && !allowNodeIdentifierCallback(nodes[nodeIndex + nodeIdOffset]))
    226230                continue;
     
    254258    {
    255259        let nodeOrdinal = this._nodeIdentifierToOrdinal.get(nodeIdentifier);
    256         let nodeIndex = nodeOrdinal * nodeFieldCount;
     260        let nodeIndex = nodeOrdinal * this._nodeFieldCount;
    257261        return this.serializeNode(nodeIndex);
    258262    }
     
    298302        for (let nodeOrdinal = 0; nodeOrdinal < this._nodeCount; ++nodeOrdinal) {
    299303            if (this._nodeOrdinalToDominatorNodeOrdinal[nodeOrdinal] === targetNodeOrdinal)
    300                 dominatedNodes.push(nodeOrdinal * nodeFieldCount);
     304                dominatedNodes.push(nodeOrdinal * this._nodeFieldCount);
    301305        }
    302306
     
    314318            let toNodeIdentifier = this._edges[edgeIndex + edgeToIdOffset];
    315319            let toNodeOrdinal = this._nodeIdentifierToOrdinal.get(toNodeIdentifier);
    316             let toNodeIndex = toNodeOrdinal * nodeFieldCount;
     320            let toNodeIndex = toNodeOrdinal * this._nodeFieldCount;
    317321            retainedNodes.push(toNodeIndex);
    318322            edges.push(edgeIndex);
     
    335339        for (let edgeIndex = incomingEdgeIndex; edgeIndex < incomingEdgeIndexEnd; ++edgeIndex) {
    336340            let fromNodeOrdinal = this._incomingNodes[edgeIndex];
    337             let fromNodeIndex = fromNodeOrdinal * nodeFieldCount;
     341            let fromNodeIndex = fromNodeOrdinal * this._nodeFieldCount;
    338342            retainers.push(fromNodeIndex);
    339343            edges.push(this._incomingEdges[edgeIndex]);
     
    348352    updateDeadNodesAndGatherCollectionData(snapshots)
    349353    {
     354        console.assert(!this._imported, "Should never use an imported snapshot to modify snapshots");
     355        console.assert(snapshots.every((x) => !x._imported), "Should never modify nodes of imported snapshots");
     356
    350357        let previousSnapshotIndex = snapshots.indexOf(this) - 1;
    351358        let previousSnapshot = snapshots[previousSnapshotIndex];
     
    357364        // All of the node identifiers that could have existed prior to this snapshot.
    358365        let known = new Map;
    359         for (let nodeIndex = 0; nodeIndex < this._nodes.length; nodeIndex += nodeFieldCount) {
     366        for (let nodeIndex = 0; nodeIndex < this._nodes.length; nodeIndex += this._nodeFieldCount) {
    360367            let nodeIdentifier = this._nodes[nodeIndex + nodeIdOffset];
    361368            if (nodeIdentifier > lastNodeIdentifier)
     
    366373        // Determine which node identifiers have since been deleted.
    367374        let collectedNodesList = [];
    368         for (let nodeIndex = 0; nodeIndex < previousSnapshot._nodes.length; nodeIndex += nodeFieldCount) {
     375        for (let nodeIndex = 0; nodeIndex < previousSnapshot._nodes.length; nodeIndex += this._nodeFieldCount) {
    369376            let nodeIdentifier = previousSnapshot._nodes[nodeIndex + nodeIdOffset];
    370377            let wasDeleted = !known.has(nodeIdentifier);
     
    404411            liveSize: this._liveSize,
    405412            categories: this._categories,
     413            imported: this._imported,
    406414        };
    407415    }
     
    409417    serializeNode(nodeIndex)
    410418    {
    411         console.assert((nodeIndex % nodeFieldCount) === 0, "Invalid nodeIndex to serialize");
     419        console.assert((nodeIndex % this._nodeFieldCount) === 0, "Invalid nodeIndex to serialize");
    412420
    413421        let nodeIdentifier = this._nodes[nodeIndex + nodeIdOffset];
    414         let nodeOrdinal = nodeIndex / nodeFieldCount;
     422        let nodeOrdinal = nodeIndex / this._nodeFieldCount;
    415423        let edgeIndex = this._nodeOrdinalToFirstOutgoingEdge[nodeOrdinal];
    416424        let hasChildren = this._edges[edgeIndex + edgeFromIdOffset] === nodeIdentifier;
    417425
    418426        let dominatorNodeOrdinal = this._nodeOrdinalToDominatorNodeOrdinal[nodeOrdinal];
    419         let dominatorNodeIndex = dominatorNodeOrdinal * nodeFieldCount;
     427        let dominatorNodeIndex = dominatorNodeOrdinal * this._nodeFieldCount;
    420428        let dominatorNodeIdentifier = this._nodes[dominatorNodeIndex + nodeIdOffset];
    421429
     
    534542        while (stackTop >= 0) {
    535543            let nodeOrdinal = stackNodes[stackTop];
    536             let nodeIdentifier = this._nodes[(nodeOrdinal * nodeFieldCount) + nodeIdOffset];
     544            let nodeIdentifier = this._nodes[(nodeOrdinal * this._nodeFieldCount) + nodeIdOffset];
    537545            let edgeIndex = stackEdges[stackTop];
    538546
     
    658666
    659667                    let outgoingEdgeIndex = this._nodeOrdinalToFirstOutgoingEdge[nodeOrdinal];
    660                     let nodeIdentifier = this._nodes[(nodeOrdinal * nodeFieldCount) + nodeIdOffset];
     668                    let nodeIdentifier = this._nodes[(nodeOrdinal * this._nodeFieldCount) + nodeIdOffset];
    661669                    for (let edgeIndex = outgoingEdgeIndex; this._edges[edgeIndex + edgeFromIdOffset] === nodeIdentifier; edgeIndex += edgeFieldCount) {
    662670                        let toNodeIdentifier = this._edges[edgeIndex + edgeToIdOffset];
     
    679687    {
    680688        // Self size.
    681         for (let nodeIndex = 0, nodeOrdinal = 0; nodeOrdinal < this._nodeCount; nodeIndex += nodeFieldCount, nodeOrdinal++)
     689        for (let nodeIndex = 0, nodeOrdinal = 0; nodeOrdinal < this._nodeCount; nodeIndex += this._nodeFieldCount, nodeOrdinal++)
    682690            this._nodeOrdinalToRetainedSizes[nodeOrdinal] = this._nodes[nodeIndex + nodeSizeOffset];
    683691
     
    732740            if (this._nodeOrdinalIsGCRoot[nodeOrdinal]) {
    733741                let fullPath = currentPath.slice();
    734                 let nodeIndex = nodeOrdinal * nodeFieldCount;
     742                let nodeIndex = nodeOrdinal * this._nodeFieldCount;
    735743                fullPath.push({node: nodeIndex});
    736744                paths.push(fullPath);
     
    742750            visited[nodeOrdinal] = 1;
    743751
    744             let nodeIndex = nodeOrdinal * nodeFieldCount;
     752            let nodeIndex = nodeOrdinal * this._nodeFieldCount;
    745753            currentPath.push({node: nodeIndex});
    746754
     
    751759            for (let incomingEdgeIndex = incomingEdgeIndexEnd - 1; incomingEdgeIndex >= incomingEdgeIndexStart; --incomingEdgeIndex) {
    752760                let fromNodeOrdinal = this._incomingNodes[incomingEdgeIndex];
    753                 let fromNodeIndex = fromNodeOrdinal * nodeFieldCount;
     761                let fromNodeIndex = fromNodeOrdinal * this._nodeFieldCount;
    754762                let fromNodeIsInternal = this._nodes[fromNodeIndex + nodeInternalOffset];
    755763                if (fromNodeIsInternal)
  • trunk/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js

    r205424 r241219  
    4848    }
    4949
    50     createSnapshot(snapshotString, title)
     50    createSnapshot(snapshotString, title, imported)
    5151    {
    5252        let objectId = this._nextObjectId++;
    53         let snapshot = new HeapSnapshot(objectId, snapshotString, title);
    54         this._snapshots.push(snapshot);
     53        let snapshot = new HeapSnapshot(objectId, snapshotString, title, imported);
    5554        this._objects.set(objectId, snapshot);
    5655
    57         if (this._snapshots.length > 1) {
    58             setTimeout(() => {
    59                 let collectionData = snapshot.updateDeadNodesAndGatherCollectionData(this._snapshots);
    60                 if (!collectionData || !collectionData.affectedSnapshots.length)
    61                     return;
    62                 this.sendEvent("HeapSnapshot.CollectionEvent", collectionData);
    63             }, 0);
     56        if (!imported) {
     57            this._snapshots.push(snapshot);
     58
     59            if (this._snapshots.length > 1) {
     60                setTimeout(() => {
     61                    let collectionData = snapshot.updateDeadNodesAndGatherCollectionData(this._snapshots);
     62                    if (!collectionData || !collectionData.affectedSnapshots.length)
     63                        return;
     64                    this.sendEvent("HeapSnapshot.CollectionEvent", collectionData);
     65                }, 0);
     66            }           
    6467        }
    6568
Note: See TracChangeset for help on using the changeset viewer.