Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 Array.prototype.clone = function() { return this.slice(0); }
9 function makeSample(frames, extraInfo, lines) {
10 return {
11 frames: frames,
12 extraInfo: extraInfo,
13 lines: lines
14 };
15 }
17 function cloneSample(sample) {
18 return makeSample(sample.frames.clone(), sample.extraInfo, sample.lines.clone());
19 }
21 function bucketsBySplittingArray(array, maxItemsPerBucket) {
22 var buckets = [];
23 while (buckets.length * maxItemsPerBucket < array.length) {
24 buckets.push(array.slice(buckets.length * maxItemsPerBucket,
25 (buckets.length + 1) * maxItemsPerBucket));
26 }
27 return buckets;
28 }
30 var gParserWorker = new Worker("profiler/cleopatra/js/parserWorker.js");
31 gParserWorker.nextRequestID = 0;
33 function WorkerRequest(worker) {
34 var self = this;
35 this._eventListeners = {};
36 var requestID = worker.nextRequestID++;
37 this._requestID = requestID;
38 this._worker = worker;
39 this._totalReporter = new ProgressReporter();
40 this._totalReporter.addListener(function (reporter) {
41 self._fireEvent("progress", reporter.getProgress(), reporter.getAction());
42 })
43 this._sendChunkReporter = this._totalReporter.addSubreporter(500);
44 this._executeReporter = this._totalReporter.addSubreporter(3000);
45 this._receiveChunkReporter = this._totalReporter.addSubreporter(100);
46 this._totalReporter.begin("Processing task in worker...");
47 var partialResult = null;
48 function onMessageFromWorker(msg) {
49 pendingMessages.push(msg);
50 scheduleMessageProcessing();
51 }
52 function processMessage(msg) {
53 var startTime = Date.now();
54 var data = msg.data;
55 var readTime = Date.now() - startTime;
57 if (data.requestID == requestID || !data.requestID) {
58 switch(data.type) {
59 case "error":
60 self._sendChunkReporter.setAction("Error in worker: " + data.error);
61 self._executeReporter.setAction("Error in worker: " + data.error);
62 self._receiveChunkReporter.setAction("Error in worker: " + data.error);
63 self._totalReporter.setAction("Error in worker: " + data.error);
64 PROFILERERROR("Error in worker: " + data.error);
65 self._fireEvent("error", data.error);
66 break;
67 case "progress":
68 self._executeReporter.setProgress(data.progress);
69 break;
70 case "finished":
71 self._executeReporter.finish();
72 self._receiveChunkReporter.begin("Receiving data from worker...");
73 self._receiveChunkReporter.finish();
74 self._fireEvent("finished", data.result);
75 worker.removeEventListener("message", onMessageFromWorker);
76 break;
77 case "finishedStart":
78 partialResult = null;
79 self._totalReceiveChunks = data.numChunks;
80 self._gotReceiveChunks = 0;
81 self._executeReporter.finish();
82 self._receiveChunkReporter.begin("Receiving data from worker...");
83 break;
84 case "finishedChunk":
85 partialResult = partialResult ? partialResult.concat(data.chunk) : data.chunk;
86 var chunkIndex = self._gotReceiveChunks++;
87 self._receiveChunkReporter.setProgress((chunkIndex + 1) / self._totalReceiveChunks);
88 break;
89 case "finishedEnd":
90 self._receiveChunkReporter.finish();
91 self._fireEvent("finished", partialResult);
92 worker.removeEventListener("message", onMessageFromWorker);
93 break;
94 }
95 // dump log if present
96 if (data.log) {
97 for (var line in data.log) {
98 PROFILERLOG(line);
99 }
100 }
101 }
102 }
103 var pendingMessages = [];
104 var messageProcessingTimer = 0;
105 function processMessages() {
106 messageProcessingTimer = 0;
107 processMessage(pendingMessages.shift());
108 if (pendingMessages.length)
109 scheduleMessageProcessing();
110 }
111 function scheduleMessageProcessing() {
112 if (messageProcessingTimer)
113 return;
114 messageProcessingTimer = setTimeout(processMessages, 10);
115 }
116 worker.addEventListener("message", onMessageFromWorker);
117 }
119 WorkerRequest.prototype = {
120 send: function WorkerRequest_send(task, taskData) {
121 this._sendChunkReporter.begin("Sending data to worker...");
122 var startTime = Date.now();
123 this._worker.postMessage({
124 requestID: this._requestID,
125 task: task,
126 taskData: taskData
127 });
128 var postTime = Date.now() - startTime;
129 this._sendChunkReporter.finish();
130 this._executeReporter.begin("Processing worker request...");
131 },
132 sendInChunks: function WorkerRequest_sendInChunks(task, taskData, params, maxChunkSize) {
133 this._sendChunkReporter.begin("Sending data to worker...");
134 var self = this;
135 var chunks = bucketsBySplittingArray(taskData, maxChunkSize);
136 var pendingMessages = [
137 {
138 requestID: this._requestID,
139 task: "chunkedStart",
140 numChunks: chunks.length
141 }
142 ].concat(chunks.map(function (chunk) {
143 return {
144 requestID: self._requestID,
145 task: "chunkedChunk",
146 chunk: chunk
147 };
148 })).concat([
149 {
150 requestID: this._requestID,
151 task: "chunkedEnd"
152 },
153 {
154 requestID: this._requestID,
155 params: params,
156 task: task
157 },
158 ]);
159 var totalMessages = pendingMessages.length;
160 var numSentMessages = 0;
161 function postMessage(msg) {
162 var msgIndex = numSentMessages++;
163 var startTime = Date.now();
164 self._worker.postMessage(msg);
165 var postTime = Date.now() - startTime;
166 self._sendChunkReporter.setProgress((msgIndex + 1) / totalMessages);
167 }
168 var messagePostingTimer = 0;
169 function postMessages() {
170 messagePostingTimer = 0;
171 postMessage(pendingMessages.shift());
172 if (pendingMessages.length) {
173 scheduleMessagePosting();
174 } else {
175 self._sendChunkReporter.finish();
176 self._executeReporter.begin("Processing worker request...");
177 }
178 }
179 function scheduleMessagePosting() {
180 if (messagePostingTimer)
181 return;
182 messagePostingTimer = setTimeout(postMessages, 10);
183 }
184 scheduleMessagePosting();
185 },
187 // TODO: share code with TreeView
188 addEventListener: function WorkerRequest_addEventListener(eventName, callbackFunction) {
189 if (!(eventName in this._eventListeners))
190 this._eventListeners[eventName] = [];
191 if (this._eventListeners[eventName].indexOf(callbackFunction) != -1)
192 return;
193 this._eventListeners[eventName].push(callbackFunction);
194 },
195 removeEventListener: function WorkerRequest_removeEventListener(eventName, callbackFunction) {
196 if (!(eventName in this._eventListeners))
197 return;
198 var index = this._eventListeners[eventName].indexOf(callbackFunction);
199 if (index == -1)
200 return;
201 this._eventListeners[eventName].splice(index, 1);
202 },
203 _fireEvent: function WorkerRequest__fireEvent(eventName, eventObject, p1) {
204 if (!(eventName in this._eventListeners))
205 return;
206 this._eventListeners[eventName].forEach(function (callbackFunction) {
207 callbackFunction(eventObject, p1);
208 });
209 },
210 }
212 var Parser = {
213 parse: function Parser_parse(data, params) {
214 var request = new WorkerRequest(gParserWorker);
215 request.sendInChunks("parseRawProfile", data, params, 3000000);
216 return request;
217 },
219 updateFilters: function Parser_updateFilters(filters) {
220 var request = new WorkerRequest(gParserWorker);
221 request.send("updateFilters", {
222 filters: filters,
223 profileID: 0
224 });
225 return request;
226 },
228 updateViewOptions: function Parser_updateViewOptions(options) {
229 var request = new WorkerRequest(gParserWorker);
230 request.send("updateViewOptions", {
231 options: options,
232 profileID: 0
233 });
234 return request;
235 },
237 getSerializedProfile: function Parser_getSerializedProfile(complete, callback) {
238 var request = new WorkerRequest(gParserWorker);
239 request.send("getSerializedProfile", {
240 profileID: 0,
241 complete: complete
242 });
243 request.addEventListener("finished", callback);
244 },
246 calculateHistogramData: function Parser_calculateHistogramData() {
247 var request = new WorkerRequest(gParserWorker);
248 request.send("calculateHistogramData", {
249 profileID: 0
250 });
251 return request;
252 },
254 calculateDiagnosticItems: function Parser_calculateDiagnosticItems(meta) {
255 var request = new WorkerRequest(gParserWorker);
256 request.send("calculateDiagnosticItems", {
257 profileID: 0,
258 meta: meta
259 });
260 return request;
261 },
263 updateLogSetting: function Parser_updateLogSetting() {
264 var request = new WorkerRequest(gParserWorker);
265 request.send("initWorker", {
266 debugLog: gDebugLog,
267 debugTrace: gDebugTrace,
268 });
269 return request;
270 },
271 };