From 25bb65f902660711d9c8a1f9700a1c2bb96d0dce Mon Sep 17 00:00:00 2001 From: Jason Laster Date: Sat, 11 Nov 2017 00:52:17 +0100 Subject: [PATCH 01/10] Bug 1416358 - Update Debugger frontend (11-10). r=jdescottes MozReview-Commit-ID: 1aEWMEignDN --HG-- extra : rebase_source : fa3233ac56268bc8db55d5876514e5ff52c9dab7 --- devtools/client/debugger/new/README.mozilla | 2 +- devtools/client/debugger/new/debugger.css | 2 - devtools/client/debugger/new/debugger.js | 192 +++++++++++++++++- devtools/client/debugger/new/parser-worker.js | 5 +- .../debugger/new/pretty-print-worker.js | 5 +- devtools/client/debugger/new/search-worker.js | 185 ++++++++++++++++- 6 files changed, 368 insertions(+), 23 deletions(-) diff --git a/devtools/client/debugger/new/README.mozilla b/devtools/client/debugger/new/README.mozilla index 911972c16e50..856bb015785c 100644 --- a/devtools/client/debugger/new/README.mozilla +++ b/devtools/client/debugger/new/README.mozilla @@ -1,7 +1,7 @@ This is the debugger.html project output. See https://github.com/devtools-html/debugger.html -Taken from upstream commit: be179268c9b89390c13bdc9c4cca6000f6f583e5 +Taken from upstream commit: 09d6d4f93135367b2639d78ad884434f73ab449c Packages: - babel-plugin-transform-es2015-modules-commonjs @6.26.0 diff --git a/devtools/client/debugger/new/debugger.css b/devtools/client/debugger/new/debugger.css index d1cafe3b8a6d..562ea469c6b5 100644 --- a/devtools/client/debugger/new/debugger.css +++ b/devtools/client/debugger/new/debugger.css @@ -3739,5 +3739,3 @@ html[dir="rtl"] .dropdown { .theme-dark .result-list { background-color: var(--theme-body-background); } - -/*# sourceMappingURL=debugger.css.map*/ \ No newline at end of file diff --git a/devtools/client/debugger/new/debugger.js b/devtools/client/debugger/new/debugger.js index b22899cc45dd..0374571c9c8e 100644 --- a/devtools/client/debugger/new/debugger.js +++ b/devtools/client/debugger/new/debugger.js @@ -17612,7 +17612,7 @@ const { isOriginalId } = __webpack_require__(1389); -const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1363); +const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1390); const dispatcher = new WorkerDispatcher(); @@ -18277,9 +18277,9 @@ WorkerDispatcher.prototype = { } if (!this.worker) { - reject("Oops, The worker has shutdown!"); return; } + this.worker.removeEventListener("message", listener); if (result.error) { reject(result.error); @@ -20810,9 +20810,181 @@ module.exports = { }; /***/ }), -/* 1390 */, -/* 1391 */, -/* 1392 */, +/* 1390 */ +/***/ (function(module, exports, __webpack_require__) { + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const networkRequest = __webpack_require__(1391); +const workerUtils = __webpack_require__(1392); + +module.exports = { + networkRequest, + workerUtils +}; + +/***/ }), +/* 1391 */ +/***/ (function(module, exports) { + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function networkRequest(url, opts) { + return fetch(url, { + cache: opts.loadFromCache ? "default" : "no-cache" + }).then(res => { + if (res.status >= 200 && res.status < 300) { + return res.text().then(text => ({ content: text })); + } + return Promise.reject(`request failed with status ${res.status}`); + }); +} + +module.exports = networkRequest; + +/***/ }), +/* 1392 */ +/***/ (function(module, exports) { + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +function WorkerDispatcher() { + this.msgId = 1; + this.worker = null; +} /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +WorkerDispatcher.prototype = { + start(url) { + this.worker = new Worker(url); + this.worker.onerror = () => { + console.error(`Error in worker ${url}`); + }; + }, + + stop() { + if (!this.worker) { + return; + } + + this.worker.terminate(); + this.worker = null; + }, + + task(method) { + return (...args) => { + return new Promise((resolve, reject) => { + const id = this.msgId++; + this.worker.postMessage({ id, method, args }); + + const listener = ({ data: result }) => { + if (result.id !== id) { + return; + } + + if (!this.worker) { + reject("Oops, The worker has shutdown!"); + return; + } + this.worker.removeEventListener("message", listener); + if (result.error) { + reject(result.error); + } else { + resolve(result.response); + } + }; + + this.worker.addEventListener("message", listener); + }); + }; + } +}; + +function workerHandler(publicInterface) { + return function (msg) { + const { id, method, args } = msg.data; + try { + const response = publicInterface[method].apply(undefined, args); + if (response instanceof Promise) { + response.then(val => self.postMessage({ id, response: val }), + // Error can't be sent via postMessage, so be sure to + // convert to string. + err => self.postMessage({ id, error: err.toString() })); + } else { + self.postMessage({ id, response }); + } + } catch (error) { + // Error can't be sent via postMessage, so be sure to convert to + // string. + self.postMessage({ id, error: error.toString() }); + } + }; +} + +function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) { + let streamingWorker = (() => { + var _ref = _asyncToGenerator(function* (id, tasks) { + let isWorking = true; + + const intervalId = setTimeout(function () { + isWorking = false; + }, timeout); + + const results = []; + while (tasks.length !== 0 && isWorking) { + const { callback, context, args } = tasks.shift(); + const result = yield callback.call(context, args); + results.push(result); + } + worker.postMessage({ id, status: "pending", data: results }); + clearInterval(intervalId); + + if (tasks.length !== 0) { + yield streamingWorker(id, tasks); + } + }); + + return function streamingWorker(_x, _x2) { + return _ref.apply(this, arguments); + }; + })(); + + return (() => { + var _ref2 = _asyncToGenerator(function* (msg) { + const { id, method, args } = msg.data; + const workerMethod = publicInterface[method]; + if (!workerMethod) { + console.error(`Could not find ${method} defined in worker.`); + } + worker.postMessage({ id, status: "start" }); + + try { + const tasks = workerMethod(args); + yield streamingWorker(id, tasks); + worker.postMessage({ id, status: "done" }); + } catch (error) { + worker.postMessage({ id, status: "error", error }); + } + }); + + return function (_x3) { + return _ref2.apply(this, arguments); + }; + })(); +} + +module.exports = { + WorkerDispatcher, + workerHandler, + streamingWorkerHandler +}; + +/***/ }), /* 1393 */ /***/ (function(module, exports, __webpack_require__) { @@ -21820,6 +21992,9 @@ function setSymbols(sourceId) { source, symbols }); + + dispatch(setEmptyLines(source.id)); + dispatch(setSourceMetaData(source.id)); }; } @@ -24782,9 +24957,7 @@ function loadSourceText(source) { } await (0, _parser.setSource)(newSource); - await dispatch((0, _ast.setSymbols)(source.id)); - await dispatch((0, _ast.setEmptyLines)(source.id)); - await dispatch((0, _ast.setSourceMetaData)(source.id)); + dispatch((0, _ast.setSymbols)(source.id)); }; } @@ -45767,5 +45940,4 @@ function timing(store) { /***/ }) /******/ ]); -}); -//# sourceMappingURL=debugger.js.map \ No newline at end of file +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/parser-worker.js b/devtools/client/debugger/new/parser-worker.js index 7c713952cdd4..93d7ba4e916f 100644 --- a/devtools/client/debugger/new/parser-worker.js +++ b/devtools/client/debugger/new/parser-worker.js @@ -35432,9 +35432,9 @@ WorkerDispatcher.prototype = { } if (!this.worker) { - reject("Oops, The worker has shutdown!"); return; } + this.worker.removeEventListener("message", listener); if (result.error) { reject(result.error); @@ -41824,5 +41824,4 @@ function extendsComponent(classes) { /***/ }) /******/ ]); -}); -//# sourceMappingURL=parser-worker.js.map \ No newline at end of file +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/pretty-print-worker.js b/devtools/client/debugger/new/pretty-print-worker.js index 142074b8fd9b..128d64a1f622 100644 --- a/devtools/client/debugger/new/pretty-print-worker.js +++ b/devtools/client/debugger/new/pretty-print-worker.js @@ -163,9 +163,9 @@ WorkerDispatcher.prototype = { } if (!this.worker) { - reject("Oops, The worker has shutdown!"); return; } + this.worker.removeEventListener("message", listener); if (result.error) { reject(result.error); @@ -7591,5 +7591,4 @@ exports.SourceNode = SourceNode; /***/ }) /******/ }); -}); -//# sourceMappingURL=pretty-print-worker.js.map \ No newline at end of file +}); \ No newline at end of file diff --git a/devtools/client/debugger/new/search-worker.js b/devtools/client/debugger/new/search-worker.js index d6f449705606..1579b53d8e93 100644 --- a/devtools/client/debugger/new/search-worker.js +++ b/devtools/client/debugger/new/search-worker.js @@ -746,7 +746,7 @@ const { isOriginalId } = __webpack_require__(1389); -const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1363); +const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1390); const dispatcher = new WorkerDispatcher(); @@ -945,9 +945,9 @@ WorkerDispatcher.prototype = { } if (!this.worker) { - reject("Oops, The worker has shutdown!"); return; } + this.worker.removeEventListener("message", listener); if (result.error) { reject(result.error); @@ -1124,6 +1124,184 @@ module.exports = { /***/ }), +/***/ 1390: +/***/ (function(module, exports, __webpack_require__) { + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const networkRequest = __webpack_require__(1391); +const workerUtils = __webpack_require__(1392); + +module.exports = { + networkRequest, + workerUtils +}; + +/***/ }), + +/***/ 1391: +/***/ (function(module, exports) { + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function networkRequest(url, opts) { + return fetch(url, { + cache: opts.loadFromCache ? "default" : "no-cache" + }).then(res => { + if (res.status >= 200 && res.status < 300) { + return res.text().then(text => ({ content: text })); + } + return Promise.reject(`request failed with status ${res.status}`); + }); +} + +module.exports = networkRequest; + +/***/ }), + +/***/ 1392: +/***/ (function(module, exports) { + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +function WorkerDispatcher() { + this.msgId = 1; + this.worker = null; +} /* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +WorkerDispatcher.prototype = { + start(url) { + this.worker = new Worker(url); + this.worker.onerror = () => { + console.error(`Error in worker ${url}`); + }; + }, + + stop() { + if (!this.worker) { + return; + } + + this.worker.terminate(); + this.worker = null; + }, + + task(method) { + return (...args) => { + return new Promise((resolve, reject) => { + const id = this.msgId++; + this.worker.postMessage({ id, method, args }); + + const listener = ({ data: result }) => { + if (result.id !== id) { + return; + } + + if (!this.worker) { + reject("Oops, The worker has shutdown!"); + return; + } + this.worker.removeEventListener("message", listener); + if (result.error) { + reject(result.error); + } else { + resolve(result.response); + } + }; + + this.worker.addEventListener("message", listener); + }); + }; + } +}; + +function workerHandler(publicInterface) { + return function (msg) { + const { id, method, args } = msg.data; + try { + const response = publicInterface[method].apply(undefined, args); + if (response instanceof Promise) { + response.then(val => self.postMessage({ id, response: val }), + // Error can't be sent via postMessage, so be sure to + // convert to string. + err => self.postMessage({ id, error: err.toString() })); + } else { + self.postMessage({ id, response }); + } + } catch (error) { + // Error can't be sent via postMessage, so be sure to convert to + // string. + self.postMessage({ id, error: error.toString() }); + } + }; +} + +function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) { + let streamingWorker = (() => { + var _ref = _asyncToGenerator(function* (id, tasks) { + let isWorking = true; + + const intervalId = setTimeout(function () { + isWorking = false; + }, timeout); + + const results = []; + while (tasks.length !== 0 && isWorking) { + const { callback, context, args } = tasks.shift(); + const result = yield callback.call(context, args); + results.push(result); + } + worker.postMessage({ id, status: "pending", data: results }); + clearInterval(intervalId); + + if (tasks.length !== 0) { + yield streamingWorker(id, tasks); + } + }); + + return function streamingWorker(_x, _x2) { + return _ref.apply(this, arguments); + }; + })(); + + return (() => { + var _ref2 = _asyncToGenerator(function* (msg) { + const { id, method, args } = msg.data; + const workerMethod = publicInterface[method]; + if (!workerMethod) { + console.error(`Could not find ${method} defined in worker.`); + } + worker.postMessage({ id, status: "start" }); + + try { + const tasks = workerMethod(args); + yield streamingWorker(id, tasks); + worker.postMessage({ id, status: "done" }); + } catch (error) { + worker.postMessage({ id, status: "error", error }); + } + }); + + return function (_x3) { + return _ref2.apply(this, arguments); + }; + })(); +} + +module.exports = { + WorkerDispatcher, + workerHandler, + streamingWorkerHandler +}; + +/***/ }), + /***/ 1393: /***/ (function(module, exports, __webpack_require__) { @@ -3293,5 +3471,4 @@ module.exports = freeGlobal; /***/ }) /******/ }); -}); -//# sourceMappingURL=search-worker.js.map \ No newline at end of file +}); \ No newline at end of file From 0590afed91290949bc60c1ae41ab762b8ddccaf7 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 10 Nov 2017 12:50:14 +0100 Subject: [PATCH 02/10] Bug 1416199 - Don't try to set signal handlers in Windows coverage build. r=froydnj --HG-- extra : rebase_source : f74f90bf0e146d674044eeef2c2e9b546335a564 --- js/src/shell/js.cpp | 2 ++ tools/code-coverage/CodeCoverageHandler.cpp | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 79842e404f04..16ee93bc66a8 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -181,6 +181,7 @@ void counters_reset(int) { static void InstallCoverageSignalHandlers() { +#ifndef XP_WIN fprintf(stderr, "[CodeCoverage] Setting handlers for process %d.\n", getpid()); struct sigaction dump_sa; @@ -196,6 +197,7 @@ InstallCoverageSignalHandlers() sigemptyset(&reset_sa.sa_mask); mozilla::DebugOnly r2 = sigaction(SIGUSR2, &reset_sa, nullptr); MOZ_ASSERT(r2 == 0, "Failed to install GCOV SIGUSR2 handler"); +#endif } #endif diff --git a/tools/code-coverage/CodeCoverageHandler.cpp b/tools/code-coverage/CodeCoverageHandler.cpp index 4629070f6e0a..76dd399759a4 100644 --- a/tools/code-coverage/CodeCoverageHandler.cpp +++ b/tools/code-coverage/CodeCoverageHandler.cpp @@ -3,9 +3,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include #include +#ifndef XP_WIN +#include #include +#endif #include "mozilla/CodeCoverageHandler.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/DebugOnly.h" @@ -62,6 +64,7 @@ void CodeCoverageHandler::ResetCounters(int) void CodeCoverageHandler::SetSignalHandlers() { +#ifndef XP_WIN printf_stderr("[CodeCoverage] Setting handlers for process %d.\n", getpid()); struct sigaction dump_sa; @@ -77,6 +80,7 @@ void CodeCoverageHandler::SetSignalHandlers() sigemptyset(&reset_sa.sa_mask); DebugOnly r2 = sigaction(SIGUSR2, &reset_sa, nullptr); MOZ_ASSERT(r2 == 0, "Failed to install GCOV SIGUSR2 handler"); +#endif } CodeCoverageHandler::CodeCoverageHandler() From f1dd5129102e029a1a56c31d8ffb986b4904bdf5 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 10 Nov 2017 11:34:22 +0100 Subject: [PATCH 03/10] Bug 1416008 - Support downloading grcov for Windows. r=jmaher --HG-- extra : rebase_source : 88359894a12fbd26deadbdb07694fc16d21cce67 --- .../tooltool-manifests/win32/ccov.manifest | 9 +++++++++ .../mozilla/testing/codecoverage.py | 20 +++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 testing/config/tooltool-manifests/win32/ccov.manifest diff --git a/testing/config/tooltool-manifests/win32/ccov.manifest b/testing/config/tooltool-manifests/win32/ccov.manifest new file mode 100644 index 000000000000..ae2b715619cf --- /dev/null +++ b/testing/config/tooltool-manifests/win32/ccov.manifest @@ -0,0 +1,9 @@ +[ + { + "size": 271486, + "digest": "6956eb1cab16dff465861cd1966e3115f31b533334089553b8b94897bc138c6dec279bf7c60b34fe3fc67c8cb0d41e30f55982adaad07320090dab053e018dec", + "algorithm": "sha512", + "filename": "grcov-win-i686.tar.bz2", + "unpack": false + } +] diff --git a/testing/mozharness/mozharness/mozilla/testing/codecoverage.py b/testing/mozharness/mozharness/mozilla/testing/codecoverage.py index 78b68003263d..cec947d0c045 100644 --- a/testing/mozharness/mozharness/mozilla/testing/codecoverage.py +++ b/testing/mozharness/mozharness/mozilla/testing/codecoverage.py @@ -5,8 +5,11 @@ import os import shutil +import sys +import tarfile import tempfile +import mozinfo from mozharness.base.script import ( PreScriptAction, PostScriptAction, @@ -94,15 +97,24 @@ class CodeCoverageMixin(object): # Create the grcov directory, get the tooltool manifest, and finally # download and unpack the grcov binary. self.grcov_dir = tempfile.mkdtemp() + + if mozinfo.os == 'linux': + platform = 'linux64' + tar_file = 'grcov-linux-standalone-x86_64.tar.bz2' + elif mozinfo.os == 'win': + platform = 'win32' + tar_file = 'grcov-win-i686.tar.bz2' + manifest = os.path.join(dirs.get('abs_test_install_dir', os.path.join(dirs['abs_work_dir'], 'tests')), \ - 'config/tooltool-manifests/linux64/ccov.manifest') + 'config/tooltool-manifests/%s/ccov.manifest' % platform) tooltool_path = self._fetch_tooltool_py() - cmd = [tooltool_path, '--url', 'https://tooltool.mozilla-releng.net/', 'fetch', \ + cmd = [sys.executable, tooltool_path, '--url', 'https://tooltool.mozilla-releng.net/', 'fetch', \ '-m', manifest, '-o', '-c', '/builds/worker/tooltool-cache'] self.run_command(cmd, cwd=self.grcov_dir) - self.run_command(['tar', '-jxvf', os.path.join(self.grcov_dir, 'grcov-linux-standalone-x86_64.tar.bz2'), \ - '-C', self.grcov_dir], cwd=self.grcov_dir) + + with tarfile.open(os.path.join(self.grcov_dir, tar_file)) as tar: + tar.extractall(self.grcov_dir) @PostScriptAction('run-tests') def _package_coverage_data(self, action, success=None): From 0c39f198abf3885d8ba57f187b0fa8bd40f7969c Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 10 Nov 2017 15:39:32 +0100 Subject: [PATCH 04/10] Bug 1416008 - Support packaging code coverage files and running grcov on Windows. r=jmaher --HG-- extra : rebase_source : 80f6f51cbff0e35933563f3b1b2467041c571b8e --- .../mozilla/testing/codecoverage.py | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/testing/mozharness/mozharness/mozilla/testing/codecoverage.py b/testing/mozharness/mozharness/mozilla/testing/codecoverage.py index cec947d0c045..7e0bd12ceb61 100644 --- a/testing/mozharness/mozharness/mozilla/testing/codecoverage.py +++ b/testing/mozharness/mozharness/mozilla/testing/codecoverage.py @@ -53,7 +53,7 @@ class CodeCoverageMixin(object): return True # XXX workaround because bug 1110465 is hard - return self.buildbot_config['properties']['stage_platform'] in ('linux64-ccov',) + return 'ccov' in self.buildbot_config['properties']['stage_platform'] except (AttributeError, KeyError, TypeError): return False @@ -73,7 +73,7 @@ class CodeCoverageMixin(object): return True # XXX workaround because bug 1110465 is hard - return self.buildbot_config['properties']['stage_platform'] in ('linux64-jsdcov',) + return 'jsdcov' in self.buildbot_config['properties']['stage_platform'] except (AttributeError, KeyError, TypeError): return False @@ -138,6 +138,7 @@ class CodeCoverageMixin(object): if not self.code_coverage_enabled: return + del os.environ['GCOV_PREFIX'] del os.environ['JS_CODE_COVERAGE_OUTPUT_DIR'] @@ -152,50 +153,59 @@ class CodeCoverageMixin(object): if any(d in dirs for d in canary_dirs): rel_topsrcdir = root break - else: + + if rel_topsrcdir is None: # Unable to upload code coverage files. Since this is the whole # point of code coverage, making this fatal. - self.fatal("Could not find relative topsrcdir in code coverage " - "data!") + self.fatal("Could not find relative topsrcdir in code coverage data!") + + dirs = self.query_abs_dirs() # Package GCOV coverage data. - dirs = self.query_abs_dirs() - file_path_gcda = os.path.join( - dirs['abs_blob_upload_dir'], 'code-coverage-gcda.zip') - command = ['zip', '-r', file_path_gcda, '.'] - self.run_command(command, cwd=rel_topsrcdir) + file_path_gcda = os.path.join(dirs['abs_blob_upload_dir'], 'code-coverage-gcda.zip') + self.run_command(['zip', '-r', file_path_gcda, '.'], cwd=rel_topsrcdir) # Package JSVM coverage data. - dirs = self.query_abs_dirs() - file_path_jsvm = os.path.join( - dirs['abs_blob_upload_dir'], 'code-coverage-jsvm.zip') - command = ['zip', '-r', file_path_jsvm, '.'] - self.run_command(command, cwd=self.jsvm_dir) + file_path_jsvm = os.path.join(dirs['abs_blob_upload_dir'], 'code-coverage-jsvm.zip') + self.run_command(['zip', '-r', file_path_jsvm, '.'], cwd=self.jsvm_dir) # GRCOV post-processing # Download the gcno fom the build machine. self.download_file(self.url_to_gcno, file_name=None, parent_dir=self.grcov_dir) + if mozinfo.os == 'linux': + prefix = '/builds/worker/workspace/build/src/' + elif mozinfo.os == 'win': + prefix = 'z:/build/build/src/' + # Run grcov on the zipped .gcno and .gcda files. grcov_command = [ os.path.join(self.grcov_dir, 'grcov'), '-t', 'lcov', - '-p', '/builds/worker/workspace/build/src/', + '-p', prefix, '--ignore-dir', 'gcc', os.path.join(self.grcov_dir, 'target.code-coverage-gcno.zip'), file_path_gcda ] # 'grcov_output' will be a tuple, the first variable is the path to the lcov output, # the other is the path to the standard error output. - grcov_output = self.get_output_from_command(grcov_command, cwd=self.grcov_dir, \ - silent=True, tmpfile_base_path=os.path.join(self.grcov_dir, 'grcov_lcov_output'), \ - save_tmpfiles=True, return_type='files') + grcov_output = self.get_output_from_command( + grcov_command, + cwd=self.grcov_dir, + silent=True, + tmpfile_base_path=os.path.join(self.grcov_dir, 'grcov_lcov_output'), + save_tmpfiles=True, + return_type='files' + ) new_output_name = grcov_output[0] + '.info' os.rename(grcov_output[0], new_output_name) # Zip the grcov output and upload it. - command = ['zip', os.path.join(dirs['abs_blob_upload_dir'], 'code-coverage-grcov.zip'), new_output_name] - self.run_command(command, cwd=self.grcov_dir) + self.run_command( + ['zip', os.path.join(dirs['abs_blob_upload_dir'], 'code-coverage-grcov.zip'), new_output_name], + cwd=self.grcov_dir + ) + shutil.rmtree(self.gcov_dir) shutil.rmtree(self.jsvm_dir) shutil.rmtree(self.grcov_dir) From 8b031732c0e6e63af07df5f707f26a150197d102 Mon Sep 17 00:00:00 2001 From: JerryShih Date: Sat, 11 Nov 2017 18:57:31 +0800 Subject: [PATCH 05/10] Bug 1371838 - export the gecko profiler registering function to WR. r=jrmuizel MozReview-Commit-ID: 2gVAmU2xomP --- gfx/layers/wr/WebRenderBridgeParent.cpp | 13 +++++++++++++ gfx/webrender_bindings/src/bindings.rs | 5 +++++ gfx/webrender_bindings/webrender_ffi.h | 2 ++ gfx/webrender_bindings/webrender_ffi_generated.h | 4 ++++ 4 files changed, 24 insertions(+) diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 86bd86f971bd..a3c519081221 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -101,6 +101,19 @@ void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname) return reinterpret_cast(p); } +void +gecko_profiler_register_thread(const char* name) +{ + char stackTop; + profiler_register_thread(name, &stackTop); +} + +void +gecko_profiler_unregister_thread() +{ + profiler_unregister_thread(); +} + namespace mozilla { namespace layers { diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 6797a84d1811..74e14f5ae9fe 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -587,6 +587,11 @@ pub unsafe extern "C" fn wr_rendered_epochs_delete(pipeline_epochs: *mut WrRende Box::from_raw(pipeline_epochs); } +extern "C" { + fn gecko_profiler_register_thread(name: *const ::std::os::raw::c_char); + fn gecko_profiler_unregister_thread(); +} + pub struct WrThreadPool(Arc); #[no_mangle] diff --git a/gfx/webrender_bindings/webrender_ffi.h b/gfx/webrender_bindings/webrender_ffi.h index 0c6b27e4e468..a4336b7df10e 100644 --- a/gfx/webrender_bindings/webrender_ffi.h +++ b/gfx/webrender_bindings/webrender_ffi.h @@ -26,6 +26,8 @@ void gfx_critical_note(const char* msg); void gfx_critical_error(const char* msg); void gecko_printf_stderr_output(const char* msg); void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname); +void gecko_profiler_register_thread(const char* threadname); +void gecko_profiler_unregister_thread(); } // extern "C" diff --git a/gfx/webrender_bindings/webrender_ffi_generated.h b/gfx/webrender_bindings/webrender_ffi_generated.h index 8c83cba1fe12..f52c94f4c224 100644 --- a/gfx/webrender_bindings/webrender_ffi_generated.h +++ b/gfx/webrender_bindings/webrender_ffi_generated.h @@ -943,6 +943,10 @@ extern void DeleteFontData(WrFontKey aKey); extern void gecko_printf_stderr_output(const char *aMsg); +extern void gecko_profiler_register_thread(const char *aName); + +extern void gecko_profiler_unregister_thread(); + extern void gfx_critical_error(const char *aMsg); extern void gfx_critical_note(const char *aMsg); From 56d62614659022f2500bf3b586f1a2d346d6b2b9 Mon Sep 17 00:00:00 2001 From: JerryShih Date: Sat, 11 Nov 2017 18:57:31 +0800 Subject: [PATCH 06/10] Bug 1371838 - register the WR thread pool's thread to gecko profiler. r=jrmuizel MozReview-Commit-ID: BUyTq2vz3cO --- gfx/webrender_bindings/src/bindings.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 74e14f5ae9fe..a90de4648842 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -597,9 +597,14 @@ pub struct WrThreadPool(Arc); #[no_mangle] pub unsafe extern "C" fn wr_thread_pool_new() -> *mut WrThreadPool { let worker_config = rayon::Configuration::new() - .thread_name(|idx|{ format!("WebRender:Worker#{}", idx) }) + .thread_name(|idx|{ format!("WRWorker#{}", idx) }) .start_handler(|idx| { - register_thread_with_profiler(format!("WebRender:Worker#{}", idx)); + let name = format!("WRWorker#{}", idx); + register_thread_with_profiler(name.clone()); + gecko_profiler_register_thread(CString::new(name).unwrap().as_ptr()); + }) + .exit_handler(|_idx| { + gecko_profiler_unregister_thread(); }); let workers = Arc::new(rayon::ThreadPool::new(worker_config).unwrap()); From 4eb77c1992f29d32af404bbf9af9e6351a2981b5 Mon Sep 17 00:00:00 2001 From: JerryShih Date: Sat, 11 Nov 2017 18:57:31 +0800 Subject: [PATCH 07/10] Bug 1371838 - add a custom thread listener to WR. r=jrmuizel MozReview-Commit-ID: yyFwBr21F3 --- gfx/webrender_bindings/src/bindings.rs | 27 +++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index a90de4648842..1aca9ed2619e 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -7,7 +7,7 @@ use std::os::raw::{c_void, c_char, c_float}; use gleam::gl; use webrender_api::*; -use webrender::{ReadPixelsFormat, Renderer, RendererOptions}; +use webrender::{ReadPixelsFormat, Renderer, RendererOptions, ThreadListener}; use webrender::{ExternalImage, ExternalImageHandler, ExternalImageSource}; use webrender::DebugFlags; use webrender::{ApiRecordingReceiver, BinaryRecorder}; @@ -592,6 +592,30 @@ extern "C" { fn gecko_profiler_unregister_thread(); } +struct GeckoProfilerThreadListener {} + +impl GeckoProfilerThreadListener { + pub fn new() -> GeckoProfilerThreadListener { + GeckoProfilerThreadListener{} + } +} + +impl ThreadListener for GeckoProfilerThreadListener { + fn thread_started(&self, thread_name: &str) { + let name = CString::new(thread_name).unwrap(); + unsafe { + // gecko_profiler_register_thread copies the passed name here. + gecko_profiler_register_thread(name.as_ptr()); + } + } + + fn thread_stopped(&self, _: &str) { + unsafe { + gecko_profiler_unregister_thread(); + } + } +} + pub struct WrThreadPool(Arc); #[no_mangle] @@ -660,6 +684,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId, recorder: recorder, blob_image_renderer: Some(Box::new(Moz2dImageRenderer::new(workers.clone()))), workers: Some(workers.clone()), + thread_listener: Some(Box::new(GeckoProfilerThreadListener::new())), enable_render_on_scroll: false, resource_override_path: unsafe { let override_charptr = gfx_wr_resource_path_override(); From c061f3959ddc46d4e522c766cebdff7a4ab6acac Mon Sep 17 00:00:00 2001 From: JerryShih Date: Sat, 11 Nov 2017 18:57:31 +0800 Subject: [PATCH 08/10] Bug 1371838 - set the window_id as renderer_id to WR. r=jrmuizel MozReview-Commit-ID: 7YbQNzTNpmE --- gfx/webrender_bindings/src/bindings.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 1aca9ed2619e..6a49007c24fd 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -697,6 +697,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId, } } }, + renderer_id: Some(window_id.0), ..Default::default() }; From 4e36e5851a90ac20df8af26563e7cdbb10807566 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Sat, 11 Nov 2017 13:32:56 +0100 Subject: [PATCH 09/10] Bug 1415489 - Use SingletonObject for Array.prototype[@@unscopables]. r=bhackett --- js/src/jsarray.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index bdd75dc4b6da..d1ef5099f6c3 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -3673,7 +3673,8 @@ static bool array_proto_finish(JSContext* cx, JS::HandleObject ctor, JS::HandleObject proto) { // Add Array.prototype[@@unscopables]. ECMA-262 draft (2016 Mar 19) 22.1.3.32. - RootedObject unscopables(cx, NewObjectWithGivenProto(cx, nullptr, TenuredObject)); + RootedObject unscopables(cx, NewObjectWithGivenProto(cx, nullptr, + SingletonObject)); if (!unscopables) return false; From 49c97adb4e258ac41fc7763d724617ae9fc4616f Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Sat, 11 Nov 2017 15:32:58 +0000 Subject: [PATCH 10/10] Bug 1411625 - Remove the constructor from gfxShapedText::CompressedGlyph to make it a trivial class, and provide a couple of convenience "factory" methods to create simple and complex glyph values. r=andi --- gfx/thebes/gfxCoreTextShaper.cpp | 15 ++++++----- gfx/thebes/gfxFT2Fonts.cpp | 17 +++++++----- gfx/thebes/gfxFont.cpp | 6 ++--- gfx/thebes/gfxFont.h | 45 +++++++++++++++++++++++++------- gfx/thebes/gfxGraphiteShaper.cpp | 21 ++++++++------- gfx/thebes/gfxHarfBuzzShaper.cpp | 20 +++++++------- gfx/thebes/gfxTextRun.cpp | 8 +++--- gfx/thebes/gfxTextRun.h | 1 + layout/mathml/nsMathMLChar.cpp | 6 ++--- 9 files changed, 87 insertions(+), 52 deletions(-) diff --git a/gfx/thebes/gfxCoreTextShaper.cpp b/gfx/thebes/gfxCoreTextShaper.cpp index 9a55c513c6f2..a8e38198110e 100644 --- a/gfx/thebes/gfxCoreTextShaper.cpp +++ b/gfx/thebes/gfxCoreTextShaper.cpp @@ -244,6 +244,8 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, uint32_t aLength, CTRunRef aCTRun) { + typedef gfxShapedText::CompressedGlyph CompressedGlyph; + int32_t direction = aShapedText->IsRightToLeft() ? -1 : 1; int32_t numGlyphs = ::CTRunGetGlyphCount(aCTRun); @@ -319,8 +321,7 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, nullptr, nullptr, nullptr); AutoTArray detailedGlyphs; - gfxShapedText::CompressedGlyph *charGlyphs = - aShapedText->GetCharacterGlyphs() + aOffset; + CompressedGlyph* charGlyphs = aShapedText->GetCharacterGlyphs() + aOffset; // CoreText gives us the glyphindex-to-charindex mapping, which relates each glyph // to a source text character; we also need the charindex-to-glyphindex mapping to @@ -540,10 +541,10 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, advance = int32_t(toNextGlyph * appUnitsPerDevUnit); } - gfxTextRun::CompressedGlyph textRunGlyph; - textRunGlyph.SetComplex(charGlyphs[baseCharIndex].IsClusterStart(), - true, detailedGlyphs.Length()); - aShapedText->SetGlyphs(aOffset + baseCharIndex, textRunGlyph, + bool isClusterStart = charGlyphs[baseCharIndex].IsClusterStart(); + aShapedText->SetGlyphs(aOffset + baseCharIndex, + CompressedGlyph::MakeComplex(isClusterStart, true, + detailedGlyphs.Length()), detailedGlyphs.Elements()); detailedGlyphs.Clear(); @@ -551,7 +552,7 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, // the rest of the chars in the group are ligature continuations, no associated glyphs while (++baseCharIndex != endCharIndex && baseCharIndex < wordLength) { - gfxShapedText::CompressedGlyph &shapedTextGlyph = charGlyphs[baseCharIndex]; + CompressedGlyph &shapedTextGlyph = charGlyphs[baseCharIndex]; NS_ASSERTION(!shapedTextGlyph.IsSimpleGlyph(), "overwriting a simple glyph"); shapedTextGlyph.SetComplex(inOrder && shapedTextGlyph.IsClusterStart(), false, 0); } diff --git a/gfx/thebes/gfxFT2Fonts.cpp b/gfx/thebes/gfxFT2Fonts.cpp index d2ef0f293692..b6d302544fa5 100644 --- a/gfx/thebes/gfxFT2Fonts.cpp +++ b/gfx/thebes/gfxFT2Fonts.cpp @@ -66,13 +66,14 @@ void gfxFT2Font::AddRange(const char16_t *aText, uint32_t aOffset, uint32_t aLength, gfxShapedText *aShapedText) { + typedef gfxShapedText::CompressedGlyph CompressedGlyph; + const uint32_t appUnitsPerDevUnit = aShapedText->GetAppUnitsPerDevUnit(); // we'll pass this in/figure it out dynamically, but at this point there can be only one face. gfxFT2LockedFace faceLock(this); FT_Face face = faceLock.get(); - gfxShapedText::CompressedGlyph *charGlyphs = - aShapedText->GetCharacterGlyphs(); + CompressedGlyph* charGlyphs = aShapedText->GetCharacterGlyphs(); const gfxFT2Font::CachedGlyphData *cgd = nullptr, *cgdNext = nullptr; @@ -139,8 +140,8 @@ gfxFT2Font::AddRange(const char16_t *aText, uint32_t aOffset, } if (advance >= 0 && - gfxShapedText::CompressedGlyph::IsSimpleAdvance(advance) && - gfxShapedText::CompressedGlyph::IsSimpleGlyphID(gid)) { + CompressedGlyph::IsSimpleAdvance(advance) && + CompressedGlyph::IsSimpleGlyphID(gid)) { charGlyphs[aOffset].SetSimpleGlyph(advance, gid); } else if (gid == 0) { // gid = 0 only happens when the glyph is missing from the font @@ -151,9 +152,11 @@ gfxFT2Font::AddRange(const char16_t *aText, uint32_t aOffset, NS_ASSERTION(details.mGlyphID == gid, "Seriously weird glyph ID detected!"); details.mAdvance = advance; - gfxShapedText::CompressedGlyph g; - g.SetComplex(charGlyphs[aOffset].IsClusterStart(), true, 1); - aShapedText->SetGlyphs(aOffset, g, &details); + bool isClusterStart = charGlyphs[aOffset].IsClusterStart(); + aShapedText->SetGlyphs(aOffset, + CompressedGlyph::MakeComplex(isClusterStart, + true, 1), + &details); } } } diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 9e0114d5b1f2..0f08cf727e63 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -571,10 +571,10 @@ gfxShapedText::SetupClusterBoundaries(uint32_t aOffset, const char16_t *aString, uint32_t aLength) { - CompressedGlyph *glyphs = GetCharacterGlyphs() + aOffset; + CompressedGlyph* glyphs = GetCharacterGlyphs() + aOffset; - gfxTextRun::CompressedGlyph extendCluster; - extendCluster.SetComplex(false, true, 0); + CompressedGlyph extendCluster = + CompressedGlyph::MakeComplex(false, true, 0); ClusterIterator iter(aString, aLength); diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 07d2c15fe17d..03ef44c70e88 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -763,8 +763,6 @@ public: */ class CompressedGlyph { public: - CompressedGlyph() { mValue = 0; } - enum { // Indicates that a cluster and ligature group starts at this // character; this character has a single glyph with a reasonable @@ -894,25 +892,52 @@ public: return toggle; } - CompressedGlyph& SetSimpleGlyph(uint32_t aAdvanceAppUnits, uint32_t aGlyph) { + // Create a CompressedGlyph value representing a simple glyph with + // no extra flags (line-break or is_space) set. + static CompressedGlyph + MakeSimpleGlyph(uint32_t aAdvanceAppUnits, uint32_t aGlyph) { NS_ASSERTION(IsSimpleAdvance(aAdvanceAppUnits), "Advance overflow"); NS_ASSERTION(IsSimpleGlyphID(aGlyph), "Glyph overflow"); + CompressedGlyph g; + g.mValue = FLAG_IS_SIMPLE_GLYPH | + (aAdvanceAppUnits << ADVANCE_SHIFT) | + aGlyph; + return g; + } + + // Assign a simple glyph value to an existing CompressedGlyph record, + // preserving line-break/is-space flags if present. + CompressedGlyph& SetSimpleGlyph(uint32_t aAdvanceAppUnits, + uint32_t aGlyph) { NS_ASSERTION(!CharTypeFlags(), "Char type flags lost"); mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_CHAR_IS_SPACE)) | - FLAG_IS_SIMPLE_GLYPH | - (aAdvanceAppUnits << ADVANCE_SHIFT) | aGlyph; + MakeSimpleGlyph(aAdvanceAppUnits, aGlyph).mValue; return *this; } + + // Create a CompressedGlyph value representing a complex glyph record, + // without any line-break or char-type flags. + static CompressedGlyph + MakeComplex(bool aClusterStart, bool aLigatureStart, + uint32_t aGlyphCount) { + CompressedGlyph g; + g.mValue = FLAG_NOT_MISSING | + (aClusterStart ? 0 : FLAG_NOT_CLUSTER_START) | + (aLigatureStart ? 0 : FLAG_NOT_LIGATURE_GROUP_START) | + (aGlyphCount << GLYPH_COUNT_SHIFT); + return g; + } + + // Assign a complex glyph value to an existing CompressedGlyph record, + // preserving line-break/char-type flags if present. CompressedGlyph& SetComplex(bool aClusterStart, bool aLigatureStart, - uint32_t aGlyphCount) { + uint32_t aGlyphCount) { mValue = (mValue & (FLAGS_CAN_BREAK_BEFORE | FLAG_CHAR_IS_SPACE)) | - FLAG_NOT_MISSING | CharTypeFlags() | - (aClusterStart ? 0 : FLAG_NOT_CLUSTER_START) | - (aLigatureStart ? 0 : FLAG_NOT_LIGATURE_GROUP_START) | - (aGlyphCount << GLYPH_COUNT_SHIFT); + MakeComplex(aClusterStart, aLigatureStart, aGlyphCount).mValue; return *this; } + /** * Missing glyphs are treated as ligature group starts; don't mess with * the cluster-start flag (see bugs 618870 and 619286). diff --git a/gfx/thebes/gfxGraphiteShaper.cpp b/gfx/thebes/gfxGraphiteShaper.cpp index 381bd57a5355..78a38b0584fa 100644 --- a/gfx/thebes/gfxGraphiteShaper.cpp +++ b/gfx/thebes/gfxGraphiteShaper.cpp @@ -216,6 +216,8 @@ gfxGraphiteShaper::SetGlyphsFromSegment(gfxShapedText *aShapedText, gr_segment *aSegment, RoundingFlags aRounding) { + typedef gfxShapedText::CompressedGlyph CompressedGlyph; + int32_t dev2appUnits = aShapedText->GetAppUnitsPerDevUnit(); bool rtl = aShapedText->IsRightToLeft(); @@ -289,8 +291,7 @@ gfxGraphiteShaper::SetGlyphsFromSegment(gfxShapedText *aShapedText, } } - gfxShapedText::CompressedGlyph *charGlyphs = - aShapedText->GetCharacterGlyphs() + aOffset; + CompressedGlyph* charGlyphs = aShapedText->GetCharacterGlyphs() + aOffset; bool roundX = bool(aRounding & RoundingFlags::kRoundX); bool roundY = bool(aRounding & RoundingFlags::kRoundY); @@ -326,8 +327,8 @@ gfxGraphiteShaper::SetGlyphsFromSegment(gfxShapedText *aShapedText, uint32_t appAdvance = roundX ? NSToIntRound(adv) * dev2appUnits : NSToIntRound(adv * dev2appUnits); if (c.nGlyphs == 1 && - gfxShapedText::CompressedGlyph::IsSimpleGlyphID(gids[c.baseGlyph]) && - gfxShapedText::CompressedGlyph::IsSimpleAdvance(appAdvance) && + CompressedGlyph::IsSimpleGlyphID(gids[c.baseGlyph]) && + CompressedGlyph::IsSimpleAdvance(appAdvance) && charGlyphs[offs].IsClusterStart() && yLocs[c.baseGlyph] == 0) { @@ -352,15 +353,17 @@ gfxGraphiteShaper::SetGlyphsFromSegment(gfxShapedText *aShapedText, d->mAdvance = 0; } } - gfxShapedText::CompressedGlyph g; - g.SetComplex(charGlyphs[offs].IsClusterStart(), - true, details.Length()); - aShapedText->SetGlyphs(aOffset + offs, g, details.Elements()); + bool isClusterStart = charGlyphs[offs].IsClusterStart(); + aShapedText->SetGlyphs(aOffset + offs, + CompressedGlyph::MakeComplex(isClusterStart, + true, + details.Length()), + details.Elements()); } for (uint32_t j = c.baseChar + 1; j < c.baseChar + c.nChars; ++j) { NS_ASSERTION(j < aLength, "unexpected offset"); - gfxShapedText::CompressedGlyph &g = charGlyphs[j]; + CompressedGlyph &g = charGlyphs[j]; NS_ASSERTION(!g.IsSimpleGlyph(), "overwriting a simple glyph"); g.SetComplex(g.IsClusterStart(), false, 0); } diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp index cb9adc3f01a6..1074f0c15c5d 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -1529,6 +1529,8 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, bool aVertical, RoundingFlags aRounding) { + typedef gfxShapedText::CompressedGlyph CompressedGlyph; + uint32_t numGlyphs; const hb_glyph_info_t *ginfo = hb_buffer_get_glyph_infos(mBuffer, &numGlyphs); if (numGlyphs == 0) { @@ -1569,8 +1571,7 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, } int32_t appUnitsPerDevUnit = aShapedText->GetAppUnitsPerDevUnit(); - gfxShapedText::CompressedGlyph *charGlyphs = - aShapedText->GetCharacterGlyphs() + aOffset; + CompressedGlyph* charGlyphs = aShapedText->GetCharacterGlyphs() + aOffset; // factor to convert 16.16 fixed-point pixels to app units // (only used if not rounding) @@ -1718,8 +1719,8 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, } // Check if it's a simple one-to-one mapping if (glyphsInClump == 1 && - gfxTextRun::CompressedGlyph::IsSimpleGlyphID(ginfo[glyphStart].codepoint) && - gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) && + CompressedGlyph::IsSimpleGlyphID(ginfo[glyphStart].codepoint) && + CompressedGlyph::IsSimpleAdvance(advance) && charGlyphs[baseCharIndex].IsClusterStart() && iOffset == 0 && b_offset == 0 && b_advance == 0 && bPos == 0) @@ -1789,11 +1790,12 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, } } - gfxShapedText::CompressedGlyph g; - g.SetComplex(charGlyphs[baseCharIndex].IsClusterStart(), - true, detailedGlyphs.Length()); + bool isClusterStart = charGlyphs[baseCharIndex].IsClusterStart(); aShapedText->SetGlyphs(aOffset + baseCharIndex, - g, detailedGlyphs.Elements()); + CompressedGlyph::MakeComplex(isClusterStart, + true, + detailedGlyphs.Length()), + detailedGlyphs.Elements()); detailedGlyphs.Clear(); } @@ -1802,7 +1804,7 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, // no associated glyphs while (++baseCharIndex != endCharIndex && baseCharIndex < int32_t(wordLength)) { - gfxShapedText::CompressedGlyph &g = charGlyphs[baseCharIndex]; + CompressedGlyph &g = charGlyphs[baseCharIndex]; NS_ASSERTION(!g.IsSimpleGlyph(), "overwriting a simple glyph"); g.SetComplex(g.IsClusterStart(), false, 0); } diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp index d52f77017345..082b851f4883 100644 --- a/gfx/thebes/gfxTextRun.cpp +++ b/gfx/thebes/gfxTextRun.cpp @@ -1658,8 +1658,8 @@ gfxTextRun::SetSpaceGlyphIfSimple(gfxFont* aFont, uint32_t aCharIndex, AddGlyphRun(aFont, gfxTextRange::kFontGroup, aCharIndex, false, aOrientation); - CompressedGlyph g; - g.SetSimpleGlyph(spaceWidthAppUnits, spaceGlyph); + CompressedGlyph g = + CompressedGlyph::MakeSimpleGlyph(spaceWidthAppUnits, spaceGlyph); if (aSpaceChar == ' ') { g.SetIsSpace(); } @@ -2756,8 +2756,8 @@ gfxFontGroup::InitScriptRun(DrawTarget* aDrawTarget, gfxTextRun::DetailedGlyph detailedGlyph; detailedGlyph.mGlyphID = mainFont->GetSpaceGlyph(); detailedGlyph.mAdvance = advance; - gfxShapedText::CompressedGlyph g; - g.SetComplex(true, true, 1); + CompressedGlyph g = + CompressedGlyph::MakeComplex(true, true, 1); aTextRun->SetGlyphs(aOffset + index, g, &detailedGlyph); } diff --git a/gfx/thebes/gfxTextRun.h b/gfx/thebes/gfxTextRun.h index 98caccd063a4..daa34f15f253 100644 --- a/gfx/thebes/gfxTextRun.h +++ b/gfx/thebes/gfxTextRun.h @@ -842,6 +842,7 @@ private: class gfxFontGroup final : public gfxTextRunFactory { public: typedef mozilla::unicode::Script Script; + typedef gfxShapedText::CompressedGlyph CompressedGlyph; static void Shutdown(); // platform must call this to release the languageAtomService diff --git a/layout/mathml/nsMathMLChar.cpp b/layout/mathml/nsMathMLChar.cpp index f6483f1d5c96..d5fba3eade77 100644 --- a/layout/mathml/nsMathMLChar.cpp +++ b/layout/mathml/nsMathMLChar.cpp @@ -588,9 +588,9 @@ nsOpenTypeTable::MakeTextRun(DrawTarget* aDrawTarget, NSToCoordRound(aAppUnitsPerDevPixel * aFontGroup->GetFirstValidFont()-> GetGlyphHAdvance(aDrawTarget, aGlyph.glyphID)); - gfxShapedText::CompressedGlyph g; - g.SetComplex(true, true, 1); - textRun->SetGlyphs(0, g, &detailedGlyph); + textRun->SetGlyphs(0, + gfxShapedText::CompressedGlyph::MakeComplex(true, true, 1), + &detailedGlyph); return textRun.forget(); }