2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * @param {!WebInspector.HeapSnapshotWorkerDispatcher} dispatcher
35 WebInspector.HeapSnapshotLoader = function(dispatcher)
38 this._progress = new WebInspector.HeapSnapshotProgress(dispatcher);
41 WebInspector.HeapSnapshotLoader.prototype = {
50 this._state = "find-snapshot-info";
57 this._parseStringsArray();
61 * @return {!WebInspector.JSHeapSnapshot}
63 buildSnapshot: function(constructorName)
65 this._progress.updateStatus("Processing snapshot\u2026");
66 var result = new WebInspector.JSHeapSnapshot(this._snapshot, this._progress);
71 _parseUintArray: function()
74 var char0 = "0".charCodeAt(0), char9 = "9".charCodeAt(0), closingBracket = "]".charCodeAt(0);
75 var length = this._json.length;
77 while (index < length) {
78 var code = this._json.charCodeAt(index);
79 if (char0 <= code && code <= char9)
81 else if (code === closingBracket) {
82 this._json = this._json.slice(index + 1);
87 if (index === length) {
92 var startIndex = index;
93 while (index < length) {
94 var code = this._json.charCodeAt(index);
95 if (char0 > code || code > char9)
98 nextNumber += (code - char0);
101 if (index === length) {
102 this._json = this._json.slice(startIndex);
105 this._array[this._arrayIndex++] = nextNumber;
109 _parseStringsArray: function()
111 this._progress.updateStatus("Parsing strings\u2026");
112 var closingBracketIndex = this._json.lastIndexOf("]");
113 if (closingBracketIndex === -1)
114 throw new Error("Incomplete JSON");
115 this._json = this._json.slice(0, closingBracketIndex + 1);
116 this._snapshot.strings = JSON.parse(this._json);
120 * @param {string} chunk
122 write: function(chunk)
126 switch (this._state) {
127 case "find-snapshot-info": {
128 var snapshotToken = "\"snapshot\"";
129 var snapshotTokenIndex = this._json.indexOf(snapshotToken);
130 if (snapshotTokenIndex === -1)
131 throw new Error("Snapshot token not found");
132 this._json = this._json.slice(snapshotTokenIndex + snapshotToken.length + 1);
133 this._state = "parse-snapshot-info";
134 this._progress.updateStatus("Loading snapshot info\u2026");
137 case "parse-snapshot-info": {
138 var closingBracketIndex = WebInspector.TextUtils.findBalancedCurlyBrackets(this._json);
139 if (closingBracketIndex === -1)
141 this._snapshot.snapshot = /** @type {!HeapSnapshotHeader} */ (JSON.parse(this._json.slice(0, closingBracketIndex)));
142 this._json = this._json.slice(closingBracketIndex);
143 this._state = "find-nodes";
147 var nodesToken = "\"nodes\"";
148 var nodesTokenIndex = this._json.indexOf(nodesToken);
149 if (nodesTokenIndex === -1)
151 var bracketIndex = this._json.indexOf("[", nodesTokenIndex);
152 if (bracketIndex === -1)
154 this._json = this._json.slice(bracketIndex + 1);
155 var node_fields_count = this._snapshot.snapshot.meta.node_fields.length;
156 var nodes_length = this._snapshot.snapshot.node_count * node_fields_count;
157 this._array = new Uint32Array(nodes_length);
158 this._arrayIndex = 0;
159 this._state = "parse-nodes";
162 case "parse-nodes": {
163 var hasMoreData = this._parseUintArray();
164 this._progress.updateProgress("Loading nodes\u2026 %d\%", this._arrayIndex, this._array.length);
167 this._snapshot.nodes = this._array;
168 this._state = "find-edges";
173 var edgesToken = "\"edges\"";
174 var edgesTokenIndex = this._json.indexOf(edgesToken);
175 if (edgesTokenIndex === -1)
177 var bracketIndex = this._json.indexOf("[", edgesTokenIndex);
178 if (bracketIndex === -1)
180 this._json = this._json.slice(bracketIndex + 1);
181 var edge_fields_count = this._snapshot.snapshot.meta.edge_fields.length;
182 var edges_length = this._snapshot.snapshot.edge_count * edge_fields_count;
183 this._array = new Uint32Array(edges_length);
184 this._arrayIndex = 0;
185 this._state = "parse-edges";
188 case "parse-edges": {
189 var hasMoreData = this._parseUintArray();
190 this._progress.updateProgress("Loading edges\u2026 %d\%", this._arrayIndex, this._array.length);
193 this._snapshot.edges = this._array;
195 // If there is allocation info parse it, otherwise jump straight to strings.
196 if (this._snapshot.snapshot.trace_function_count)
197 this._state = "find-trace-function-infos";
199 this._state = "find-strings";
202 case "find-trace-function-infos": {
203 var tracesToken = "\"trace_function_infos\"";
204 var tracesTokenIndex = this._json.indexOf(tracesToken);
205 if (tracesTokenIndex === -1)
207 var bracketIndex = this._json.indexOf("[", tracesTokenIndex);
208 if (bracketIndex === -1)
210 this._json = this._json.slice(bracketIndex + 1);
212 var trace_function_info_field_count = this._snapshot.snapshot.meta.trace_function_info_fields.length;
213 var trace_function_info_length = this._snapshot.snapshot.trace_function_count * trace_function_info_field_count;
214 this._array = new Uint32Array(trace_function_info_length);
215 this._arrayIndex = 0;
216 this._state = "parse-trace-function-infos";
219 case "parse-trace-function-infos": {
220 if (this._parseUintArray())
222 this._snapshot.trace_function_infos = this._array;
224 this._state = "find-trace-tree";
227 case "find-trace-tree": {
228 var tracesToken = "\"trace_tree\"";
229 var tracesTokenIndex = this._json.indexOf(tracesToken);
230 if (tracesTokenIndex === -1)
232 var bracketIndex = this._json.indexOf("[", tracesTokenIndex);
233 if (bracketIndex === -1)
235 this._json = this._json.slice(bracketIndex);
236 this._state = "parse-trace-tree";
239 case "parse-trace-tree": {
240 var stringsToken = "\"strings\"";
241 var stringsTokenIndex = this._json.indexOf(stringsToken);
242 if (stringsTokenIndex === -1)
244 var bracketIndex = this._json.lastIndexOf("]", stringsTokenIndex);
245 this._snapshot.trace_tree = JSON.parse(this._json.substring(0, bracketIndex + 1));
246 this._json = this._json.slice(bracketIndex);
247 this._state = "find-strings";
248 this._progress.updateStatus("Loading strings\u2026");
251 case "find-strings": {
252 var stringsToken = "\"strings\"";
253 var stringsTokenIndex = this._json.indexOf(stringsToken);
254 if (stringsTokenIndex === -1)
256 var bracketIndex = this._json.indexOf("[", stringsTokenIndex);
257 if (bracketIndex === -1)
259 this._json = this._json.slice(bracketIndex);
260 this._state = "accumulate-strings";
263 case "accumulate-strings":