Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / HeapSnapshotLoader.js
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30
31 /**
32  * @constructor
33  * @param {!WebInspector.HeapSnapshotWorkerDispatcher} dispatcher
34  */
35 WebInspector.HeapSnapshotLoader = function(dispatcher)
36 {
37     this._reset();
38     this._progress = new WebInspector.HeapSnapshotProgress(dispatcher);
39 }
40
41 WebInspector.HeapSnapshotLoader.prototype = {
42     dispose: function()
43     {
44         this._reset();
45     },
46
47     _reset: function()
48     {
49         this._json = "";
50         this._state = "find-snapshot-info";
51         this._snapshot = {};
52     },
53
54     close: function()
55     {
56         if (this._json)
57             this._parseStringsArray();
58     },
59
60     /**
61      * @return {!WebInspector.JSHeapSnapshot}
62      */
63     buildSnapshot: function(constructorName)
64     {
65         this._progress.updateStatus("Processing snapshot\u2026");
66         var result = new WebInspector.JSHeapSnapshot(this._snapshot, this._progress);
67         this._reset();
68         return result;
69     },
70
71     _parseUintArray: function()
72     {
73         var index = 0;
74         var char0 = "0".charCodeAt(0), char9 = "9".charCodeAt(0), closingBracket = "]".charCodeAt(0);
75         var length = this._json.length;
76         while (true) {
77             while (index < length) {
78                 var code = this._json.charCodeAt(index);
79                 if (char0 <= code && code <= char9)
80                     break;
81                 else if (code === closingBracket) {
82                     this._json = this._json.slice(index + 1);
83                     return false;
84                 }
85                 ++index;
86             }
87             if (index === length) {
88                 this._json = "";
89                 return true;
90             }
91             var nextNumber = 0;
92             var startIndex = index;
93             while (index < length) {
94                 var code = this._json.charCodeAt(index);
95                 if (char0 > code || code > char9)
96                     break;
97                 nextNumber *= 10;
98                 nextNumber += (code - char0);
99                 ++index;
100             }
101             if (index === length) {
102                 this._json = this._json.slice(startIndex);
103                 return true;
104             }
105             this._array[this._arrayIndex++] = nextNumber;
106         }
107     },
108
109     _parseStringsArray: function()
110     {
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);
117     },
118
119     /**
120      * @param {string} chunk
121      */
122     write: function(chunk)
123     {
124         this._json += chunk;
125         while (true) {
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");
135                 break;
136             }
137             case "parse-snapshot-info": {
138                 var closingBracketIndex = WebInspector.TextUtils.findBalancedCurlyBrackets(this._json);
139                 if (closingBracketIndex === -1)
140                     return;
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";
144                 break;
145             }
146             case "find-nodes": {
147                 var nodesToken = "\"nodes\"";
148                 var nodesTokenIndex = this._json.indexOf(nodesToken);
149                 if (nodesTokenIndex === -1)
150                     return;
151                 var bracketIndex = this._json.indexOf("[", nodesTokenIndex);
152                 if (bracketIndex === -1)
153                     return;
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";
160                 break;
161             }
162             case "parse-nodes": {
163                 var hasMoreData = this._parseUintArray();
164                 this._progress.updateProgress("Loading nodes\u2026 %d\%", this._arrayIndex, this._array.length);
165                 if (hasMoreData)
166                     return;
167                 this._snapshot.nodes = this._array;
168                 this._state = "find-edges";
169                 this._array = null;
170                 break;
171             }
172             case "find-edges": {
173                 var edgesToken = "\"edges\"";
174                 var edgesTokenIndex = this._json.indexOf(edgesToken);
175                 if (edgesTokenIndex === -1)
176                     return;
177                 var bracketIndex = this._json.indexOf("[", edgesTokenIndex);
178                 if (bracketIndex === -1)
179                     return;
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";
186                 break;
187             }
188             case "parse-edges": {
189                 var hasMoreData = this._parseUintArray();
190                 this._progress.updateProgress("Loading edges\u2026 %d\%", this._arrayIndex, this._array.length);
191                 if (hasMoreData)
192                     return;
193                 this._snapshot.edges = this._array;
194                 this._array = null;
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";
198                 else
199                     this._state = "find-strings";
200                 break;
201             }
202             case "find-trace-function-infos": {
203                 var tracesToken = "\"trace_function_infos\"";
204                 var tracesTokenIndex = this._json.indexOf(tracesToken);
205                 if (tracesTokenIndex === -1)
206                     return;
207                 var bracketIndex = this._json.indexOf("[", tracesTokenIndex);
208                 if (bracketIndex === -1)
209                     return;
210                 this._json = this._json.slice(bracketIndex + 1);
211
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";
217                 break;
218             }
219             case "parse-trace-function-infos": {
220                 if (this._parseUintArray())
221                     return;
222                 this._snapshot.trace_function_infos = this._array;
223                 this._array = null;
224                 this._state = "find-trace-tree";
225                 break;
226             }
227             case "find-trace-tree": {
228                 var tracesToken = "\"trace_tree\"";
229                 var tracesTokenIndex = this._json.indexOf(tracesToken);
230                 if (tracesTokenIndex === -1)
231                     return;
232                 var bracketIndex = this._json.indexOf("[", tracesTokenIndex);
233                 if (bracketIndex === -1)
234                     return;
235                 this._json = this._json.slice(bracketIndex);
236                 this._state = "parse-trace-tree";
237                 break;
238             }
239             case "parse-trace-tree": {
240                 var stringsToken = "\"strings\"";
241                 var stringsTokenIndex = this._json.indexOf(stringsToken);
242                 if (stringsTokenIndex === -1)
243                     return;
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");
249                 break;
250             }
251             case "find-strings": {
252                 var stringsToken = "\"strings\"";
253                 var stringsTokenIndex = this._json.indexOf(stringsToken);
254                 if (stringsTokenIndex === -1)
255                     return;
256                 var bracketIndex = this._json.indexOf("[", stringsTokenIndex);
257                 if (bracketIndex === -1)
258                     return;
259                 this._json = this._json.slice(bracketIndex);
260                 this._state = "accumulate-strings";
261                 break;
262             }
263             case "accumulate-strings":
264                 return;
265             }
266         }
267     }
268 };