From f710a7cb1dd5f38d15a3ea5317017f1749683b1f Mon Sep 17 00:00:00 2001 From: David Burns Date: Wed, 4 Sep 2013 09:05:43 +0100 Subject: [PATCH 01/86] Bug 912244: Correct screenshot with element highlighting in Marionette; r=jgriffin --- .../client/marionette/marionette.py | 5 ++++- .../marionette/tests/unit/test_screenshot.py | 7 +++++++ testing/marionette/marionette-listener.js | 20 ++++--------------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/testing/marionette/client/marionette/marionette.py b/testing/marionette/client/marionette/marionette.py index 035dafed5698..5ce6ca8ab27a 100644 --- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -1255,4 +1255,7 @@ class Marionette(object): ''' if element is not None: element = element.id - return self._send_message("screenShot", 'value', element=element, highlights=highlights) + lights = None + if highlights is not None: + lights = [highlight.id for highlight in highlights if highlights] + return self._send_message("screenShot", 'value', element=element, highlights=lights) diff --git a/testing/marionette/client/marionette/tests/unit/test_screenshot.py b/testing/marionette/client/marionette/tests/unit/test_screenshot.py index 5fcd49fa9fc4..c693a34a905f 100644 --- a/testing/marionette/client/marionette/tests/unit/test_screenshot.py +++ b/testing/marionette/client/marionette/tests/unit/test_screenshot.py @@ -10,6 +10,13 @@ class ScreenshotTests(MarionetteTestCase): self.assertEqual('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAVUlEQVRoge3PsQ0AIAzAsI78fzBwBhHykD2ePev80LweAAGJB1ILpBZILZBaILVAaoHUAqkFUgukFkgtkFogtUBqgdQCqQVSC6QWSC2QWiC1QGp9A7ma+7nyXgOpzQAAAABJRU5ErkJggg==', self.marionette.screenshot(element=el)) + def testWeCanTakeAScreenShotWithHighlightOfAnElement(self): + test_url = self.marionette.absolute_url('html5Page.html') + self.marionette.navigate(test_url) + el = self.marionette.find_element('id', 'green') + self.assertEqual('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAV0lEQVRoge3PQRGAQAwAsWINvXgsNnI3+4iAzM7sDWZn9vneoxXRFNEU0RTRFNEU0RTRFNEU0RTRFNEU0RTRFNEU0RTRFNEU0RTRFNEU0RTRFNHcF7nBD/Ha5Ye4BbsYAAAAAElFTkSuQmCC', + self.marionette.screenshot(element=el, highlights=[el])) + def testWeCanTakeAScreenShotEntireCanvas(self): test_url = self.marionette.absolute_url('html5Page.html') self.marionette.navigate(test_url) diff --git a/testing/marionette/marionette-listener.js b/testing/marionette/marionette-listener.js index 58505052c3c0..0e2d8365408a 100644 --- a/testing/marionette/marionette-listener.js +++ b/testing/marionette/marionette-listener.js @@ -1789,7 +1789,7 @@ function screenShot(msg) { let highlights = msg.json.highlights; var document = curWindow.document; - var rect, win, width, height, left, top, needsOffset; + var rect, win, width, height, left, top; // node can be either a window or an arbitrary DOM node if (node == curWindow) { // node is a window @@ -1798,8 +1798,6 @@ function screenShot(msg) { height = win.innerHeight; top = 0; left = 0; - // offset needed for highlights to take 'outerHeight' of window into account - needsOffset = true; } else { // node is an arbitrary DOM node @@ -1809,8 +1807,6 @@ function screenShot(msg) { height = rect.height; top = rect.top; left = rect.left; - // offset for highlights not needed as they will be relative to this node - needsOffset = false; } var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); @@ -1827,19 +1823,11 @@ function screenShot(msg) { ctx.save(); for (var i = 0; i < highlights.length; ++i) { - var elem = highlights[i]; + var elem = elementManager.getKnownElement(highlights[i], curWindow) rect = elem.getBoundingClientRect(); - var offsetY = 0, offsetX = 0; - if (needsOffset) { - var offset = getChromeOffset(elem); - offsetX = offset.x; - offsetY = offset.y; - } else { - // Don't need to offset the window chrome, just make relative to containing node - offsetY = -top; - offsetX = -left; - } + var offsetY = -top; + var offsetX = -left; // Draw the rectangle ctx.strokeRect(rect.left + offsetX, rect.top + offsetY, rect.width, rect.height); From ea490cb122e98753deb2ded0f6ec7eb8590dad72 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 3 Sep 2013 22:51:58 -0700 Subject: [PATCH 02/86] Bug 896797 - Part 3: Use install manifests for managing dist/include; r=glandium --- Makefile.in | 1 + js/src/Makefile.in | 1 + .../action/process_install_manifest.py | 9 +++-- .../mozbuild/backend/recursivemake.py | 34 +++++++---------- python/mozbuild/mozbuild/frontend/data.py | 6 ++- python/mozbuild/mozbuild/frontend/emitter.py | 3 +- .../test/backend/test_recursivemake.py | 38 +++++-------------- 7 files changed, 38 insertions(+), 54 deletions(-) diff --git a/Makefile.in b/Makefile.in index 3d3bc0f5bceb..923f7c263a25 100644 --- a/Makefile.in +++ b/Makefile.in @@ -99,6 +99,7 @@ TIER_precompile_CUSTOM := 1 include $(topsrcdir)/config/rules.mk default all alldep:: + $(call py_action,process_install_manifest,$(DIST)/include _build_manifests/install/dist_include js/src/_build_manifests/install/dist_include) $(call BUILDSTATUS,TIERS $(TIERS)) $(foreach tier,$(TIERS),$(call SUBMAKE,tier_$(tier))) diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 2439e81e72bd..8e6996e1e484 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -177,6 +177,7 @@ MOZILLA_DTRACE_SRC = $(srcdir)/devtools/javascript-trace.d endif default:: + $(call py_action,process_install_manifest,--no-remove $(DIST)/include _build_manifests/install/dist_include) ifneq (,$(CROSS_COMPILE)$(filter-out WINNT OS2,$(OS_ARCH))) # nsinstall doesn't get built until we enter config/ in the exports phase, diff --git a/python/mozbuild/mozbuild/action/process_install_manifest.py b/python/mozbuild/mozbuild/action/process_install_manifest.py index 33468703145c..9c5aec14196e 100644 --- a/python/mozbuild/mozbuild/action/process_install_manifest.py +++ b/python/mozbuild/mozbuild/action/process_install_manifest.py @@ -13,14 +13,14 @@ COMPLETE = 'From {dest}: Kept {existing} existing; Added/updated {updated}; ' \ 'Removed {rm_files} files and {rm_dirs} directories.' -def process_manifest(destdir, *paths): +def process_manifest(destdir, paths, remove_unaccounted=True): manifest = InstallManifest() for path in paths: manifest |= InstallManifest(path=path) copier = FileCopier() manifest.populate_registry(copier) - return copier.copy(destdir) + return copier.copy(destdir, remove_unaccounted=remove_unaccounted) if __name__ == '__main__': @@ -29,10 +29,13 @@ if __name__ == '__main__': parser.add_argument('destdir', help='Destination directory.') parser.add_argument('manifests', nargs='+', help='Path to manifest file(s).') + parser.add_argument('--no-remove', action='store_true', + help='Do not remove unaccounted files from destination.') args = parser.parse_args() - result = process_manifest(args.destdir, *args.manifests) + result = process_manifest(args.destdir, args.manifests, + remove_unaccounted=not args.no_remove) print(COMPLETE.format(dest=args.destdir, existing=result.existing_files_count, diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py index 4527e3cf477c..765f329d004f 100644 --- a/python/mozbuild/mozbuild/backend/recursivemake.py +++ b/python/mozbuild/mozbuild/backend/recursivemake.py @@ -149,11 +149,8 @@ class RecursiveMakeBackend(CommonBackend): self.backend_input_files.add(os.path.join(self.environment.topobjdir, 'config', 'autoconf.mk')) - self._install_manifests = dict() - self._purge_manifests = dict( dist_bin=PurgeManifest(relpath='dist/bin'), - dist_include=PurgeManifest(relpath='dist/include'), dist_private=PurgeManifest(relpath='dist/private'), dist_public=PurgeManifest(relpath='dist/public'), dist_sdk=PurgeManifest(relpath='dist/sdk'), @@ -163,6 +160,7 @@ class RecursiveMakeBackend(CommonBackend): self._install_manifests = dict( dist_idl=InstallManifest(), + dist_include=InstallManifest(), ) def _update_from_avoid_write(self, result): @@ -368,27 +366,22 @@ class RecursiveMakeBackend(CommonBackend): ' '.join(obj.parallel_external_make_dirs)) def _process_exports(self, obj, exports, backend_file, namespace=""): + # This may not be needed, but is present for backwards compatibility + # with the old make rules, just in case. + if not obj.dist_install: + return + strings = exports.get_strings() if namespace: - if strings: - backend_file.write('EXPORTS_NAMESPACES += %s\n' % namespace) - export_name = 'EXPORTS_%s' % namespace namespace += '/' - else: - export_name = 'EXPORTS' - # Iterate over the list of export filenames, printing out an EXPORTS - # declaration for each. - if strings: - backend_file.write('%s += %s\n' % (export_name, ' '.join(strings))) + for s in strings: + source = os.path.normpath(os.path.join(obj.srcdir, s)) + dest = '%s%s' % (namespace, os.path.basename(s)) + self._install_manifests['dist_include'].add_symlink(source, dest) - for s in strings: - source = os.path.normpath(os.path.join(obj.srcdir, s)) - if not os.path.isfile(source): - raise Exception('File listed in EXPORTS does not exist: %s' % source) - - p = '%s%s' % (namespace, s) - self._purge_manifests['dist_include'].add(p) + if not os.path.exists(source): + raise Exception('File listed in EXPORTS does not exist: %s' % source) children = exports.get_children() for subdir in sorted(children): @@ -405,7 +398,8 @@ class RecursiveMakeBackend(CommonBackend): for idl in manager.idls.values(): self._install_manifests['dist_idl'].add_symlink(idl['source'], idl['basename']) - self._purge_manifests['dist_include'].add('%s.h' % idl['root']) + self._install_manifests['dist_include'].add_optional_exists('%s.h' + % idl['root']) build_files.add(mozpath.join('headers', '%s.h' % idl['root'])) for module in manager.modules: diff --git a/python/mozbuild/mozbuild/frontend/data.py b/python/mozbuild/mozbuild/frontend/data.py index 0ca88f36cdf8..9db3d89079c4 100644 --- a/python/mozbuild/mozbuild/frontend/data.py +++ b/python/mozbuild/mozbuild/frontend/data.py @@ -161,11 +161,13 @@ class Exports(SandboxDerived): this object fills that role. It just has a reference to the underlying HierarchicalStringList, which is created when parsing EXPORTS. """ - __slots__ = ('exports') + __slots__ = ('exports', 'dist_install') - def __init__(self, sandbox, exports): + def __init__(self, sandbox, exports, dist_install=True): SandboxDerived.__init__(self, sandbox) self.exports = exports + self.dist_install = dist_install + class IPDLFile(SandboxDerived): """Describes an individual .ipdl source file.""" diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py index 4979e8b02c5f..3e8bd677582d 100644 --- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -154,7 +154,8 @@ class TreeMetadataEmitter(LoggingMixin): exports = sandbox.get('EXPORTS') if exports: - yield Exports(sandbox, exports) + yield Exports(sandbox, exports, + dist_install=not sandbox.get('NO_DIST_INSTALL', False)) program = sandbox.get('PROGRAM') if program: diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py index ff411d2701c2..a2d64e8b31c3 100644 --- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -234,33 +234,16 @@ class TestRecursiveMakeBackend(BackendTester): self.assertEqual(found, val) def test_exports(self): - """Ensure EXPORTS is written out correctly.""" + """Ensure EXPORTS is handled properly.""" env = self._consume('exports', RecursiveMakeBackend) - backend_path = os.path.join(env.topobjdir, 'backend.mk') - lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]] - - self.assertEqual(lines, [ - 'MOZBUILD_DERIVED := 1', - 'NO_MAKEFILE_RULE := 1', - 'NO_SUBMAKEFILES_RULE := 1', - 'EXPORTS += foo.h', - 'EXPORTS_NAMESPACES += mozilla', - 'EXPORTS_mozilla += mozilla1.h mozilla2.h', - 'EXPORTS_NAMESPACES += mozilla/dom', - 'EXPORTS_mozilla/dom += dom1.h dom2.h', - 'EXPORTS_NAMESPACES += mozilla/gfx', - 'EXPORTS_mozilla/gfx += gfx.h', - 'EXPORTS_NAMESPACES += nspr/private', - 'EXPORTS_nspr/private += pprio.h', - ]) - - # EXPORTS files should appear in the dist_include purge manifest. - m = PurgeManifest(path=os.path.join(env.topobjdir, - '_build_manifests', 'purge', 'dist_include')) - self.assertIn('foo.h', m.entries) - self.assertIn('mozilla/mozilla1.h', m.entries) - self.assertIn('mozilla/dom/dom2.h', m.entries) + # EXPORTS files should appear in the dist_include install manifest. + m = InstallManifest(path=os.path.join(env.topobjdir, + '_build_manifests', 'install', 'dist_include')) + self.assertEqual(len(m), 7) + self.assertIn('foo.h', m) + self.assertIn('mozilla/mozilla1.h', m) + self.assertIn('mozilla/dom/dom2.h', m) def test_xpcshell_manifests(self): """Ensure XPCSHELL_TESTS_MANIFESTS is written out correctly.""" @@ -297,8 +280,8 @@ class TestRecursiveMakeBackend(BackendTester): self.assertIn('bar.idl', m) self.assertIn('foo.idl', m) - m = PurgeManifest(path=os.path.join(purge_dir, 'dist_include')) - self.assertIn('foo.h', m.entries) + m = InstallManifest(path=os.path.join(install_dir, 'dist_include')) + self.assertIn('foo.h', m) p = os.path.join(env.topobjdir, 'config/makefiles/xpidl') self.assertTrue(os.path.isdir(p)) @@ -325,7 +308,6 @@ class TestRecursiveMakeBackend(BackendTester): expected = [ 'dist_bin', - 'dist_include', 'dist_private', 'dist_public', 'dist_sdk', From cac20eed1e2ad87daae9bb2c28278fec8776f28b Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 4 Sep 2013 15:02:04 +1200 Subject: [PATCH 03/86] revert 3171b6ad0055 b=907986 --HG-- extra : transplant_source : K%83%1FS%27%A7%20%82%C4P%08%E5n%8C%830%B6%2C%24%97 --- content/media/webaudio/PannerNode.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index 3c9c3c9edcc3..eda79dd31a2f 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -444,8 +444,11 @@ PannerNodeEngine::ComputeConeGain() ThreeDPoint sourceToListener = mListenerPosition - mPosition; sourceToListener.Normalize(); + ThreeDPoint normalizedSourceOrientation = mOrientation; + normalizedSourceOrientation.Normalize(); + // Angle between the source orientation vector and the source-listener vector - double dotProduct = sourceToListener.DotProduct(mOrientation); + double dotProduct = sourceToListener.DotProduct(normalizedSourceOrientation); double angle = 180 * acos(dotProduct) / M_PI; double absAngle = fabs(angle); From 21298924c4824f694a3a1bd4ea313d7b389857d2 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 4 Sep 2013 21:10:32 +1200 Subject: [PATCH 04/86] crashtests for bug 907986 --HG-- extra : transplant_source : %1A%09%7D%14MM%B2_p%2B%27%C4M%C3%A2%83%F3C%C4%DC --- content/media/test/crashtests/907986-1.html | 17 +++++++++++++++++ content/media/test/crashtests/907986-2.html | 17 +++++++++++++++++ content/media/test/crashtests/907986-3.html | 17 +++++++++++++++++ content/media/test/crashtests/907986-4.html | 15 +++++++++++++++ content/media/test/crashtests/crashtests.list | 4 ++++ 5 files changed, 70 insertions(+) create mode 100644 content/media/test/crashtests/907986-1.html create mode 100644 content/media/test/crashtests/907986-2.html create mode 100644 content/media/test/crashtests/907986-3.html create mode 100644 content/media/test/crashtests/907986-4.html diff --git a/content/media/test/crashtests/907986-1.html b/content/media/test/crashtests/907986-1.html new file mode 100644 index 000000000000..320b8eadd0cf --- /dev/null +++ b/content/media/test/crashtests/907986-1.html @@ -0,0 +1,17 @@ + + + diff --git a/content/media/test/crashtests/907986-2.html b/content/media/test/crashtests/907986-2.html new file mode 100644 index 000000000000..e0626ba2c26b --- /dev/null +++ b/content/media/test/crashtests/907986-2.html @@ -0,0 +1,17 @@ + + + diff --git a/content/media/test/crashtests/907986-3.html b/content/media/test/crashtests/907986-3.html new file mode 100644 index 000000000000..75b756c36347 --- /dev/null +++ b/content/media/test/crashtests/907986-3.html @@ -0,0 +1,17 @@ + + + diff --git a/content/media/test/crashtests/907986-4.html b/content/media/test/crashtests/907986-4.html new file mode 100644 index 000000000000..a73500efcac9 --- /dev/null +++ b/content/media/test/crashtests/907986-4.html @@ -0,0 +1,15 @@ + + + diff --git a/content/media/test/crashtests/crashtests.list b/content/media/test/crashtests/crashtests.list index 42195b4111fe..c78dc38eea44 100644 --- a/content/media/test/crashtests/crashtests.list +++ b/content/media/test/crashtests/crashtests.list @@ -51,3 +51,7 @@ test-pref(media.webvtt.enabled,true) load 882549.html load 884459.html load 889042.html test-pref(media.webvtt.enabled,true) load 894104.html +load 907986-1.html +load 907986-2.html +load 907986-3.html +load 907986-4.html From ce7c2ca91b2a7558aa7b2effdc88e34fb019990b Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 4 Sep 2013 21:20:58 +1200 Subject: [PATCH 05/86] b=907986 don't calculate upProjection twice r=padenot --HG-- extra : transplant_source : %8E%E1r%9F%AC%EB%C6%9A%EE_%10%0F%B9%1D%EF%85%EBu%CD%96 --- content/media/webaudio/PannerNode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index eda79dd31a2f..c218f6a410e1 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -422,7 +422,7 @@ PannerNodeEngine::ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation) aAzimuth = 450 - aAzimuth; } - aElevation = 90 - 180 * acos(sourceListener.DotProduct(up)) / M_PI; + aElevation = 90 - 180 * acos(upProjection) / M_PI; if (aElevation > 90) { aElevation = 180 - aElevation; From de80c0afe2b7dc136512f27209f2836d07fd5607 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 4 Sep 2013 21:20:58 +1200 Subject: [PATCH 06/86] b=907986 avoid under and overflow in Normalize() r=padenot --HG-- extra : transplant_source : %83%C5%A4%92%28%2Bf%7DHT%13%DE7L%26%B89x%E4%FF --- content/media/webaudio/ThreeDPoint.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/content/media/webaudio/ThreeDPoint.h b/content/media/webaudio/ThreeDPoint.h index 847e53bfbbcb..45aaed5cac7e 100644 --- a/content/media/webaudio/ThreeDPoint.h +++ b/content/media/webaudio/ThreeDPoint.h @@ -8,6 +8,7 @@ #define ThreeDPoint_h_ #include +#include namespace mozilla { @@ -34,6 +35,12 @@ struct ThreeDPoint { void Normalize() { + // Normalize with the maximum norm first to avoid overflow and underflow. + double invMax = 1 / MaxNorm(); + x *= invMax; + y *= invMax; + z *= invMax; + double invDistance = 1 / Magnitude(); x *= invDistance; y *= invDistance; @@ -62,6 +69,12 @@ struct ThreeDPoint { return x == 0 && y == 0 && z == 0; } double x, y, z; + +private: + double MaxNorm() const + { + return std::max(fabs(x), std::max(fabs(y), fabs(z))); + } }; ThreeDPoint operator-(const ThreeDPoint& lhs, const ThreeDPoint& rhs); From 4affe59604b66629497c67693dabacec864d327b Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 4 Sep 2013 21:20:59 +1200 Subject: [PATCH 07/86] b=907986 normalize orientation vectors early and keep existing state if directions are undefined r=padenot Normalizing the AudioListener front orientation vectors before taking their cross product avoids the possibility of overflow. The panning effect and the azimuth and elevation calculation in the Web Audio spec becomes undefined with linearly dependent listener vectors, so keep existing state in these situations. PannerNode orientation is normalized for consistency, but zero is permitted for this vector because the sound cone algorithm in the Web Audio specifies behavior for this case. --HG-- extra : transplant_source : %DA%C7e%E7%90%14%AF%EA%08%94x%C1%A2g%F1%9A%EE%16%EB%29 --- content/media/webaudio/AudioListener.cpp | 42 +++++++++++++++++++++--- content/media/webaudio/AudioListener.h | 24 ++------------ content/media/webaudio/PannerNode.cpp | 30 +++++++---------- content/media/webaudio/PannerNode.h | 18 +++++----- content/media/webaudio/ThreeDPoint.cpp | 9 +++++ content/media/webaudio/ThreeDPoint.h | 4 +++ 6 files changed, 74 insertions(+), 53 deletions(-) diff --git a/content/media/webaudio/AudioListener.cpp b/content/media/webaudio/AudioListener.cpp index 1d52a41673f1..7e1ad8d50a09 100644 --- a/content/media/webaudio/AudioListener.cpp +++ b/content/media/webaudio/AudioListener.cpp @@ -19,8 +19,8 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioListener, Release) AudioListener::AudioListener(AudioContext* aContext) : mContext(aContext) , mPosition() - , mOrientation(0., 0., -1.) - , mUpVector(0., 1., 0.) + , mFrontVector(0., 0., -1.) + , mRightVector(1., 0., 0.) , mVelocity() , mDopplerFactor(1.) , mSpeedOfSound(343.3) // meters/second @@ -35,6 +35,40 @@ AudioListener::WrapObject(JSContext* aCx, JS::Handle aScope) return AudioListenerBinding::Wrap(aCx, aScope, this); } +void +AudioListener::SetOrientation(double aX, double aY, double aZ, + double aXUp, double aYUp, double aZUp) +{ + ThreeDPoint front(aX, aY, aZ); + // The panning effect and the azimuth and elevation calculation in the Web + // Audio spec becomes undefined with linearly dependent vectors, so keep + // existing state in these situations. + if (front.IsZero()) { + return; + } + // Normalize before using CrossProduct() to avoid overflow. + front.Normalize(); + ThreeDPoint up(aXUp, aYUp, aZUp); + if (up.IsZero()) { + return; + } + up.Normalize(); + ThreeDPoint right = front.CrossProduct(up); + if (right.IsZero()) { + return; + } + right.Normalize(); + + if (!mFrontVector.FuzzyEqual(front)) { + mFrontVector = front; + SendThreeDPointParameterToStream(PannerNode::LISTENER_FRONT_VECTOR, front); + } + if (!mRightVector.FuzzyEqual(right)) { + mRightVector = right; + SendThreeDPointParameterToStream(PannerNode::LISTENER_RIGHT_VECTOR, right); + } +} + void AudioListener::RegisterPannerNode(PannerNode* aPannerNode) { @@ -42,8 +76,8 @@ AudioListener::RegisterPannerNode(PannerNode* aPannerNode) // Let the panner node know about our parameters aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_POSITION, mPosition); - aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_ORIENTATION, mOrientation); - aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_UPVECTOR, mUpVector); + aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_FRONT_VECTOR, mFrontVector); + aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_RIGHT_VECTOR, mRightVector); aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_VELOCITY, mVelocity); aPannerNode->SendDoubleParameterToStream(PannerNode::LISTENER_DOPPLER_FACTOR, mDopplerFactor); aPannerNode->SendDoubleParameterToStream(PannerNode::LISTENER_SPEED_OF_SOUND, mSpeedOfSound); diff --git a/content/media/webaudio/AudioListener.h b/content/media/webaudio/AudioListener.h index 91bd4733529e..4fb1ef18a2f8 100644 --- a/content/media/webaudio/AudioListener.h +++ b/content/media/webaudio/AudioListener.h @@ -84,25 +84,7 @@ public: } void SetOrientation(double aX, double aY, double aZ, - double aXUp, double aYUp, double aZUp) - { - if (WebAudioUtils::FuzzyEqual(mOrientation.x, aX) && - WebAudioUtils::FuzzyEqual(mOrientation.y, aY) && - WebAudioUtils::FuzzyEqual(mOrientation.z, aZ) && - WebAudioUtils::FuzzyEqual(mUpVector.x, aX) && - WebAudioUtils::FuzzyEqual(mUpVector.y, aY) && - WebAudioUtils::FuzzyEqual(mUpVector.z, aZ)) { - return; - } - mOrientation.x = aX; - mOrientation.y = aY; - mOrientation.z = aZ; - mUpVector.x = aXUp; - mUpVector.y = aYUp; - mUpVector.z = aZUp; - SendThreeDPointParameterToStream(PannerNode::LISTENER_ORIENTATION, mOrientation); - SendThreeDPointParameterToStream(PannerNode::LISTENER_UPVECTOR, mUpVector); - } + double aXUp, double aYUp, double aZUp); const ThreeDPoint& Velocity() const { @@ -135,8 +117,8 @@ private: friend class PannerNode; nsRefPtr mContext; ThreeDPoint mPosition; - ThreeDPoint mOrientation; - ThreeDPoint mUpVector; + ThreeDPoint mFrontVector; + ThreeDPoint mRightVector; ThreeDPoint mVelocity; double mDopplerFactor; double mSpeedOfSound; diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index c218f6a410e1..ef77af59d5a2 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -109,8 +109,8 @@ public: { switch (aIndex) { case PannerNode::LISTENER_POSITION: mListenerPosition = aParam; break; - case PannerNode::LISTENER_ORIENTATION: mListenerOrientation = aParam; break; - case PannerNode::LISTENER_UPVECTOR: mListenerUpVector = aParam; break; + case PannerNode::LISTENER_FRONT_VECTOR: mListenerFrontVector = aParam; break; + case PannerNode::LISTENER_RIGHT_VECTOR: mListenerRightVector = aParam; break; case PannerNode::LISTENER_VELOCITY: mListenerVelocity = aParam; break; case PannerNode::POSITION: mPosition = aParam; break; case PannerNode::ORIENTATION: mOrientation = aParam; break; @@ -178,8 +178,8 @@ public: double mConeOuterAngle; double mConeOuterGain; ThreeDPoint mListenerPosition; - ThreeDPoint mListenerOrientation; - ThreeDPoint mListenerUpVector; + ThreeDPoint mListenerFrontVector; + ThreeDPoint mListenerRightVector; ThreeDPoint mListenerVelocity; double mListenerDopplerFactor; double mListenerSpeedOfSound; @@ -376,7 +376,7 @@ PannerNodeEngine::DistanceAndConeGain(AudioChunk* aChunk, float aGain) AudioBufferInPlaceScale(samples, channelCount, aGain); } -// This algorithm is specicied in the webaudio spec. +// This algorithm is specified in the webaudio spec. void PannerNodeEngine::ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation) { @@ -391,14 +391,9 @@ PannerNodeEngine::ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation) sourceListener.Normalize(); // Project the source-listener vector on the x-z plane. - ThreeDPoint& listenerFront = mListenerOrientation; - ThreeDPoint listenerRightNorm = listenerFront.CrossProduct(mListenerUpVector); - listenerRightNorm.Normalize(); - - ThreeDPoint listenerFrontNorm(listenerFront); - listenerFrontNorm.Normalize(); - - ThreeDPoint up = listenerRightNorm.CrossProduct(listenerFrontNorm); + const ThreeDPoint& listenerFront = mListenerFrontVector; + const ThreeDPoint& listenerRight = mListenerRightVector; + ThreeDPoint up = listenerRight.CrossProduct(listenerFront); double upProjection = sourceListener.DotProduct(up); @@ -406,11 +401,11 @@ PannerNodeEngine::ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation) projectedSource.Normalize(); // Actually compute the angle, and convert to degrees - double projection = projectedSource.DotProduct(listenerRightNorm); + double projection = projectedSource.DotProduct(listenerRight); aAzimuth = 180 * acos(projection) / M_PI; // Compute whether the source is in front or behind the listener. - double frontBack = projectedSource.DotProduct(listenerFrontNorm); + double frontBack = projectedSource.DotProduct(listenerFront); if (frontBack < 0) { aAzimuth = 360 - aAzimuth; } @@ -444,11 +439,8 @@ PannerNodeEngine::ComputeConeGain() ThreeDPoint sourceToListener = mListenerPosition - mPosition; sourceToListener.Normalize(); - ThreeDPoint normalizedSourceOrientation = mOrientation; - normalizedSourceOrientation.Normalize(); - // Angle between the source orientation vector and the source-listener vector - double dotProduct = sourceToListener.DotProduct(normalizedSourceOrientation); + double dotProduct = sourceToListener.DotProduct(mOrientation); double angle = 180 * acos(dotProduct) / M_PI; double absAngle = fabs(angle); diff --git a/content/media/webaudio/PannerNode.h b/content/media/webaudio/PannerNode.h index 9d06f97191fd..eb8e764e8df3 100644 --- a/content/media/webaudio/PannerNode.h +++ b/content/media/webaudio/PannerNode.h @@ -120,14 +120,14 @@ public: void SetOrientation(double aX, double aY, double aZ) { - if (WebAudioUtils::FuzzyEqual(mOrientation.x, aX) && - WebAudioUtils::FuzzyEqual(mOrientation.y, aY) && - WebAudioUtils::FuzzyEqual(mOrientation.z, aZ)) { + ThreeDPoint orientation(aX, aY, aZ); + if (!orientation.IsZero()) { + orientation.Normalize(); + } + if (mOrientation.FuzzyEqual(orientation)) { return; } - mOrientation.x = aX; - mOrientation.y = aY; - mOrientation.z = aZ; + mOrientation = orientation; SendThreeDPointParameterToStream(ORIENTATION, mOrientation); } @@ -233,15 +233,15 @@ private: friend class PannerNodeEngine; enum EngineParameters { LISTENER_POSITION, - LISTENER_ORIENTATION, - LISTENER_UPVECTOR, + LISTENER_FRONT_VECTOR, // unit length + LISTENER_RIGHT_VECTOR, // unit length, orthogonal to LISTENER_FRONT_VECTOR LISTENER_VELOCITY, LISTENER_DOPPLER_FACTOR, LISTENER_SPEED_OF_SOUND, PANNING_MODEL, DISTANCE_MODEL, POSITION, - ORIENTATION, + ORIENTATION, // unit length or zero VELOCITY, REF_DISTANCE, MAX_DISTANCE, diff --git a/content/media/webaudio/ThreeDPoint.cpp b/content/media/webaudio/ThreeDPoint.cpp index f4187e7b37f9..422c36078ace 100644 --- a/content/media/webaudio/ThreeDPoint.cpp +++ b/content/media/webaudio/ThreeDPoint.cpp @@ -9,11 +9,20 @@ */ #include "ThreeDPoint.h" +#include "WebAudioUtils.h" namespace mozilla { namespace dom { +bool +ThreeDPoint::FuzzyEqual(const ThreeDPoint& other) +{ + return WebAudioUtils::FuzzyEqual(x, other.x) && + WebAudioUtils::FuzzyEqual(y, other.y) && + WebAudioUtils::FuzzyEqual(z, other.z); +} + ThreeDPoint operator-(const ThreeDPoint& lhs, const ThreeDPoint& rhs) { return ThreeDPoint(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); diff --git a/content/media/webaudio/ThreeDPoint.h b/content/media/webaudio/ThreeDPoint.h index 45aaed5cac7e..c9c8eba068d4 100644 --- a/content/media/webaudio/ThreeDPoint.h +++ b/content/media/webaudio/ThreeDPoint.h @@ -68,6 +68,10 @@ struct ThreeDPoint { { return x == 0 && y == 0 && z == 0; } + + // For comparing two vectors of close to unit magnitude. + bool FuzzyEqual(const ThreeDPoint& other); + double x, y, z; private: From 23ae39aad238b411cd6966a487be55b36d37ac7b Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 4 Sep 2013 21:20:59 +1200 Subject: [PATCH 08/86] test equalpower panning effect with panner directly above b=907986 --HG-- extra : transplant_source : %8E%99%9B%F8%288%5C%A5%E8%D1%C3%E2%9F%89%5C%D0C%B1l%B0 --- content/media/webaudio/test/Makefile.in | 1 + .../webaudio/test/test_pannerNodeAbove.html | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 content/media/webaudio/test/test_pannerNodeAbove.html diff --git a/content/media/webaudio/test/Makefile.in b/content/media/webaudio/test/Makefile.in index 2fe44cb346c3..e687f81dfc39 100644 --- a/content/media/webaudio/test/Makefile.in +++ b/content/media/webaudio/test/Makefile.in @@ -82,6 +82,7 @@ MOCHITEST_FILES := \ test_oscillatorNode.html \ test_oscillatorNodeStart.html \ test_pannerNode.html \ + test_pannerNodeAbove.html \ test_pannerNode_equalPower.html \ test_periodicWave.html \ test_scriptProcessorNode.html \ diff --git a/content/media/webaudio/test/test_pannerNodeAbove.html b/content/media/webaudio/test/test_pannerNodeAbove.html new file mode 100644 index 000000000000..d7a6e6cb4dfa --- /dev/null +++ b/content/media/webaudio/test/test_pannerNodeAbove.html @@ -0,0 +1,50 @@ + + + + Test PannerNode directly above + + + + +
+
+
+
+ + From 95c6c435c149c1224e64db14c25bccafb9102228 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 4 Sep 2013 21:20:59 +1200 Subject: [PATCH 09/86] b=907986 handle zero front-right plane projection without NaNs r=padenot The azimuth calculation in the Web Audio spec becomes undefined in this situation as it requires normalizing a zero vector. The panning effect should not depend on azimuth when the source is directly above the listener (because position does not depend on azimuth), but the specified "equalpower" panning model does depend on azimuth even at this elevation. Setting azimuth to zero produces the same result as if the normalized projection were replaced with a zero vector. --HG-- extra : transplant_source : f%A4h%CB7%7Bp%87%AE%09%9F%2Cu%D7%CD%9D%5E%A8%EC%0D --- content/media/webaudio/PannerNode.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index ef77af59d5a2..481fb08e870b 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -396,8 +396,20 @@ PannerNodeEngine::ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation) ThreeDPoint up = listenerRight.CrossProduct(listenerFront); double upProjection = sourceListener.DotProduct(up); + aElevation = 90 - 180 * acos(upProjection) / M_PI; + + if (aElevation > 90) { + aElevation = 180 - aElevation; + } else if (aElevation < -90) { + aElevation = -180 - aElevation; + } ThreeDPoint projectedSource = sourceListener - up * upProjection; + if (projectedSource.IsZero()) { + // source - listener direction is up or down. + aAzimuth = 0.0; + return; + } projectedSource.Normalize(); // Actually compute the angle, and convert to degrees @@ -416,14 +428,6 @@ PannerNodeEngine::ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation) } else { aAzimuth = 450 - aAzimuth; } - - aElevation = 90 - 180 * acos(upProjection) / M_PI; - - if (aElevation > 90) { - aElevation = 180 - aElevation; - } else if (aElevation < -90) { - aElevation = -180 - aElevation; - } } // This algorithm is described in the WebAudio spec. From 07f97e64236b03035d40322396be127f2eab0b2a Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 4 Sep 2013 21:21:00 +1200 Subject: [PATCH 10/86] b=907986 remove unused ThreeDPoint::Distance() r=padenot --HG-- extra : transplant_source : %19%DD%A9%CB%CC%B1%C42%E2%8EY%CE%22%89o_%97i%03_ --- content/media/webaudio/ThreeDPoint.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/content/media/webaudio/ThreeDPoint.h b/content/media/webaudio/ThreeDPoint.h index c9c8eba068d4..24a6a32e0d2d 100644 --- a/content/media/webaudio/ThreeDPoint.h +++ b/content/media/webaudio/ThreeDPoint.h @@ -59,11 +59,6 @@ struct ThreeDPoint { return x * rhs.x + y * rhs.y + z * rhs.z; } - double Distance(const ThreeDPoint& rhs) - { - return sqrt(hypot(rhs.x, x) + hypot(rhs.y, y) + hypot(rhs.z, z)); - } - bool IsZero() const { return x == 0 && y == 0 && z == 0; From e18bfe88a52d287cc9517247005b59ee0d90e597 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 5 Sep 2013 07:44:04 +1200 Subject: [PATCH 11/86] tests for convolver and panner channelCount b=906966 --HG-- extra : transplant_source : %17%A2WFH%18%7E-c%2CZVC%AAc%85%FB%02%BE%BD --- content/media/webaudio/test/Makefile.in | 7 +++ .../test/test_convolverNodeChannelCount.html | 61 +++++++++++++++++++ .../test/test_pannerNodeChannelCount.html | 50 +++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 content/media/webaudio/test/test_convolverNodeChannelCount.html create mode 100644 content/media/webaudio/test/test_pannerNodeChannelCount.html diff --git a/content/media/webaudio/test/Makefile.in b/content/media/webaudio/test/Makefile.in index e687f81dfc39..afeb3635d2c8 100644 --- a/content/media/webaudio/test/Makefile.in +++ b/content/media/webaudio/test/Makefile.in @@ -115,8 +115,15 @@ MOCHITEST_FILES := \ ifneq ($(MOZ_DEBUG)+$(MOZ_WIDGET_TOOLKIT),+gtk2) # bug 911777 MOCHITEST_FILES += \ + test_convolverNodeChannelCount.html \ test_delayNodeAtMax.html \ $(NULL) +endif # bug 911777 + +ifneq ($(OS_TARGET),Android) # bug 912474 +MOCHITEST_FILES += \ + test_pannerNodeChannelCount.html \ + $(NULL) endif include $(topsrcdir)/config/rules.mk diff --git a/content/media/webaudio/test/test_convolverNodeChannelCount.html b/content/media/webaudio/test/test_convolverNodeChannelCount.html new file mode 100644 index 000000000000..3e85fa033795 --- /dev/null +++ b/content/media/webaudio/test/test_convolverNodeChannelCount.html @@ -0,0 +1,61 @@ + + + + Test PannerNode directly above + + + + +
+
+
+
+ + diff --git a/content/media/webaudio/test/test_pannerNodeChannelCount.html b/content/media/webaudio/test/test_pannerNodeChannelCount.html new file mode 100644 index 000000000000..636fdaa677c8 --- /dev/null +++ b/content/media/webaudio/test/test_pannerNodeChannelCount.html @@ -0,0 +1,50 @@ + + + + Test PannerNode directly above + + + + +
+
+
+
+ + From 3d1ac8d90cb5901c212c67f28a58bca9951c3169 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 5 Sep 2013 07:44:35 +1200 Subject: [PATCH 12/86] b=906966 limit ConvolverNode and PannerNode input channel count through channelCount and channelCountMode r=ehsan --HG-- extra : transplant_source : %8A%FB%BC%D3%D0%F3Ct%A5%D1%B1%AF%3D%9Bk%896%7F%7F%1F --- content/media/webaudio/AudioNode.h | 2 +- content/media/webaudio/ConvolverNode.h | 16 ++++++++++++++++ content/media/webaudio/PannerNode.h | 17 +++++++++++++++++ content/media/webaudio/blink/HRTFPanner.cpp | 5 ++--- content/media/webaudio/blink/Reverb.cpp | 5 +---- dom/webidl/AudioNode.webidl | 1 + 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/content/media/webaudio/AudioNode.h b/content/media/webaudio/AudioNode.h index 2ee253abbfd2..cd58f51abe39 100644 --- a/content/media/webaudio/AudioNode.h +++ b/content/media/webaudio/AudioNode.h @@ -171,7 +171,7 @@ public: { return mChannelCountMode; } - void SetChannelCountModeValue(ChannelCountMode aMode) + virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) { mChannelCountMode = aMode; SendChannelMixingParametersToStream(); diff --git a/content/media/webaudio/ConvolverNode.h b/content/media/webaudio/ConvolverNode.h index 3f2a2b870e18..03ce38ced503 100644 --- a/content/media/webaudio/ConvolverNode.h +++ b/content/media/webaudio/ConvolverNode.h @@ -40,6 +40,22 @@ public: void SetNormalize(bool aNormal); + virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) MOZ_OVERRIDE + { + if (aChannelCount > 2) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } + AudioNode::SetChannelCount(aChannelCount, aRv); + } + virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) MOZ_OVERRIDE + { + if (aMode == ChannelCountMode::Max) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } + AudioNode::SetChannelCountModeValue(aMode, aRv); + } virtual void NotifyInputConnected() MOZ_OVERRIDE { mMediaStreamGraphUpdateIndexAtLastInputConnection = diff --git a/content/media/webaudio/PannerNode.h b/content/media/webaudio/PannerNode.h index eb8e764e8df3..81b0e08c0107 100644 --- a/content/media/webaudio/PannerNode.h +++ b/content/media/webaudio/PannerNode.h @@ -34,6 +34,23 @@ public: virtual void DestroyMediaStream() MOZ_OVERRIDE; + virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) MOZ_OVERRIDE + { + if (aChannelCount > 2) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } + AudioNode::SetChannelCount(aChannelCount, aRv); + } + virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) MOZ_OVERRIDE + { + if (aMode == ChannelCountMode::Max) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } + AudioNode::SetChannelCountModeValue(aMode, aRv); + } + NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PannerNode, AudioNode) diff --git a/content/media/webaudio/blink/HRTFPanner.cpp b/content/media/webaudio/blink/HRTFPanner.cpp index a14893706119..2af45ef4d1b9 100644 --- a/content/media/webaudio/blink/HRTFPanner.cpp +++ b/content/media/webaudio/blink/HRTFPanner.cpp @@ -115,14 +115,13 @@ void HRTFPanner::pan(double desiredAzimuth, double elevation, const AudioChunk* unsigned numInputChannels = inputBus->IsNull() ? 0 : inputBus->mChannelData.Length(); - bool isInputGood = inputBus && numInputChannels <= 2; - MOZ_ASSERT(isInputGood); + MOZ_ASSERT(numInputChannels <= 2); MOZ_ASSERT(framesToProcess <= inputBus->mDuration); bool isOutputGood = outputBus && outputBus->mChannelData.Length() == 2 && framesToProcess <= outputBus->mDuration; MOZ_ASSERT(isOutputGood); - if (!isInputGood || !isOutputGood) { + if (!isOutputGood) { if (outputBus) outputBus->SetNull(outputBus->mDuration); return; diff --git a/content/media/webaudio/blink/Reverb.cpp b/content/media/webaudio/blink/Reverb.cpp index 213f38295a13..997abefc7967 100644 --- a/content/media/webaudio/blink/Reverb.cpp +++ b/content/media/webaudio/blink/Reverb.cpp @@ -146,10 +146,7 @@ void Reverb::process(const AudioChunk* sourceBus, AudioChunk* destinationBus, si return; // For now only handle mono or stereo output - if (destinationBus->mChannelData.Length() > 2) { - destinationBus->SetNull(destinationBus->mDuration); - return; - } + MOZ_ASSERT(destinationBus->mChannelData.Length() <= 2); float* destinationChannelL = static_cast(const_cast(destinationBus->mChannelData[0])); const float* sourceBusL = static_cast(sourceBus->mChannelData[0]); diff --git a/dom/webidl/AudioNode.webidl b/dom/webidl/AudioNode.webidl index 8f5805386b39..460fda837049 100644 --- a/dom/webidl/AudioNode.webidl +++ b/dom/webidl/AudioNode.webidl @@ -38,6 +38,7 @@ interface AudioNode : EventTarget { // Channel up-mixing and down-mixing rules for all inputs. [SetterThrows] attribute unsigned long channelCount; + [SetterThrows] attribute ChannelCountMode channelCountMode; attribute ChannelInterpretation channelInterpretation; From 57d8fb0391773201cc33be3d6574b91c8aff990f Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 5 Sep 2013 07:44:37 +1200 Subject: [PATCH 13/86] b=906966 limit ScriptProcessorNode input channel count through channelCount and channelCountMode r=ehsan --HG-- extra : transplant_source : %E6-%8A%10%BEb%FEg%8C%C3f%2C%1F%C6%859%E5%27%1C%60 --- .../media/webaudio/ScriptProcessorNode.cpp | 26 +++---------------- content/media/webaudio/ScriptProcessorNode.h | 15 +++++++++++ .../test_scriptProcessorNodeChannelCount.html | 9 +++++-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/content/media/webaudio/ScriptProcessorNode.cpp b/content/media/webaudio/ScriptProcessorNode.cpp index 65b4a14a3319..7a2bc8f25c16 100644 --- a/content/media/webaudio/ScriptProcessorNode.cpp +++ b/content/media/webaudio/ScriptProcessorNode.cpp @@ -213,10 +213,11 @@ public: , mSource(nullptr) , mDestination(static_cast (aDestination->Stream())) , mBufferSize(aBufferSize) - , mDefaultNumberOfInputChannels(aNumberOfInputChannels) , mInputWriteIndex(0) , mSeenNonSilenceInput(false) { + mInputChannels.SetLength(aNumberOfInputChannels); + AllocateInputBlock(); } void SetSourceStream(AudioNodeStream* aSource) @@ -237,8 +238,6 @@ public: return; } - EnsureInputChannels(aInput.mChannelData.Length()); - // First, record our input buffer for (uint32_t i = 0; i < mInputChannels.Length(); ++i) { if (aInput.IsNull()) { @@ -247,6 +246,7 @@ public: } else { mSeenNonSilenceInput = true; MOZ_ASSERT(aInput.GetDuration() == WEBAUDIO_BLOCK_SIZE, "sanity check"); + MOZ_ASSERT(aInput.mChannelData.Length() == mInputChannels.Length()); AudioBlockCopyChannelWithScale(static_cast(aInput.mChannelData[i]), aInput.mVolume, mInputChannels[i] + mInputWriteIndex); @@ -277,25 +277,6 @@ private: } } - void EnsureInputChannels(uint32_t aNumberOfChannels) - { - if (aNumberOfChannels == 0) { - aNumberOfChannels = mDefaultNumberOfInputChannels; - } - if (mInputChannels.Length() == 0) { - mInputChannels.SetLength(aNumberOfChannels); - AllocateInputBlock(); - } else if (aNumberOfChannels < mInputChannels.Length()) { - mInputChannels.SetLength(aNumberOfChannels); - } else if (aNumberOfChannels > mInputChannels.Length()) { - uint32_t oldLength = mInputChannels.Length(); - mInputChannels.SetLength(aNumberOfChannels); - for (uint32_t i = oldLength; i < aNumberOfChannels; ++i) { - mInputChannels[i] = new float[mBufferSize]; - } - } - } - void SendBuffersToMainThread(AudioNodeStream* aStream) { MOZ_ASSERT(!NS_IsMainThread()); @@ -411,7 +392,6 @@ private: AudioNodeStream* mDestination; InputChannels mInputChannels; const uint32_t mBufferSize; - const uint32_t mDefaultNumberOfInputChannels; // The write index into the current input buffer uint32_t mInputWriteIndex; bool mSeenNonSilenceInput; diff --git a/content/media/webaudio/ScriptProcessorNode.h b/content/media/webaudio/ScriptProcessorNode.h index b8dbd358d30c..efda98864cb0 100644 --- a/content/media/webaudio/ScriptProcessorNode.h +++ b/content/media/webaudio/ScriptProcessorNode.h @@ -59,6 +59,21 @@ public: } } + virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) MOZ_OVERRIDE + { + if (aChannelCount != ChannelCount()) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + } + return; + } + virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) MOZ_OVERRIDE + { + if (aMode != ChannelCountMode::Explicit) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + } + return; + } + uint32_t BufferSize() const { return mBufferSize; diff --git a/content/media/webaudio/test/test_scriptProcessorNodeChannelCount.html b/content/media/webaudio/test/test_scriptProcessorNodeChannelCount.html index 2fead4ed363c..45b9cd9915fe 100644 --- a/content/media/webaudio/test/test_scriptProcessorNodeChannelCount.html +++ b/content/media/webaudio/test/test_scriptProcessorNodeChannelCount.html @@ -32,9 +32,14 @@ addLoadEvent(function() { var source = context.createBufferSource(); - var sp = context.createScriptProcessor(2048); - sp.channelCount = 3; + var sp = context.createScriptProcessor(2048, 3); + expectException(function() { sp.channelCount = 2; }, + DOMException.NOT_SUPPORTED_ERR); sp.channelCountMode = "explicit"; + expectException(function() { sp.channelCountMode = "max"; }, + DOMException.NOT_SUPPORTED_ERR); + expectException(function() { sp.channelCountMode = "clamped-max"; }, + DOMException.NOT_SUPPORTED_ERR); sp.channelInterpretation = "discrete"; source.start(0); source.buffer = buffer; From d47399769eb9aff4e6b4aae284c0fcea4af06b89 Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Wed, 4 Sep 2013 16:39:25 -0400 Subject: [PATCH 14/86] bug 907800 - only retry http 408 when it is suspected of being a persistent reuse race r=jduell --- netwerk/protocol/http/nsHttpConnection.cpp | 37 ++++++++++++++-------- netwerk/protocol/http/nsHttpConnection.h | 1 + 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index 5300c6e2fce6..d8aeefd53254 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -120,7 +120,7 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info, NS_ENSURE_TRUE(!mConnInfo, NS_ERROR_ALREADY_INITIALIZED); mConnInfo = info; - mLastReadTime = PR_IntervalNow(); + mLastWriteTime = mLastReadTime = PR_IntervalNow(); mSupportsPipelining = gHttpHandler->ConnMgr()->SupportsPipelining(mConnInfo); mRtt = rtt; @@ -315,7 +315,7 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, uint32_t caps, int32_t pri NS_ENSURE_TRUE(!mTransaction, NS_ERROR_IN_PROGRESS); // reset the read timers to wash away any idle time - mLastReadTime = PR_IntervalNow(); + mLastWriteTime = mLastReadTime = PR_IntervalNow(); // Update security callbacks nsCOMPtr callbacks; @@ -702,17 +702,6 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans, NS_ENSURE_ARG_POINTER(trans); MOZ_ASSERT(responseHead, "No response head?"); - // If the server issued an explicit timeout, then we need to close down the - // socket transport. We pass an error code of NS_ERROR_NET_RESET to - // trigger the transactions 'restart' mechanism. We tell it to reset its - // response headers so that it will be ready to receive the new response. - uint16_t responseStatus = responseHead->Status(); - if (responseStatus == 408) { - Close(NS_ERROR_NET_RESET); - *reset = true; - return NS_OK; - } - // we won't change our keep-alive policy unless the server has explicitly // told us to do so. @@ -727,6 +716,27 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans, explicitKeepAlive = responseHead->HasHeaderValue(nsHttp::Connection, "keep-alive") || responseHead->HasHeaderValue(nsHttp::Proxy_Connection, "keep-alive"); + // deal with 408 Server Timeouts + uint16_t responseStatus = responseHead->Status(); + static const PRIntervalTime k1000ms = PR_MillisecondsToInterval(1000); + if (responseStatus == 408) { + // If this error could be due to a persistent connection reuse then + // we pass an error code of NS_ERROR_NET_RESET to + // trigger the transaction 'restart' mechanism. We tell it to reset its + // response headers so that it will be ready to receive the new response. + if (mIsReused && ((PR_IntervalNow() - mLastWriteTime) < k1000ms)) { + Close(NS_ERROR_NET_RESET); + *reset = true; + return NS_OK; + } + + // timeouts that are not caused by persistent connection reuse should + // not be retried for browser compatibility reasons. bug 907800. The + // server driven close is implicit in the 408. + explicitClose = true; + explicitKeepAlive = false; + } + // reset to default (the server may have changed since we last checked) mSupportsPipelining = false; @@ -1219,6 +1229,7 @@ nsHttpConnection::OnReadSegment(const char *buf, else if (*countRead == 0) mSocketOutCondition = NS_BASE_STREAM_CLOSED; else { + mLastWriteTime = PR_IntervalNow(); mSocketOutCondition = NS_OK; // reset condition if (!mProxyConnectInProgress) mTotalBytesWritten += *countRead; diff --git a/netwerk/protocol/http/nsHttpConnection.h b/netwerk/protocol/http/nsHttpConnection.h index b40fffd41277..bc047fe57063 100644 --- a/netwerk/protocol/http/nsHttpConnection.h +++ b/netwerk/protocol/http/nsHttpConnection.h @@ -214,6 +214,7 @@ private: nsRefPtr mConnInfo; PRIntervalTime mLastReadTime; + PRIntervalTime mLastWriteTime; PRIntervalTime mMaxHangTime; // max download time before dropping keep-alive status PRIntervalTime mIdleTimeout; // value of keep-alive: timeout= PRIntervalTime mConsiderReusedAfterInterval; From 85316040d32d6f491e77bbf46c5c36e1efcf4458 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 4 Sep 2013 16:43:12 -0400 Subject: [PATCH 15/86] Bug 910795 part 1. Add a way to Rebind() an nsString to be a dependent string. r=bsmedberg --- xpcom/string/public/nsTDependentString.h | 20 ++++---------------- xpcom/string/public/nsTString.h | 14 +++++++++++++- xpcom/string/src/nsTDependentString.cpp | 12 ------------ xpcom/string/src/nsTString.cpp | 12 ++++++++++++ 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/xpcom/string/public/nsTDependentString.h b/xpcom/string/public/nsTDependentString.h index 530d9316e7cf..4ed17315ce73 100644 --- a/xpcom/string/public/nsTDependentString.h +++ b/xpcom/string/public/nsTDependentString.h @@ -24,17 +24,6 @@ class nsTDependentString_CharT : public nsTString_CharT public: - /** - * verify restrictions - */ - void AssertValid() - { - NS_ASSERTION(mData, "nsTDependentString must wrap a non-NULL buffer"); - NS_ASSERTION(mLength != size_type(-1), "nsTDependentString has bogus length"); - NS_ASSERTION(mData[mLength] == 0, "nsTDependentString must wrap only null-terminated strings"); - } - - /** * constructors */ @@ -42,20 +31,20 @@ class nsTDependentString_CharT : public nsTString_CharT nsTDependentString_CharT( const char_type* start, const char_type* end ) : string_type(const_cast(start), uint32_t(end - start), F_TERMINATED) { - AssertValid(); + AssertValidDepedentString(); } nsTDependentString_CharT( const char_type* data, uint32_t length ) : string_type(const_cast(data), length, F_TERMINATED) { - AssertValid(); + AssertValidDepedentString(); } explicit nsTDependentString_CharT( const char_type* data ) : string_type(const_cast(data), uint32_t(char_traits::length(data)), F_TERMINATED) { - AssertValid(); + AssertValidDepedentString(); } nsTDependentString_CharT( const string_type& str, uint32_t startPos ) @@ -78,13 +67,12 @@ class nsTDependentString_CharT : public nsTString_CharT * allow this class to be bound to a different string... */ + using nsTString_CharT::Rebind; void Rebind( const char_type* data ) { Rebind(data, uint32_t(char_traits::length(data))); } - void Rebind( const char_type* data, size_type length ); - void Rebind( const char_type* start, const char_type* end ) { Rebind(start, uint32_t(end - start)); diff --git a/xpcom/string/public/nsTString.h b/xpcom/string/public/nsTString.h index be633bd56e27..ca694736f26c 100644 --- a/xpcom/string/public/nsTString.h +++ b/xpcom/string/public/nsTString.h @@ -358,6 +358,18 @@ class nsTString_CharT : public nsTSubstring_CharT #endif // !MOZ_STRING_WITH_OBSOLETE_API + void Rebind( const char_type* data, size_type length ); + + /** + * verify restrictions for dependent strings + */ + void AssertValidDepedentString() + { + NS_ASSERTION(mData, "nsTDependentString must wrap a non-NULL buffer"); + NS_ASSERTION(mLength != size_type(-1), "nsTDependentString has bogus length"); + NS_ASSERTION(mData[mLength] == 0, "nsTDependentString must wrap only null-terminated strings"); + } + protected: @@ -368,7 +380,7 @@ class nsTString_CharT : public nsTSubstring_CharT // allow subclasses to initialize fields directly nsTString_CharT( char_type* data, size_type length, uint32_t flags ) : substring_type(data, length, flags) {} - }; +}; class nsTFixedString_CharT : public nsTString_CharT diff --git a/xpcom/string/src/nsTDependentString.cpp b/xpcom/string/src/nsTDependentString.cpp index f9c401f153c1..230df222036e 100644 --- a/xpcom/string/src/nsTDependentString.cpp +++ b/xpcom/string/src/nsTDependentString.cpp @@ -4,18 +4,6 @@ * 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/. */ -void -nsTDependentString_CharT::Rebind( const char_type* data, size_type length ) - { - // If we currently own a buffer, release it. - Finalize(); - - mData = const_cast(data); - mLength = length; - SetDataFlags(F_TERMINATED); - AssertValid(); - } - void nsTDependentString_CharT::Rebind( const string_type& str, uint32_t startPos ) { diff --git a/xpcom/string/src/nsTString.cpp b/xpcom/string/src/nsTString.cpp index 4957e82edb8f..561e99eef71e 100644 --- a/xpcom/string/src/nsTString.cpp +++ b/xpcom/string/src/nsTString.cpp @@ -36,3 +36,15 @@ nsTAdoptingString_CharT::operator=( const self_type& str ) return *this; } +void +nsTString_CharT::Rebind( const char_type* data, size_type length ) + { + // If we currently own a buffer, release it. + Finalize(); + + mData = const_cast(data); + mLength = length; + SetDataFlags(F_TERMINATED); + AssertValidDepedentString(); + } + From 0931f880af223b92f5abf4df475d0be1877f8e05 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 4 Sep 2013 16:43:12 -0400 Subject: [PATCH 16/86] Bug 910795 part 2. Use the new Rebind() setup to avoid creating string copies for variadic string arguments. r=smaug --- content/base/src/nsDOMTokenList.cpp | 21 ++++++++++----------- dom/bindings/BindingUtils.h | 10 ++++++++++ dom/bindings/Codegen.py | 16 ++++++++++++---- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/content/base/src/nsDOMTokenList.cpp b/content/base/src/nsDOMTokenList.cpp index 5737cbe65ba7..08688dc42acf 100644 --- a/content/base/src/nsDOMTokenList.cpp +++ b/content/base/src/nsDOMTokenList.cpp @@ -140,7 +140,6 @@ nsDOMTokenList::AddInternal(const nsAttrValue* aAttr, bool oneWasAdded = false; nsAutoTArray addedClasses; - addedClasses.SetCapacity(aTokens.Length()); for (uint32_t i = 0, l = aTokens.Length(); i < l; ++i) { const nsString& aToken = aTokens[i]; @@ -180,9 +179,9 @@ nsDOMTokenList::Add(const nsTArray& aTokens, ErrorResult& aError) void nsDOMTokenList::Add(const nsAString& aToken, mozilla::ErrorResult& aError) { - nsAutoTArray aTokens; - aTokens.AppendElement(aToken); - Add(aTokens, aError); + nsAutoTArray tokens; + tokens.AppendElement(aToken); + Add(tokens, aError); } void @@ -266,9 +265,9 @@ nsDOMTokenList::Remove(const nsTArray& aTokens, ErrorResult& aError) void nsDOMTokenList::Remove(const nsAString& aToken, mozilla::ErrorResult& aError) { - nsAutoTArray aTokens; - aTokens.AppendElement(aToken); - Remove(aTokens, aError); + nsAutoTArray tokens; + tokens.AppendElement(aToken); + Remove(tokens, aError); } bool @@ -286,17 +285,17 @@ nsDOMTokenList::Toggle(const nsAString& aToken, const bool forceOff = aForce.WasPassed() && !aForce.Value(); bool isPresent = attr && attr->Contains(aToken); - nsAutoTArray aTokens; - aTokens.AppendElement(aToken); + nsAutoTArray tokens; + (*tokens.AppendElement()).Rebind(aToken.Data(), aToken.Length()); if (isPresent) { if (!forceOn) { - RemoveInternal(attr, aTokens); + RemoveInternal(attr, tokens); isPresent = false; } } else { if (!forceOff) { - AddInternal(attr, aTokens); + AddInternal(attr, tokens); isPresent = true; } } diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index a4e09b055794..c469cee47372 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -1513,6 +1513,16 @@ struct FakeDependentString { mFlags |= nsDependentString::F_VOIDED; } + const nsDependentString::char_type* Data() const + { + return mData; + } + + nsDependentString::size_type Length() const + { + return mLength; + } + // If this ever changes, change the corresponding code in the // Optional specialization as well. const nsAString* ToAStringPtr() const { diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index d1aa360775fb..cfbf934e3723 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -3396,15 +3396,23 @@ for (uint32_t i = 0; i < length; ++i) { return handleDefault(conversionCode, defaultCode) if isMember: - # We have to make a copy, because our jsval may well not - # live as long as our string needs to. + # We have to make a copy, except in the variadic case, because our + # jsval may well not live as long as our string needs to. declType = CGGeneric("nsString") + if isMember == "Variadic": + # The string is kept alive by the argument, so we can just + # depend on it. + assignString = "${declName}.Rebind(str.Data(), str.Length())" + else: + assignString = "${declName} = str" return JSToNativeConversionInfo( "{\n" " FakeDependentString str;\n" "%s\n" - " ${declName} = str;\n" - "}\n" % CGIndenter(CGGeneric(getConversionCode("str"))).define(), + " %s;\n" + "}\n" % ( + CGIndenter(CGGeneric(getConversionCode("str"))).define(), + assignString), declType=declType, dealWithOptional=isOptional) if isOptional: From a45b31c6ac9dc739024fe5ca1c619d279c10fac9 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 4 Sep 2013 16:43:12 -0400 Subject: [PATCH 17/86] Bug 911771. Remove uses of MOZ_DEBUG in .cpp files, since there is no such thing there. Use DEBUG instead. r=glandium --- content/base/src/nsContentSink.cpp | 4 ++-- layout/generic/nsSelection.cpp | 2 +- toolkit/crashreporter/nsExceptionHandler.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index ad4c1c843e09..266ee39fd3a4 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -1220,7 +1220,7 @@ nsContentSink::Notify(nsITimer *timer) return NS_OK; } -#ifdef MOZ_DEBUG +#ifdef DEBUG { PRTime now = PR_Now(); @@ -1232,7 +1232,7 @@ nsContentSink::Notify(nsITimer *timer) ("nsContentSink::Notify: reflow on a timer: %d milliseconds " "late, backoff count: %d", delay, mBackoffCount)); } -#endif +#endif // DEBUG if (WaitForPendingSheets()) { mDeferredFlushTags = true; diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 46926d061f8c..2017311f7ad4 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -92,7 +92,7 @@ static void printRange(nsRange *aDomRange); #define DEBUG_OUT_RANGE(x) printRange(x) #else #define DEBUG_OUT_RANGE(x) -#endif //MOZ_DEBUG +#endif // PRINT_RANGE diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp index 67413ff128b3..c674ce2349f8 100644 --- a/toolkit/crashreporter/nsExceptionHandler.cpp +++ b/toolkit/crashreporter/nsExceptionHandler.cpp @@ -802,7 +802,7 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory, if (gExceptionHandler) return NS_ERROR_ALREADY_INITIALIZED; -#if defined(MOZ_DEBUG) +#if defined(DEBUG) // In debug builds, disable the crash reporter by default, and allow to // enable it with the MOZ_CRASHREPORTER environment variable. const char *envvar = PR_GetEnv("MOZ_CRASHREPORTER"); From 0819e225af2424a629ff70ae7eb61cffc6cc0087 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Wed, 4 Sep 2013 13:47:24 -0700 Subject: [PATCH 18/86] Bug 859807: Request longer timeout for test_transitions_per_property.html. r=dbaron --- layout/style/test/test_transitions_per_property.html | 1 + 1 file changed, 1 insertion(+) diff --git a/layout/style/test/test_transitions_per_property.html b/layout/style/test/test_transitions_per_property.html index 079ff9bdc1eb..2d03f0660271 100644 --- a/layout/style/test/test_transitions_per_property.html +++ b/layout/style/test/test_transitions_per_property.html @@ -41,6 +41,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=435441 /** Test for Bug 435441 **/ +SimpleTest.requestLongerTimeout(2); SimpleTest.waitForExplicitFinish(); function has_num(str) From 409c5e42ea2f23d18ef023f6818d15aa182909b9 Mon Sep 17 00:00:00 2001 From: Neil Rashbrook Date: Wed, 4 Sep 2013 21:52:51 +0100 Subject: [PATCH 19/86] Bug 910899 Plugin placeholder XBL anonymous elements need anonids r=jaws --- .../mozapps/plugins/content/pluginProblem.xml | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/toolkit/mozapps/plugins/content/pluginProblem.xml b/toolkit/mozapps/plugins/content/pluginProblem.xml index a68aba2cfe5f..0546f95f859c 100644 --- a/toolkit/mozapps/plugins/content/pluginProblem.xml +++ b/toolkit/mozapps/plugins/content/pluginProblem.xml @@ -22,12 +22,12 @@ - + - + &tapToPlayPlugin; - &clickToActivatePlugin; + &clickToActivatePlugin; @@ -36,27 +36,29 @@ &disabledPlugin; &blockedPlugin.label; - + - &reloadPlugin.pre;&reloadPlugin.middle;&reloadPlugin.post; + &reloadPlugin.pre;&reloadPlugin.middle;&reloadPlugin.post; - - + + &installPlugin; &managePlugins; - + - &report.pageURL; + &report.pageURL; - + @@ -70,7 +72,7 @@ - + From f488d3c533108d436dae396d6281c6fc1ad01d0d Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Wed, 4 Sep 2013 16:53:54 -0400 Subject: [PATCH 20/86] Bug 907544 - Pass the D3DSurface9 down into Cairo for LockRect. r=jrmuizel --HG-- extra : rebase_source : 71c0f776360435d242987ffd3e2cbab8a3535c67 --- gfx/cairo/README | 2 + gfx/cairo/cairo/src/cairo-rename.h | 1 + .../cairo/src/cairo-win32-printing-surface.c | 1 + gfx/cairo/cairo/src/cairo-win32-private.h | 2 + gfx/cairo/cairo/src/cairo-win32-surface.c | 166 +++++-- gfx/cairo/cairo/src/cairo-win32.h | 5 +- gfx/cairo/win32-d3dsurface9.patch | 464 ++++++++++++++++++ gfx/layers/d3d9/ThebesLayerD3D9.cpp | 38 +- gfx/thebes/gfxWindowsSurface.cpp | 15 + gfx/thebes/gfxWindowsSurface.h | 8 +- layout/media/symbols.def.in | 1 + 11 files changed, 663 insertions(+), 40 deletions(-) create mode 100644 gfx/cairo/win32-d3dsurface9.patch diff --git a/gfx/cairo/README b/gfx/cairo/README index 4fe0e2567d1d..b27e4b2b6ffd 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -234,6 +234,8 @@ use-show-text-glyphs-if-glyph-path-fails.patch: fall back to show_text_glyphs ev pixman-enable-altivec-acceleration.patch: enable building the altivec acceleration +win32-d3dsurface9.patch: Create a win32 d3d9 surface to support LockRect + ==== disable printing patch ==== disable-printing.patch: allows us to use NS_PRINTING to disable printing. diff --git a/gfx/cairo/cairo/src/cairo-rename.h b/gfx/cairo/cairo/src/cairo-rename.h index cf7349a2635c..c44577f5062a 100644 --- a/gfx/cairo/cairo/src/cairo-rename.h +++ b/gfx/cairo/cairo/src/cairo-rename.h @@ -340,6 +340,7 @@ #define cairo_win32_scaled_font_get_metrics_factor _moz_cairo_win32_scaled_font_get_metrics_factor #define cairo_win32_scaled_font_select_font _moz_cairo_win32_scaled_font_select_font #define cairo_win32_surface_create _moz_cairo_win32_surface_create +#define cairo_win32_surface_create_with_d3dsurface9 _moz_cairo_win32_surface_create_with_d3dsurface9 #define cairo_win32_surface_create_with_ddb _moz_cairo_win32_surface_create_with_ddb #define cairo_win32_surface_create_with_dib _moz_cairo_win32_surface_create_with_dib #define cairo_win32_surface_get_dc _moz_cairo_win32_surface_get_dc diff --git a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c index be3856e263e2..8ecd003b3846 100644 --- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c @@ -1857,6 +1857,7 @@ cairo_win32_printing_surface_create (HDC hdc) surface->image = NULL; surface->format = CAIRO_FORMAT_RGB24; surface->content = CAIRO_CONTENT_COLOR_ALPHA; + surface->d3d9surface = NULL; surface->dc = hdc; surface->bitmap = NULL; diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h index 83887d909b61..44c38535fef9 100644 --- a/gfx/cairo/cairo/src/cairo-win32-private.h +++ b/gfx/cairo/cairo/src/cairo-win32-private.h @@ -59,6 +59,8 @@ typedef struct _cairo_win32_surface { HDC dc; + struct IDirect3DSurface9 *d3d9surface; + /* We create off-screen surfaces as DIBs or DDBs, based on what we created * originally*/ HBITMAP bitmap; diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c index e38f3653b187..0d038ae700ce 100644 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c @@ -59,6 +59,7 @@ #include "cairo-private.h" #include #include +#include #if defined(__MINGW32__) && !defined(ETO_PDY) # define ETO_PDY 0x2000 @@ -389,6 +390,7 @@ _cairo_win32_surface_create_for_dc (HDC original_dc, goto FAIL; surface->format = format; + surface->d3d9surface = NULL; surface->clip_rect.x = 0; surface->clip_rect.y = 0; @@ -486,6 +488,11 @@ _cairo_win32_surface_finish (void *abstract_surface) _cairo_win32_restore_initial_clip (surface); } + if (surface->d3d9surface) { + IDirect3DSurface9_ReleaseDC (surface->d3d9surface, surface->dc); + IDirect3DSurface9_Release (surface->d3d9surface); + } + if (surface->initial_clip_rgn) DeleteObject (surface->initial_clip_rgn); @@ -495,6 +502,48 @@ _cairo_win32_surface_finish (void *abstract_surface) return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +_cairo_win32_surface_d3d9_lock_rect (cairo_win32_surface_t *surface, + int x, + int y, + int width, + int height, + cairo_image_surface_t **local_out) +{ + cairo_image_surface_t *local; + cairo_int_status_t status; + + RECT rectin = { x, y, x+width, y+height }; + D3DLOCKED_RECT rectout; + HRESULT hr; + hr = IDirect3DSurface9_ReleaseDC (surface->d3d9surface, surface->dc); + hr = IDirect3DSurface9_LockRect (surface->d3d9surface, + &rectout, &rectin, 0); + surface->dc = 0; // Don't use the DC when this is locked! + if (hr) { + IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); + return CAIRO_INT_STATUS_UNSUPPORTED; + } + local = cairo_image_surface_create_for_data (rectout.pBits, + surface->format, + width, height, + rectout.Pitch); + if (local == NULL) { + IDirect3DSurface9_UnlockRect (surface->d3d9surface); + IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); + return CAIRO_INT_STATUS_UNSUPPORTED; + } + if (local->base.status) { + IDirect3DSurface9_UnlockRect (surface->d3d9surface); + IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); + return local->base.status; + } + + *local_out = local; + + return CAIRO_STATUS_SUCCESS; +} + static cairo_status_t _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface, int x, @@ -604,7 +653,6 @@ _cairo_win32_surface_acquire_source_image (void *abstract_sur void **image_extra) { cairo_win32_surface_t *surface = abstract_surface; - cairo_win32_surface_t *local; cairo_status_t status; if (!surface->image && !surface->is_dib && surface->bitmap && @@ -624,14 +672,30 @@ _cairo_win32_surface_acquire_source_image (void *abstract_sur return CAIRO_STATUS_SUCCESS; } - status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0, - surface->extents.width, - surface->extents.height, &local); - if (status) - return status; + if (surface->d3d9surface) { + cairo_image_surface_t *local; + status = _cairo_win32_surface_d3d9_lock_rect (abstract_surface, 0, 0, + surface->extents.width, + surface->extents.height, &local); + if (status) + return status; + + *image_out = local; + *image_extra = surface; + } else { + cairo_win32_surface_t *local; + status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0, + surface->extents.width, + surface->extents.height, &local); + if (status) + return status; + + *image_out = (cairo_image_surface_t *)local->image; + *image_extra = local; + } + // image_extra is always of type cairo_win32_surface_t. For d3d9surface it points + // to the original surface to get back the d3d9surface and properly unlock. - *image_out = (cairo_image_surface_t *)local->image; - *image_extra = local; return CAIRO_STATUS_SUCCESS; } @@ -640,10 +704,16 @@ _cairo_win32_surface_release_source_image (void *abstract_surf cairo_image_surface_t *image, void *image_extra) { + cairo_win32_surface_t *surface = abstract_surface; cairo_win32_surface_t *local = image_extra; - if (local) + if (local && local->d3d9surface) { + IDirect3DSurface9_UnlockRect (local->d3d9surface); + IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc); + cairo_surface_destroy ((cairo_surface_t *)image); + } else { cairo_surface_destroy ((cairo_surface_t *)local); + } } static cairo_status_t @@ -654,7 +724,6 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa void **image_extra) { cairo_win32_surface_t *surface = abstract_surface; - cairo_win32_surface_t *local = NULL; cairo_status_t status; if (surface->image) { @@ -666,17 +735,36 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa return CAIRO_STATUS_SUCCESS; } - status = _cairo_win32_surface_get_subimage (abstract_surface, + if (surface->d3d9surface) { + cairo_image_surface_t *local = NULL; + status = _cairo_win32_surface_d3d9_lock_rect (abstract_surface, interest_rect->x, interest_rect->y, interest_rect->width, - interest_rect->height, - &local); - if (status) - return status; + interest_rect->height, &local); + + if (status) + return status; + + *image_out = local; + *image_extra = surface; + } else { + cairo_win32_surface_t *local = NULL; + status = _cairo_win32_surface_get_subimage (abstract_surface, + interest_rect->x, + interest_rect->y, + interest_rect->width, + interest_rect->height, &local); + + if (status) + return status; + + *image_out = (cairo_image_surface_t *) local->image; + *image_extra = local; + } + // image_extra is always of type cairo_win32_surface_t. For d3d9surface it points + // to the original surface to get back the d3d9surface and properly unlock. - *image_out = (cairo_image_surface_t *) local->image; - *image_extra = local; *image_rect = *interest_rect; return CAIRO_STATUS_SUCCESS; } @@ -694,19 +782,27 @@ _cairo_win32_surface_release_dest_image (void *abstract_surfa if (!local) return; - /* clear any clip that's currently set on the surface - so that we can blit uninhibited. */ - _cairo_win32_surface_set_clip_region (surface, NULL); + if (local->d3d9surface) { + IDirect3DSurface9_UnlockRect (local->d3d9surface); + IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc); + cairo_surface_destroy ((cairo_surface_t *)image); + } else { - if (!BitBlt (surface->dc, - image_rect->x, image_rect->y, - image_rect->width, image_rect->height, - local->dc, - 0, 0, - SRCCOPY)) - _cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image"); + /* clear any clip that's currently set on the surface + so that we can blit uninhibited. */ + _cairo_win32_surface_set_clip_region (surface, NULL); + + if (!BitBlt (surface->dc, + image_rect->x, image_rect->y, + image_rect->width, image_rect->height, + local->dc, + 0, 0, + SRCCOPY)) + _cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image"); + + cairo_surface_destroy ((cairo_surface_t *)local); + } - cairo_surface_destroy ((cairo_surface_t *)local); } cairo_status_t @@ -1854,6 +1950,7 @@ cairo_win32_surface_create_internal (HDC hdc, cairo_format_t format) surface->image = NULL; surface->format = format; + surface->d3d9surface = NULL; surface->dc = hdc; surface->bitmap = NULL; surface->is_dib = FALSE; @@ -2014,6 +2111,19 @@ FINISH: return (cairo_surface_t*) new_surf; } +cairo_public cairo_surface_t * +cairo_win32_surface_create_with_d3dsurface9 (IDirect3DSurface9 *surface) +{ + HDC dc; + cairo_win32_surface_t *win_surface; + + IDirect3DSurface9_AddRef (surface); + IDirect3DSurface9_GetDC (surface, &dc); + win_surface = cairo_win32_surface_create_internal(dc, CAIRO_FORMAT_RGB24); + win_surface->d3d9surface = surface; + return (cairo_surface_t*) win_surface; + +} /** * _cairo_surface_is_win32: * @surface: a #cairo_surface_t diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h index 07a7557838a1..5330a954d1ac 100644 --- a/gfx/cairo/cairo/src/cairo-win32.h +++ b/gfx/cairo/cairo/src/cairo-win32.h @@ -64,7 +64,6 @@ cairo_public cairo_surface_t * cairo_win32_surface_create_with_dib (cairo_format_t format, int width, int height); - cairo_public HDC cairo_win32_surface_get_dc (cairo_surface_t *surface); @@ -148,6 +147,10 @@ cairo_dwrite_get_cleartype_rendering_mode(); #endif /* CAIRO_HAS_DWRITE_FONT */ +cairo_public cairo_surface_t * +cairo_win32_surface_create_with_d3dsurface9 (struct IDirect3DSurface9 *surface); + + #if CAIRO_HAS_D2D_SURFACE struct _cairo_device diff --git a/gfx/cairo/win32-d3dsurface9.patch b/gfx/cairo/win32-d3dsurface9.patch new file mode 100644 index 000000000000..92d0244be290 --- /dev/null +++ b/gfx/cairo/win32-d3dsurface9.patch @@ -0,0 +1,464 @@ +diff --git a/gfx/cairo/cairo/src/cairo-rename.h b/gfx/cairo/cairo/src/cairo-rename.h +--- a/gfx/cairo/cairo/src/cairo-rename.h ++++ b/gfx/cairo/cairo/src/cairo-rename.h +@@ -335,16 +335,17 @@ + #define cairo_win32_font_face_create_for_logfontw_hfont _moz_cairo_win32_font_face_create_for_logfontw_hfont + #define cairo_win32_printing_surface_create _moz_cairo_win32_printing_surface_create + #define cairo_win32_scaled_font_done_font _moz_cairo_win32_scaled_font_done_font + #define cairo_win32_scaled_font_get_device_to_logical _moz_cairo_win32_scaled_font_get_device_to_logical + #define cairo_win32_scaled_font_get_logical_to_device _moz_cairo_win32_scaled_font_get_logical_to_device + #define cairo_win32_scaled_font_get_metrics_factor _moz_cairo_win32_scaled_font_get_metrics_factor + #define cairo_win32_scaled_font_select_font _moz_cairo_win32_scaled_font_select_font + #define cairo_win32_surface_create _moz_cairo_win32_surface_create ++#define cairo_win32_surface_create_with_d3dsurface9 _moz_cairo_win32_surface_create_with_d3dsurface9 + #define cairo_win32_surface_create_with_ddb _moz_cairo_win32_surface_create_with_ddb + #define cairo_win32_surface_create_with_dib _moz_cairo_win32_surface_create_with_dib + #define cairo_win32_surface_get_dc _moz_cairo_win32_surface_get_dc + #define cairo_win32_surface_get_image _moz_cairo_win32_surface_get_image + #define cairo_xcb_surface_create _moz_cairo_xcb_surface_create + #define cairo_xcb_surface_create_for_bitmap _moz_cairo_xcb_surface_create_for_bitmap + #define cairo_xcb_surface_create_with_xrender_format _moz_cairo_xcb_surface_create_with_xrender_format + #define cairo_xcb_surface_set_size _moz_cairo_xcb_surface_set_size +diff --git a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c +--- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c ++++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c +@@ -1852,16 +1852,17 @@ cairo_win32_printing_surface_create (HDC + } + + _cairo_surface_clipper_init (&surface->clipper, + _cairo_win32_printing_surface_clipper_intersect_clip_path); + + surface->image = NULL; + surface->format = CAIRO_FORMAT_RGB24; + surface->content = CAIRO_CONTENT_COLOR_ALPHA; ++ surface->d3d9surface = NULL; + + surface->dc = hdc; + surface->bitmap = NULL; + surface->is_dib = FALSE; + surface->saved_dc_bitmap = NULL; + surface->brush = NULL; + surface->old_brush = NULL; + surface->font_subsets = _cairo_scaled_font_subsets_create_scaled (); +diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h +--- a/gfx/cairo/cairo/src/cairo-win32-private.h ++++ b/gfx/cairo/cairo/src/cairo-win32-private.h +@@ -54,16 +54,18 @@ CAIRO_BEGIN_DECLS + + typedef struct _cairo_win32_surface { + cairo_surface_t base; + + cairo_format_t format; + + HDC dc; + ++ struct IDirect3DSurface9 *d3d9surface; ++ + /* We create off-screen surfaces as DIBs or DDBs, based on what we created + * originally*/ + HBITMAP bitmap; + cairo_bool_t is_dib; + + /* Used to save the initial 1x1 monochrome bitmap for the DC to + * select back into the DC before deleting the DC and our + * bitmap. For Windows XP, this doesn't seem to be necessary +diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c +--- a/gfx/cairo/cairo/src/cairo-win32-surface.c ++++ b/gfx/cairo/cairo/src/cairo-win32-surface.c +@@ -54,16 +54,17 @@ + #include "cairo-win32-private.h" + #include "cairo-scaled-font-subsets-private.h" + #include "cairo-surface-fallback-private.h" + #include "cairo-surface-clipper-private.h" + #include "cairo-gstate-private.h" + #include "cairo-private.h" + #include + #include ++#include + + #if defined(__MINGW32__) && !defined(ETO_PDY) + # define ETO_PDY 0x2000 + #endif + + #undef DEBUG_COMPOSITE + + /* for older SDKs */ +@@ -384,16 +385,17 @@ static cairo_surface_t * + + surface->image = cairo_image_surface_create_for_data (bits, format, + width, height, rowstride); + status = surface->image->status; + if (status) + goto FAIL; + + surface->format = format; ++ surface->d3d9surface = NULL; + + surface->clip_rect.x = 0; + surface->clip_rect.y = 0; + surface->clip_rect.width = width; + surface->clip_rect.height = height; + + surface->initial_clip_rgn = NULL; + surface->had_simple_clip = FALSE; +@@ -481,26 +483,73 @@ cairo_status_t + if (surface->bitmap) { + SelectObject (surface->dc, surface->saved_dc_bitmap); + DeleteObject (surface->bitmap); + DeleteDC (surface->dc); + } else { + _cairo_win32_restore_initial_clip (surface); + } + ++ if (surface->d3d9surface) { ++ IDirect3DSurface9_ReleaseDC (surface->d3d9surface, surface->dc); ++ IDirect3DSurface9_Release (surface->d3d9surface); ++ } ++ + if (surface->initial_clip_rgn) + DeleteObject (surface->initial_clip_rgn); + + if (surface->font_subsets != NULL) + _cairo_scaled_font_subsets_destroy (surface->font_subsets); + + return CAIRO_STATUS_SUCCESS; + } + + static cairo_status_t ++_cairo_win32_surface_d3d9_lock_rect (cairo_win32_surface_t *surface, ++ int x, ++ int y, ++ int width, ++ int height, ++ cairo_image_surface_t **local_out) ++{ ++ cairo_image_surface_t *local; ++ cairo_int_status_t status; ++ ++ RECT rectin = { x, y, x+width, y+height }; ++ D3DLOCKED_RECT rectout; ++ HRESULT hr; ++ hr = IDirect3DSurface9_ReleaseDC (surface->d3d9surface, surface->dc); ++ hr = IDirect3DSurface9_LockRect (surface->d3d9surface, ++ &rectout, &rectin, 0); ++ surface->dc = 0; // Don't use the DC when this is locked! ++ if (hr) { ++ IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); ++ return CAIRO_INT_STATUS_UNSUPPORTED; ++ } ++ local = cairo_image_surface_create_for_data (rectout.pBits, ++ surface->format, ++ width, height, ++ rectout.Pitch); ++ if (local == NULL) { ++ IDirect3DSurface9_UnlockRect (surface->d3d9surface); ++ IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); ++ return CAIRO_INT_STATUS_UNSUPPORTED; ++ } ++ if (local->base.status) { ++ IDirect3DSurface9_UnlockRect (surface->d3d9surface); ++ IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc); ++ return local->base.status; ++ } ++ ++ *local_out = local; ++ ++ return CAIRO_STATUS_SUCCESS; ++} ++ ++static cairo_status_t + _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface, + int x, + int y, + int width, + int height, + cairo_win32_surface_t **local_out) + { + cairo_win32_surface_t *local; +@@ -599,17 +648,16 @@ static void + } + + static cairo_status_t + _cairo_win32_surface_acquire_source_image (void *abstract_surface, + cairo_image_surface_t **image_out, + void **image_extra) + { + cairo_win32_surface_t *surface = abstract_surface; +- cairo_win32_surface_t *local; + cairo_status_t status; + + if (!surface->image && !surface->is_dib && surface->bitmap && + (surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0) + { + /* This is a DDB, and we're being asked to use it as a source for + * something that we couldn't support natively. So turn it into + * a DIB, so that we have an equivalent image surface, as long +@@ -619,69 +667,109 @@ static cairo_status_t + } + + if (surface->image) { + *image_out = (cairo_image_surface_t *)surface->image; + *image_extra = NULL; + return CAIRO_STATUS_SUCCESS; + } + +- status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0, +- surface->extents.width, +- surface->extents.height, &local); +- if (status) +- return status; +- +- *image_out = (cairo_image_surface_t *)local->image; +- *image_extra = local; ++ if (surface->d3d9surface) { ++ cairo_image_surface_t *local; ++ status = _cairo_win32_surface_d3d9_lock_rect (abstract_surface, 0, 0, ++ surface->extents.width, ++ surface->extents.height, &local); ++ if (status) ++ return status; ++ ++ *image_out = local; ++ *image_extra = surface; ++ } else { ++ cairo_win32_surface_t *local; ++ status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0, ++ surface->extents.width, ++ surface->extents.height, &local); ++ if (status) ++ return status; ++ ++ *image_out = (cairo_image_surface_t *)local->image; ++ *image_extra = local; ++ } ++ // image_extra is always of type cairo_win32_surface_t. For d3d9surface it points ++ // to the original surface to get back the d3d9surface and properly unlock. ++ + return CAIRO_STATUS_SUCCESS; + } + + static void + _cairo_win32_surface_release_source_image (void *abstract_surface, + cairo_image_surface_t *image, + void *image_extra) + { ++ cairo_win32_surface_t *surface = abstract_surface; + cairo_win32_surface_t *local = image_extra; + +- if (local) ++ if (local && local->d3d9surface) { ++ IDirect3DSurface9_UnlockRect (local->d3d9surface); ++ IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc); ++ cairo_surface_destroy ((cairo_surface_t *)image); ++ } else { + cairo_surface_destroy ((cairo_surface_t *)local); ++ } + } + + static cairo_status_t + _cairo_win32_surface_acquire_dest_image (void *abstract_surface, + cairo_rectangle_int_t *interest_rect, + cairo_image_surface_t **image_out, + cairo_rectangle_int_t *image_rect, + void **image_extra) + { + cairo_win32_surface_t *surface = abstract_surface; +- cairo_win32_surface_t *local = NULL; + cairo_status_t status; + + if (surface->image) { + GdiFlush(); + + *image_out = (cairo_image_surface_t *) surface->image; + *image_extra = NULL; + *image_rect = surface->extents; + return CAIRO_STATUS_SUCCESS; + } + +- status = _cairo_win32_surface_get_subimage (abstract_surface, ++ if (surface->d3d9surface) { ++ cairo_image_surface_t *local = NULL; ++ status = _cairo_win32_surface_d3d9_lock_rect (abstract_surface, + interest_rect->x, + interest_rect->y, + interest_rect->width, +- interest_rect->height, +- &local); +- if (status) +- return status; +- +- *image_out = (cairo_image_surface_t *) local->image; +- *image_extra = local; ++ interest_rect->height, &local); ++ ++ if (status) ++ return status; ++ ++ *image_out = local; ++ *image_extra = surface; ++ } else { ++ cairo_win32_surface_t *local = NULL; ++ status = _cairo_win32_surface_get_subimage (abstract_surface, ++ interest_rect->x, ++ interest_rect->y, ++ interest_rect->width, ++ interest_rect->height, &local); ++ ++ if (status) ++ return status; ++ ++ *image_out = (cairo_image_surface_t *) local->image; ++ *image_extra = local; ++ } ++ // image_extra is always of type cairo_win32_surface_t. For d3d9surface it points ++ // to the original surface to get back the d3d9surface and properly unlock. ++ + *image_rect = *interest_rect; + return CAIRO_STATUS_SUCCESS; + } + + static void + _cairo_win32_surface_release_dest_image (void *abstract_surface, + cairo_rectangle_int_t *interest_rect, + cairo_image_surface_t *image, +@@ -689,29 +777,37 @@ static void + void *image_extra) + { + cairo_win32_surface_t *surface = abstract_surface; + cairo_win32_surface_t *local = image_extra; + + if (!local) + return; + +- /* clear any clip that's currently set on the surface +- so that we can blit uninhibited. */ +- _cairo_win32_surface_set_clip_region (surface, NULL); +- +- if (!BitBlt (surface->dc, +- image_rect->x, image_rect->y, +- image_rect->width, image_rect->height, +- local->dc, +- 0, 0, +- SRCCOPY)) +- _cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image"); +- +- cairo_surface_destroy ((cairo_surface_t *)local); ++ if (local->d3d9surface) { ++ IDirect3DSurface9_UnlockRect (local->d3d9surface); ++ IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc); ++ cairo_surface_destroy ((cairo_surface_t *)image); ++ } else { ++ ++ /* clear any clip that's currently set on the surface ++ so that we can blit uninhibited. */ ++ _cairo_win32_surface_set_clip_region (surface, NULL); ++ ++ if (!BitBlt (surface->dc, ++ image_rect->x, image_rect->y, ++ image_rect->width, image_rect->height, ++ local->dc, ++ 0, 0, ++ SRCCOPY)) ++ _cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image"); ++ ++ cairo_surface_destroy ((cairo_surface_t *)local); ++ } ++ + } + + cairo_status_t + _cairo_win32_surface_set_clip_region (void *abstract_surface, + cairo_region_t *region) + { + cairo_win32_surface_t *surface = abstract_surface; + cairo_status_t status = CAIRO_STATUS_SUCCESS; +@@ -1849,16 +1945,17 @@ cairo_win32_surface_create_internal (HDC + free (surface); + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + } + + surface->clip_region = NULL; + surface->image = NULL; + surface->format = format; + ++ surface->d3d9surface = NULL; + surface->dc = hdc; + surface->bitmap = NULL; + surface->is_dib = FALSE; + surface->saved_dc_bitmap = NULL; + surface->brush = NULL; + surface->old_brush = NULL; + surface->font_subsets = NULL; + +@@ -2009,16 +2106,29 @@ cairo_win32_surface_create_with_ddb (HDC + + FINISH: + if (screen_dc) + ReleaseDC (NULL, screen_dc); + + return (cairo_surface_t*) new_surf; + } + ++cairo_public cairo_surface_t * ++cairo_win32_surface_create_with_d3dsurface9 (IDirect3DSurface9 *surface) ++{ ++ HDC dc; ++ cairo_win32_surface_t *win_surface; ++ ++ IDirect3DSurface9_AddRef (surface); ++ IDirect3DSurface9_GetDC (surface, &dc); ++ win_surface = cairo_win32_surface_create_internal(dc, CAIRO_FORMAT_RGB24); ++ win_surface->d3d9surface = surface; ++ return (cairo_surface_t*) win_surface; ++ ++} + /** + * _cairo_surface_is_win32: + * @surface: a #cairo_surface_t + * + * Checks if a surface is a win32 surface. This will + * return False if this is a win32 printing surface; use + * _cairo_surface_is_win32_printing() to check for that. + * +diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h +--- a/gfx/cairo/cairo/src/cairo-win32.h ++++ b/gfx/cairo/cairo/src/cairo-win32.h +@@ -59,17 +59,16 @@ cairo_win32_surface_create_with_ddb (HDC + cairo_format_t format, + int width, + int height); + + cairo_public cairo_surface_t * + cairo_win32_surface_create_with_dib (cairo_format_t format, + int width, + int height); +- + cairo_public HDC + cairo_win32_surface_get_dc (cairo_surface_t *surface); + + cairo_public HDC + cairo_win32_get_dc_with_clip (cairo_t *cr); + + cairo_public cairo_surface_t * + cairo_win32_surface_get_image (cairo_surface_t *surface); +@@ -143,16 +142,20 @@ cairo_dwrite_scaled_font_get_force_GDI_c + void + cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode); + + int + cairo_dwrite_get_cleartype_rendering_mode(); + + #endif /* CAIRO_HAS_DWRITE_FONT */ + ++cairo_public cairo_surface_t * ++cairo_win32_surface_create_with_d3dsurface9 (struct IDirect3DSurface9 *surface); ++ ++ + #if CAIRO_HAS_D2D_SURFACE + + struct _cairo_device + { + int type; + int refcount; + }; + diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index 906475f5d768..01efe8dc74a1 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -343,7 +343,7 @@ ThebesLayerD3D9::VerifyContentType(SurfaceMode aMode) class OpaqueRenderer { public: OpaqueRenderer(const nsIntRegion& aUpdateRegion) : - mUpdateRegion(aUpdateRegion), mDC(nullptr) {} + mUpdateRegion(aUpdateRegion) {} ~OpaqueRenderer() { End(); } already_AddRefed Begin(LayerD3D9* aLayer); void End(); @@ -353,7 +353,7 @@ private: const nsIntRegion& mUpdateRegion; nsRefPtr mTmpTexture; nsRefPtr mSurface; - HDC mDC; + nsRefPtr mD3D9ThebesSurface; }; already_AddRefed @@ -378,24 +378,32 @@ OpaqueRenderer::Begin(LayerD3D9* aLayer) return nullptr; } - hr = mSurface->GetDC(&mDC); - if (FAILED(hr)) { - NS_WARNING("Failed to get device context for texture surface."); + nsRefPtr result = new gfxWindowsSurface(mSurface); + if (!result) { + NS_WARNING("Failed to d3d9 cairo surface."); return nullptr; } + mD3D9ThebesSurface = result; - nsRefPtr result = new gfxWindowsSurface(mDC); return result.forget(); } void OpaqueRenderer::End() { - if (mSurface && mDC) { - mSurface->ReleaseDC(mDC); - mSurface = nullptr; - mDC = nullptr; + mSurface = nullptr; + // gfxWindowsSurface returned from ::Begin() should be released before the + // texture is used. This will assert that this is the case +#if 1 + if (mD3D9ThebesSurface) { + mD3D9ThebesSurface->AddRef(); + nsrefcnt c = mD3D9ThebesSurface->Release(); + if (c != 1) + NS_RUNTIMEABORT("Reference mD3D9ThebesSurface must be released by caller of Begin() before calling End()"); } +#endif + mD3D9ThebesSurface = nullptr; + } static void @@ -503,11 +511,16 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode, } } + // Release the cairo d3d9 surface before we try to composite it + context = nullptr; + nsAutoTArray srcTextures; nsAutoTArray destTextures; switch (aMode) { case SURFACE_OPAQUE: + // Must release reference to dest surface before ending drawing + destinationSurface = nullptr; opaqueRenderer.End(); srcTextures.AppendElement(opaqueRenderer.GetTexture()); destTextures.AppendElement(mTexture); @@ -535,6 +548,8 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode, context->Paint(); } + // Must release reference to dest surface before ending drawing + destinationSurface = nullptr; imgSurface = nullptr; srcTextures.AppendElement(tmpTexture); @@ -543,6 +558,8 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode, } case SURFACE_COMPONENT_ALPHA: { + // Must release reference to dest surface before ending drawing + destinationSurface = nullptr; opaqueRenderer.End(); opaqueRendererOnWhite.End(); srcTextures.AppendElement(opaqueRenderer.GetTexture()); @@ -553,6 +570,7 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode, } } NS_ASSERTION(srcTextures.Length() == destTextures.Length(), "Mismatched lengths"); + // Copy to the texture. for (uint32_t i = 0; i < srcTextures.Length(); ++i) { diff --git a/gfx/thebes/gfxWindowsSurface.cpp b/gfx/thebes/gfxWindowsSurface.cpp index 0fe3ee969f88..b94070975cc3 100644 --- a/gfx/thebes/gfxWindowsSurface.cpp +++ b/gfx/thebes/gfxWindowsSurface.cpp @@ -34,6 +34,14 @@ gfxWindowsSurface::gfxWindowsSurface(HDC dc, uint32_t flags) : InitWithDC(flags); } +gfxWindowsSurface::gfxWindowsSurface(IDirect3DSurface9 *surface, uint32_t flags) : + mOwnsDC(false), mForPrinting(false), mDC(0), mWnd(nullptr) +{ + cairo_surface_t *surf = cairo_win32_surface_create_with_d3dsurface9(surface); + Init(surf); +} + + void gfxWindowsSurface::MakeInvalid(gfxIntSize& size) { @@ -161,6 +169,13 @@ gfxWindowsSurface::GetDCWithClip(gfxContext *ctx) return cairo_win32_get_dc_with_clip (ctx->GetCairo()); } +HDC +gfxWindowsSurface::GetDC() +{ + return cairo_win32_surface_get_dc (CairoSurface()); +} + + already_AddRefed gfxWindowsSurface::GetAsImageSurface() { diff --git a/gfx/thebes/gfxWindowsSurface.h b/gfx/thebes/gfxWindowsSurface.h index 1e8cc92627f9..1bb6cd838573 100644 --- a/gfx/thebes/gfxWindowsSurface.h +++ b/gfx/thebes/gfxWindowsSurface.h @@ -11,6 +11,9 @@ /* include windows.h for the HWND and HDC definitions that we need. */ #include + +struct IDirect3DSurface9; + /* undefine LoadImage because our code uses that name */ #undef LoadImage @@ -27,6 +30,9 @@ public: gfxWindowsSurface(HWND wnd, uint32_t flags = 0); gfxWindowsSurface(HDC dc, uint32_t flags = 0); + // Create from a shared d3d9surface + gfxWindowsSurface(IDirect3DSurface9 *surface, uint32_t flags = 0); + // Create a DIB surface gfxWindowsSurface(const gfxIntSize& size, gfxImageFormat imageFormat = ImageFormatRGB24); @@ -45,7 +51,7 @@ public: virtual ~gfxWindowsSurface(); - HDC GetDC() { return mDC; } + HDC GetDC(); HDC GetDCWithClip(gfxContext *); diff --git a/layout/media/symbols.def.in b/layout/media/symbols.def.in index 120c0257de5e..34e99c7771bc 100644 --- a/layout/media/symbols.def.in +++ b/layout/media/symbols.def.in @@ -476,6 +476,7 @@ _moz_cairo_win32_font_face_create_for_logfontw_hfont _moz_cairo_win32_printing_surface_create _moz_cairo_win32_scaled_font_select_font _moz_cairo_win32_surface_create +_moz_cairo_win32_surface_create_with_d3dsurface9 _moz_cairo_win32_surface_create_with_ddb _moz_cairo_win32_surface_create_with_dib _moz_cairo_win32_surface_get_dc From ff55e5d0b4b0f01794f1210d6d657093e28127d0 Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Wed, 4 Sep 2013 17:01:02 -0400 Subject: [PATCH 21/86] bug 912582 - false start rc4 and rsa accomodations need exact principal matches r=dkeeler --- netwerk/protocol/http/nsHttpChannel.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 3b66e859ea31..3a5e6de10bf5 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -724,14 +724,17 @@ nsHttpChannel::RetrieveSSLOptions() return; uint32_t perm; - nsresult rv = permMgr->TestPermissionFromPrincipal(principal, - "falsestart-rsa", &perm); + nsresult rv = permMgr->TestExactPermissionFromPrincipal(principal, + "falsestart-rsa", + &perm); if (NS_SUCCEEDED(rv) && perm == nsIPermissionManager::ALLOW_ACTION) { LOG(("nsHttpChannel::RetrieveSSLOptions [this=%p] " "falsestart-rsa permission found\n", this)); mCaps |= NS_HTTP_ALLOW_RSA_FALSESTART; } - rv = permMgr->TestPermissionFromPrincipal(principal, "falsestart-rc4", &perm); + rv = permMgr->TestExactPermissionFromPrincipal(principal, + "falsestart-rc4", + &perm); if (NS_SUCCEEDED(rv) && perm == nsIPermissionManager::ALLOW_ACTION) { LOG(("nsHttpChannel::RetrieveSSLOptions [this=%p] " "falsestart-rc4 permission found\n", this)); From 89ee39c30da013ca21c7716bd874638226204302 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Wed, 4 Sep 2013 17:01:48 -0400 Subject: [PATCH 22/86] Bug 912450: remove WEBRTC_EXPORT to avoid exporting webrtc symbols from xul.dll r=ted --- media/webrtc/trunk/webrtc/build/common.gypi | 1 - 1 file changed, 1 deletion(-) diff --git a/media/webrtc/trunk/webrtc/build/common.gypi b/media/webrtc/trunk/webrtc/build/common.gypi index a5e18c84d6fa..5b8a0761926d 100644 --- a/media/webrtc/trunk/webrtc/build/common.gypi +++ b/media/webrtc/trunk/webrtc/build/common.gypi @@ -325,7 +325,6 @@ ['OS=="win"', { 'defines': [ 'WEBRTC_WIN', - 'WEBRTC_EXPORT', ], # TODO(andrew): enable all warnings when possible. # TODO(phoglund): get rid of 4373 supression when From 7367a3a5b867c266d3206e90b0fae5ea76d6d6a0 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:54 -0700 Subject: [PATCH 23/86] Bug 899367 - Only use JSOPTION_UNROOTED_GLOBAL for DOM JSContexts. r=mccr8 We don't cycle collect any other kind, so there's no difference between marking them gray and letting the JS engine mark them black. This also gets rid of that nasty code which reset the flag, which billm theorizes has to do with faulty logic in ContextHolder when creating ephemeral sandbox cxes. The assertion in this patch should catch us if anything goes wrong. --- dom/base/nsJSEnvironment.cpp | 3 ++- dom/workers/RuntimeService.cpp | 3 +-- js/xpconnect/src/XPCJSRuntime.cpp | 2 +- xpcom/base/CycleCollectedJSRuntime.cpp | 31 +++++--------------------- xpcom/base/CycleCollectedJSRuntime.h | 5 +---- 5 files changed, 11 insertions(+), 33 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index f128832b7f14..ab87ddd64aac 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -851,7 +851,8 @@ nsJSContext::nsJSContext(bool aGCOnDestruction, ++sContextCount; - mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS; + mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS | + JSOPTION_UNROOTED_GLOBAL; mContext = ::JS_NewContext(sRuntime, gStackSize); if (mContext) { diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 8c342c4b4d8c..df60c974fbc9 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -831,8 +831,7 @@ public: // call to JS_SetGCParameter inside CreateJSContextForWorker. WorkerJSRuntime(WorkerPrivate* aWorkerPrivate) : CycleCollectedJSRuntime(WORKER_DEFAULT_RUNTIME_HEAPSIZE, - JS_NO_HELPER_THREADS, - false), + JS_NO_HELPER_THREADS), mWorkerPrivate(aWorkerPrivate) { // We need to ensure that a JSContext outlives the cycle collector, and diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 59a2be26a8f9..02c3a6cd93bc 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -2874,7 +2874,7 @@ SourceHook(JSContext *cx, JS::Handle script, jschar **src, } XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) - : CycleCollectedJSRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS, true), + : CycleCollectedJSRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS), mJSContextStack(new XPCJSContextStack()), mCallContext(nullptr), mAutoRoots(nullptr), diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 1b0587687ca4..219f50e9bcce 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -475,12 +475,10 @@ NoteJSChildGrayWrapperShim(void* aData, void* aThing) static const JSZoneParticipant sJSZoneCycleCollectorGlobal; CycleCollectedJSRuntime::CycleCollectedJSRuntime(uint32_t aMaxbytes, - JSUseHelperThreads aUseHelperThreads, - bool aExpectUnrootedGlobals) + JSUseHelperThreads aUseHelperThreads) : mGCThingCycleCollectorGlobal(sGCThingCycleCollectorGlobal), mJSZoneCycleCollectorGlobal(sJSZoneCycleCollectorGlobal), - mJSRuntime(nullptr), - mExpectUnrootedGlobals(aExpectUnrootedGlobals) + mJSRuntime(nullptr) #ifdef DEBUG , mObjectToUnlink(nullptr) #endif @@ -545,7 +543,10 @@ CycleCollectedJSRuntime::MaybeTraceGlobals(JSTracer* aTracer) const { JSContext* iter = nullptr; while (JSContext* acx = JS_ContextIterator(Runtime(), &iter)) { - MOZ_ASSERT(js::HasUnrootedGlobal(acx) == mExpectUnrootedGlobals); + // DOM JSContexts are the only JSContexts that cycle-collect their default + // compartment object, so they're the only ones that we need to do the + // JSOPTION_UNROOTED_GLOBAL dance for. The other ones are just marked black. + MOZ_ASSERT(js::HasUnrootedGlobal(acx) == !!GetScriptContextFromJSContext(acx)); if (!js::HasUnrootedGlobal(acx)) { continue; } @@ -1187,21 +1188,7 @@ CycleCollectedJSRuntime::OnGC(JSGCStatus aStatus) { switch (aStatus) { case JSGC_BEGIN: - { - // XXXkhuey do we still need this? - // We seem to sometime lose the unrooted global flag. Restore it - // here. FIXME: bug 584495. - if (mExpectUnrootedGlobals){ - JSContext* iter = nullptr; - while (JSContext* acx = JS_ContextIterator(Runtime(), &iter)) { - if (!js::HasUnrootedGlobal(acx)) { - JS_ToggleOptions(acx, JSOPTION_UNROOTED_GLOBAL); - } - } - } - break; - } case JSGC_END: { /* @@ -1230,11 +1217,5 @@ CycleCollectedJSRuntime::OnGC(JSGCStatus aStatus) bool CycleCollectedJSRuntime::OnContext(JSContext* aCx, unsigned aOperation) { - if (mExpectUnrootedGlobals && aOperation == JSCONTEXT_NEW) { - // XXXkhuey bholley is going to make this go away, but for now XPConnect - // needs it. - JS_ToggleOptions(aCx, JSOPTION_UNROOTED_GLOBAL); - } - return CustomContextCallback(aCx, aOperation); } diff --git a/xpcom/base/CycleCollectedJSRuntime.h b/xpcom/base/CycleCollectedJSRuntime.h index d8ed35c38652..d317e0efb4b3 100644 --- a/xpcom/base/CycleCollectedJSRuntime.h +++ b/xpcom/base/CycleCollectedJSRuntime.h @@ -83,8 +83,7 @@ class CycleCollectedJSRuntime friend class IncrementalFinalizeRunnable; protected: CycleCollectedJSRuntime(uint32_t aMaxbytes, - JSUseHelperThreads aUseHelperThreads, - bool aExpectUnrootedGlobals); + JSUseHelperThreads aUseHelperThreads); virtual ~CycleCollectedJSRuntime(); size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; @@ -223,8 +222,6 @@ private: nsRefPtr mFinalizeRunnable; - bool mExpectUnrootedGlobals; - #ifdef DEBUG void* mObjectToUnlink; #endif From b239d46a8b012030c1108c54d8dee3a5a130bdc1 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:54 -0700 Subject: [PATCH 24/86] Bug 899367 - Add an API to determine if we're marking gray. r=billm This allows us to assert that certain callbacks get invoked during the gray phase of a marking GC. --- js/src/jsapi.cpp | 9 +++++++++ js/src/jsapi.h | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 88b5aa9ad21d..28e89ff3190b 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2379,6 +2379,15 @@ JS_IsGCMarkingTracer(JSTracer *trc) return IS_GC_MARKING_TRACER(trc); } +#ifdef DEBUG +extern JS_PUBLIC_API(bool) +JS_IsMarkingGray(JSTracer *trc) +{ + JS_ASSERT(JS_IsGCMarkingTracer(trc)); + return trc->callback == GCMarker::GrayCallback; +} +#endif + JS_PUBLIC_API(void) JS_GC(JSRuntime *rt) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 4dce3f78cfbf..d3229ed00f4c 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2210,6 +2210,12 @@ JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb); extern JS_PUBLIC_API(bool) JS_IsGCMarkingTracer(JSTracer *trc); +/* For assertions only. */ +#ifdef DEBUG +extern JS_PUBLIC_API(bool) +JS_IsMarkingGray(JSTracer *trc); +#endif + /* * JS_IsAboutToBeFinalized checks if the given object is going to be finalized * at the end of the current GC. When called outside of the context of a GC, From 6188191d877f5135730818fdd6e82787a00daa97 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:54 -0700 Subject: [PATCH 25/86] Bug 899367 - Explicitly trace outer windows, rather than doing it via JSContext iteration. r=mccr8 --- dom/base/nsJSEnvironment.cpp | 15 +++++++++++++++ dom/base/nsJSEnvironment.h | 11 +++++++++++ js/xpconnect/src/XPCJSRuntime.cpp | 4 ++++ xpcom/base/CycleCollectedJSRuntime.cpp | 22 ---------------------- xpcom/base/CycleCollectedJSRuntime.h | 3 --- 5 files changed, 30 insertions(+), 25 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index ab87ddd64aac..659a71c5d040 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2940,6 +2940,21 @@ mozilla::dom::ShutdownJSEnvironment() sDidShutdown = true; } +void +mozilla::dom::TraceOuterWindows(JSTracer* aTracer) +{ + MOZ_ASSERT_IF(JS_IsGCMarkingTracer(aTracer), JS_IsMarkingGray(aTracer)); + for (nsJSContext* cx = sContextList; cx; cx = cx->mNext) { + JSObject* outer; + if (cx->mContext && + (outer = js::DefaultObjectForContextOrNull(cx->mContext))) + { + JS::AssertGCThingMustBeTenured(outer); + JS_CallObjectTracer(aTracer, &outer, "Outer Window"); + } + } +} + // A fast-array class for JS. This class supports both nsIJSScriptArray and // nsIArray. If it is JS itself providing and consuming this class, all work // can be done via nsIJSScriptArray, and avoid the conversion of elements diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index 20aaf87cc28f..6c46f981c452 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -29,6 +29,14 @@ template class Maybe; // a page) and doing the actual GC. #define NS_GC_DELAY 4000 // ms +namespace mozilla { +namespace dom { + +void TraceOuterWindows(JSTracer *aTracer); + +} /* namespace dom */ +} /* namespace mozilla */ + class nsJSContext : public nsIScriptContext { public: @@ -172,6 +180,9 @@ private: nsJSContext *mNext; nsJSContext **mPrev; + /* This function needs access to the linked list members above. */ + friend void mozilla::dom::TraceOuterWindows(JSTracer *aTracer); + // mGlobalObjectRef ensures that the outer window stays alive as long as the // context does. It is eventually collected by the cycle collector. nsCOMPtr mGlobalObjectRef; diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 02c3a6cd93bc..e1a70a460b2f 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -496,6 +496,10 @@ void XPCJSRuntime::TraceAdditionalNativeGrayRoots(JSTracer *trc) { XPCAutoLock lock(mMapLock); + // Trace outer windows, which are the default compartment objects for DOM + // JSContexts. + dom::TraceOuterWindows(trc); + XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(trc, this); for (XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 219f50e9bcce..afb13e44c632 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -538,26 +538,6 @@ CycleCollectedJSRuntime::UnmarkSkippableJSHolders() mJSHolders.Enumerate(UnmarkJSHolder, nullptr); } -void -CycleCollectedJSRuntime::MaybeTraceGlobals(JSTracer* aTracer) const -{ - JSContext* iter = nullptr; - while (JSContext* acx = JS_ContextIterator(Runtime(), &iter)) { - // DOM JSContexts are the only JSContexts that cycle-collect their default - // compartment object, so they're the only ones that we need to do the - // JSOPTION_UNROOTED_GLOBAL dance for. The other ones are just marked black. - MOZ_ASSERT(js::HasUnrootedGlobal(acx) == !!GetScriptContextFromJSContext(acx)); - if (!js::HasUnrootedGlobal(acx)) { - continue; - } - - if (JSObject* global = js::DefaultObjectForContextOrNull(acx)) { - JS::AssertGCThingMustBeTenured(global); - JS_CallObjectTracer(aTracer, &global, "Global Object"); - } - } -} - void CycleCollectedJSRuntime::DescribeGCThing(bool aIsMarked, void* aThing, JSGCTraceKind aTraceKind, @@ -840,8 +820,6 @@ TraceJSHolder(void* aHolder, nsScriptObjectTracer*& aTracer, void* aArg) void CycleCollectedJSRuntime::TraceNativeGrayRoots(JSTracer* aTracer) { - MaybeTraceGlobals(aTracer); - // NB: This is here just to preserve the existing XPConnect order. I doubt it // would hurt to do this after the JS holders. TraceAdditionalNativeGrayRoots(aTracer); diff --git a/xpcom/base/CycleCollectedJSRuntime.h b/xpcom/base/CycleCollectedJSRuntime.h index d317e0efb4b3..339fc432dc0c 100644 --- a/xpcom/base/CycleCollectedJSRuntime.h +++ b/xpcom/base/CycleCollectedJSRuntime.h @@ -146,9 +146,6 @@ private: void TraverseNativeRoots(nsCycleCollectionNoteRootCallback& aCb); - void MaybeTraceGlobals(JSTracer* aTracer) const; - - static void TraceBlackJS(JSTracer* aTracer, void* aData); static void TraceGrayJS(JSTracer* aTracer, void* aData); static void GCCallback(JSRuntime* aRuntime, JSGCStatus aStatus, void* aData); From d4eab5f3afb61955ed2d13be9e8e1a37e70c382f Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:54 -0700 Subject: [PATCH 26/86] Bug 899367 - Explicitly traverse outer windows, rather than doing it via JSContext iteration. r=mccr8 Note that this machinery will go away in further patches. But we want to be deliberate about each of these steps. --- dom/base/nsJSEnvironment.cpp | 17 +++++++++++++++++ dom/base/nsJSEnvironment.h | 3 +++ js/xpconnect/src/XPCJSRuntime.cpp | 4 ++++ xpcom/base/CycleCollectedJSRuntime.cpp | 23 ----------------------- xpcom/base/CycleCollectedJSRuntime.h | 2 -- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 659a71c5d040..5fb6d9418b98 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -79,7 +79,9 @@ #include "mozilla/dom/BindingUtils.h" #include "mozilla/Attributes.h" #include "mozilla/dom/CanvasRenderingContext2DBinding.h" +#include "mozilla/CycleCollectedJSRuntime.h" +#include "nsCycleCollectionNoteRootCallback.h" #include "GeckoProfiler.h" using namespace mozilla; @@ -2955,6 +2957,21 @@ mozilla::dom::TraceOuterWindows(JSTracer* aTracer) } } +void +mozilla::dom::TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb) +{ + nsCycleCollectionParticipant* participant = mozilla::CycleCollectedJSRuntime::JSContextParticipant(); + for (nsJSContext* cx = sContextList; cx; cx = cx->mNext) { + JSObject* outer; + if (cx->mContext && + (outer = js::DefaultObjectForContextOrNull(cx->mContext)) && + xpc_IsGrayGCThing(outer)) + { + aCb.NoteNativeRoot(cx->mContext, participant); + } + } +} + // A fast-array class for JS. This class supports both nsIJSScriptArray and // nsIArray. If it is JS itself providing and consuming this class, all work // can be done via nsIJSScriptArray, and avoid the conversion of elements diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index 6c46f981c452..b200347a522f 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -20,6 +20,7 @@ class nsICycleCollectorListener; class nsIXPConnectJSObjectHolder; class nsRootedJSValueArray; class nsScriptNameSpaceManager; +class nsCycleCollectionNoteRootCallback; namespace mozilla { template class Maybe; @@ -33,6 +34,7 @@ namespace mozilla { namespace dom { void TraceOuterWindows(JSTracer *aTracer); +void TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb); } /* namespace dom */ } /* namespace mozilla */ @@ -182,6 +184,7 @@ private: /* This function needs access to the linked list members above. */ friend void mozilla::dom::TraceOuterWindows(JSTracer *aTracer); + friend void mozilla::dom::TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb); // mGlobalObjectRef ensures that the outer window stays alive as long as the // context does. It is eventually collected by the cycle collector. diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index e1a70a460b2f..736a379ae222 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -561,6 +561,10 @@ XPCJSRuntime::TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback &c { XPCAutoLock lock(mMapLock); + // Traverse outer windows, which are the default compartment objects for DOM + // JSContexts. + dom::TraverseOuterWindows(cb); + XPCWrappedNativeScope::SuspectAllWrappers(this, cb); for (XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) { diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index afb13e44c632..5a46af9ca63f 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -715,32 +715,9 @@ CycleCollectedJSRuntime::TraverseObjectShim(void* aData, void* aThing) JSTRACE_OBJECT, closure->cb); } -// For all JS objects that are held by native objects but aren't held -// through rooting or locking, we need to add all the native objects that -// hold them so that the JS objects are colored correctly in the cycle -// collector. This includes JSContexts that don't have outstanding requests, -// because their global object wasn't marked by the JS GC. All other JS -// roots were marked by the JS GC and will be colored correctly in the cycle -// collector. -void -CycleCollectedJSRuntime::MaybeTraverseGlobals(nsCycleCollectionNoteRootCallback& aCb) const -{ - JSContext *iter = nullptr, *acx; - while ((acx = JS_ContextIterator(Runtime(), &iter))) { - // Add the context to the CC graph only if traversing it would - // end up doing something. - JSObject* global = js::DefaultObjectForContextOrNull(acx); - if (global && xpc_IsGrayGCThing(global)) { - aCb.NoteNativeRoot(acx, JSContextParticipant()); - } - } -} - void CycleCollectedJSRuntime::TraverseNativeRoots(nsCycleCollectionNoteRootCallback& aCb) { - MaybeTraverseGlobals(aCb); - // NB: This is here just to preserve the existing XPConnect order. I doubt it // would hurt to do this after the JS holders. TraverseAdditionalNativeRoots(aCb); diff --git a/xpcom/base/CycleCollectedJSRuntime.h b/xpcom/base/CycleCollectedJSRuntime.h index 339fc432dc0c..fe3ad22b878f 100644 --- a/xpcom/base/CycleCollectedJSRuntime.h +++ b/xpcom/base/CycleCollectedJSRuntime.h @@ -142,8 +142,6 @@ private: static void TraverseObjectShim(void* aData, void* aThing); - void MaybeTraverseGlobals(nsCycleCollectionNoteRootCallback& aCb) const; - void TraverseNativeRoots(nsCycleCollectionNoteRootCallback& aCb); static void TraceBlackJS(JSTracer* aTracer, void* aData); From a699320c1da255c265a51f89b68eb42408a7a37a Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:55 -0700 Subject: [PATCH 27/86] Bug 899367 - Add an API to opt out of default compartment objects. r=luke We need this explicit API because otherwise the default compartment object will get set implicitly during the first call to InitClasses. --- js/src/jsapi.h | 6 +++++- js/src/jscntxt.h | 5 ++++- js/src/jscntxtinlines.h | 6 +++++- js/src/vm/SelfHosting.cpp | 12 +++++++++--- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d3229ed00f4c..ba2bdf71cb71 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1526,7 +1526,11 @@ JS_StringToVersion(const char *string); /* JS_BIT(10) is currently unused. */ -/* JS_BIT(11) is currently unused. */ +#define JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT JS_BIT(11) /* This JSContext does not use a + default compartment object. Such + an object will not be set implicitly, + and attempts to get or set it will + assert. */ #define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12) /* A promise to the compiler that a null rval out-param diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 9344245a6d76..9ef434396d9b 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -449,7 +449,10 @@ struct JSContext : public js::ExclusiveContext, public: inline void setDefaultCompartmentObject(JSObject *obj); inline void setDefaultCompartmentObjectIfUnset(JSObject *obj); - JSObject *maybeDefaultCompartmentObject() const { return defaultCompartmentObject_; } + JSObject *maybeDefaultCompartmentObject() const { + JS_ASSERT(!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT)); + return defaultCompartmentObject_; + } /* Wrap cx->exception for the current compartment. */ void wrapPendingException(); diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index c1c6cc3c97ea..466cb1b4cfca 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -438,14 +438,18 @@ JSContext::setPendingException(js::Value v) { inline void JSContext::setDefaultCompartmentObject(JSObject *obj) { + JS_ASSERT(!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT)); defaultCompartmentObject_ = obj; } inline void JSContext::setDefaultCompartmentObjectIfUnset(JSObject *obj) { - if (!defaultCompartmentObject_) + if (!hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT) && + !defaultCompartmentObject_) + { setDefaultCompartmentObject(obj); + } } inline void diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index a8590b2c9ad6..2a6471fb1cda 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -682,12 +682,17 @@ bool JSRuntime::initSelfHosting(JSContext *cx) { JS_ASSERT(!selfHostingGlobal_); - RootedObject savedGlobal(cx, js::DefaultObjectForContextOrNull(cx)); + + bool receivesDefaultObject = !cx->hasOption(JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT); + RootedObject savedGlobal(cx, receivesDefaultObject + ? js::DefaultObjectForContextOrNull(cx) + : NULL); if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class, NULL, JS::DontFireOnNewGlobalHook))) return false; JSAutoCompartment ac(cx, selfHostingGlobal_); - js::SetDefaultObjectForContext(cx, selfHostingGlobal_); + if (receivesDefaultObject) + js::SetDefaultObjectForContext(cx, selfHostingGlobal_); Rooted shg(cx, &selfHostingGlobal_->as()); /* * During initialization of standard classes for the self-hosting global, @@ -756,7 +761,8 @@ JSRuntime::initSelfHosting(JSContext *cx) ok = Evaluate(cx, shg, options, src, srcLen, &rv); } JS_SetErrorReporter(cx, oldReporter); - js::SetDefaultObjectForContext(cx, savedGlobal); + if (receivesDefaultObject) + js::SetDefaultObjectForContext(cx, savedGlobal); return ok; } From 921c772767e704eeba3eed69c4c84725a3b8b3c1 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:55 -0700 Subject: [PATCH 28/86] Bug 899367 - Stop depending on the default compartment object for DOM JSContexts. r=mccr8 --- dom/base/nsDOMJSUtils.h | 2 ++ dom/base/nsJSUtils.cpp | 23 ++++++++++++++++++++++- js/jsd/jsd_xpc.cpp | 3 ++- js/xpconnect/src/XPCJSContextStack.cpp | 8 ++++++-- js/xpconnect/src/nsCxPusher.cpp | 8 ++++++-- 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/dom/base/nsDOMJSUtils.h b/dom/base/nsDOMJSUtils.h index 1d0a62207442..bac8aff65983 100644 --- a/dom/base/nsDOMJSUtils.h +++ b/dom/base/nsDOMJSUtils.h @@ -28,6 +28,8 @@ GetScriptContextFromJSContext(JSContext *cx) return scx; } +JSObject* GetDefaultScopeFromJSContext(JSContext *cx); + // A factory function for turning a JS::Value argv into an nsIArray // but also supports an effecient way of extracting the original argv. // Bug 312003 describes why this must be "void *", but argv will be cast to diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp index 872b30e82c1c..985b8505471b 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp @@ -14,6 +14,7 @@ #include "nsJSUtils.h" #include "jsapi.h" #include "js/OldDebugAPI.h" +#include "jsfriendapi.h" #include "nsIScriptContext.h" #include "nsIScriptGlobalObject.h" #include "nsIXPConnect.h" @@ -140,7 +141,11 @@ nsJSUtils::ReportPendingException(JSContext *aContext) if (JS_IsExceptionPending(aContext)) { bool saved = JS_SaveFrameChain(aContext); { - JSAutoCompartment ac(aContext, js::DefaultObjectForContextOrNull(aContext)); + nsIScriptContext* scx = GetScriptContextFromJSContext(aContext); + JS::Rooted scope(aContext); + scope = scx ? scx->GetNativeGlobal() + : js::DefaultObjectForContextOrNull(aContext); + JSAutoCompartment ac(aContext, scope); JS_ReportPendingException(aContext); } if (saved) { @@ -287,3 +292,19 @@ nsJSUtils::EvaluateString(JSContext* aCx, return NS_ERROR_OUT_OF_MEMORY; return rv; } + +// +// nsDOMJSUtils.h +// + +JSObject* GetDefaultScopeFromJSContext(JSContext *cx) +{ + // DOM JSContexts don't store their default compartment object on + // the cx, so in those cases we need to fetch it via the scx + // instead. + nsIScriptContext *scx = GetScriptContextFromJSContext(cx); + if (scx) { + return scx->GetNativeGlobal(); + } + return js::DefaultObjectForContextOrNull(cx); +} diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index 3175fba345ab..a480882659f6 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -30,6 +30,7 @@ /* XXX DOM dependency */ #include "nsIScriptContext.h" +#include "nsDOMJSUtils.h" #include "SandboxPrivate.h" #include "nsJSPrincipals.h" #include "nsContentUtils.h" @@ -1696,7 +1697,7 @@ NS_IMETHODIMP jsdContext::GetGlobalObject (jsdIValue **_rval) { ASSERT_VALID_EPHEMERAL; - JSObject *glob = js::DefaultObjectForContextOrNull(mJSCx); + JSObject *glob = GetDefaultScopeFromJSContext(mJSCx); JSDValue *jsdv = JSD_NewValue (mJSDCx, OBJECT_TO_JSVAL(glob)); if (!jsdv) return NS_ERROR_FAILURE; diff --git a/js/xpconnect/src/XPCJSContextStack.cpp b/js/xpconnect/src/XPCJSContextStack.cpp index f5b987d6b2af..798938b1709f 100644 --- a/js/xpconnect/src/XPCJSContextStack.cpp +++ b/js/xpconnect/src/XPCJSContextStack.cpp @@ -70,10 +70,14 @@ XPCJSContextStack::Push(JSContext *cx) // compartment that's same-origin with the current one, we can skip it. nsIScriptSecurityManager* ssm = XPCWrapper::GetSecurityManager(); if ((e.cx == cx) && ssm) { - RootedObject defaultGlobal(cx, js::DefaultObjectForContextOrNull(cx)); + // DOM JSContexts don't store their default compartment object on + // the cx, so in those cases we need to fetch it via the scx + // instead. + RootedObject defaultScope(cx, GetDefaultScopeFromJSContext(cx)); + nsIPrincipal *currentPrincipal = GetCompartmentPrincipal(js::GetContextCompartment(cx)); - nsIPrincipal *defaultPrincipal = GetObjectPrincipal(defaultGlobal); + nsIPrincipal *defaultPrincipal = GetObjectPrincipal(defaultScope); bool equal = false; currentPrincipal->Equals(defaultPrincipal, &equal); if (equal) { diff --git a/js/xpconnect/src/nsCxPusher.cpp b/js/xpconnect/src/nsCxPusher.cpp index 260fe671b538..b35082691d1a 100644 --- a/js/xpconnect/src/nsCxPusher.cpp +++ b/js/xpconnect/src/nsCxPusher.cpp @@ -129,8 +129,12 @@ AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull) // old XPCAutoRequest as well. if (cx) { mAutoRequest.construct(cx); - if (js::DefaultObjectForContextOrNull(cx)) - mAutoCompartment.construct(cx, js::DefaultObjectForContextOrNull(cx)); + + // DOM JSContexts don't store their default compartment object on the cx. + JSObject *compartmentObject = mScx ? mScx->GetNativeGlobal() + : js::DefaultObjectForContextOrNull(cx); + if (compartmentObject) + mAutoCompartment.construct(cx, compartmentObject); xpc_UnmarkGrayContext(cx); } } From c8fbffcb9d6e91b49e60abab7e929fa4b0588e2f Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:55 -0700 Subject: [PATCH 29/86] Bug 899367 - Have nsGlobalWindow go through nsJSContext to access the outer. r=mccr8 --- dom/base/nsGlobalWindow.cpp | 11 ++++------- dom/base/nsIScriptContext.h | 11 +++++++++-- dom/base/nsJSEnvironment.cpp | 20 +++++++++++++++++++- dom/base/nsJSEnvironment.h | 4 ++++ xpcom/base/CycleCollectedJSRuntime.cpp | 2 +- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 630067d10e4c..e808f92e7901 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2049,8 +2049,9 @@ nsGlobalWindow::SetOuterObject(JSContext* aCx, JS::Handle aOuterObjec { JSAutoCompartment ac(aCx, aOuterObject); - // Indicate the default compartment object associated with this cx. - js::SetDefaultObjectForContext(aCx, aOuterObject); + // Inform the nsJSContext, which is the canonical holder of the outer. + MOZ_ASSERT(IsOuterWindow()); + mContext->SetWindowProxy(aOuterObject); // Set up the prototype for the outer object. JS::Rooted inner(aCx, JS_GetParent(aOuterObject)); @@ -2446,11 +2447,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, newInnerWindow->FastGetGlobalJSObject()); #endif - // Now that we're connecting the outer global to the inner one, - // we must have transplanted it. The JS engine tries to maintain - // the global object's compartment as its default compartment, - // so update that now since it might have changed. - js::SetDefaultObjectForContext(cx, mJSObject); + MOZ_ASSERT(mContext->GetWindowProxy() == mJSObject); #ifdef DEBUG JS::Rooted rootedJSObject(cx, mJSObject); JS::Rooted proto1(cx), proto2(cx); diff --git a/dom/base/nsIScriptContext.h b/dom/base/nsIScriptContext.h index 5c72e4781526..8d09d52f735a 100644 --- a/dom/base/nsIScriptContext.h +++ b/dom/base/nsIScriptContext.h @@ -27,8 +27,8 @@ class nsIDOMWindow; class nsIURI; #define NS_ISCRIPTCONTEXT_IID \ -{ 0x1d931a17, 0x453a, 0x47fb, \ - { 0x94, 0x66, 0x2d, 0x3e, 0xd1, 0xef, 0x7a, 0xc5 } } +{ 0x03c0874e, 0xcb49, 0x41c8, \ + { 0xa3, 0x0b, 0xef, 0x3e, 0xc1, 0x88, 0xb1, 0x1f } } /* This MUST match JSVERSION_DEFAULT. This version stuff if we don't know what language we have is a little silly... */ @@ -165,6 +165,13 @@ public: * Tell the context we're done reinitializing it. */ virtual void DidInitializeContext() = 0; + + /** + * Access the Window Proxy. The setter should only be called by nsGlobalWindow. + */ + virtual void SetWindowProxy(JS::Handle aWindowProxy) = 0; + virtual JSObject* GetWindowProxy() = 0; + virtual JSObject* GetWindowProxyPreserveColor() = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContext, NS_ISCRIPTCONTEXT_IID) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 5fb6d9418b98..9c1bd22d1e52 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1152,7 +1152,7 @@ nsJSContext::GetGlobalObject() JSObject* nsJSContext::GetNativeGlobal() { - return js::DefaultObjectForContextOrNull(mContext); + return GetWindowProxy(); } JSContext* @@ -2598,6 +2598,24 @@ nsJSContext::ReportPendingException() } } +void +nsJSContext::SetWindowProxy(JS::Handle aWindowProxy) +{ + js::SetDefaultObjectForContext(mContext, aWindowProxy); +} + +JSObject* +nsJSContext::GetWindowProxy() +{ + return xpc_UnmarkGrayObject(GetWindowProxyPreserveColor()); +} + +JSObject* +nsJSContext::GetWindowProxyPreserveColor() +{ + return js::DefaultObjectForContextOrNull(mContext); +} + void nsJSContext::LikelyShortLivingObjectCreated() { diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index b200347a522f..cf23ecf0bfcb 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -81,6 +81,10 @@ public: virtual void WillInitializeContext() MOZ_OVERRIDE; virtual void DidInitializeContext() MOZ_OVERRIDE; + virtual void SetWindowProxy(JS::Handle aWindowProxy) MOZ_OVERRIDE; + virtual JSObject* GetWindowProxy() MOZ_OVERRIDE; + virtual JSObject* GetWindowProxyPreserveColor() MOZ_OVERRIDE; + static void LoadStart(); static void LoadEnd(); diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 5a46af9ca63f..b2fda0236169 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -932,7 +932,7 @@ CycleCollectedJSRuntime::UsefulToMergeZones() const // NativeGlobal() is not an outer window (this happens with XUL Prototype // compilation scopes, for example, which we're not interested in). nsIScriptContext* scx = GetScriptContextFromJSContext(cx); - JS::RootedObject global(cx, scx ? scx->GetNativeGlobal() : nullptr); + JS::RootedObject global(cx, scx ? scx->GetWindowProxyPreserveColor() : nullptr); if (!global || !js::GetObjectParent(global)) { continue; } From 44f0d562b57c8ae646347b52a4c67aa7b1ae3ce5 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:56 -0700 Subject: [PATCH 30/86] Bug 899367 - Stop storing the window proxy on the JSContext. r=mccr8 We need to simultaneously report the new Heap Pointer to the cycle collector, and remove the old machinery for cycle-collecting the default object via the JSContext. --- dom/base/nsJSEnvironment.cpp | 50 ++++++-------------------- dom/base/nsJSEnvironment.h | 15 ++------ js/xpconnect/idl/nsIXPConnect.idl | 17 +-------- js/xpconnect/src/XPCJSRuntime.cpp | 8 ----- js/xpconnect/src/nsXPConnect.cpp | 8 ----- js/xpconnect/src/xpcpublic.h | 7 +++- xpcom/base/CycleCollectedJSRuntime.cpp | 48 ------------------------- xpcom/base/CycleCollectedJSRuntime.h | 3 -- 8 files changed, 19 insertions(+), 137 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 9c1bd22d1e52..9e358f2f4ed3 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -839,7 +839,8 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data) nsJSContext::nsJSContext(bool aGCOnDestruction, nsIScriptGlobalObject* aGlobalObject) - : mGCOnDestruction(aGCOnDestruction) + : mWindowProxy(nullptr) + , mGCOnDestruction(aGCOnDestruction) , mGlobalObjectRef(aGlobalObject) { EnsureStatics(); @@ -854,7 +855,7 @@ nsJSContext::nsJSContext(bool aGCOnDestruction, ++sContextCount; mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS | - JSOPTION_UNROOTED_GLOBAL; + JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT; mContext = ::JS_NewContext(sRuntime, gStackSize); if (mContext) { @@ -873,6 +874,7 @@ nsJSContext::nsJSContext(bool aGCOnDestruction, mIsInitialized = false; mScriptsEnabled = true; mProcessingScriptTag = false; + NS_HOLD_JS_OBJECTS(this, nsJSContext); } nsJSContext::~nsJSContext() @@ -923,12 +925,14 @@ nsJSContext::DestroyJSContext() JS_DestroyContextNoGC(mContext); mContext = nullptr; + NS_DROP_JS_OBJECTS(this, nsJSContext); } // QueryInterface implementation for nsJSContext NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSContext) NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSContext) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mWindowProxy) NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSContext) @@ -936,18 +940,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSContext) "Trying to unlink a context with outstanding requests."); tmp->mIsInitialized = false; tmp->mGCOnDestruction = false; - if (tmp->mContext) { - JSAutoRequest ar(tmp->mContext); - js::SetDefaultObjectForContext(tmp->mContext, nullptr); - } + tmp->mWindowProxy = nullptr; tmp->DestroyJSContext(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobalObjectRef) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSContext) NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsJSContext, tmp->GetCCRefcnt()) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobalObjectRef) - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContext"); - nsContentUtils::XPConnect()->NoteJSContext(tmp->mContext, cb); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSContext) @@ -2601,7 +2601,7 @@ nsJSContext::ReportPendingException() void nsJSContext::SetWindowProxy(JS::Handle aWindowProxy) { - js::SetDefaultObjectForContext(mContext, aWindowProxy); + mWindowProxy = aWindowProxy; } JSObject* @@ -2613,7 +2613,7 @@ nsJSContext::GetWindowProxy() JSObject* nsJSContext::GetWindowProxyPreserveColor() { - return js::DefaultObjectForContextOrNull(mContext); + return mWindowProxy; } void @@ -2960,36 +2960,6 @@ mozilla::dom::ShutdownJSEnvironment() sDidShutdown = true; } -void -mozilla::dom::TraceOuterWindows(JSTracer* aTracer) -{ - MOZ_ASSERT_IF(JS_IsGCMarkingTracer(aTracer), JS_IsMarkingGray(aTracer)); - for (nsJSContext* cx = sContextList; cx; cx = cx->mNext) { - JSObject* outer; - if (cx->mContext && - (outer = js::DefaultObjectForContextOrNull(cx->mContext))) - { - JS::AssertGCThingMustBeTenured(outer); - JS_CallObjectTracer(aTracer, &outer, "Outer Window"); - } - } -} - -void -mozilla::dom::TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb) -{ - nsCycleCollectionParticipant* participant = mozilla::CycleCollectedJSRuntime::JSContextParticipant(); - for (nsJSContext* cx = sContextList; cx; cx = cx->mNext) { - JSObject* outer; - if (cx->mContext && - (outer = js::DefaultObjectForContextOrNull(cx->mContext)) && - xpc_IsGrayGCThing(outer)) - { - aCb.NoteNativeRoot(cx->mContext, participant); - } - } -} - // A fast-array class for JS. This class supports both nsIJSScriptArray and // nsIArray. If it is JS itself providing and consuming this class, all work // can be done via nsIJSScriptArray, and avoid the conversion of elements diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index cf23ecf0bfcb..7ce497d12b19 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -30,15 +30,6 @@ template class Maybe; // a page) and doing the actual GC. #define NS_GC_DELAY 4000 // ms -namespace mozilla { -namespace dom { - -void TraceOuterWindows(JSTracer *aTracer); -void TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb); - -} /* namespace dom */ -} /* namespace mozilla */ - class nsJSContext : public nsIScriptContext { public: @@ -165,12 +156,14 @@ protected: // function will set aside the frame chain on mContext before // reporting. void ReportPendingException(); + private: void DestroyJSContext(); nsrefcnt GetCCRefcnt(); JSContext *mContext; + JS::Heap mWindowProxy; bool mIsInitialized; bool mScriptsEnabled; @@ -186,10 +179,6 @@ private: nsJSContext *mNext; nsJSContext **mPrev; - /* This function needs access to the linked list members above. */ - friend void mozilla::dom::TraceOuterWindows(JSTracer *aTracer); - friend void mozilla::dom::TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb); - // mGlobalObjectRef ensures that the outer window stays alive as long as the // context does. It is eventually collected by the cycle collector. nsCOMPtr mGlobalObjectRef; diff --git a/js/xpconnect/idl/nsIXPConnect.idl b/js/xpconnect/idl/nsIXPConnect.idl index 85dd06151f36..e4b9d2502361 100644 --- a/js/xpconnect/idl/nsIXPConnect.idl +++ b/js/xpconnect/idl/nsIXPConnect.idl @@ -43,8 +43,6 @@ class nsWrapperCache; native JSEqualityOp(JSEqualityOp); [ptr] native JSScriptPtr(JSScript); [ptr] native voidPtrPtr(void*); -[ptr] native nsScriptObjectTracerPtr(nsScriptObjectTracer); -[ref] native nsCCTraversalCallbackRef(nsCycleCollectionTraversalCallback); [ptr] native nsAXPCNativeCallContextPtr(nsAXPCNativeCallContext); [ptr] native nsWrapperCachePtr(nsWrapperCache); [ref] native JSCompartmentOptions(JS::CompartmentOptions); @@ -61,11 +59,6 @@ interface nsIInterfaceInfo; interface nsIXPCSecurityManager; interface nsIPrincipal; -%{C++ -class nsCycleCollectionTraversalCallback; -class nsScriptObjectTracer; -%} - /***************************************************************************/ [uuid(909e8641-7c54-4dff-9b94-ba631f057b33)] interface nsIXPConnectJSObjectHolder : nsISupports @@ -294,7 +287,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(0ebc00f0-f3ad-11e2-b778-0800200c9a66)] +[uuid(c4d0187c-6a78-4bdf-9cd9-d218644b715a)] interface nsIXPConnect : nsISupports { %{ C++ @@ -562,14 +555,6 @@ interface nsIXPConnect : nsISupports in JSObjectPtr sandbox, in boolean returnStringOnly); - /** - * Note aJSContext as a child to the cycle collector. - * @param aJSContext The JSContext to note. - * @param aCb The cycle collection traversal callback. - */ - [noscript,notxpcom] void noteJSContext(in JSContextPtr aJSContext, - in nsCCTraversalCallbackRef aCb); - /** * Whether or not XPConnect should report all JS exceptions when returning * from JS into C++. False by default, although any value set in the diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 736a379ae222..02c3a6cd93bc 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -496,10 +496,6 @@ void XPCJSRuntime::TraceAdditionalNativeGrayRoots(JSTracer *trc) { XPCAutoLock lock(mMapLock); - // Trace outer windows, which are the default compartment objects for DOM - // JSContexts. - dom::TraceOuterWindows(trc); - XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(trc, this); for (XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) @@ -561,10 +557,6 @@ XPCJSRuntime::TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback &c { XPCAutoLock lock(mMapLock); - // Traverse outer windows, which are the default compartment objects for DOM - // JSContexts. - dom::TraverseOuterWindows(cb); - XPCWrappedNativeScope::SuspectAllWrappers(this, cb); for (XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) { diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 45796a8f5534..559c29bb933a 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -342,14 +342,6 @@ xpc_TryUnmarkWrappedGrayObject(nsISupports* aWrappedJS) } } -NS_IMETHODIMP_(void) -nsXPConnect::NoteJSContext(JSContext *aJSContext, - nsCycleCollectionTraversalCallback &aCb) -{ - aCb.NoteNativeChild(aJSContext, mozilla::CycleCollectedJSRuntime::JSContextParticipant()); -} - - /***************************************************************************/ /***************************************************************************/ // nsIXPConnect interface methods... diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index ad9df47d6eb7..b36369032960 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -24,6 +24,7 @@ #include "nsStringBuffer.h" #include "nsIGlobalObject.h" #include "mozilla/dom/BindingDeclarations.h" +#include "nsDOMJSUtils.h" class nsIPrincipal; class nsIXPConnectWrappedJS; @@ -166,7 +167,11 @@ xpc_UnmarkGrayScript(JSScript *script) inline JSContext * xpc_UnmarkGrayContext(JSContext *cx) { - if (cx) { + // There's no default compartment object for DOM JSContexts, so we have + // nothing to do in that case. In fact, this whole function is obsolete, + // because nothing else is ever gray. But for now let's be deliberate. + // We'll remove this thing in the next patch. + if (cx && !GetScriptContextFromJSContext(cx)) { JSObject *global = js::DefaultObjectForContextOrNull(cx); xpc_UnmarkGrayObject(global); if (global && JS_IsInRequest(JS_GetRuntime(cx))) { diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index b2fda0236169..35c721e2f6db 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -278,47 +278,6 @@ private: bool mAnyMarked; }; -class JSContextParticipant : public nsCycleCollectionParticipant -{ -public: - NS_IMETHOD Root(void *n) - { - return NS_OK; - } - NS_IMETHOD Unlink(void *n) - { - return NS_OK; - } - NS_IMETHOD Unroot(void *n) - { - return NS_OK; - } - NS_IMETHOD_(void) DeleteCycleCollectable(void *n) - { - } - NS_IMETHOD Traverse(void *n, nsCycleCollectionTraversalCallback &cb) - { - JSContext *cx = static_cast(n); - - // JSContexts do not have an internal refcount and always have a single - // owner (e.g., nsJSContext). Thus, the default refcount is 1. However, - // in the (abnormal) case of synchronous cycle-collection, the context - // may be actively executing code in which case we want to treat it as - // rooted by adding an extra refcount. - unsigned refCount = js::ContextHasOutstandingRequests(cx) ? 2 : 1; - - cb.DescribeRefCountedNode(refCount, "JSContext"); - if (JSObject *global = js::DefaultObjectForContextOrNull(cx)) { - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[global object]"); - cb.NoteJSChild(global); - } - - return NS_OK; - } -}; - -static JSContextParticipant JSContext_cycleCollectorGlobal; - struct Closure { bool cycleCollectionEnabled; @@ -872,13 +831,6 @@ CycleCollectedJSRuntime::AssertNoObjectsToTrace(void* aPossibleJSHolder) } #endif -// static -nsCycleCollectionParticipant* -CycleCollectedJSRuntime::JSContextParticipant() -{ - return &JSContext_cycleCollectorGlobal; -} - nsCycleCollectionParticipant* CycleCollectedJSRuntime::GCThingParticipant() { diff --git a/xpcom/base/CycleCollectedJSRuntime.h b/xpcom/base/CycleCollectedJSRuntime.h index fe3ad22b878f..36d3d42c4217 100644 --- a/xpcom/base/CycleCollectedJSRuntime.h +++ b/xpcom/base/CycleCollectedJSRuntime.h @@ -172,9 +172,6 @@ public: void AssertNoObjectsToTrace(void* aPossibleJSHolder); #endif - // This returns the singleton nsCycleCollectionParticipant for JSContexts. - static nsCycleCollectionParticipant* JSContextParticipant(); - nsCycleCollectionParticipant* GCThingParticipant(); nsCycleCollectionParticipant* ZoneParticipant(); From 9ea45e61e6387ca823c2b306e1c9c8760adbdeb0 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:56 -0700 Subject: [PATCH 31/86] Bug 899367 - Remove JSOPTION_UNROOTED_GLOBAL. r=luke,mccr8 \o/ --- js/src/jsapi.h | 6 ++---- js/src/jscntxt.cpp | 2 +- js/src/jsfriendapi.cpp | 6 ------ js/src/jsfriendapi.h | 3 --- 4 files changed, 3 insertions(+), 14 deletions(-) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index ba2bdf71cb71..b2721ffa52cb 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1536,10 +1536,8 @@ JS_StringToVersion(const char *string); that a null rval out-param will be passed to each call to JS_ExecuteScript. */ -#define JSOPTION_UNROOTED_GLOBAL JS_BIT(13) /* The GC will not root the - contexts' default compartment - object, leaving that up to the - embedding. */ + +/* JS_BIT(13) is currently unused. */ #define JSOPTION_BASELINE JS_BIT(14) /* Baseline compiler. */ diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 7f8783fd2f26..156c18468cf7 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -1285,7 +1285,7 @@ JSContext::mark(JSTracer *trc) /* Stack frames and slots are traced by StackSpace::mark. */ /* Mark other roots-by-definition in the JSContext. */ - if (defaultCompartmentObject_ && !hasOption(JSOPTION_UNROOTED_GLOBAL)) + if (defaultCompartmentObject_) MarkObjectRoot(trc, &defaultCompartmentObject_, "default compartment object"); if (isExceptionPending()) MarkValueRoot(trc, &exception, "exception"); diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 0f60b2a48342..f90b00d04e69 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -805,12 +805,6 @@ js::ContextHasOutstandingRequests(const JSContext *cx) } #endif -JS_FRIEND_API(bool) -js::HasUnrootedGlobal(const JSContext *cx) -{ - return cx->hasOption(JSOPTION_UNROOTED_GLOBAL); -} - JS_FRIEND_API(void) js::SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg) { diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 763adebd77a9..e32dabc39d62 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -676,9 +676,6 @@ JS_FRIEND_API(bool) ContextHasOutstandingRequests(const JSContext *cx); #endif -JS_FRIEND_API(bool) -HasUnrootedGlobal(const JSContext *cx); - typedef void (* ActivityCallback)(void *arg, bool active); From 666aaa00ac6ebfbee88c502207c1e6823f7c8c5e Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:56 -0700 Subject: [PATCH 32/86] Bug 899367 - Remove xpc_UnmarkGrayContext. r=mccr8 Default compartment objects are never gray anymore. --- dom/base/nsJSEnvironment.cpp | 2 +- js/xpconnect/src/XPCWrappedJSClass.cpp | 2 +- js/xpconnect/src/nsCxPusher.cpp | 4 ---- js/xpconnect/src/nsXPConnect.cpp | 3 +-- js/xpconnect/src/xpcpublic.h | 20 -------------------- 5 files changed, 3 insertions(+), 28 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 9e358f2f4ed3..423d0dea6f6c 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1158,7 +1158,7 @@ nsJSContext::GetNativeGlobal() JSContext* nsJSContext::GetNativeContext() { - return xpc_UnmarkGrayContext(mContext); + return mContext; } nsresult diff --git a/js/xpconnect/src/XPCWrappedJSClass.cpp b/js/xpconnect/src/XPCWrappedJSClass.cpp index 0c563f4da6fc..f82b1455a5e5 100644 --- a/js/xpconnect/src/XPCWrappedJSClass.cpp +++ b/js/xpconnect/src/XPCWrappedJSClass.cpp @@ -1152,7 +1152,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex, return retval; XPCContext *xpcc = ccx.GetXPCContext(); - JSContext *cx = xpc_UnmarkGrayContext(ccx.GetJSContext()); + JSContext *cx = ccx.GetJSContext(); if (!cx || !xpcc || !IsReflectable(methodIndex)) return NS_ERROR_FAILURE; diff --git a/js/xpconnect/src/nsCxPusher.cpp b/js/xpconnect/src/nsCxPusher.cpp index b35082691d1a..b9be9343543d 100644 --- a/js/xpconnect/src/nsCxPusher.cpp +++ b/js/xpconnect/src/nsCxPusher.cpp @@ -124,9 +124,6 @@ AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull) // Enter a request and a compartment for the duration that the cx is on the // stack if non-null. - // - // NB: We call UnmarkGrayContext so that this can obsolete the need for the - // old XPCAutoRequest as well. if (cx) { mAutoRequest.construct(cx); @@ -135,7 +132,6 @@ AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull) : js::DefaultObjectForContextOrNull(cx); if (compartmentObject) mAutoCompartment.construct(cx, compartmentObject); - xpc_UnmarkGrayContext(cx); } } diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 559c29bb933a..61ea9fb7fda2 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -1315,8 +1315,7 @@ xpc_ActivateDebugMode() JSContext* nsXPConnect::GetCurrentJSContext() { - JSContext *cx = GetRuntime()->GetJSContextStack()->Peek(); - return xpc_UnmarkGrayContext(cx); + return GetRuntime()->GetJSContextStack()->Peek(); } /* virtual */ diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index b36369032960..430791f2caef 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -24,7 +24,6 @@ #include "nsStringBuffer.h" #include "nsIGlobalObject.h" #include "mozilla/dom/BindingDeclarations.h" -#include "nsDOMJSUtils.h" class nsIPrincipal; class nsIXPConnectWrappedJS; @@ -164,25 +163,6 @@ xpc_UnmarkGrayScript(JSScript *script) return script; } -inline JSContext * -xpc_UnmarkGrayContext(JSContext *cx) -{ - // There's no default compartment object for DOM JSContexts, so we have - // nothing to do in that case. In fact, this whole function is obsolete, - // because nothing else is ever gray. But for now let's be deliberate. - // We'll remove this thing in the next patch. - if (cx && !GetScriptContextFromJSContext(cx)) { - JSObject *global = js::DefaultObjectForContextOrNull(cx); - xpc_UnmarkGrayObject(global); - if (global && JS_IsInRequest(JS_GetRuntime(cx))) { - JSObject *scope = JS::CurrentGlobalOrNull(cx); - if (scope != global) - xpc_UnmarkGrayObject(scope); - } - } - return cx; -} - // If aVariant is an XPCVariant, this marks the object to be in aGeneration. // This also unmarks the gray JSObject. extern void From b2a143459c757138e34389c5e4ffc776e74702c2 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:56 -0700 Subject: [PATCH 33/86] Bug 899367 - Remove check for non-WindowProxy objects on an scx. r=mccr8 --- xpcom/base/CycleCollectedJSRuntime.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 35c721e2f6db..b155e3cf68f7 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -880,19 +880,18 @@ CycleCollectedJSRuntime::UsefulToMergeZones() const JSContext* cx; JSAutoRequest ar(nsContentUtils::GetSafeJSContext()); while ((cx = JS_ContextIterator(mJSRuntime, &iter))) { - // Skip anything without an nsIScriptContext, as well as any scx whose - // NativeGlobal() is not an outer window (this happens with XUL Prototype - // compilation scopes, for example, which we're not interested in). + // Skip anything without an nsIScriptContext. nsIScriptContext* scx = GetScriptContextFromJSContext(cx); - JS::RootedObject global(cx, scx ? scx->GetWindowProxyPreserveColor() : nullptr); - if (!global || !js::GetObjectParent(global)) { + JS::RootedObject obj(cx, scx ? scx->GetWindowProxyPreserveColor() : nullptr); + if (!obj) { continue; } + MOZ_ASSERT(js::IsOuterObject(obj)); // Grab the inner from the outer. - global = JS_ObjectToInnerObject(cx, global); - MOZ_ASSERT(!js::GetObjectParent(global)); - if (JS::GCThingIsMarkedGray(global) && - !js::IsSystemCompartment(js::GetObjectCompartment(global))) { + obj = JS_ObjectToInnerObject(cx, obj); + MOZ_ASSERT(!js::GetObjectParent(obj)); + if (JS::GCThingIsMarkedGray(obj) && + !js::IsSystemCompartment(js::GetObjectCompartment(obj))) { return true; } } From 83c76ab7608c98755a582c365dcca50f0ca42eed Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 14:06:57 -0700 Subject: [PATCH 34/86] Bug 899367 - Make GetNativeGlobal consumers call GetWindowProxy and rm the former. r=mccr8 Some of the uses of this are a bit nonsensical now, but that's a problem for another day. --- caps/src/nsSecurityManagerFactory.cpp | 2 +- content/events/src/nsEventListenerManager.cpp | 2 +- dom/base/nsGlobalWindow.cpp | 2 +- dom/base/nsIScriptContext.h | 10 ++-------- dom/base/nsJSEnvironment.cpp | 12 +++--------- dom/base/nsJSEnvironment.h | 3 +-- dom/base/nsJSUtils.cpp | 4 ++-- dom/bluetooth/BluetoothManager.cpp | 2 +- dom/file/ArchiveRequest.cpp | 2 +- dom/file/FileRequest.cpp | 2 +- dom/mobilemessage/src/MobileMessageCallback.cpp | 2 +- .../src/MobileMessageCursorCallback.cpp | 2 +- dom/mobilemessage/src/MobileMessageManager.cpp | 2 +- js/xpconnect/src/nsCxPusher.cpp | 2 +- 14 files changed, 18 insertions(+), 31 deletions(-) diff --git a/caps/src/nsSecurityManagerFactory.cpp b/caps/src/nsSecurityManagerFactory.cpp index e13971c82c67..071bef3ffa1b 100644 --- a/caps/src/nsSecurityManagerFactory.cpp +++ b/caps/src/nsSecurityManagerFactory.cpp @@ -66,7 +66,7 @@ NS_IMETHODIMP nsSecurityNameSet::InitializeNameSet(nsIScriptContext* aScriptContext) { AutoJSContext cx; - JS::Rooted global(cx, aScriptContext->GetNativeGlobal()); + JS::Rooted global(cx, aScriptContext->GetWindowProxy()); JSAutoCompartment ac(cx, global); /* diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index 1a0b0e525b96..2fb03b248043 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -893,7 +893,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS aListenerStruct->mTypeAtom, &argCount, &argNames); - JSAutoCompartment ac(cx, context->GetNativeGlobal()); + JSAutoCompartment ac(cx, context->GetWindowProxy()); JS::CompileOptions options(cx); options.setFileAndLine(url.get(), lineNo) .setVersion(SCRIPTVERSION_DEFAULT); diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index e808f92e7901..33d2baf800a9 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2363,7 +2363,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, CreateOuterObject(newInnerWindow); mContext->DidInitializeContext(); - mJSObject = mContext->GetNativeGlobal(); + mJSObject = mContext->GetWindowProxy(); SetWrapper(mJSObject); } else { JS::Rooted global(cx, diff --git a/dom/base/nsIScriptContext.h b/dom/base/nsIScriptContext.h index 8d09d52f735a..931867a6e757 100644 --- a/dom/base/nsIScriptContext.h +++ b/dom/base/nsIScriptContext.h @@ -27,8 +27,8 @@ class nsIDOMWindow; class nsIURI; #define NS_ISCRIPTCONTEXT_IID \ -{ 0x03c0874e, 0xcb49, 0x41c8, \ - { 0xa3, 0x0b, 0xef, 0x3e, 0xc1, 0x88, 0xb1, 0x1f } } +{ 0xf3859ce7, 0x7551, 0x4760, \ + { 0x84, 0x29, 0x64, 0x4f, 0x26, 0x1e, 0xdb, 0x91 } } /* This MUST match JSVERSION_DEFAULT. This version stuff if we don't know what language we have is a little silly... */ @@ -103,12 +103,6 @@ public: **/ virtual JSContext* GetNativeContext() = 0; - /** - * Return the native global object for this context. - * - **/ - virtual JSObject* GetNativeGlobal() = 0; - /** * Initialize the context generally. Does not create a global object. **/ diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 423d0dea6f6c..a703d6b58d37 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1100,7 +1100,7 @@ nsIScriptGlobalObject * nsJSContext::GetGlobalObject() { AutoJSContext cx; - JS::Rooted global(mContext, GetNativeGlobal()); + JS::Rooted global(mContext, GetWindowProxy()); if (!global) { return nullptr; } @@ -1149,12 +1149,6 @@ nsJSContext::GetGlobalObject() return sgo; } -JSObject* -nsJSContext::GetNativeGlobal() -{ - return GetWindowProxy(); -} - JSContext* nsJSContext::GetNativeContext() { @@ -1198,7 +1192,7 @@ nsJSContext::SetProperty(JS::Handle aTarget, const char* aPropName, n Maybe tempStorage; - JS::Rooted global(mContext, GetNativeGlobal()); + JS::Rooted global(mContext, GetWindowProxy()); nsresult rv = ConvertSupportsTojsvals(aArgs, global, &argc, &argv, tempStorage); NS_ENSURE_SUCCESS(rv, rv); @@ -1494,7 +1488,7 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv) AutoFree iidGuard(iid); // Free iid upon destruction. nsCOMPtr wrapper; - JS::Rooted global(cx, xpc_UnmarkGrayObject(GetNativeGlobal())); + JS::Rooted global(cx, GetWindowProxy()); JS::Rooted v(cx); nsresult rv = nsContentUtils::WrapNative(cx, global, data, iid, v.address(), diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index 7ce497d12b19..090663241faa 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -55,7 +55,6 @@ public: inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; } virtual JSContext* GetNativeContext() MOZ_OVERRIDE; - virtual JSObject* GetNativeGlobal() MOZ_OVERRIDE; virtual nsresult InitContext() MOZ_OVERRIDE; virtual bool IsContextInitialized() MOZ_OVERRIDE; @@ -131,7 +130,7 @@ public: { // Verify that we have a global so that this // does always return a null when GetGlobalObject() is null. - JSObject* global = GetNativeGlobal(); + JSObject* global = GetWindowProxy(); return global ? mGlobalObjectRef.get() : nullptr; } protected: diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp index 985b8505471b..8157ffa926eb 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp @@ -143,7 +143,7 @@ nsJSUtils::ReportPendingException(JSContext *aContext) { nsIScriptContext* scx = GetScriptContextFromJSContext(aContext); JS::Rooted scope(aContext); - scope = scx ? scx->GetNativeGlobal() + scope = scx ? scx->GetWindowProxy() : js::DefaultObjectForContextOrNull(aContext); JSAutoCompartment ac(aContext, scope); JS_ReportPendingException(aContext); @@ -304,7 +304,7 @@ JSObject* GetDefaultScopeFromJSContext(JSContext *cx) // instead. nsIScriptContext *scx = GetScriptContextFromJSContext(cx); if (scx) { - return scx->GetNativeGlobal(); + return scx->GetWindowProxy(); } return js::DefaultObjectForContextOrNull(cx); } diff --git a/dom/bluetooth/BluetoothManager.cpp b/dom/bluetooth/BluetoothManager.cpp index 43118c15fa39..1fcce356898c 100644 --- a/dom/bluetooth/BluetoothManager.cpp +++ b/dom/bluetooth/BluetoothManager.cpp @@ -68,7 +68,7 @@ public: AutoPushJSContext cx(sc->GetNativeContext()); - JS::Rooted global(cx, sc->GetNativeGlobal()); + JS::Rooted global(cx, sc->GetWindowProxy()); rv = nsContentUtils::WrapNative(cx, global, adapter, aValue); if (NS_FAILED(rv)) { NS_WARNING("Cannot create native object!"); diff --git a/dom/file/ArchiveRequest.cpp b/dom/file/ArchiveRequest.cpp index 5d2230bc76c9..e66fa3e24208 100644 --- a/dom/file/ArchiveRequest.cpp +++ b/dom/file/ArchiveRequest.cpp @@ -135,7 +135,7 @@ ArchiveRequest::ReaderReady(nsTArray >& aFileList, AutoPushJSContext cx(sc->GetNativeContext()); NS_ASSERTION(cx, "Failed to get a context!"); - JS::Rooted global(cx, sc->GetNativeGlobal()); + JS::Rooted global(cx, sc->GetWindowProxy()); NS_ASSERTION(global, "Failed to get global object!"); JSAutoCompartment ac(cx, global); diff --git a/dom/file/FileRequest.cpp b/dom/file/FileRequest.cpp index 0893466bb9b6..7de459f2bfcc 100644 --- a/dom/file/FileRequest.cpp +++ b/dom/file/FileRequest.cpp @@ -79,7 +79,7 @@ FileRequest::NotifyHelperCompleted(FileHelper* aFileHelper) JS::Rooted result(cx); - JS::Rooted global(cx, sc->GetNativeGlobal()); + JS::Rooted global(cx, sc->GetWindowProxy()); NS_ASSERTION(global, "Failed to get global object!"); JSAutoCompartment ac(cx, global); diff --git a/dom/mobilemessage/src/MobileMessageCallback.cpp b/dom/mobilemessage/src/MobileMessageCallback.cpp index f81dd5432843..05951a234223 100644 --- a/dom/mobilemessage/src/MobileMessageCallback.cpp +++ b/dom/mobilemessage/src/MobileMessageCallback.cpp @@ -56,7 +56,7 @@ MobileMessageCallback::NotifySuccess(nsISupports *aMessage) AutoPushJSContext cx(scriptContext->GetNativeContext()); NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE); - JS::Rooted global(cx, scriptContext->GetNativeGlobal()); + JS::Rooted global(cx, scriptContext->GetWindowProxy()); NS_ENSURE_TRUE(global, NS_ERROR_FAILURE); JSAutoCompartment ac(cx, global); diff --git a/dom/mobilemessage/src/MobileMessageCursorCallback.cpp b/dom/mobilemessage/src/MobileMessageCursorCallback.cpp index 77af8722e44d..c22030e4f947 100644 --- a/dom/mobilemessage/src/MobileMessageCursorCallback.cpp +++ b/dom/mobilemessage/src/MobileMessageCursorCallback.cpp @@ -67,7 +67,7 @@ MobileMessageCursorCallback::NotifyCursorResult(nsISupports* aResult) AutoPushJSContext cx(scriptContext->GetNativeContext()); NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE); - JS::Rooted global(cx, scriptContext->GetNativeGlobal()); + JS::Rooted global(cx, scriptContext->GetWindowProxy()); NS_ENSURE_TRUE(global, NS_ERROR_FAILURE); JSAutoCompartment ac(cx, global); diff --git a/dom/mobilemessage/src/MobileMessageManager.cpp b/dom/mobilemessage/src/MobileMessageManager.cpp index 57724428403f..76e896442194 100644 --- a/dom/mobilemessage/src/MobileMessageManager.cpp +++ b/dom/mobilemessage/src/MobileMessageManager.cpp @@ -155,7 +155,7 @@ MobileMessageManager::Send(const JS::Value& aNumber_, const nsAString& aMessage, return NS_ERROR_INVALID_ARG; } - JS::Rooted global(cx, sc->GetNativeGlobal()); + JS::Rooted global(cx, sc->GetWindowProxy()); NS_ASSERTION(global, "Failed to get global object!"); JSAutoCompartment ac(cx, global); diff --git a/js/xpconnect/src/nsCxPusher.cpp b/js/xpconnect/src/nsCxPusher.cpp index b9be9343543d..c762318dd434 100644 --- a/js/xpconnect/src/nsCxPusher.cpp +++ b/js/xpconnect/src/nsCxPusher.cpp @@ -128,7 +128,7 @@ AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull) mAutoRequest.construct(cx); // DOM JSContexts don't store their default compartment object on the cx. - JSObject *compartmentObject = mScx ? mScx->GetNativeGlobal() + JSObject *compartmentObject = mScx ? mScx->GetWindowProxy() : js::DefaultObjectForContextOrNull(cx); if (compartmentObject) mAutoCompartment.construct(cx, compartmentObject); From 63d2cabdae6c8a305946c03adf962e18c7efdc8b Mon Sep 17 00:00:00 2001 From: Georg Fritzsche Date: Wed, 4 Sep 2013 16:05:21 +0200 Subject: [PATCH 35/86] Bug 899080 - Let all plugins except Flash default to click-to-play. r=bsmedberg --- browser/app/profile/firefox.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index f2b93c002b2d..736acfd4a68a 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -641,6 +641,10 @@ pref("plugins.update.notifyUser", false); pref("plugins.click_to_play", true); +// let all plugins except Flash default to click-to-play +pref("plugin.default.state", 1); +pref("plugin.state.flash", 2); + // display door hanger if flash not installed pref("plugins.notifyMissingFlash", true); From 613349b08263e5f72e5195fc46fd2603524dbf3c Mon Sep 17 00:00:00 2001 From: Georg Fritzsche Date: Wed, 4 Sep 2013 16:05:31 +0200 Subject: [PATCH 36/86] Bug 899080 - Test fixup part 1 - Always enable test-plugins for reftests. r=jmaher --- layout/tools/reftest/reftest.js | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/layout/tools/reftest/reftest.js b/layout/tools/reftest/reftest.js index 41305e0ccade..6f7ad3ea81ea 100644 --- a/layout/tools/reftest/reftest.js +++ b/layout/tools/reftest/reftest.js @@ -109,6 +109,9 @@ var gUnexpectedCrashDumpFiles = { }; var gCrashDumpDir; var gFailedNoPaint = false; +// The enabled-state of the test-plugins, stored so they can be reset later +var gTestPluginEnabledStates = null; + const TYPE_REFTEST_EQUAL = '=='; const TYPE_REFTEST_NOTEQUAL = '!='; const TYPE_LOAD = 'load'; // test without a reference (just test that it does @@ -208,6 +211,20 @@ function IDForEventTarget(event) } } +function getTestPlugin(aName) { + var ph = CC["@mozilla.org/plugin/host;1"].getService(CI.nsIPluginHost); + var tags = ph.getPluginTags(); + + // Find the test plugin + for (var i = 0; i < tags.length; i++) { + if (tags[i].name == aName) + return tags[i]; + } + + LogWarning("Failed to find the test-plugin."); + return null; +} + this.OnRefTestLoad = function OnRefTestLoad(win) { gCrashDumpDir = CC[NS_DIRECTORY_SERVICE_CONTRACTID] @@ -267,6 +284,17 @@ this.OnRefTestLoad = function OnRefTestLoad(win) document.getElementById("reftest-window").appendChild(gBrowser); #endif + // reftests should have the test plugins enabled, not click-to-play + let plugin1 = getTestPlugin("Test Plug-in"); + let plugin2 = getTestPlugin("Second Test Plug-in"); + if (plugin1 && plugin2) { + gTestPluginEnabledStates = [plugin1.enabledState, plugin2.enabledState]; + plugin1.enabledState = CI.nsIPluginTag.STATE_ENABLED; + plugin2.enabledState = CI.nsIPluginTag.STATE_ENABLED; + } else { + LogWarning("Could not get test plugin tags."); + } + gBrowserMessageManager = gBrowser.QueryInterface(CI.nsIFrameLoaderOwner) .frameLoader.messageManager; // The content script waits for the initial onload, then notifies @@ -498,6 +526,14 @@ function StartTests() function OnRefTestUnload() { + let plugin1 = getTestPlugin("Test Plug-in"); + let plugin2 = getTestPlugin("Second Test Plug-in"); + if (plugin1 && plugin2) { + plugin1.enabledState = gTestPluginEnabledStates[0]; + plugin2.enabledState = gTestPluginEnabledStates[1]; + } else { + LogWarning("Failed to get test plugin tags."); + } } // Read all available data from an input stream and return it From ce4d217ed21bf06234a455a41a23d1c3e1668215 Mon Sep 17 00:00:00 2001 From: Georg Fritzsche Date: Wed, 4 Sep 2013 16:05:40 +0200 Subject: [PATCH 37/86] Bug 899080 - Test fixup part 2 - dom/plugins. r=bsmedberg --- dom/plugins/test/mochitest/test_GCrace.html | 6 ++- .../mochitest/test_NPNVdocumentOrigin.html | 6 ++- ...test_NPPVpluginWantsAllNetworkStreams.html | 15 ++++-- dom/plugins/test/mochitest/test_bug479979.xul | 6 ++- .../test/mochitest/test_bug532208.html | 7 ++- .../test/mochitest/test_bug539565-1.html | 2 + .../test/mochitest/test_bug539565-2.html | 2 + .../test/mochitest/test_bug751809.html | 20 +------- .../test/mochitest/test_bug771202.html | 2 + .../test/mochitest/test_bug777098.html | 2 + .../test/mochitest/test_bug784131.html | 6 +++ .../test/mochitest/test_bug813906.html | 20 ++++---- .../test/mochitest/test_bug854082.html | 2 + .../test/mochitest/test_bug863792.html | 2 + dom/plugins/test/mochitest/test_busy_hang.xul | 4 ++ .../test/mochitest/test_clear_site_data.html | 5 ++ .../test/mochitest/test_cocoa_focus.html | 2 + .../mochitest/test_cocoa_window_focus.html | 2 + .../test/mochitest/test_convertpoint.xul | 4 ++ dom/plugins/test/mochitest/test_cookies.html | 6 ++- dom/plugins/test/mochitest/test_copyText.html | 2 + .../mochitest/test_crash_nested_loop.html | 2 + .../test/mochitest/test_crash_notify.xul | 4 ++ .../mochitest/test_crash_notify_no_report.xul | 4 ++ .../test/mochitest/test_crash_submit.xul | 4 ++ dom/plugins/test/mochitest/test_crashing.html | 2 + .../test/mochitest/test_crashing2.html | 2 + .../test/mochitest/test_defaultValue.html | 6 ++- .../test/mochitest/test_enumerate.html | 10 ++-- dom/plugins/test/mochitest/test_fullpage.html | 2 + .../mochitest/test_getauthenticationinfo.html | 3 ++ .../test/mochitest/test_hang_submit.xul | 4 ++ dom/plugins/test/mochitest/test_hanging.html | 2 + dom/plugins/test/mochitest/test_idle_hang.xul | 4 ++ .../mochitest/test_instance_re-parent.html | 36 +++++++------ .../mochitest/test_instance_unparent1.html | 14 ++--- .../mochitest/test_instance_unparent2.html | 26 +++++----- .../mochitest/test_instance_unparent3.html | 18 ++++--- .../test/mochitest/test_instantiation.html | 2 + .../test_multipleinstanceobjects.html | 8 +-- .../mochitest/test_newstreamondestroy.html | 10 ++-- .../test/mochitest/test_npn_asynccall.html | 16 +++--- .../test/mochitest/test_npn_timers.html | 16 +++--- .../test/mochitest/test_npobject_getters.html | 6 ++- dom/plugins/test/mochitest/test_npruntime.xul | 4 ++ .../mochitest/test_npruntime_construct.html | 5 ++ .../mochitest/test_npruntime_identifiers.html | 2 + .../mochitest/test_npruntime_npnevaluate.html | 51 ++++++++++--------- .../mochitest/test_npruntime_npninvoke.html | 13 +++-- .../test_npruntime_npninvokedefault.html | 16 +++--- .../test_npruntime_npnsetexception.html | 14 ++--- dom/plugins/test/mochitest/test_painting.html | 29 ++++++----- .../test_plugin_scroll_painting.html | 4 ++ .../test_plugin_tag_clicktoplay.html | 26 +++++----- .../mochitest/test_pluginstream_asfile.html | 4 ++ .../test_pluginstream_asfileonly.html | 4 ++ .../test/mochitest/test_pluginstream_err.html | 2 + .../mochitest/test_pluginstream_geturl.html | 4 ++ .../test_pluginstream_geturlnotify.html | 4 ++ .../test_pluginstream_newstream.html | 4 ++ .../mochitest/test_pluginstream_post.html | 4 ++ .../test_pluginstream_poststream.html | 4 ++ .../mochitest/test_pluginstream_referer.html | 11 ++-- .../mochitest/test_pluginstream_seek.html | 4 ++ .../test_pluginstream_seek_close.html | 2 + .../test/mochitest/test_pluginstream_src.html | 4 ++ .../test_pluginstream_src_dynamic.html | 4 ++ .../test_pluginstream_src_referer.html | 2 + .../test/mochitest/test_positioning.html | 10 ++-- .../test_privatemode_perwindowpb.xul | 4 ++ .../mochitest/test_propertyAndMethod.html | 6 ++- .../test_queryContentsScaleFactor.html | 6 ++- .../mochitest/test_redirect_handling.html | 15 ++++-- .../test_refresh_navigator_plugins.html | 3 ++ .../test/mochitest/test_secondPlugin.html | 7 ++- .../test/mochitest/test_src_url_change.html | 14 ++--- .../test/mochitest/test_streamNotify.html | 6 ++- .../test/mochitest/test_streamatclose.html | 15 +++--- .../test/mochitest/test_twostreams.html | 2 + .../test/mochitest/test_visibility.html | 1 + .../mochitest/test_windowed_invalidate.html | 25 +++++---- dom/plugins/test/mochitest/test_wmode.xul | 4 ++ .../test_xulbrowser_plugin_visibility.xul | 2 + .../test/mochitest/test_zero_opacity.html | 13 +++-- dom/plugins/test/mochitest/utils.js | 27 ++++++++++ 85 files changed, 483 insertions(+), 222 deletions(-) diff --git a/dom/plugins/test/mochitest/test_GCrace.html b/dom/plugins/test/mochitest/test_GCrace.html index 3300c9fef0d4..027bc5b78e2e 100644 --- a/dom/plugins/test/mochitest/test_GCrace.html +++ b/dom/plugins/test/mochitest/test_GCrace.html @@ -3,15 +3,15 @@ +

- - + + diff --git a/dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html b/dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html index c8db4176e155..9a7ff19416da 100644 --- a/dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html +++ b/dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html @@ -2,12 +2,12 @@ Test NPNVdocumentOrigin + - - + + diff --git a/dom/plugins/test/mochitest/test_NPPVpluginWantsAllNetworkStreams.html b/dom/plugins/test/mochitest/test_NPPVpluginWantsAllNetworkStreams.html index 1a1f7ccb950f..6baed937130f 100644 --- a/dom/plugins/test/mochitest/test_NPPVpluginWantsAllNetworkStreams.html +++ b/dom/plugins/test/mochitest/test_NPPVpluginWantsAllNetworkStreams.html @@ -2,14 +2,14 @@ Test NPPVpluginWantsAllNetworkStreams + - - - + + + diff --git a/dom/plugins/test/mochitest/test_bug479979.xul b/dom/plugins/test/mochitest/test_bug479979.xul index 47154f1c9322..473b299f149c 100644 --- a/dom/plugins/test/mochitest/test_bug479979.xul +++ b/dom/plugins/test/mochitest/test_bug479979.xul @@ -8,12 +8,12 @@ NPAPI Set Undefined Value Test - - + + diff --git a/dom/plugins/test/mochitest/test_bug532208.html b/dom/plugins/test/mochitest/test_bug532208.html index 7afb5187da8e..85fad098eb81 100644 --- a/dom/plugins/test/mochitest/test_bug532208.html +++ b/dom/plugins/test/mochitest/test_bug532208.html @@ -4,13 +4,13 @@ + - + + diff --git a/dom/plugins/test/mochitest/test_bug539565-1.html b/dom/plugins/test/mochitest/test_bug539565-1.html index 69f26cc7d8cb..9f0c21a220aa 100644 --- a/dom/plugins/test/mochitest/test_bug539565-1.html +++ b/dom/plugins/test/mochitest/test_bug539565-1.html @@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=539565 Test #1 for Bug 539565 + diff --git a/dom/plugins/test/mochitest/test_bug539565-2.html b/dom/plugins/test/mochitest/test_bug539565-2.html index 843309a5319d..2eef252042b3 100644 --- a/dom/plugins/test/mochitest/test_bug539565-2.html +++ b/dom/plugins/test/mochitest/test_bug539565-2.html @@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=539565 Test #2 for Bug 539565 + diff --git a/dom/plugins/test/mochitest/test_bug751809.html b/dom/plugins/test/mochitest/test_bug751809.html index 344bd7489af9..27a6b8800bc8 100644 --- a/dom/plugins/test/mochitest/test_bug751809.html +++ b/dom/plugins/test/mochitest/test_bug751809.html @@ -4,25 +4,11 @@ + @@ -104,8 +90,6 @@ } Services.prefs.clearUserPref("plugins.click_to_play"); - let plugin = getTestPlugin(); - plugin.enabledState = Components.interfaces.nsIPluginTag.STATE_ENABLED; SimpleTest.finish(); } diff --git a/dom/plugins/test/mochitest/test_bug771202.html b/dom/plugins/test/mochitest/test_bug771202.html index 83f6787a0936..26252f4e005e 100644 --- a/dom/plugins/test/mochitest/test_bug771202.html +++ b/dom/plugins/test/mochitest/test_bug771202.html @@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=771202 Test for Bug 771202 + @@ -16,6 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=771202 /** Test for recreating spliced plugin prototype chains after tranplant. **/ SimpleTest.waitForExplicitFinish(); +setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); function go() { // Set things up. diff --git a/dom/plugins/test/mochitest/test_bug777098.html b/dom/plugins/test/mochitest/test_bug777098.html index 6b1385dedd38..79a2559ff068 100644 --- a/dom/plugins/test/mochitest/test_bug777098.html +++ b/dom/plugins/test/mochitest/test_bug777098.html @@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=777098 Test for Bug 777098 + @@ -16,6 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=777098 /** Test for passing dead NPObjects back into plugins. **/ SimpleTest.waitForExplicitFinish(); +setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); function go() { var plugin = document.getElementById('plugin'); diff --git a/dom/plugins/test/mochitest/test_bug784131.html b/dom/plugins/test/mochitest/test_bug784131.html index deed04d981c1..eac426bb628f 100644 --- a/dom/plugins/test/mochitest/test_bug784131.html +++ b/dom/plugins/test/mochitest/test_bug784131.html @@ -3,6 +3,7 @@ Test for Bug 784131 + @@ -10,10 +11,15 @@ + +
+ + @@ -16,17 +17,9 @@ function f() { } - - - - - - - - - + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug854082.html b/dom/plugins/test/mochitest/test_bug854082.html index 6561d02eef80..22e133c7aa94 100644 --- a/dom/plugins/test/mochitest/test_bug854082.html +++ b/dom/plugins/test/mochitest/test_bug854082.html @@ -3,6 +3,7 @@ Test for Bug 854082 + @@ -14,6 +15,7 @@ // crash SimpleTest.waitForExplicitFinish(); + setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); // Create an object that will spawn asynchronously var o = document.createElement("object"); diff --git a/dom/plugins/test/mochitest/test_bug863792.html b/dom/plugins/test/mochitest/test_bug863792.html index 0b0b8412a060..0bb60f89e74e 100644 --- a/dom/plugins/test/mochitest/test_bug863792.html +++ b/dom/plugins/test/mochitest/test_bug863792.html @@ -3,6 +3,7 @@ Test for Bug 863792 + @@ -14,6 +15,7 @@ // inside NPP_New. We should not leak the instance. See also test_bug854082 SimpleTest.waitForExplicitFinish(); +setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); var i = document.createElement("iframe"); i.src = "file_bug863792.html"; diff --git a/dom/plugins/test/mochitest/test_busy_hang.xul b/dom/plugins/test/mochitest/test_busy_hang.xul index f4842c07e921..b385a0ffebe6 100644 --- a/dom/plugins/test/mochitest/test_busy_hang.xul +++ b/dom/plugins/test/mochitest/test_busy_hang.xul @@ -10,6 +10,10 @@ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> + diff --git a/dom/plugins/test/mochitest/test_clear_site_data.html b/dom/plugins/test/mochitest/test_clear_site_data.html index dce7c5cb3f92..749376d8deff 100644 --- a/dom/plugins/test/mochitest/test_clear_site_data.html +++ b/dom/plugins/test/mochitest/test_clear_site_data.html @@ -3,8 +3,13 @@ NPAPI ClearSiteData/GetSitesWithData Functionality + + + + + + diff --git a/dom/plugins/test/mochitest/test_cookies.html b/dom/plugins/test/mochitest/test_cookies.html index 7cd22d517fed..6e1934994fd0 100644 --- a/dom/plugins/test/mochitest/test_cookies.html +++ b/dom/plugins/test/mochitest/test_cookies.html @@ -2,12 +2,14 @@ NPAPI Cookie Tests + - + + diff --git a/dom/plugins/test/mochitest/test_copyText.html b/dom/plugins/test/mochitest/test_copyText.html index 032c94c27f31..86e67da81df2 100644 --- a/dom/plugins/test/mochitest/test_copyText.html +++ b/dom/plugins/test/mochitest/test_copyText.html @@ -3,6 +3,7 @@ Test copying text from browser to plugin + diff --git a/dom/plugins/test/mochitest/test_crash_nested_loop.html b/dom/plugins/test/mochitest/test_crash_nested_loop.html index 702a3bf69935..2d20e63db7a7 100644 --- a/dom/plugins/test/mochitest/test_crash_nested_loop.html +++ b/dom/plugins/test/mochitest/test_crash_nested_loop.html @@ -1,10 +1,12 @@ Plugin crashing in nested loop + + diff --git a/dom/plugins/test/mochitest/test_crash_notify_no_report.xul b/dom/plugins/test/mochitest/test_crash_notify_no_report.xul index 9f3a1429aa72..3e0a64e745de 100644 --- a/dom/plugins/test/mochitest/test_crash_notify_no_report.xul +++ b/dom/plugins/test/mochitest/test_crash_notify_no_report.xul @@ -8,6 +8,10 @@ Plugin Crash Notification Test + diff --git a/dom/plugins/test/mochitest/test_crash_submit.xul b/dom/plugins/test/mochitest/test_crash_submit.xul index 78a3ec1ce436..ba8044f38e23 100644 --- a/dom/plugins/test/mochitest/test_crash_submit.xul +++ b/dom/plugins/test/mochitest/test_crash_submit.xul @@ -10,6 +10,10 @@ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> + diff --git a/dom/plugins/test/mochitest/test_crashing.html b/dom/plugins/test/mochitest/test_crashing.html index 3878ff0943f3..4fa6f7bb549a 100644 --- a/dom/plugins/test/mochitest/test_crashing.html +++ b/dom/plugins/test/mochitest/test_crashing.html @@ -1,10 +1,12 @@ Plugin crashing + + + - - + + diff --git a/dom/plugins/test/mochitest/test_enumerate.html b/dom/plugins/test/mochitest/test_enumerate.html index 0d7ad96ce839..035c42eb5aae 100644 --- a/dom/plugins/test/mochitest/test_enumerate.html +++ b/dom/plugins/test/mochitest/test_enumerate.html @@ -2,17 +2,17 @@ NPAPI Cookie Tests + -

- - + +

+ + diff --git a/dom/plugins/test/mochitest/test_fullpage.html b/dom/plugins/test/mochitest/test_fullpage.html index 5a348cde0d11..18ef16380d93 100644 --- a/dom/plugins/test/mochitest/test_fullpage.html +++ b/dom/plugins/test/mochitest/test_fullpage.html @@ -3,6 +3,7 @@ + @@ -11,6 +12,7 @@ + @@ -58,6 +59,8 @@ function iframeLoad() { } SimpleTest.waitForExplicitFinish(); +setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); + var iframe = document.getElementById("iframe"); var am = Cc["@mozilla.org/network/http-auth-manager;1"]. getService(Ci.nsIHttpAuthManager); diff --git a/dom/plugins/test/mochitest/test_hang_submit.xul b/dom/plugins/test/mochitest/test_hang_submit.xul index be2fa48a3788..24a26723c2e5 100644 --- a/dom/plugins/test/mochitest/test_hang_submit.xul +++ b/dom/plugins/test/mochitest/test_hang_submit.xul @@ -10,6 +10,10 @@ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> + diff --git a/dom/plugins/test/mochitest/test_hanging.html b/dom/plugins/test/mochitest/test_hanging.html index bd4cfa7779c9..cecf0a8ee86e 100644 --- a/dom/plugins/test/mochitest/test_hanging.html +++ b/dom/plugins/test/mochitest/test_hanging.html @@ -1,10 +1,12 @@ Plugin hanging + + diff --git a/dom/plugins/test/mochitest/test_instance_re-parent.html b/dom/plugins/test/mochitest/test_instance_re-parent.html index 3eb2d722f19f..fd2d1f9676b2 100644 --- a/dom/plugins/test/mochitest/test_instance_re-parent.html +++ b/dom/plugins/test/mochitest/test_instance_re-parent.html @@ -5,27 +5,17 @@ + -

- -
- - -
-
-
- + +

+ +
+ + +
+
+
diff --git a/dom/plugins/test/mochitest/test_instance_unparent1.html b/dom/plugins/test/mochitest/test_instance_unparent1.html index a9dea72489a2..b8d42addd0d3 100644 --- a/dom/plugins/test/mochitest/test_instance_unparent1.html +++ b/dom/plugins/test/mochitest/test_instance_unparent1.html @@ -4,17 +4,13 @@ Test removing an instance's DOM node + -

- -
- -
- + +

+ +
+ +
diff --git a/dom/plugins/test/mochitest/test_instance_unparent2.html b/dom/plugins/test/mochitest/test_instance_unparent2.html index 7756c0e2db32..6b251b896ec3 100644 --- a/dom/plugins/test/mochitest/test_instance_unparent2.html +++ b/dom/plugins/test/mochitest/test_instance_unparent2.html @@ -4,23 +4,13 @@ Test removing an instance's DOM node + -

- -
- -
- -
-
- -
-
- + +

+ +
+ +
+ +
+
+ +
+
diff --git a/dom/plugins/test/mochitest/test_instance_unparent3.html b/dom/plugins/test/mochitest/test_instance_unparent3.html index 92f8e89765e7..8e454e784aad 100644 --- a/dom/plugins/test/mochitest/test_instance_unparent3.html +++ b/dom/plugins/test/mochitest/test_instance_unparent3.html @@ -4,19 +4,13 @@ Test removing an instance's DOM node + -

- -
-
- - - + +

+ +
+
+ + diff --git a/dom/plugins/test/mochitest/test_instantiation.html b/dom/plugins/test/mochitest/test_instantiation.html index 732cf5e073ff..d84d39ebdd30 100644 --- a/dom/plugins/test/mochitest/test_instantiation.html +++ b/dom/plugins/test/mochitest/test_instantiation.html @@ -1,12 +1,14 @@ Plugin instantiation + + - - - + + + diff --git a/dom/plugins/test/mochitest/test_newstreamondestroy.html b/dom/plugins/test/mochitest/test_newstreamondestroy.html index 811465ae8efb..9f1c56beeb2d 100644 --- a/dom/plugins/test/mochitest/test_newstreamondestroy.html +++ b/dom/plugins/test/mochitest/test_newstreamondestroy.html @@ -1,17 +1,15 @@ NPN_GetURL called from NPP_Destroy + -

- - - + +

+ + diff --git a/dom/plugins/test/mochitest/test_npn_asynccall.html b/dom/plugins/test/mochitest/test_npn_asynccall.html index 64dc5bfcd62c..14617aa5f277 100644 --- a/dom/plugins/test/mochitest/test_npn_asynccall.html +++ b/dom/plugins/test/mochitest/test_npn_asynccall.html @@ -3,19 +3,16 @@ NPN_AsyncCallback Tests + -

- - - - - + +

+ + + + diff --git a/dom/plugins/test/mochitest/test_npn_timers.html b/dom/plugins/test/mochitest/test_npn_timers.html index 4d2ad8cac087..076c04f0dace 100644 --- a/dom/plugins/test/mochitest/test_npn_timers.html +++ b/dom/plugins/test/mochitest/test_npn_timers.html @@ -3,19 +3,16 @@ NPN_Timer Tests + -

- - - - - + +

+ + + + diff --git a/dom/plugins/test/mochitest/test_npobject_getters.html b/dom/plugins/test/mochitest/test_npobject_getters.html index b6105207a720..4c3a6981477b 100644 --- a/dom/plugins/test/mochitest/test_npobject_getters.html +++ b/dom/plugins/test/mochitest/test_npobject_getters.html @@ -1,14 +1,14 @@ NPNV*NPObject accessibility tests + - - + + diff --git a/dom/plugins/test/mochitest/test_npruntime.xul b/dom/plugins/test/mochitest/test_npruntime.xul index 7a335500b827..2d8f83ee6714 100644 --- a/dom/plugins/test/mochitest/test_npruntime.xul +++ b/dom/plugins/test/mochitest/test_npruntime.xul @@ -8,6 +8,10 @@ Basic Plugin Tests + diff --git a/dom/plugins/test/mochitest/test_npruntime_construct.html b/dom/plugins/test/mochitest/test_npruntime_construct.html index a8845c470e50..f481884f9f96 100644 --- a/dom/plugins/test/mochitest/test_npruntime_construct.html +++ b/dom/plugins/test/mochitest/test_npruntime_construct.html @@ -3,9 +3,14 @@ Test whether windowless plugins receive correct visible/invisible notifications. + + +

diff --git a/dom/plugins/test/mochitest/test_npruntime_identifiers.html b/dom/plugins/test/mochitest/test_npruntime_identifiers.html index 158c9638ff7a..cba0355440c1 100644 --- a/dom/plugins/test/mochitest/test_npruntime_identifiers.html +++ b/dom/plugins/test/mochitest/test_npruntime_identifiers.html @@ -3,6 +3,7 @@ NPN_Invoke Tests + @@ -15,6 +16,7 @@ // that identifiers are translated to values correctly. SimpleTest.waitForExplicitFinish(); + setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); var testsRun = 0; diff --git a/dom/plugins/test/mochitest/test_npruntime_npnevaluate.html b/dom/plugins/test/mochitest/test_npruntime_npnevaluate.html index f365b2d83934..1223c55e859e 100644 --- a/dom/plugins/test/mochitest/test_npruntime_npnevaluate.html +++ b/dom/plugins/test/mochitest/test_npruntime_npnevaluate.html @@ -3,18 +3,15 @@ NPN_Evaluate Tests + -

- - - - - + +

+ + + +
diff --git a/dom/plugins/test/mochitest/test_npruntime_npninvoke.html b/dom/plugins/test/mochitest/test_npruntime_npninvoke.html index 885266c2a9a7..86eb04c23714 100644 --- a/dom/plugins/test/mochitest/test_npruntime_npninvoke.html +++ b/dom/plugins/test/mochitest/test_npruntime_npninvoke.html @@ -3,14 +3,11 @@ NPN_Invoke Tests + -

- - - - + +

+ + + +
diff --git a/dom/plugins/test/mochitest/test_npruntime_npninvokedefault.html b/dom/plugins/test/mochitest/test_npruntime_npninvokedefault.html index bb24d3b20de6..597db0cc1c96 100644 --- a/dom/plugins/test/mochitest/test_npruntime_npninvokedefault.html +++ b/dom/plugins/test/mochitest/test_npruntime_npninvokedefault.html @@ -3,19 +3,16 @@ NPN_Invoke_Default Tests + -

- - - - - + +

+ + + +
diff --git a/dom/plugins/test/mochitest/test_npruntime_npnsetexception.html b/dom/plugins/test/mochitest/test_npruntime_npnsetexception.html index e5de74cefc7d..a926a2ad19c6 100644 --- a/dom/plugins/test/mochitest/test_npruntime_npnsetexception.html +++ b/dom/plugins/test/mochitest/test_npruntime_npnsetexception.html @@ -3,17 +3,14 @@ NPN_SetException Tests + -

- - - - - + +

+ + + +
diff --git a/dom/plugins/test/mochitest/test_painting.html b/dom/plugins/test/mochitest/test_painting.html index a8a6e973f15b..44bbeb3f274c 100644 --- a/dom/plugins/test/mochitest/test_painting.html +++ b/dom/plugins/test/mochitest/test_painting.html @@ -37,23 +37,11 @@ -

-
- -
- -
-
- -
-
+ +

+
+ +
+ +
+
+ +
+
+ diff --git a/dom/plugins/test/mochitest/test_plugin_scroll_painting.html b/dom/plugins/test/mochitest/test_plugin_scroll_painting.html index e065e9f6558a..cfb363125c77 100644 --- a/dom/plugins/test/mochitest/test_plugin_scroll_painting.html +++ b/dom/plugins/test/mochitest/test_plugin_scroll_painting.html @@ -3,6 +3,10 @@ Test that scrolling a windowless plugin doesn't force us to repaint it + + diff --git a/dom/plugins/test/mochitest/test_plugin_tag_clicktoplay.html b/dom/plugins/test/mochitest/test_plugin_tag_clicktoplay.html index 27bb8a07fdb0..fcc84fdd59e2 100644 --- a/dom/plugins/test/mochitest/test_plugin_tag_clicktoplay.html +++ b/dom/plugins/test/mochitest/test_plugin_tag_clicktoplay.html @@ -5,30 +5,30 @@ Test Modifying Plugin click-to-play Flag + diff --git a/dom/plugins/test/mochitest/test_pluginstream_asfile.html b/dom/plugins/test/mochitest/test_pluginstream_asfile.html index 1418479510c5..af7110b6a5a5 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_asfile.html +++ b/dom/plugins/test/mochitest/test_pluginstream_asfile.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_asfileonly.html b/dom/plugins/test/mochitest/test_pluginstream_asfileonly.html index 05dcd1df1535..be49cc4601c1 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_asfileonly.html +++ b/dom/plugins/test/mochitest/test_pluginstream_asfileonly.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_err.html b/dom/plugins/test/mochitest/test_pluginstream_err.html index 8e8d234c44b3..dc5d598f3998 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_err.html +++ b/dom/plugins/test/mochitest/test_pluginstream_err.html @@ -9,6 +9,7 @@ Tests for plugin stream error conditions. NPAPI Stream Error Tests + @@ -32,6 +33,7 @@ Tests for plugin stream error conditions. function $(id) { return document.getElementById(id); } SimpleTest.waitForExplicitFinish(); +setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); var tests = [ diff --git a/dom/plugins/test/mochitest/test_pluginstream_geturl.html b/dom/plugins/test/mochitest/test_pluginstream_geturl.html index 36c8c7ac1b0f..12de91f70e3e 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_geturl.html +++ b/dom/plugins/test/mochitest/test_pluginstream_geturl.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html b/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html index 58def7682c3a..07a813d6f4bf 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html +++ b/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_newstream.html b/dom/plugins/test/mochitest/test_pluginstream_newstream.html index f03d59fb28e4..a499196f0d24 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_newstream.html +++ b/dom/plugins/test/mochitest/test_pluginstream_newstream.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_post.html b/dom/plugins/test/mochitest/test_pluginstream_post.html index bf0c0a3e702a..a74e0e6f4254 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_post.html +++ b/dom/plugins/test/mochitest/test_pluginstream_post.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_poststream.html b/dom/plugins/test/mochitest/test_pluginstream_poststream.html index 4d642d8357df..f32ff7cf7985 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_poststream.html +++ b/dom/plugins/test/mochitest/test_pluginstream_poststream.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_referer.html b/dom/plugins/test/mochitest/test_pluginstream_referer.html index 66cf523b658a..e0b3409928d2 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_referer.html +++ b/dom/plugins/test/mochitest/test_pluginstream_referer.html @@ -2,17 +2,14 @@ Do plugin stream requests send the Referer header correctly? + -

- - - - +

+ + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_seek.html b/dom/plugins/test/mochitest/test_pluginstream_seek.html index 63b409642457..984d43d3b013 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_seek.html +++ b/dom/plugins/test/mochitest/test_pluginstream_seek.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_seek_close.html b/dom/plugins/test/mochitest/test_pluginstream_seek_close.html index af127582f888..07958ddd7b41 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_seek_close.html +++ b/dom/plugins/test/mochitest/test_pluginstream_seek_close.html @@ -3,12 +3,14 @@ NPAPI Seekable NPStream Test + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_src_dynamic.html b/dom/plugins/test/mochitest/test_pluginstream_src_dynamic.html index 921d36c21b32..b679008a3dcf 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_src_dynamic.html +++ b/dom/plugins/test/mochitest/test_pluginstream_src_dynamic.html @@ -5,6 +5,10 @@ src="/tests/SimpleTest/SimpleTest.js"> + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_src_referer.html b/dom/plugins/test/mochitest/test_pluginstream_src_referer.html index fe85de4d069a..9a191b82c6fa 100644 --- a/dom/plugins/test/mochitest/test_pluginstream_src_referer.html +++ b/dom/plugins/test/mochitest/test_pluginstream_src_referer.html @@ -2,6 +2,7 @@ Do plugin stream src requests send the Referer header correctly? + @@ -10,6 +11,7 @@ + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 8b28ccd272ef..20e161a852dc 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1370,7 +1370,7 @@ fails-if(Android) == 488685-1.html 488685-1-ref.html == 495385-2c.html 495385-2-ref.html == 495385-2d.html 495385-2-ref.html == 495385-2e.html 495385-2-ref.html -== 495385-2f.xhtml 495385-2-ref.html +pref(dom.use_xbl_scopes_for_remote_xul,true) == 495385-2f.xhtml 495385-2-ref.html == 495385-2g.html 495385-2-ref.html == 495385-2h.html 495385-2-ref.html == 495385-2i.html 495385-2-ref.html diff --git a/layout/style/test/test_selectors_on_anonymous_content.html b/layout/style/test/test_selectors_on_anonymous_content.html index 89da83fe8869..7a65f532894c 100644 --- a/layout/style/test/test_selectors_on_anonymous_content.html +++ b/layout/style/test/test_selectors_on_anonymous_content.html @@ -42,7 +42,7 @@ function run() { style_text.data = selector + "{ z-index: " + zi + " }"; var doc_div = document.getElementById("display"); - var anon_div = document.getAnonymousNodes(doc_div)[0]; + var anon_div = SpecialPowers.unwrap(SpecialPowers.wrap(document).getAnonymousNodes(doc_div))[0]; var should_match = []; var should_not_match = []; (matches_docdiv ? should_match : should_not_match).push(doc_div); diff --git a/layout/xul/base/src/crashtests/328135-1.xul b/layout/xul/base/src/crashtests/328135-1.xul index 1a532e1869a3..77a4679099db 100644 --- a/layout/xul/base/src/crashtests/328135-1.xul +++ b/layout/xul/base/src/crashtests/328135-1.xul @@ -9,7 +9,7 @@ function init() { var pop = document.getElementsByTagName("popup")[0]; - document.getAnonymousNodes(pop)[0]; + SpecialPowers.wrap(document).getAnonymousNodes(pop)[0]; eval.eee = document.documentElement; }; diff --git a/layout/xul/base/src/crashtests/329477-1.xhtml b/layout/xul/base/src/crashtests/329477-1.xhtml index 87c8bd63666f..fcbd3da872cc 100644 --- a/layout/xul/base/src/crashtests/329477-1.xhtml +++ b/layout/xul/base/src/crashtests/329477-1.xhtml @@ -9,8 +9,8 @@ function init() { var textbox = document.getElementsByTagName("textbox")[0]; - var hbox = document.getAnonymousNodes(textbox)[0]; - var menupopup = document.getAnonymousNodes(hbox)[1]; + var hbox = SpecialPowers.wrap(document).getAnonymousNodes(textbox)[0]; + var menupopup = SpecialPowers.wrap(document).getAnonymousNodes(hbox)[1]; menupopup.click(); } diff --git a/toolkit/content/tests/widgets/test_popupanchor.xul b/toolkit/content/tests/widgets/test_popupanchor.xul index 404c177067f1..b255c06ba8b2 100644 --- a/toolkit/content/tests/widgets/test_popupanchor.xul +++ b/toolkit/content/tests/widgets/test_popupanchor.xul @@ -383,7 +383,7 @@ SimpleTest.waitForExplicitFinish(); addEventListener("load", function() { // anchor is set by the test runner above panel = document.getElementById("testPanel"); - arrow = document.getAnonymousElementByAttribute(panel, "anonid", "arrow"); + arrow = SpecialPowers.wrap(document).getAnonymousElementByAttribute(panel, "anonid", "arrow"); // Cancel the arrow panel slide-in transition (bug 767133) so the size and // position are "stable" enough to test without jumping through hoops... arrow.style.transition = "none"; From 618a975abe0859c993582619820a176ce924ab3b Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 4 Sep 2013 19:05:52 -0700 Subject: [PATCH 68/86] Bug 912322 - Stop making XBL methods available to the web. r=bz --- dom/webidl/Document.webidl | 5 ++- js/xpconnect/tests/mochitest/Makefile.in | 1 + .../tests/mochitest/test_bug912322.html | 35 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 js/xpconnect/tests/mochitest/test_bug912322.html diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index 81d84c799c74..518fbb823926 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -277,11 +277,14 @@ partial interface Document { partial interface Document { // nsIDOMDocumentXBL. Wish we could make these [ChromeOnly], but // that would likely break bindings running with the page principal. + [Func="IsChromeOrXBL"] NodeList? getAnonymousNodes(Element elt); + [Func="IsChromeOrXBL"] Element? getAnonymousElementByAttribute(Element elt, DOMString attrName, DOMString attrValue); + [Func="IsChromeOrXBL"] Element? getBindingParent(Node node); - [Throws] + [Throws, Func="IsChromeOrXBL"] void loadBindingDocument(DOMString documentURL); // nsIDOMDocumentTouch diff --git a/js/xpconnect/tests/mochitest/Makefile.in b/js/xpconnect/tests/mochitest/Makefile.in index 1d58390ff8f7..df908fcf40f1 100644 --- a/js/xpconnect/tests/mochitest/Makefile.in +++ b/js/xpconnect/tests/mochitest/Makefile.in @@ -87,6 +87,7 @@ MOCHITEST_FILES = chrome_wrappers_helper.html \ test_bug865260.html \ test_bug870423.html \ test_bug871887.html \ + test_bug912322.html \ file_crosscompartment_weakmap.html \ test_crosscompartment_weakmap.html \ test_asmjs.html \ diff --git a/js/xpconnect/tests/mochitest/test_bug912322.html b/js/xpconnect/tests/mochitest/test_bug912322.html new file mode 100644 index 000000000000..22fcc9f96c50 --- /dev/null +++ b/js/xpconnect/tests/mochitest/test_bug912322.html @@ -0,0 +1,35 @@ + + + + + + Test for Bug 912322 + + + + + +Mozilla Bug 912322 +

+ +
+
+ + From 32806e97e55bc28753e76b8a689773a72ea1bb88 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 20:06:07 -0700 Subject: [PATCH 69/86] Bug 910782 - SpiderMonkey: Delete obsolete comments. r=jorendorff --- js/src/jsopcode.tbl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index b8229b3b9eac..9e72369ba3fc 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -223,7 +223,6 @@ OPDEF(JSOP_LEAVEFORLETIN, 105,"leaveforletin",NULL, 1, 0, 0, JOF_BYTE) /* The argument is the offset to the next statement and is used by IonMonkey. */ OPDEF(JSOP_LABEL, 106,"label", NULL, 5, 0, 0, JOF_JUMP) -/* Performs the dynamic validation step of type-checked asm.js. */ OPDEF(JSOP_UNUSED107, 107,"unused107", NULL, 1, 0, 0, JOF_BYTE) /* Like JSOP_FUNAPPLY but for f.call instead of f.apply. */ @@ -275,11 +274,6 @@ OPDEF(JSOP_EVAL, 123,"eval", NULL, 3, -1, 1, JOF_UINT16|JOF_ */ OPDEF(JSOP_ENUMELEM, 124,"enumelem", NULL, 1, 3, 0, JOF_BYTE |JOF_SET|JOF_TMPSLOT) -/* - * Getter and setter prefix bytecodes. These modify the next bytecode, either - * an assignment or a property initializer code, which then defines a property - * getter or setter. - */ OPDEF(JSOP_UNUSED125, 125, "unused125", NULL, 1, 0, 0, JOF_BYTE) OPDEF(JSOP_UNUSED126, 126, "unused126", NULL, 1, 0, 0, JOF_BYTE) From 663d485da74d412c6098bf1d9cdca5a934fc7127 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 20:06:07 -0700 Subject: [PATCH 70/86] Bug 910782 - SpiderMonkey: Simply uses of BRANCH. r=luke --- js/src/vm/Interpreter.cpp | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 89908b55639b..67b338b43a3a 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1303,9 +1303,10 @@ Interpret(JSContext *cx, RunState &state) #define BRANCH(n) \ JS_BEGIN_MACRO \ - regs.pc += (n); \ + int32_t nlen = (n); \ + regs.pc += nlen; \ op = (JSOp) *regs.pc; \ - if ((n) <= 0) \ + if (nlen <= 0) \ goto check_backedge; \ DO_OP(); \ JS_END_MACRO @@ -1705,19 +1706,15 @@ BEGIN_CASE(JSOP_DEFAULT) /* FALL THROUGH */ BEGIN_CASE(JSOP_GOTO) { - len = GET_JUMP_OFFSET(regs.pc); - BRANCH(len); + BRANCH(GET_JUMP_OFFSET(regs.pc)); } -END_CASE(JSOP_GOTO) BEGIN_CASE(JSOP_IFEQ) { bool cond = ToBooleanOp(regs); regs.sp--; - if (cond == false) { - len = GET_JUMP_OFFSET(regs.pc); - BRANCH(len); - } + if (!cond) + BRANCH(GET_JUMP_OFFSET(regs.pc)); } END_CASE(JSOP_IFEQ) @@ -1725,17 +1722,15 @@ BEGIN_CASE(JSOP_IFNE) { bool cond = ToBooleanOp(regs); regs.sp--; - if (cond != false) { - len = GET_JUMP_OFFSET(regs.pc); - BRANCH(len); - } + if (cond) + BRANCH(GET_JUMP_OFFSET(regs.pc)); } END_CASE(JSOP_IFNE) BEGIN_CASE(JSOP_OR) { bool cond = ToBooleanOp(regs); - if (cond == true) { + if (cond) { len = GET_JUMP_OFFSET(regs.pc); goto advanceAndDoOp; } @@ -1745,7 +1740,7 @@ END_CASE(JSOP_OR) BEGIN_CASE(JSOP_AND) { bool cond = ToBooleanOp(regs); - if (cond == false) { + if (!cond) { len = GET_JUMP_OFFSET(regs.pc); goto advanceAndDoOp; } @@ -1766,8 +1761,7 @@ END_CASE(JSOP_AND) regs.sp -= (spdec); \ if ((cond) == (diff_ != 0)) { \ ++regs.pc; \ - len = GET_JUMP_OFFSET(regs.pc); \ - BRANCH(len); \ + BRANCH(GET_JUMP_OFFSET(regs.pc)); \ } \ len = 1 + JSOP_IFEQ_LENGTH; \ goto advanceAndDoOp; \ @@ -2012,8 +2006,7 @@ BEGIN_CASE(JSOP_CASE) STRICT_EQUALITY_OP(==, cond); if (cond) { regs.sp--; - len = GET_JUMP_OFFSET(regs.pc); - BRANCH(len); + BRANCH(GET_JUMP_OFFSET(regs.pc)); } } END_CASE(JSOP_CASE) From 738e86b47649482b88a7ee433764a3348595da75 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 20:06:07 -0700 Subject: [PATCH 71/86] Bug 910782 - SpiderMonkey: Inline check_backedge, which is only used in one place. r=luke --- js/src/vm/Interpreter.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 67b338b43a3a..84fc30c0fd67 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1307,7 +1307,7 @@ Interpret(JSContext *cx, RunState &state) regs.pc += nlen; \ op = (JSOp) *regs.pc; \ if (nlen <= 0) \ - goto check_backedge; \ + CHECK_BRANCH(); \ DO_OP(); \ JS_END_MACRO @@ -1554,12 +1554,6 @@ END_CASE(JSOP_LOOPHEAD) BEGIN_CASE(JSOP_LABEL) END_CASE(JSOP_LABEL) -check_backedge: -{ - CHECK_BRANCH(); - DO_OP(); -} - BEGIN_CASE(JSOP_LOOPENTRY) #ifdef JS_ION From 11463021401a89beff1ceba68bffee7ce68bd8f3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 20:06:07 -0700 Subject: [PATCH 72/86] Bug 910782 - SpiderMonkey: Remove the for(;;) surrounding the interpreter loop, as it isn't needed, and adjust indentation for consistency. r=luke --- js/src/vm/Interpreter.cpp | 171 +++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 85 deletions(-) diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 84fc30c0fd67..859d1fcac0eb 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1416,88 +1416,88 @@ Interpret(JSContext *cx, RunState &state) if (rt->profilingScripts || cx->runtime()->debugHooks.interruptHook) switchMask = -1; /* Enable interrupts. */ - for (;;) { - advanceAndDoOp: - js::gc::MaybeVerifyBarriers(cx); - regs.pc += len; - op = (JSOp) *regs.pc; + advanceAndDoOp: + js::gc::MaybeVerifyBarriers(cx); + regs.pc += len; + op = (JSOp) *regs.pc; - do_op: - CHECK_PCCOUNT_INTERRUPTS(); - switchOp = int(op) | switchMask; - do_switch: - switch (switchOp) { + do_op: + CHECK_PCCOUNT_INTERRUPTS(); + switchOp = int(op) | switchMask; + do_switch: + switch (switchOp) { - case -1: +case -1: +{ JS_ASSERT(switchMask == -1); - { - bool moreInterrupts = false; - if (cx->runtime()->profilingScripts) { - if (!script->hasScriptCounts) - script->initScriptCounts(cx); - moreInterrupts = true; - } + bool moreInterrupts = false; - if (script->hasScriptCounts) { - PCCounts counts = script->getPCCounts(regs.pc); - counts.get(PCCounts::BASE_INTERP)++; - moreInterrupts = true; - } - - JSInterruptHook hook = cx->runtime()->debugHooks.interruptHook; - if (hook || script->stepModeEnabled()) { - RootedValue rval(cx); - JSTrapStatus status = JSTRAP_CONTINUE; - if (hook) - status = hook(cx, script, regs.pc, rval.address(), cx->runtime()->debugHooks.interruptHookData); - if (status == JSTRAP_CONTINUE && script->stepModeEnabled()) - status = Debugger::onSingleStep(cx, &rval); - switch (status) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - regs.fp()->setReturnValue(rval); - interpReturnOK = true; - goto forced_return; - case JSTRAP_THROW: - cx->setPendingException(rval); - goto error; - default:; - } - moreInterrupts = true; - } - - if (script->hasAnyBreakpointsOrStepMode()) - moreInterrupts = true; - - if (script->hasBreakpointsAt(regs.pc)) { - RootedValue rval(cx); - JSTrapStatus status = Debugger::onTrap(cx, &rval); - switch (status) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_RETURN: - regs.fp()->setReturnValue(rval); - interpReturnOK = true; - goto forced_return; - case JSTRAP_THROW: - cx->setPendingException(rval); - goto error; - default: - break; - } - JS_ASSERT(status == JSTRAP_CONTINUE); - JS_ASSERT(rval.isInt32() && rval.toInt32() == op); - } - - switchMask = moreInterrupts ? -1 : 0; - switchOp = int(op); - goto do_switch; + if (cx->runtime()->profilingScripts) { + if (!script->hasScriptCounts) + script->initScriptCounts(cx); + moreInterrupts = true; } + if (script->hasScriptCounts) { + PCCounts counts = script->getPCCounts(regs.pc); + counts.get(PCCounts::BASE_INTERP)++; + moreInterrupts = true; + } + + JSInterruptHook hook = cx->runtime()->debugHooks.interruptHook; + if (hook || script->stepModeEnabled()) { + RootedValue rval(cx); + JSTrapStatus status = JSTRAP_CONTINUE; + if (hook) + status = hook(cx, script, regs.pc, rval.address(), cx->runtime()->debugHooks.interruptHookData); + if (status == JSTRAP_CONTINUE && script->stepModeEnabled()) + status = Debugger::onSingleStep(cx, &rval); + switch (status) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + regs.fp()->setReturnValue(rval); + interpReturnOK = true; + goto forced_return; + case JSTRAP_THROW: + cx->setPendingException(rval); + goto error; + default:; + } + moreInterrupts = true; + } + + if (script->hasAnyBreakpointsOrStepMode()) + moreInterrupts = true; + + if (script->hasBreakpointsAt(regs.pc)) { + RootedValue rval(cx); + JSTrapStatus status = Debugger::onTrap(cx, &rval); + switch (status) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_RETURN: + regs.fp()->setReturnValue(rval); + interpReturnOK = true; + goto forced_return; + case JSTRAP_THROW: + cx->setPendingException(rval); + goto error; + default: + break; + } + JS_ASSERT(status == JSTRAP_CONTINUE); + JS_ASSERT(rval.isInt32() && rval.toInt32() == op); + } + + switchMask = moreInterrupts ? -1 : 0; + switchOp = int(op); + goto do_switch; +} + /* Various 1-byte no-ops. */ BEGIN_CASE(JSOP_NOP) BEGIN_CASE(JSOP_UNUSED125) @@ -3254,17 +3254,18 @@ BEGIN_CASE(JSOP_ARRAYPUSH) } END_CASE(JSOP_ARRAYPUSH) - default: - { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%d", op); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_BYTECODE, numBuf); - goto error; - } +default: +{ + char numBuf[12]; + JS_snprintf(numBuf, sizeof numBuf, "%d", op); + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_BAD_BYTECODE, numBuf); + goto error; +} - } /* switch (op) */ - } /* for (;;) */ + } /* switch (op) */ + + MOZ_ASSUME_UNREACHABLE("Interpreter loop exited via fallthrough"); error: JS_ASSERT(uint32_t(regs.pc - script->code) < script->length); From 72a87a573ef87edc9e0875ef634480e31b7dcf15 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 20:06:07 -0700 Subject: [PATCH 73/86] Bug 910782 - SpiderMonkey: Use jsbytecode instead of int for the switch mask variables, and name the magic opcode used to enable interrupts. r=luke --- js/src/vm/Interpreter.cpp | 30 ++++++++++++++++++------------ js/src/vm/Stack-inl.h | 2 +- js/src/vm/Stack.h | 11 ++++++++--- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 859d1fcac0eb..51923da35572 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1261,7 +1261,8 @@ Interpret(JSContext *cx, RunState &state) JS_ASSERT(!cx->compartment()->activeAnalysis); -#define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(script->hasScriptCounts, switchMask == -1) +#define CHECK_PCCOUNT_INTERRUPTS() \ + JS_ASSERT_IF(script->hasScriptCounts, switchMask == EnableInterruptsPseudoOpcode) /* * When Debugger puts a script in single-step mode, all js::Interpret @@ -1272,10 +1273,15 @@ Interpret(JSContext *cx, RunState &state) * JavaScript to run: each place an object might be coerced to a primitive * or a number, for example. So instead, we expose a simple mechanism to * let Debugger tweak the affected js::Interpret frames when an onStep - * handler is added: setting switchMask to -1 will enable interrupts. + * handler is added: setting switchMask to EnableInterruptsPseudoOpcode + * will enable interrupts. */ - register int switchMask = 0; - int switchOp; + static_assert(EnableInterruptsPseudoOpcode >= JSOP_LIMIT, + "EnableInterruptsPseudoOpcode must be greater than any opcode"); + static_assert(EnableInterruptsPseudoOpcode == jsbytecode(-1), + "EnableInterruptsPseudoOpcode must be the maximum jsbytecode value"); + jsbytecode switchMask = 0; + jsbytecode switchOp; #define DO_OP() goto do_op @@ -1315,7 +1321,7 @@ Interpret(JSContext *cx, RunState &state) JS_BEGIN_MACRO \ script = (s); \ if (script->hasAnyBreakpointsOrStepMode() || script->hasScriptCounts) \ - switchMask = -1; /* Enable interrupts. */ \ + switchMask = EnableInterruptsPseudoOpcode; /* Enable interrupts. */ \ JS_END_MACRO FrameRegs regs; @@ -1414,7 +1420,7 @@ Interpret(JSContext *cx, RunState &state) len = 0; if (rt->profilingScripts || cx->runtime()->debugHooks.interruptHook) - switchMask = -1; /* Enable interrupts. */ + switchMask = EnableInterruptsPseudoOpcode; /* Enable interrupts. */ advanceAndDoOp: js::gc::MaybeVerifyBarriers(cx); @@ -1423,14 +1429,12 @@ Interpret(JSContext *cx, RunState &state) do_op: CHECK_PCCOUNT_INTERRUPTS(); - switchOp = int(op) | switchMask; + switchOp = jsbytecode(op) | switchMask; do_switch: switch (switchOp) { -case -1: +BEGIN_CASE(EnableInterruptsPseudoOpcode) { - JS_ASSERT(switchMask == -1); - bool moreInterrupts = false; if (cx->runtime()->profilingScripts) { @@ -1493,8 +1497,10 @@ case -1: JS_ASSERT(rval.isInt32() && rval.toInt32() == op); } - switchMask = moreInterrupts ? -1 : 0; - switchOp = int(op); + JS_ASSERT(switchMask == EnableInterruptsPseudoOpcode); + switchMask = moreInterrupts ? EnableInterruptsPseudoOpcode : 0; + + switchOp = jsbytecode(op); goto do_switch; } diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index ddfb6afa59b3..f45ea205ec7d 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -840,7 +840,7 @@ Activation::~Activation() } InterpreterActivation::InterpreterActivation(JSContext *cx, StackFrame *entry, FrameRegs ®s, - int *const switchMask) + jsbytecode *const switchMask) : Activation(cx, Interpreter), entry_(entry), regs_(regs), diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 59ea0b47824b..4377ddceeaf7 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1216,6 +1216,11 @@ class Activation void operator=(const Activation &other) MOZ_DELETE; }; +// The value to assign to InterpreterActivation's *switchMask_ to enable +// interrupts. This value is greater than the greatest opcode, and is chosen +// such that the bitwise or of this value with any opcode is this value. +static const jsbytecode EnableInterruptsPseudoOpcode = -1; + class InterpreterFrameIterator; class InterpreterActivation : public Activation @@ -1224,7 +1229,7 @@ class InterpreterActivation : public Activation StackFrame *const entry_; // Entry frame for this activation. FrameRegs ®s_; - int *const switchMask_; // For debugger interrupts, see js::Interpret. + jsbytecode *const switchMask_; // For debugger interrupts, see js::Interpret. #ifdef DEBUG size_t oldFrameCount_; @@ -1232,7 +1237,7 @@ class InterpreterActivation : public Activation public: inline InterpreterActivation(JSContext *cx, StackFrame *entry, FrameRegs ®s, - int *const switchMask); + jsbytecode *const switchMask); inline ~InterpreterActivation(); inline bool pushInlineFrame(const CallArgs &args, HandleScript script, @@ -1252,7 +1257,7 @@ class InterpreterActivation : public Activation enableInterruptsUnconditionally(); } void enableInterruptsUnconditionally() { - *switchMask_ = -1; + *switchMask_ = EnableInterruptsPseudoOpcode; } }; From b78633b185c0fe6c4367abe1ee121deb385087ee Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 20:06:07 -0700 Subject: [PATCH 74/86] Bug 910782 - SpiderMonkey: Add an explicit scope aroud the InvokeState object's lifetime. r=luke --- js/src/vm/Interpreter.cpp | 50 ++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 51923da35572..03225f0d2ea1 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -2472,33 +2472,35 @@ BEGIN_CASE(JSOP_FUNCALL) TypeMonitorCall(cx, args, construct); #ifdef JS_ION - InvokeState state(cx, args, initial); - if (newType) - state.setUseNewType(); + { + InvokeState state(cx, args, initial); + if (newType) + state.setUseNewType(); - if (!newType && jit::IsIonEnabled(cx)) { - jit::MethodStatus status = jit::CanEnter(cx, state); - if (status == jit::Method_Error) - goto error; - if (status == jit::Method_Compiled) { - jit::IonExecStatus exec = jit::Cannon(cx, state); - CHECK_BRANCH(); - regs.sp = args.spAfterCall(); - interpReturnOK = !IsErrorStatus(exec); - goto jit_return; + if (!newType && jit::IsIonEnabled(cx)) { + jit::MethodStatus status = jit::CanEnter(cx, state); + if (status == jit::Method_Error) + goto error; + if (status == jit::Method_Compiled) { + jit::IonExecStatus exec = jit::Cannon(cx, state); + CHECK_BRANCH(); + regs.sp = args.spAfterCall(); + interpReturnOK = !IsErrorStatus(exec); + goto jit_return; + } } - } - if (jit::IsBaselineEnabled(cx)) { - jit::MethodStatus status = jit::CanEnterBaselineMethod(cx, state); - if (status == jit::Method_Error) - goto error; - if (status == jit::Method_Compiled) { - jit::IonExecStatus exec = jit::EnterBaselineMethod(cx, state); - CHECK_BRANCH(); - regs.sp = args.spAfterCall(); - interpReturnOK = !IsErrorStatus(exec); - goto jit_return; + if (jit::IsBaselineEnabled(cx)) { + jit::MethodStatus status = jit::CanEnterBaselineMethod(cx, state); + if (status == jit::Method_Error) + goto error; + if (status == jit::Method_Compiled) { + jit::IonExecStatus exec = jit::EnterBaselineMethod(cx, state); + CHECK_BRANCH(); + regs.sp = args.spAfterCall(); + interpReturnOK = !IsErrorStatus(exec); + goto jit_return; + } } } #endif From 1f32372424fa1ed674d988d843a603feb0fd648e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 Aug 2013 16:24:51 -0700 Subject: [PATCH 75/86] Bug 910517 - Remove nsIMemoryReporter, and rename nsIMemoryMultiReporter as nsIMemoryReporter. r=mmcr8. --HG-- rename : content/canvas/src/WebGLMemoryMultiReporterWrapper.h => content/canvas/src/WebGLMemoryReporterWrapper.h extra : rebase_source : 9142be547b2eeef37a8073a710ce23070f98cf65 --- addon-sdk/source/lib/sdk/test/harness.js | 12 +- content/base/src/nsContentUtils.cpp | 4 +- content/base/src/nsDOMFile.cpp | 8 +- .../canvas/src/CanvasRenderingContext2D.cpp | 4 +- content/canvas/src/WebGLContext.cpp | 10 +- content/canvas/src/WebGLContext.h | 2 +- content/canvas/src/WebGLContextReporter.cpp | 84 +++--- ...Wrapper.h => WebGLMemoryReporterWrapper.h} | 20 +- content/media/MediaDecoder.cpp | 12 +- dom/base/nsScriptNameSpaceManager.cpp | 4 +- dom/base/nsWindowMemoryReporter.cpp | 47 +-- dom/base/nsWindowMemoryReporter.h | 27 +- dom/ipc/ContentChild.cpp | 39 +-- dom/ipc/ContentParent.cpp | 101 ++++--- dom/ipc/ContentParent.h | 17 +- dom/workers/WorkerPrivate.cpp | 10 +- dom/workers/WorkerPrivate.h | 1 - .../spellcheck/hunspell/src/mozHunspell.cpp | 4 +- gfx/gl/GLContext.h | 6 +- gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp | 4 +- gfx/thebes/gfxASurface.cpp | 8 +- gfx/thebes/gfxAndroidPlatform.cpp | 6 +- gfx/thebes/gfxFont.cpp | 6 +- gfx/thebes/gfxFont.h | 4 +- gfx/thebes/gfxPlatformFontList.cpp | 6 +- gfx/thebes/gfxPlatformFontList.h | 4 +- gfx/thebes/gfxWindowsPlatform.cpp | 38 +-- gfx/thebes/gfxWindowsPlatform.h | 4 +- image/src/imgLoader.cpp | 12 +- image/test/mochitest/test_bug601470.html | 18 +- ipc/glue/SharedMemory.cpp | 8 +- js/xpconnect/src/XPCJSMemoryReporter.h | 8 +- js/xpconnect/src/XPCJSRuntime.cpp | 68 ++--- js/xpconnect/src/xpcpublic.h | 4 +- layout/base/nsStyleSheetService.cpp | 4 +- layout/style/nsLayoutStylesheetCache.cpp | 4 +- modules/libpref/src/Preferences.cpp | 4 +- netwerk/cache/nsDiskCacheDevice.cpp | 4 +- netwerk/cache/nsMemoryCacheDevice.cpp | 4 +- netwerk/dns/nsEffectiveTLDService.cpp | 4 +- startupcache/StartupCache.cpp | 8 +- storage/src/mozStorageService.cpp | 29 +- storage/src/mozStorageService.h | 5 +- .../aboutmemory/content/aboutMemory.js | 144 ++++----- .../tests/test_aboutcompartments.xul | 87 ++---- .../aboutmemory/tests/test_aboutmemory.xul | 243 +++++++-------- .../aboutmemory/tests/test_aboutmemory2.xul | 82 ++--- .../aboutmemory/tests/test_aboutmemory3.xul | 44 +-- .../tests/test_memoryReporters.xul | 5 - .../tests/test_sqliteMultiReporter.xul | 6 +- toolkit/components/places/History.cpp | 4 +- toolkit/components/telemetry/Telemetry.cpp | 4 +- toolkit/components/telemetry/TelemetryPing.js | 30 +- .../nsUrlClassifierPrefixSet.cpp | 4 +- xpcom/base/AvailableMemoryTracker.cpp | 103 ++----- xpcom/base/MapsMemoryReporter.cpp | 30 +- xpcom/base/nsCycleCollector.cpp | 14 +- xpcom/base/nsIMemoryReporter.idl | 269 +++++++---------- xpcom/base/nsMemoryInfoDumper.cpp | 89 ++---- xpcom/base/nsMemoryReporterManager.cpp | 281 ++++-------------- xpcom/base/nsMemoryReporterManager.h | 3 - xpcom/build/nsXPComInit.cpp | 4 +- xpcom/components/nsCategoryManager.cpp | 4 +- xpcom/components/nsComponentManager.cpp | 4 +- xpcom/ds/nsObserverService.cpp | 12 +- xpcom/ds/nsObserverService.h | 4 +- .../xptinfo/src/xptiInterfaceInfoManager.cpp | 4 +- 67 files changed, 855 insertions(+), 1295 deletions(-) rename content/canvas/src/{WebGLMemoryMultiReporterWrapper.h => WebGLMemoryReporterWrapper.h} (90%) diff --git a/addon-sdk/source/lib/sdk/test/harness.js b/addon-sdk/source/lib/sdk/test/harness.js index 7139aea70107..5bb12a59f890 100644 --- a/addon-sdk/source/lib/sdk/test/harness.js +++ b/addon-sdk/source/lib/sdk/test/harness.js @@ -148,6 +148,9 @@ function reportMemoryUsage() { var mgr = Cc["@mozilla.org/memory-reporter-manager;1"] .getService(Ci.nsIMemoryReporterManager); + // XXX: this code is *so* bogus -- nsIMemoryReporter changed its |memoryUsed| + // field to |amount| *years* ago, and even bigger changes have happened + // since -- that it must just never be run. var reporters = mgr.enumerateReporters(); if (reporters.hasMoreElements()) print("\n"); @@ -376,14 +379,7 @@ function getPotentialLeaks() { let enm = mgr.enumerateReporters(); while (enm.hasMoreElements()) { - let reporter = enm.getNext().QueryInterface(Ci.nsIMemoryReporter); - logReporter(reporter.process, reporter.path, reporter.kind, reporter.units, - reporter.amount, reporter.description); - } - - let enm = mgr.enumerateMultiReporters(); - while (enm.hasMoreElements()) { - let mr = enm.getNext().QueryInterface(Ci.nsIMemoryMultiReporter); + let mr = enm.getNext().QueryInterface(Ci.nsIMemoryReporter); mr.collectReports(logReporter, null); } diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 6befb2a62a0d..d20a93aaa2b5 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -255,11 +255,11 @@ static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); static PLDHashTable sEventListenerManagersHash; -class DOMEventListenerManagersHashReporter MOZ_FINAL : public MemoryReporterBase +class DOMEventListenerManagersHashReporter MOZ_FINAL : public MemoryUniReporter { public: DOMEventListenerManagersHashReporter() - : MemoryReporterBase( + : MemoryUniReporter( "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES, diff --git a/content/base/src/nsDOMFile.cpp b/content/base/src/nsDOMFile.cpp index b8a5507db5f4..c65a635ce26e 100644 --- a/content/base/src/nsDOMFile.cpp +++ b/content/base/src/nsDOMFile.cpp @@ -641,7 +641,7 @@ nsDOMMemoryFile::DataOwner::sMemoryReporterRegistered; NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerMallocSizeOf) class nsDOMMemoryFileDataOwnerMemoryReporter MOZ_FINAL - : public nsIMemoryMultiReporter + : public nsIMemoryReporter { NS_DECL_THREADSAFE_ISUPPORTS @@ -651,7 +651,7 @@ class nsDOMMemoryFileDataOwnerMemoryReporter MOZ_FINAL return NS_OK; } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCallback, + NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCallback, nsISupports *aClosure) { typedef nsDOMMemoryFile::DataOwner DataOwner; @@ -725,7 +725,7 @@ class nsDOMMemoryFileDataOwnerMemoryReporter MOZ_FINAL }; NS_IMPL_ISUPPORTS1(nsDOMMemoryFileDataOwnerMemoryReporter, - nsIMemoryMultiReporter) + nsIMemoryReporter) /* static */ void nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered() @@ -737,7 +737,7 @@ nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered() nsRefPtr reporter = new nsDOMMemoryFileDataOwnerMemoryReporter(); - NS_RegisterMemoryMultiReporter(reporter); + NS_RegisterMemoryReporter(reporter); sMemoryReporterRegistered = true; } diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp index 89f040d93190..c3e56b39fd6e 100644 --- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -143,11 +143,11 @@ static int64_t gCanvasAzureMemoryUsed = 0; // This is KIND_OTHER because it's not always clear where in memory the pixels // of a canvas are stored. Furthermore, this memory will be tracked by the // underlying surface implementations. See bug 655638 for details. -class Canvas2dPixelsReporter MOZ_FINAL : public MemoryReporterBase +class Canvas2dPixelsReporter MOZ_FINAL : public MemoryUniReporter { public: Canvas2dPixelsReporter() - : MemoryReporterBase("canvas-2d-pixels", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("canvas-2d-pixels", KIND_OTHER, UNITS_BYTES, "Memory used by 2D canvases. Each canvas requires (width * height * 4) bytes.") {} private: diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index d27463547bab..1886d442c126 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -10,7 +10,7 @@ #include "WebGLContextUtils.h" #include "WebGLBuffer.h" #include "WebGLVertexAttribData.h" -#include "WebGLMemoryMultiReporterWrapper.h" +#include "WebGLMemoryReporterWrapper.h" #include "WebGLFramebuffer.h" #include "WebGLVertexArray.h" #include "WebGLQuery.h" @@ -179,7 +179,7 @@ WebGLContext::WebGLContext() mPixelStorePackAlignment = 4; mPixelStoreUnpackAlignment = 4; - WebGLMemoryMultiReporterWrapper::AddWebGLContext(this); + WebGLMemoryReporterWrapper::AddWebGLContext(this); mAllowRestore = true; mContextLossTimerRunning = false; @@ -213,7 +213,7 @@ WebGLContext::WebGLContext() WebGLContext::~WebGLContext() { DestroyResourcesAndContext(); - WebGLMemoryMultiReporterWrapper::RemoveWebGLContext(this); + WebGLMemoryReporterWrapper::RemoveWebGLContext(this); TerminateContextLossTimer(); mContextRestorer = nullptr; } @@ -653,8 +653,8 @@ void WebGLContext::LoseOldestWebGLContextIfLimitExceeded() // when choosing which one to lose first. UpdateLastUseIndex(); - WebGLMemoryMultiReporterWrapper::ContextsArrayType &contexts - = WebGLMemoryMultiReporterWrapper::Contexts(); + WebGLMemoryReporterWrapper::ContextsArrayType &contexts + = WebGLMemoryReporterWrapper::Contexts(); // quick exit path, should cover a majority of cases if (contexts.Length() <= kMaxWebGLContextsPerPrincipal) { diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 4a03e67955ec..586f6caf736f 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -118,7 +118,7 @@ class WebGLContext : { friend class WebGLContextUserData; friend class WebGLMemoryPressureObserver; - friend class WebGLMemoryMultiReporterWrapper; + friend class WebGLMemoryReporterWrapper; friend class WebGLExtensionLoseContext; friend class WebGLExtensionCompressedTextureS3TC; friend class WebGLExtensionCompressedTextureATC; diff --git a/content/canvas/src/WebGLContextReporter.cpp b/content/canvas/src/WebGLContextReporter.cpp index a7bcebb6ec42..8b42f8b475bc 100644 --- a/content/canvas/src/WebGLContextReporter.cpp +++ b/content/canvas/src/WebGLContextReporter.cpp @@ -4,32 +4,32 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebGLContext.h" -#include "WebGLMemoryMultiReporterWrapper.h" +#include "WebGLMemoryReporterWrapper.h" #include "nsIMemoryReporter.h" using namespace mozilla; NS_IMPL_ISUPPORTS1(WebGLMemoryPressureObserver, nsIObserver) -class WebGLMemoryMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter +class WebGLMemoryReporter MOZ_FINAL : public nsIMemoryReporter { public: NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYMULTIREPORTER + NS_DECL_NSIMEMORYREPORTER }; -NS_IMPL_ISUPPORTS1(WebGLMemoryMultiReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(WebGLMemoryReporter, nsIMemoryReporter) NS_IMETHODIMP -WebGLMemoryMultiReporter::GetName(nsACString &aName) +WebGLMemoryReporter::GetName(nsACString &aName) { aName.AssignLiteral("webgl"); return NS_OK; } NS_IMETHODIMP -WebGLMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, - nsISupports* aClosure) +WebGLMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb, + nsISupports* aClosure) { #define REPORT(_path, _kind, _units, _amount, _desc) \ do { \ @@ -42,21 +42,21 @@ WebGLMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, REPORT("webgl-texture-memory", nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetTextureMemoryUsed(), + WebGLMemoryReporterWrapper::GetTextureMemoryUsed(), "Memory used by WebGL textures.The OpenGL" " implementation is free to store these textures in either video" " memory or main memory. This measurement is only a lower bound," - " actual memory usage may be higher for example if the storage" + " actual memory usage may be higher for example if the storage" " is strided."); - + REPORT("webgl-texture-count", nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetTextureCount(), + WebGLMemoryReporterWrapper::GetTextureCount(), "Number of WebGL textures."); REPORT("webgl-buffer-memory", nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetBufferMemoryUsed(), + WebGLMemoryReporterWrapper::GetBufferMemoryUsed(), "Memory used by WebGL buffers. The OpenGL" " implementation is free to store these buffers in either video" " memory or main memory. This measurement is only a lower bound," @@ -65,7 +65,7 @@ WebGLMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, REPORT("explicit/webgl/buffer-cache-memory", nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed(), + WebGLMemoryReporterWrapper::GetBufferCacheMemoryUsed(), "Memory used by WebGL buffer caches. The WebGL" " implementation caches the contents of element array buffers" " only.This adds up with the webgl-buffer-memory value, but" @@ -74,69 +74,69 @@ WebGLMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, REPORT("webgl-buffer-count", nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetBufferCount(), - "Number of WebGL buffers."); - + WebGLMemoryReporterWrapper::GetBufferCount(), + "Number of WebGL buffers."); + REPORT("webgl-renderbuffer-memory", nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetRenderbufferMemoryUsed(), + WebGLMemoryReporterWrapper::GetRenderbufferMemoryUsed(), "Memory used by WebGL renderbuffers. The OpenGL" " implementation is free to store these renderbuffers in either" " video memory or main memory. This measurement is only a lower" " bound, actual memory usage may be higher for example if the" " storage is strided."); - + REPORT("webgl-renderbuffer-count", nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetRenderbufferCount(), + WebGLMemoryReporterWrapper::GetRenderbufferCount(), "Number of WebGL renderbuffers."); - + REPORT("explicit/webgl/shader", nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetShaderSize(), + WebGLMemoryReporterWrapper::GetShaderSize(), "Combined size of WebGL shader ASCII sources and translation" - " logs cached on the heap."); + " logs cached on the heap."); REPORT("webgl-shader-count", nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetShaderCount(), - "Number of WebGL shaders."); + WebGLMemoryReporterWrapper::GetShaderCount(), + "Number of WebGL shaders."); REPORT("webgl-context-count", nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetContextCount(), - "Number of WebGL contexts."); + WebGLMemoryReporterWrapper::GetContextCount(), + "Number of WebGL contexts."); #undef REPORT return NS_OK; } -WebGLMemoryMultiReporterWrapper* WebGLMemoryMultiReporterWrapper::sUniqueInstance = nullptr; +WebGLMemoryReporterWrapper* WebGLMemoryReporterWrapper::sUniqueInstance = nullptr; -WebGLMemoryMultiReporterWrapper* WebGLMemoryMultiReporterWrapper::UniqueInstance() +WebGLMemoryReporterWrapper* WebGLMemoryReporterWrapper::UniqueInstance() { if (!sUniqueInstance) { - sUniqueInstance = new WebGLMemoryMultiReporterWrapper; + sUniqueInstance = new WebGLMemoryReporterWrapper; } - return sUniqueInstance; + return sUniqueInstance; } -WebGLMemoryMultiReporterWrapper::WebGLMemoryMultiReporterWrapper() -{ - mReporter = new WebGLMemoryMultiReporter; - NS_RegisterMemoryMultiReporter(mReporter); -} - -WebGLMemoryMultiReporterWrapper::~WebGLMemoryMultiReporterWrapper() +WebGLMemoryReporterWrapper::WebGLMemoryReporterWrapper() { - NS_UnregisterMemoryMultiReporter(mReporter); + mReporter = new WebGLMemoryReporter; + NS_RegisterMemoryReporter(mReporter); +} + +WebGLMemoryReporterWrapper::~WebGLMemoryReporterWrapper() +{ + NS_UnregisterMemoryReporter(mReporter); } NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLBufferMallocSizeOf) -int64_t -WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed() { +int64_t +WebGLMemoryReporterWrapper::GetBufferCacheMemoryUsed() { const ContextsArrayType & contexts = Contexts(); int64_t result = 0; for(size_t i = 0; i < contexts.Length(); ++i) { @@ -153,8 +153,8 @@ WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed() { NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLShaderMallocSizeOf) -int64_t -WebGLMemoryMultiReporterWrapper::GetShaderSize() { +int64_t +WebGLMemoryReporterWrapper::GetShaderSize() { const ContextsArrayType & contexts = Contexts(); int64_t result = 0; for(size_t i = 0; i < contexts.Length(); ++i) { diff --git a/content/canvas/src/WebGLMemoryMultiReporterWrapper.h b/content/canvas/src/WebGLMemoryReporterWrapper.h similarity index 90% rename from content/canvas/src/WebGLMemoryMultiReporterWrapper.h rename to content/canvas/src/WebGLMemoryReporterWrapper.h index 9527ff17eeee..098d661748a1 100644 --- a/content/canvas/src/WebGLMemoryMultiReporterWrapper.h +++ b/content/canvas/src/WebGLMemoryReporterWrapper.h @@ -3,8 +3,8 @@ * 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/. */ -#ifndef WEBGLMEMORYMULTIREPORTWRAPER_H_ -#define WEBGLMEMORYMULTIREPORTWRAPER_H_ +#ifndef WEBGLMEMORYREPORTWRAPER_H_ +#define WEBGLMEMORYREPORTWRAPER_H_ #include "WebGLContext.h" #include "WebGLBuffer.h" @@ -17,21 +17,21 @@ namespace mozilla { -class WebGLMemoryMultiReporterWrapper +class WebGLMemoryReporterWrapper { - WebGLMemoryMultiReporterWrapper(); - ~WebGLMemoryMultiReporterWrapper(); - static WebGLMemoryMultiReporterWrapper* sUniqueInstance; + WebGLMemoryReporterWrapper(); + ~WebGLMemoryReporterWrapper(); + static WebGLMemoryReporterWrapper* sUniqueInstance; - // here we store plain pointers, not RefPtrs: we don't want the - // WebGLMemoryMultiReporterWrapper unique instance to keep alive all + // here we store plain pointers, not RefPtrs: we don't want the + // WebGLMemoryReporterWrapper unique instance to keep alive all // WebGLContexts ever created. typedef nsTArray ContextsArrayType; ContextsArrayType mContexts; - nsCOMPtr mReporter; + nsCOMPtr mReporter; - static WebGLMemoryMultiReporterWrapper* UniqueInstance(); + static WebGLMemoryReporterWrapper* UniqueInstance(); static ContextsArrayType & Contexts() { return UniqueInstance()->mContexts; } diff --git a/content/media/MediaDecoder.cpp b/content/media/MediaDecoder.cpp index c1ff95aa9176..4a1ff88d20b4 100644 --- a/content/media/MediaDecoder.cpp +++ b/content/media/MediaDecoder.cpp @@ -74,7 +74,7 @@ class MediaMemoryTracker DecodersArray mDecoders; - nsCOMPtr mReporter; + nsCOMPtr mReporter; public: static void AddMediaDecoder(MediaDecoder* aDecoder) @@ -1725,7 +1725,7 @@ MediaDecoder::IsWMFEnabled() } #endif -class MediaReporter MOZ_FINAL : public nsIMemoryMultiReporter +class MediaReporter MOZ_FINAL : public nsIMemoryReporter { public: NS_DECL_ISUPPORTS @@ -1736,7 +1736,7 @@ public: return NS_OK; } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback* aCb, + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { int64_t video, audio; @@ -1762,7 +1762,7 @@ public: } }; -NS_IMPL_ISUPPORTS1(MediaReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(MediaReporter, nsIMemoryReporter) MediaDecoderOwner* MediaDecoder::GetOwner() @@ -1774,12 +1774,12 @@ MediaDecoder::GetOwner() MediaMemoryTracker::MediaMemoryTracker() : mReporter(new MediaReporter()) { - NS_RegisterMemoryMultiReporter(mReporter); + NS_RegisterMemoryReporter(mReporter); } MediaMemoryTracker::~MediaMemoryTracker() { - NS_UnregisterMemoryMultiReporter(mReporter); + NS_UnregisterMemoryReporter(mReporter); } } // namespace mozilla diff --git a/dom/base/nsScriptNameSpaceManager.cpp b/dom/base/nsScriptNameSpaceManager.cpp index 4d6b0cf7ffb7..32d48d6258bb 100644 --- a/dom/base/nsScriptNameSpaceManager.cpp +++ b/dom/base/nsScriptNameSpaceManager.cpp @@ -116,11 +116,11 @@ GlobalNameHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, return true; } -class ScriptNameSpaceManagerReporter MOZ_FINAL : public MemoryReporterBase +class ScriptNameSpaceManagerReporter MOZ_FINAL : public MemoryUniReporter { public: ScriptNameSpaceManagerReporter(nsScriptNameSpaceManager* aManager) - : MemoryReporterBase( + : MemoryUniReporter( "explicit/script-namespace-manager", KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index 1e02e0c13f4f..23c8acf77c27 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -25,7 +25,7 @@ nsWindowMemoryReporter::nsWindowMemoryReporter() mDetachedWindows.Init(); } -NS_IMPL_ISUPPORTS3(nsWindowMemoryReporter, nsIMemoryMultiReporter, nsIObserver, +NS_IMPL_ISUPPORTS3(nsWindowMemoryReporter, nsIMemoryReporter, nsIObserver, nsSupportsWeakReference) /* static */ @@ -34,7 +34,7 @@ nsWindowMemoryReporter::Init() { // The memory reporter manager will own this object. nsRefPtr windowReporter = new nsWindowMemoryReporter(); - NS_RegisterMemoryMultiReporter(windowReporter); + NS_RegisterMemoryReporter(windowReporter); nsCOMPtr os = services::GetObserverService(); if (os) { @@ -46,13 +46,13 @@ nsWindowMemoryReporter::Init() /* weakRef = */ true); } - nsRefPtr ghostMultiReporter = + nsRefPtr ghostURLsReporter = new GhostURLsReporter(windowReporter); - NS_RegisterMemoryMultiReporter(ghostMultiReporter); + NS_RegisterMemoryReporter(ghostURLsReporter); - nsRefPtr ghostReporter = + nsRefPtr numGhostsReporter = new NumGhostsReporter(windowReporter); - NS_RegisterMemoryReporter(ghostReporter); + NS_RegisterMemoryReporter(numGhostsReporter); } static already_AddRefed @@ -122,7 +122,7 @@ CollectWindowReports(nsGlobalWindow *aWindow, nsTHashtable *aGhostWindowIDs, WindowPaths *aWindowPaths, WindowPaths *aTopWindowPaths, - nsIMemoryMultiReporterCallback *aCb, + nsIMemoryReporterCallback *aCb, nsISupports *aClosure) { nsAutoCString windowPath("explicit/"); @@ -320,7 +320,7 @@ nsWindowMemoryReporter::GetName(nsACString &aName) } NS_IMETHODIMP -nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, +nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { nsGlobalWindow::WindowByIdTable* windowsById = @@ -356,9 +356,9 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, } // Report JS memory usage. We do this from here because the JS memory - // multi-reporter needs to be passed |windowPaths|. - nsresult rv = xpc::JSMemoryMultiReporter::CollectReports(&windowPaths, &topWindowPaths, - aCb, aClosure); + // reporter needs to be passed |windowPaths|. + nsresult rv = xpc::JSReporter::CollectReports(&windowPaths, &topWindowPaths, + aCb, aClosure); NS_ENSURE_SUCCESS(rv, rv); #define REPORT(_path, _amount, _desc) \ @@ -668,7 +668,7 @@ nsWindowMemoryReporter::CheckForGhostWindows( } NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter::GhostURLsReporter, - nsIMemoryMultiReporter) + nsIMemoryReporter) nsWindowMemoryReporter:: GhostURLsReporter::GhostURLsReporter( @@ -687,7 +687,7 @@ GhostURLsReporter::GetName(nsACString& aName) struct ReportGhostWindowsEnumeratorData { - nsIMemoryMultiReporterCallback* callback; + nsIMemoryReporterCallback* callback; nsISupports* closure; nsresult rv; }; @@ -734,7 +734,7 @@ ReportGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void* aClosure) NS_IMETHODIMP nsWindowMemoryReporter:: GhostURLsReporter::CollectReports( - nsIMemoryMultiReporterCallback* aCb, + nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { // Get the IDs of all the ghost windows in existance. @@ -752,25 +752,6 @@ GhostURLsReporter::CollectReports( return reportGhostWindowsEnumData.rv; } -NS_IMETHODIMP -nsWindowMemoryReporter:: -NumGhostsReporter::GetDescription(nsACString& aDesc) -{ - nsPrintfCString str( -"The number of ghost windows present (the number of nodes underneath \ -explicit/window-objects/top(none)/ghost, modulo race conditions). A ghost \ -window is not shown in any tab, does not share a domain with any non-detached \ -windows, and has met these criteria for at least %ds \ -(memory.ghost_window_timeout_seconds) or has survived a round of about:memory's \ -minimize memory usage button.\n\n\ -Ghost windows can happen legitimately, but they are often indicative of leaks \ -in the browser or add-ons.", - mWindowReporter->GetGhostTimeout()); - - aDesc.Assign(str); - return NS_OK; -} - int64_t nsWindowMemoryReporter::NumGhostsReporter::Amount() { diff --git a/dom/base/nsWindowMemoryReporter.h b/dom/base/nsWindowMemoryReporter.h index 7390445005c1..f08967302fe9 100644 --- a/dom/base/nsWindowMemoryReporter.h +++ b/dom/base/nsWindowMemoryReporter.h @@ -108,13 +108,13 @@ public: * the tab. * */ -class nsWindowMemoryReporter MOZ_FINAL : public nsIMemoryMultiReporter, +class nsWindowMemoryReporter MOZ_FINAL : public nsIMemoryReporter, public nsIObserver, public nsSupportsWeakReference { public: NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYMULTIREPORTER + NS_DECL_NSIMEMORYREPORTER NS_DECL_NSIOBSERVER static void Init(); @@ -126,33 +126,38 @@ private: * this list, running this report is faster than running * nsWindowMemoryReporter. */ - class GhostURLsReporter MOZ_FINAL : public nsIMemoryMultiReporter + class GhostURLsReporter MOZ_FINAL : public nsIMemoryReporter { public: GhostURLsReporter(nsWindowMemoryReporter* aWindowReporter); NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYMULTIREPORTER + NS_DECL_NSIMEMORYREPORTER private: nsRefPtr mWindowReporter; }; /** - * nsGhostWindowReporter generates the "ghost-windows" single-report, which - * counts the number of ghost windows present. + * nsGhostWindowReporter generates the "ghost-windows" report, which counts + * the number of ghost windows present. */ - class NumGhostsReporter MOZ_FINAL : public mozilla::MemoryReporterBase + class NumGhostsReporter MOZ_FINAL : public mozilla::MemoryUniReporter { public: NumGhostsReporter(nsWindowMemoryReporter* aWindowReporter) - // Description is "???" because we define GetDescription below. - : MemoryReporterBase("ghost-windows", KIND_OTHER, UNITS_COUNT, "???") + : MemoryUniReporter("ghost-windows", KIND_OTHER, UNITS_COUNT, +"The number of ghost windows present (the number of nodes underneath " +"explicit/window-objects/top(none)/ghost, modulo race conditions). A ghost " +"window is not shown in any tab, does not share a domain with any non-detached " +"windows, and has met these criteria for at least " +"memory.ghost_window_timeout_seconds, or has survived a round of " +"about:memory's minimize memory usage button.\n\n" +"Ghost windows can happen legitimately, but they are often indicative of " +"leaks in the browser or add-ons.") , mWindowReporter(aWindowReporter) {} - NS_IMETHOD GetDescription(nsACString& aDesc); - private: int64_t Amount() MOZ_OVERRIDE; diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index f1afd28ea2da..3c565e8bda57 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -398,7 +398,7 @@ ContentChild::AllocPMemoryReportRequestChild() } // This is just a wrapper for InfallibleTArray that implements -// nsISupports, so it can be passed to nsIMemoryMultiReporter::CollectReports. +// nsISupports, so it can be passed to nsIMemoryReporter::CollectReports. class MemoryReportsWrapper MOZ_FINAL : public nsISupports { public: NS_DECL_ISUPPORTS @@ -407,7 +407,7 @@ public: }; NS_IMPL_ISUPPORTS0(MemoryReportsWrapper) -class MemoryReportCallback MOZ_FINAL : public nsIMemoryMultiReporterCallback +class MemoryReportCallback MOZ_FINAL : public nsIMemoryReporterCallback { public: NS_DECL_ISUPPORTS @@ -435,53 +435,28 @@ private: }; NS_IMPL_ISUPPORTS1( MemoryReportCallback -, nsIMemoryMultiReporterCallback +, nsIMemoryReporterCallback ) bool ContentChild::RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child) { - nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); InfallibleTArray reports; nsPrintfCString process("Content (%d)", getpid()); - // First do the vanilla memory reporters. + // Run each reporter. The callback will turn each measurement into a + // MemoryReport. nsCOMPtr e; mgr->EnumerateReporters(getter_AddRefs(e)); - bool more; - while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { - nsCOMPtr r; - e->GetNext(getter_AddRefs(r)); - - nsCString path; - int32_t kind; - int32_t units; - int64_t amount; - nsCString desc; - - if (NS_SUCCEEDED(r->GetPath(path)) && - NS_SUCCEEDED(r->GetKind(&kind)) && - NS_SUCCEEDED(r->GetUnits(&units)) && - NS_SUCCEEDED(r->GetAmount(&amount)) && - NS_SUCCEEDED(r->GetDescription(desc))) - { - MemoryReport memreport(process, path, kind, units, amount, desc); - reports.AppendElement(memreport); - } - } - - // Then do the memory multi-reporters, by calling CollectReports on each - // one, whereupon the callback will turn each measurement into a - // MemoryReport. - mgr->EnumerateMultiReporters(getter_AddRefs(e)); nsRefPtr wrappedReports = new MemoryReportsWrapper(&reports); nsRefPtr cb = new MemoryReportCallback(process); + bool more; while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { - nsCOMPtr r; + nsCOMPtr r; e->GetNext(getter_AddRefs(r)); r->CollectReports(cb, wrappedReports); } diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 320e465a6271..468776789819 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -159,34 +159,54 @@ namespace dom { #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline" -// This represents a single measurement taken by a memory reporter in a child -// process and passed to this one. Its process is non-empty, and its amount is -// fixed. -class ChildMemoryReporter MOZ_FINAL : public MemoryReporterBase +// This represents all the memory reports provided by a child process. +class ChildReporter MOZ_FINAL : public nsIMemoryReporter { public: - ChildMemoryReporter(const char* aProcess, const char* aPath, int32_t aKind, - int32_t aUnits, int64_t aAmount, - const char* aDescription) - : MemoryReporterBase(aPath, aKind, aUnits, aDescription) - , mProcess(aProcess) - , mAmount(aAmount) + ChildReporter(const InfallibleTArray& childReports) { + for (uint32_t i = 0; i < childReports.Length(); i++) { + MemoryReport r(childReports[i].process(), + childReports[i].path(), + childReports[i].kind(), + childReports[i].units(), + childReports[i].amount(), + childReports[i].desc()); + + // Child reports have a non-empty process. + MOZ_ASSERT(!r.process().IsEmpty()); + + mChildReports.AppendElement(r); + } } - NS_IMETHOD GetProcess(nsACString& aProcess) + NS_DECL_ISUPPORTS + + NS_IMETHOD GetName(nsACString& name) { - aProcess.Assign(mProcess); - return NS_OK; + name.AssignLiteral("content-child"); + return NS_OK; } -private: - int64_t Amount() { return mAmount; } + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, + nsISupports* aClosure) + { + for (uint32_t i = 0; i < mChildReports.Length(); i++) { + nsresult rv; + MemoryReport r = mChildReports[i]; + rv = aCb->Callback(r.process(), r.path(), r.kind(), r.units(), + r.amount(), r.desc(), aClosure); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; + } - nsCString mProcess; - int64_t mAmount; + private: + InfallibleTArray mChildReports; }; +NS_IMPL_ISUPPORTS1(ChildReporter, nsIMemoryReporter) + class MemoryReportRequestParent : public PMemoryReportRequestParent { public: @@ -207,9 +227,9 @@ MemoryReportRequestParent::MemoryReportRequestParent() } bool -MemoryReportRequestParent::Recv__delete__(const InfallibleTArray& report) +MemoryReportRequestParent::Recv__delete__(const InfallibleTArray& childReports) { - Owner()->SetChildMemoryReporters(report); + Owner()->SetChildMemoryReports(childReports); return true; } @@ -221,15 +241,15 @@ MemoryReportRequestParent::~MemoryReportRequestParent() /** * A memory reporter for ContentParent objects themselves. */ -class ContentParentMemoryReporter MOZ_FINAL : public nsIMemoryMultiReporter +class ContentParentMemoryReporter MOZ_FINAL : public nsIMemoryReporter { public: NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYMULTIREPORTER + NS_DECL_NSIMEMORYREPORTER NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf) }; -NS_IMPL_ISUPPORTS1(ContentParentMemoryReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(ContentParentMemoryReporter, nsIMemoryReporter) NS_IMETHODIMP ContentParentMemoryReporter::GetName(nsACString& aName) @@ -239,7 +259,7 @@ ContentParentMemoryReporter::GetName(nsACString& aName) } NS_IMETHODIMP -ContentParentMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* cb, +ContentParentMemoryReporter::CollectReports(nsIMemoryReporterCallback* cb, nsISupports* aClosure) { nsAutoTArray cps; @@ -356,7 +376,7 @@ ContentParent::StartUp() } nsRefPtr mr = new ContentParentMemoryReporter(); - NS_RegisterMemoryMultiReporter(mr); + NS_RegisterMemoryReporter(mr); sCanLaunchSubprocesses = true; @@ -876,7 +896,7 @@ ContentParent::ShutDownProcess(bool aCloseWithError) // shut down the cycle collector. But by then it's too late to release any // CC'ed objects, so we need to null them out here, while we still can. See // bug 899761. - mMemoryReporters.Clear(); + mChildReporter = nullptr; if (mMessageManager) { mMessageManager->Disconnect(); mMessageManager = nullptr; @@ -1027,8 +1047,8 @@ ContentParent::ActorDestroy(ActorDestroyReason why) ppm->Disconnect(); } - // clear the child memory reporters - ClearChildMemoryReporters(); + // unregister the child memory reporter + UnregisterChildMemoryReporter(); // remove the global remote preferences observers Preferences::RemoveObserver(this, ""); @@ -2141,28 +2161,16 @@ ContentParent::DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* act } void -ContentParent::SetChildMemoryReporters(const InfallibleTArray& report) +ContentParent::SetChildMemoryReports(const InfallibleTArray& childReports) { nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); - for (int32_t i = 0; i < mMemoryReporters.Count(); i++) - mgr->UnregisterReporter(mMemoryReporters[i]); - for (uint32_t i = 0; i < report.Length(); i++) { - nsCString process = report[i].process(); - nsCString path = report[i].path(); - int32_t kind = report[i].kind(); - int32_t units = report[i].units(); - int64_t amount = report[i].amount(); - nsCString desc = report[i].desc(); + if (mChildReporter) + mgr->UnregisterReporter(mChildReporter); - nsRefPtr r = - new ChildMemoryReporter(process.get(), path.get(), kind, units, - amount, desc.get()); - - mMemoryReporters.AppendObject(r); - mgr->RegisterReporter(r); - } + mChildReporter = new ChildReporter(childReports); + mgr->RegisterReporter(mChildReporter); nsCOMPtr obs = do_GetService("@mozilla.org/observer-service;1"); @@ -2171,12 +2179,11 @@ ContentParent::SetChildMemoryReporters(const InfallibleTArray& rep } void -ContentParent::ClearChildMemoryReporters() +ContentParent::UnregisterChildMemoryReporter() { nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); - for (int32_t i = 0; i < mMemoryReporters.Count(); i++) - mgr->UnregisterReporter(mMemoryReporters[i]); + mgr->UnregisterReporter(mChildReporter); } PTestShellParent* diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 5bfa77b18d1a..716f181dcd37 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -143,8 +143,9 @@ public: bool IsAlive(); bool IsForApp(); - void SetChildMemoryReporters(const InfallibleTArray& report); - void ClearChildMemoryReporters(); + void SetChildMemoryReports(const InfallibleTArray& + childReports); + void UnregisterChildMemoryReporter(); GeckoChildProcessHost* Process() { return mSubprocess; @@ -446,11 +447,13 @@ private: uint64_t mChildID; int32_t mGeolocationWatchID; - // This is a cache of all of the memory reporters - // registered in the child process. To update this, one - // can broadcast the topic "child-memory-reporter-request" using - // the nsIObserverService. - nsCOMArray mMemoryReporters; + // This is a reporter holding the reports from the child's last + // "child-memory-reporter-update" notification. To update this, one can + // broadcast the topic "child-memory-reporter-request" using the + // nsIObserverService. + // + // Note that this assumes there is at most one child process at a time! + nsCOMPtr mChildReporter; nsString mAppManifestURL; diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 506698d1693e..06373224696a 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -1766,7 +1766,7 @@ struct WorkerPrivate::TimeoutInfo bool mCanceled; }; -class WorkerPrivate::MemoryReporter MOZ_FINAL : public nsIMemoryMultiReporter +class WorkerPrivate::MemoryReporter MOZ_FINAL : public nsIMemoryReporter { friend class WorkerPrivate; @@ -1807,7 +1807,7 @@ public: } NS_IMETHOD - CollectReports(nsIMemoryMultiReporterCallback* aCallback, + CollectReports(nsIMemoryReporterCallback* aCallback, nsISupports* aClosure) { AssertIsOnMainThread(); @@ -1883,7 +1883,7 @@ private: } }; -NS_IMPL_ISUPPORTS1(WorkerPrivate::MemoryReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(WorkerPrivate::MemoryReporter, nsIMemoryReporter) template WorkerPrivateParent::WorkerPrivateParent( @@ -3093,7 +3093,7 @@ WorkerPrivate::EnableMemoryReporter() // successfully registered the reporter. mMemoryReporter = new MemoryReporter(this); - if (NS_FAILED(NS_RegisterMemoryMultiReporter(mMemoryReporter))) { + if (NS_FAILED(NS_RegisterMemoryReporter(mMemoryReporter))) { NS_WARNING("Failed to register memory reporter!"); // No need to lock here since a failed registration means our memory // reporter can't start running. Just clean up. @@ -3148,7 +3148,7 @@ WorkerPrivate::DisableMemoryReporter() } // Finally unregister the memory reporter. - if (NS_FAILED(NS_UnregisterMemoryMultiReporter(memoryReporter))) { + if (NS_FAILED(NS_UnregisterMemoryReporter(memoryReporter))) { NS_WARNING("Failed to unregister memory reporter!"); } } diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 20794e29be1b..4d316a7fbb37 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -34,7 +34,6 @@ class JSAutoStructuredCloneBuffer; class nsIChannel; class nsIDocument; -class nsIMemoryMultiReporter; class nsIPrincipal; class nsIScriptContext; class nsIURI; diff --git a/extensions/spellcheck/hunspell/src/mozHunspell.cpp b/extensions/spellcheck/hunspell/src/mozHunspell.cpp index 73f39b70268a..d49aea441d64 100644 --- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp +++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp @@ -97,11 +97,11 @@ NS_IMPL_CYCLE_COLLECTION_3(mozHunspell, mEncoder, mDecoder) -class SpellCheckReporter MOZ_FINAL : public mozilla::MemoryReporterBase +class SpellCheckReporter MOZ_FINAL : public mozilla::MemoryUniReporter { public: SpellCheckReporter() - : MemoryReporterBase("explicit/spell-check", KIND_HEAP, UNITS_BYTES, + : MemoryUniReporter("explicit/spell-check", KIND_HEAP, UNITS_BYTES, "Memory used by the Hunspell spell checking engine's internal data structures.") { #ifdef DEBUG diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 1173e7d2e695..82efb9481085 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -3394,12 +3394,12 @@ public: #endif }; -class GfxTexturesReporter MOZ_FINAL : public MemoryReporterBase +class GfxTexturesReporter MOZ_FINAL : public MemoryUniReporter { public: GfxTexturesReporter() - : MemoryReporterBase("gfx-textures", KIND_OTHER, UNITS_BYTES, - "Memory used for storing GL textures.") + : MemoryUniReporter("gfx-textures", KIND_OTHER, UNITS_BYTES, + "Memory used for storing GL textures.") { #ifdef DEBUG // There must be only one instance of this class, due to |sAmount| diff --git a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp index b8e10eb9e2b4..1b59de593694 100644 --- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp +++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp @@ -184,13 +184,13 @@ ContentTypeFromPixelFormat(android::PixelFormat aFormat) return gfxASurface::ContentFromFormat(ImageFormatForPixelFormat(aFormat)); } -class GrallocReporter MOZ_FINAL : public MemoryReporterBase +class GrallocReporter MOZ_FINAL : public MemoryUniReporter { friend class GrallocBufferActor; public: GrallocReporter() - : MemoryReporterBase("gralloc", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("gralloc", KIND_OTHER, UNITS_BYTES, "Special RAM that can be shared between processes and directly accessed by " "both the CPU and GPU. Gralloc memory is usually a relatively precious " "resource, with much less available than generic RAM. When it's exhausted, " diff --git a/gfx/thebes/gfxASurface.cpp b/gfx/thebes/gfxASurface.cpp index 539bf86249f5..27aafff304f1 100644 --- a/gfx/thebes/gfxASurface.cpp +++ b/gfx/thebes/gfxASurface.cpp @@ -598,7 +598,7 @@ PR_STATIC_ASSERT(uint32_t(CAIRO_SURFACE_TYPE_SKIA) == static int64_t gSurfaceMemoryUsed[gfxASurface::SurfaceTypeMax] = { 0 }; class SurfaceMemoryReporter MOZ_FINAL : - public nsIMemoryMultiReporter + public nsIMemoryReporter { public: SurfaceMemoryReporter() @@ -612,7 +612,7 @@ public: return NS_OK; } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCb, + NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb, nsISupports *aClosure) { size_t len = NS_ARRAY_LENGTH(sSurfaceMemoryReporterAttrs); @@ -639,7 +639,7 @@ public: } }; -NS_IMPL_ISUPPORTS1(SurfaceMemoryReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(SurfaceMemoryReporter, nsIMemoryReporter) void gfxASurface::RecordMemoryUsedForSurfaceType(gfxASurface::gfxSurfaceType aType, @@ -652,7 +652,7 @@ gfxASurface::RecordMemoryUsedForSurfaceType(gfxASurface::gfxSurfaceType aType, static bool registered = false; if (!registered) { - NS_RegisterMemoryMultiReporter(new SurfaceMemoryReporter()); + NS_RegisterMemoryReporter(new SurfaceMemoryReporter()); registered = true; } diff --git a/gfx/thebes/gfxAndroidPlatform.cpp b/gfx/thebes/gfxAndroidPlatform.cpp index c9781a4a4bf6..81acf67eeae1 100644 --- a/gfx/thebes/gfxAndroidPlatform.cpp +++ b/gfx/thebes/gfxAndroidPlatform.cpp @@ -30,12 +30,12 @@ using namespace mozilla::gfx; static FT_Library gPlatformFTLibrary = nullptr; -class FreetypeReporter MOZ_FINAL : public MemoryReporterBase +class FreetypeReporter MOZ_FINAL : public MemoryUniReporter { public: FreetypeReporter() - : MemoryReporterBase("explicit/freetype", KIND_HEAP, UNITS_BYTES, - "Memory used by Freetype.") + : MemoryUniReporter("explicit/freetype", KIND_HEAP, UNITS_BYTES, + "Memory used by Freetype.") { #ifdef DEBUG // There must be only one instance of this class, due to |sAmount| diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 77dcae2b74e9..1b7050f2f25d 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -1252,7 +1252,7 @@ gfxFontFamily::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf, * shaped-word caches to free up memory. */ -NS_IMPL_ISUPPORTS1(gfxFontCache::MemoryReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(gfxFontCache::MemoryReporter, nsIMemoryReporter) NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontCacheMallocSizeOf) @@ -1265,7 +1265,7 @@ gfxFontCache::MemoryReporter::GetName(nsACString &aName) NS_IMETHODIMP gfxFontCache::MemoryReporter::CollectReports - (nsIMemoryMultiReporterCallback* aCb, + (nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { FontCacheSizes sizes; @@ -1324,7 +1324,7 @@ gfxFontCache::Init() if (!gGlobalCache) { return NS_ERROR_OUT_OF_MEMORY; } - NS_RegisterMemoryMultiReporter(new MemoryReporter); + NS_RegisterMemoryReporter(new MemoryReporter); return NS_OK; } diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 2f5e8bb5c193..3133c05d1e7b 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -977,11 +977,11 @@ public: protected: class MemoryReporter MOZ_FINAL - : public nsIMemoryMultiReporter + : public nsIMemoryReporter { public: NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYMULTIREPORTER + NS_DECL_NSIMEMORYREPORTER }; void DestroyFont(gfxFont *aFont); diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index 60584906c0c2..4ab0a331fd7f 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -70,7 +70,7 @@ gfxFontListPrefObserver::Observe(nsISupports *aSubject, return NS_OK; } -NS_IMPL_ISUPPORTS1(gfxPlatformFontList::MemoryReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(gfxPlatformFontList::MemoryReporter, nsIMemoryReporter) NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontListMallocSizeOf) @@ -83,7 +83,7 @@ gfxPlatformFontList::MemoryReporter::GetName(nsACString &aName) NS_IMETHODIMP gfxPlatformFontList::MemoryReporter::CollectReports - (nsIMemoryMultiReporterCallback* aCb, + (nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { FontListSizes sizes; @@ -148,7 +148,7 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames) mSharedCmaps.Init(16); - NS_RegisterMemoryMultiReporter(new MemoryReporter); + NS_RegisterMemoryReporter(new MemoryReporter); } gfxPlatformFontList::~gfxPlatformFontList() diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index 53c1c9474594..b8f1aaebec3f 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -179,11 +179,11 @@ public: protected: class MemoryReporter MOZ_FINAL - : public nsIMemoryMultiReporter + : public nsIMemoryReporter { public: NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYMULTIREPORTER + NS_DECL_NSIMEMORYREPORTER }; gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true); diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index f543a5743337..72bdaa02525d 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -73,11 +73,11 @@ static const int kSupportedFeatureLevels[] = { D3D10_FEATURE_LEVEL_10_1, D3D10_FEATURE_LEVEL_10_0, D3D10_FEATURE_LEVEL_9_3 }; -class GfxD2DSurfaceCacheReporter MOZ_FINAL : public MemoryReporterBase +class GfxD2DSurfaceCacheReporter MOZ_FINAL : public MemoryUniReporter { public: GfxD2DSurfaceCacheReporter() - : MemoryReporterBase("gfx-d2d-surface-cache", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("gfx-d2d-surface-cache", KIND_OTHER, UNITS_BYTES, "Memory used by the Direct2D internal surface cache.") {} private: @@ -110,11 +110,11 @@ bool OncePreferenceDirect2DForceEnabled() } // anonymous namespace -class GfxD2DSurfaceVramReporter MOZ_FINAL : public MemoryReporterBase +class GfxD2DSurfaceVramReporter MOZ_FINAL : public MemoryUniReporter { public: GfxD2DSurfaceVramReporter() - : MemoryReporterBase("gfx-d2d-surface-vram", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("gfx-d2d-surface-vram", KIND_OTHER, UNITS_BYTES, "Video memory used by D2D surfaces.") {} private: @@ -127,11 +127,11 @@ private: #endif -class GfxD2DVramDrawTargetReporter MOZ_FINAL : public MemoryReporterBase +class GfxD2DVramDrawTargetReporter MOZ_FINAL : public MemoryUniReporter { public: GfxD2DVramDrawTargetReporter() - : MemoryReporterBase("gfx-d2d-vram-draw-target", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("gfx-d2d-vram-draw-target", KIND_OTHER, UNITS_BYTES, "Video memory used by D2D DrawTargets.") {} private: @@ -141,11 +141,11 @@ private: } }; -class GfxD2DVramSourceSurfaceReporter MOZ_FINAL : public MemoryReporterBase +class GfxD2DVramSourceSurfaceReporter MOZ_FINAL : public MemoryUniReporter { public: GfxD2DVramSourceSurfaceReporter() - : MemoryReporterBase("gfx-d2d-vram-source-surface", + : MemoryUniReporter("gfx-d2d-vram-source-surface", KIND_OTHER, UNITS_BYTES, "Video memory used by D2D SourceSurfaces.") {} @@ -206,7 +206,7 @@ typedef HRESULT (WINAPI*D3D11CreateDeviceFunc)( ID3D11DeviceContext *ppImmediateContext ); -class GPUAdapterMultiReporter : public nsIMemoryMultiReporter { +class GPUAdapterReporter : public nsIMemoryReporter { // Callers must Release the DXGIAdapter after use or risk mem-leak static bool GetDXGIAdapter(IDXGIAdapter **DXGIAdapter) @@ -228,7 +228,7 @@ class GPUAdapterMultiReporter : public nsIMemoryMultiReporter { public: NS_DECL_ISUPPORTS - // nsIMemoryMultiReporter abstract method implementation + // nsIMemoryReporter abstract method implementation NS_IMETHOD GetName(nsACString &aName) { @@ -236,9 +236,9 @@ public: return NS_OK; } - // nsIMemoryMultiReporter abstract method implementation + // nsIMemoryReporter abstract method implementation NS_IMETHOD - CollectReports(nsIMemoryMultiReporterCallback* aCb, + CollectReports(nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { int32_t winVers, buildNum; @@ -347,7 +347,7 @@ public: return NS_OK; } }; -NS_IMPL_ISUPPORTS1(GPUAdapterMultiReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(GPUAdapterReporter, nsIMemoryReporter) static __inline void BuildKeyNameFromFontName(nsAString &aName) @@ -385,16 +385,16 @@ gfxWindowsPlatform::gfxWindowsPlatform() UpdateRenderMode(); - mGPUAdapterMultiReporter = new GPUAdapterMultiReporter(); - NS_RegisterMemoryMultiReporter(mGPUAdapterMultiReporter); + mGPUAdapterReporter = new GPUAdapterReporter(); + NS_RegisterMemoryReporter(mGPUAdapterReporter); } gfxWindowsPlatform::~gfxWindowsPlatform() { - NS_UnregisterMemoryMultiReporter(mGPUAdapterMultiReporter); - - mDeviceManager = nullptr; - + NS_UnregisterMemoryReporter(mGPUAdapterReporter); + + mDeviceManager = nullptr; + ::ReleaseDC(nullptr, mScreenDC); // not calling FT_Done_FreeType because cairo may still hold references to // these FT_Faces. See bug 458169. diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index c00332244b4d..8d1d5aac423c 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -52,7 +52,7 @@ class IDirect3DDevice9; class ID3D11Device; class IDXGIAdapter1; -class nsIMemoryMultiReporter; +class nsIMemoryReporter; // Utility to get a Windows HDC from a thebes context, // used by both GDI and Uniscribe font shapers @@ -315,7 +315,7 @@ private: // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList nsDataHashtable > > mPrefFonts; - nsIMemoryMultiReporter* mGPUAdapterMultiReporter; + nsIMemoryReporter* mGPUAdapterReporter; }; #endif /* GFX_WINDOWS_PLATFORM_H */ diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp index 024108605ff0..463583899b3d 100644 --- a/image/src/imgLoader.cpp +++ b/image/src/imgLoader.cpp @@ -61,7 +61,7 @@ using namespace mozilla::image; NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ImagesMallocSizeOf) class imgMemoryReporter MOZ_FINAL : - public nsIMemoryMultiReporter + public nsIMemoryReporter { public: imgMemoryReporter() @@ -76,7 +76,7 @@ public: return NS_OK; } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback, + NS_IMETHOD CollectReports(nsIMemoryReporterCallback *callback, nsISupports *closure) { AllSizes chrome; @@ -233,15 +233,15 @@ private: } }; -NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryReporter) // This is used by telemetry. class ImagesContentUsedUncompressedReporter MOZ_FINAL - : public MemoryReporterBase + : public MemoryUniReporter { public: ImagesContentUsedUncompressedReporter() - : MemoryReporterBase("images-content-used-uncompressed", + : MemoryUniReporter("images-content-used-uncompressed", KIND_OTHER, UNITS_BYTES, "This is the sum of the 'explicit/images/content/used/uncompressed-heap' " "and 'explicit/images/content/used/uncompressed-nonheap' numbers. However, " @@ -850,7 +850,7 @@ void imgLoader::GlobalInit() sCacheMaxSize = 5 * 1024 * 1024; sMemReporter = new imgMemoryReporter(); - NS_RegisterMemoryMultiReporter(sMemReporter); + NS_RegisterMemoryReporter(sMemReporter); NS_RegisterMemoryReporter(new ImagesContentUsedUncompressedReporter()); } diff --git a/image/test/mochitest/test_bug601470.html b/image/test/mochitest/test_bug601470.html index 7942285f5d72..bc37ea2c2048 100644 --- a/image/test/mochitest/test_bug601470.html +++ b/image/test/mochitest/test_bug601470.html @@ -25,14 +25,18 @@ window.onload = function() { var mgr = SpecialPowers.Cc["@mozilla.org/memory-reporter-manager;1"] .getService(SpecialPowers.Ci.nsIMemoryReporterManager); - var e = mgr.enumerateReporters(); - var memoryCounter = 0; - while (e.hasMoreElements()) { - var mr = - e.getNext().QueryInterface(SpecialPowers.Ci.nsIMemoryReporter); - memoryCounter += mr.amount; + var amount = 0; + var handleReport = function(aProcess, aPath, aKind, aUnits, aAmount, aDesc) { + amount += aAmount; } - ok(memoryCounter > 0, "we should be using a nonzero amount of memory"); + + var e = mgr.enumerateReporters(); + while (e.hasMoreElements()) { + var mr = e.getNext().QueryInterface(SpecialPowers.Ci.nsIMemoryReporter); + mr.collectReports(handleReport, null); + } + + ok(amount > 0, "we should be using a nonzero amount of memory"); ok(true, "yay, didn't crash!"); SimpleTest.finish(); diff --git a/ipc/glue/SharedMemory.cpp b/ipc/glue/SharedMemory.cpp index 24959ff48583..6fe916e42f7d 100644 --- a/ipc/glue/SharedMemory.cpp +++ b/ipc/glue/SharedMemory.cpp @@ -17,11 +17,11 @@ namespace ipc { static Atomic gShmemAllocated; static Atomic gShmemMapped; -class ShmemAllocatedReporter MOZ_FINAL : public MemoryReporterBase +class ShmemAllocatedReporter MOZ_FINAL : public MemoryUniReporter { public: ShmemAllocatedReporter() - : MemoryReporterBase("shmem-allocated", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("shmem-allocated", KIND_OTHER, UNITS_BYTES, "Memory shared with other processes that is accessible (but not necessarily " "mapped).") {} @@ -29,11 +29,11 @@ private: int64_t Amount() MOZ_OVERRIDE { return gShmemAllocated; } }; -class ShmemMappedReporter MOZ_FINAL : public MemoryReporterBase +class ShmemMappedReporter MOZ_FINAL : public MemoryUniReporter { public: ShmemMappedReporter() - : MemoryReporterBase("shmem-mapped", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("shmem-mapped", KIND_OTHER, UNITS_BYTES, "Memory shared with other processes that is mapped into the address space.") {} private: diff --git a/js/xpconnect/src/XPCJSMemoryReporter.h b/js/xpconnect/src/XPCJSMemoryReporter.h index ac95b7813035..447f0f3896bf 100644 --- a/js/xpconnect/src/XPCJSMemoryReporter.h +++ b/js/xpconnect/src/XPCJSMemoryReporter.h @@ -9,22 +9,22 @@ #define XPCJSMemoryReporter_h class nsISupports; -class nsIMemoryMultiReporterCallback; +class nsIMemoryReporterCallback; namespace xpc { // The key is the window ID. typedef nsDataHashtable WindowPaths; -// This is very nearly an instance of nsIMemoryMultiReporter, but it's not, +// This is very nearly an instance of nsIMemoryReporter, but it's not, // because it's invoked by nsWindowMemoryReporter in order to get |windowPaths| // in CollectReports. -class JSMemoryMultiReporter +class JSReporter { public: static nsresult CollectReports(WindowPaths *windowPaths, WindowPaths *topWindowPaths, - nsIMemoryMultiReporterCallback *cb, + nsIMemoryReporterCallback *cb, nsISupports *closure); }; diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 02c3a6cd93bc..50ce3f4c95aa 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1560,13 +1560,13 @@ GetCompartmentName(JSCompartment *c, nsCString &name, bool replaceSlashes) } } -// Telemetry relies on this being a single reporter (rather than part of the -// "js" multi-reporter). -class JSGCHeapReporter MOZ_FINAL : public MemoryReporterBase +// Telemetry relies on this being a uni-reporter (rather than part of the "js" +// reporter). +class JSGCHeapReporter MOZ_FINAL : public MemoryUniReporter { public: JSGCHeapReporter() - : MemoryReporterBase("js-gc-heap", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("js-gc-heap", KIND_OTHER, UNITS_BYTES, "Memory used by the garbage-collected JavaScript heap.") {} private: @@ -1578,19 +1578,17 @@ private: } }; -// Nb: js-compartments/system + js-compartments/user could be -// different to the number of compartments reported by -// JSMemoryMultiReporter if a garbage collection occurred -// between them being consulted. We could move these reporters into -// XPConnectJSCompartmentCount to avoid that problem, but then we couldn't -// easily report them via telemetry, so we live with the small risk of -// inconsistencies. +// Nb: js-compartments/system + js-compartments/user could be different to the +// number of compartments reported by JSReporter if a garbage collection +// occurred between them being consulted. We could move these reporters into +// JSReporter to avoid that problem, but then we couldn't easily report them +// via telemetry, so we live with the small risk of inconsistencies. -class JSCompartmentsSystemReporter MOZ_FINAL : public MemoryReporterBase +class JSCompartmentsSystemReporter MOZ_FINAL : public MemoryUniReporter { public: JSCompartmentsSystemReporter() - : MemoryReporterBase("js-compartments/system", KIND_OTHER, UNITS_COUNT, + : MemoryUniReporter("js-compartments/system", KIND_OTHER, UNITS_COUNT, "The number of JavaScript compartments for system code. The sum of this and " "'js-compartments/user' might not match the number of compartments listed " "in the 'explicit' tree if a garbage collection occurs at an inopportune " @@ -1604,11 +1602,11 @@ private: } }; -class JSCompartmentsUserReporter MOZ_FINAL : public MemoryReporterBase +class JSCompartmentsUserReporter MOZ_FINAL : public MemoryUniReporter { public: JSCompartmentsUserReporter() - : MemoryReporterBase("js-compartments/user", KIND_OTHER, UNITS_COUNT, + : MemoryUniReporter("js-compartments/user", KIND_OTHER, UNITS_COUNT, "The number of JavaScript compartments for user code. The sum of this and " "'js-compartments/system' might not match the number of compartments listed " "under 'js' if a garbage collection occurs at an inopportune time, but such " @@ -1623,11 +1621,11 @@ private: }; // This is also a single reporter so it can be used by telemetry. -class JSMainRuntimeTemporaryPeakReporter MOZ_FINAL : public MemoryReporterBase +class JSMainRuntimeTemporaryPeakReporter MOZ_FINAL : public MemoryUniReporter { public: JSMainRuntimeTemporaryPeakReporter() - : MemoryReporterBase("js-main-runtime-temporary-peak", + : MemoryUniReporter("js-main-runtime-temporary-peak", KIND_OTHER, UNITS_BYTES, "The peak size of the transient storage in the main JSRuntime (the current " "size of which is reported as 'explicit/js-non-window/runtime/temporary').") @@ -1758,7 +1756,7 @@ namespace xpc { static nsresult ReportZoneStats(const JS::ZoneStats &zStats, const xpc::ZoneStatsExtras &extras, - nsIMemoryMultiReporterCallback *cb, + nsIMemoryReporterCallback *cb, nsISupports *closure, size_t *gcTotalOut = NULL) { const nsAutoCString& pathPrefix = extras.pathPrefix; @@ -1942,7 +1940,7 @@ static nsresult ReportCompartmentStats(const JS::CompartmentStats &cStats, const xpc::CompartmentStatsExtras &extras, amIAddonManager *addonManager, - nsIMemoryMultiReporterCallback *cb, + nsIMemoryReporterCallback *cb, nsISupports *closure, size_t *gcTotalOut = NULL) { static const nsDependentCString addonPrefix("explicit/add-ons/"); @@ -2084,8 +2082,8 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats, "Memory allocated on the malloc heap for data belonging to ctypes objects."); // Note that we use cDOMPathPrefix here. This is because we measure orphan - // DOM nodes in the JS multi-reporter, but we want to report them in a - // "dom" sub-tree rather than a "js" sub-tree. + // DOM nodes in the JS reporter, but we want to report them in a "dom" + // sub-tree rather than a "js" sub-tree. ZCREPORT_BYTES(cDOMPathPrefix + NS_LITERAL_CSTRING("orphan-nodes"), cStats.objectsExtra.private_, "Memory used by orphan DOM nodes that are only reachable " @@ -2207,7 +2205,7 @@ static nsresult ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACString &rtPath, amIAddonManager* addonManager, - nsIMemoryMultiReporterCallback *cb, + nsIMemoryReporterCallback *cb, nsISupports *closure, size_t *rtTotalOut) { nsresult rv; @@ -2349,7 +2347,7 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, nsresult ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACString &rtPath, - nsIMemoryMultiReporterCallback *cb, + nsIMemoryReporterCallback *cb, nsISupports *closure, size_t *rtTotalOut) { nsCOMPtr am = @@ -2361,7 +2359,7 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, } // namespace xpc -class JSCompartmentsMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter +class JSCompartmentsReporter MOZ_FINAL : public nsIMemoryReporter { public: NS_DECL_THREADSAFE_ISUPPORTS @@ -2385,7 +2383,7 @@ class JSCompartmentsMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter paths->append(path); } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *cb, + NS_IMETHOD CollectReports(nsIMemoryReporterCallback *cb, nsISupports *closure) { // First we collect the compartment paths. Then we report them. Doing @@ -2407,9 +2405,7 @@ class JSCompartmentsMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter } }; -NS_IMPL_ISUPPORTS1(JSCompartmentsMultiReporter - , nsIMemoryMultiReporter - ) +NS_IMPL_ISUPPORTS1(JSCompartmentsReporter, nsIMemoryReporter) NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(OrphanMallocSizeOf) @@ -2567,9 +2563,9 @@ class XPCJSRuntimeStats : public JS::RuntimeStats // "compartment()/". // // extras->domPathPrefix is used for DOM orphan nodes, which are - // counted by the JS multi-reporter but reported as part of the - // DOM measurements. At this point it has the form "/dom/" - // if this compartment belongs to an nsGlobalWindow, and + // counted by the JS reporter but reported as part of the DOM + // measurements. At this point it has the form "/dom/" if + // this compartment belongs to an nsGlobalWindow, and // "explicit/dom/?!/" otherwise (in which case it shouldn't // be used, because non-nsGlobalWindow compartments shouldn't have // orphan DOM nodes). @@ -2579,10 +2575,10 @@ class XPCJSRuntimeStats : public JS::RuntimeStats }; nsresult -JSMemoryMultiReporter::CollectReports(WindowPaths *windowPaths, - WindowPaths *topWindowPaths, - nsIMemoryMultiReporterCallback *cb, - nsISupports *closure) +JSReporter::CollectReports(WindowPaths *windowPaths, + WindowPaths *topWindowPaths, + nsIMemoryReporterCallback *cb, + nsISupports *closure) { XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance(); @@ -3053,7 +3049,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) NS_RegisterMemoryReporter(new JSCompartmentsSystemReporter()); NS_RegisterMemoryReporter(new JSCompartmentsUserReporter()); NS_RegisterMemoryReporter(new JSMainRuntimeTemporaryPeakReporter()); - NS_RegisterMemoryMultiReporter(new JSCompartmentsMultiReporter); + NS_RegisterMemoryReporter(new JSCompartmentsReporter); // Install a JavaScript 'debugger' keyword handler in debug builds only #ifdef DEBUG diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 430791f2caef..5de64f5b906f 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -180,7 +180,7 @@ xpc_UnmarkSkippableJSHolders(); NS_EXPORT_(void) xpc_ActivateDebugMode(); -class nsIMemoryMultiReporterCallback; +class nsIMemoryReporterCallback; // readable string conversions, static methods and members only class XPCStringConvert @@ -376,7 +376,7 @@ private: nsresult ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACString &rtPath, - nsIMemoryMultiReporterCallback *cb, + nsIMemoryReporterCallback *cb, nsISupports *closure, size_t *rtTotal = NULL); /** diff --git a/layout/base/nsStyleSheetService.cpp b/layout/base/nsStyleSheetService.cpp index 644399f6dc03..419e30b80d9b 100644 --- a/layout/base/nsStyleSheetService.cpp +++ b/layout/base/nsStyleSheetService.cpp @@ -26,11 +26,11 @@ using namespace mozilla; class LayoutStyleSheetServiceReporter MOZ_FINAL - : public mozilla::MemoryReporterBase + : public mozilla::MemoryUniReporter { public: LayoutStyleSheetServiceReporter() - : MemoryReporterBase("explicit/layout/style-sheet-service", + : MemoryUniReporter("explicit/layout/style-sheet-service", KIND_HEAP, UNITS_BYTES, "Memory used for style sheets held by the style sheet service.") {} diff --git a/layout/style/nsLayoutStylesheetCache.cpp b/layout/style/nsLayoutStylesheetCache.cpp index 72072679b6b0..c20510e18ec2 100644 --- a/layout/style/nsLayoutStylesheetCache.cpp +++ b/layout/style/nsLayoutStylesheetCache.cpp @@ -18,11 +18,11 @@ #include "nsCSSStyleSheet.h" class LayoutStyleSheetCacheReporter MOZ_FINAL - : public mozilla::MemoryReporterBase + : public mozilla::MemoryUniReporter { public: LayoutStyleSheetCacheReporter() - : MemoryReporterBase("explicit/layout/style-sheet-cache", + : MemoryUniReporter("explicit/layout/style-sheet-cache", KIND_HEAP, UNITS_BYTES, "Memory used for some built-in style sheets.") {} diff --git a/modules/libpref/src/Preferences.cpp b/modules/libpref/src/Preferences.cpp index 10eba7a2675d..59c06be2f034 100644 --- a/modules/libpref/src/Preferences.cpp +++ b/modules/libpref/src/Preferences.cpp @@ -203,11 +203,11 @@ Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeO return n; } -class PreferencesReporter MOZ_FINAL : public MemoryReporterBase +class PreferencesReporter MOZ_FINAL : public MemoryUniReporter { public: PreferencesReporter() - : MemoryReporterBase("explicit/preferences", KIND_HEAP, UNITS_BYTES, + : MemoryUniReporter("explicit/preferences", KIND_HEAP, UNITS_BYTES, "Memory used by the preferences system.") {} private: diff --git a/netwerk/cache/nsDiskCacheDevice.cpp b/netwerk/cache/nsDiskCacheDevice.cpp index a6dcd50164e7..97c1ad8964c1 100644 --- a/netwerk/cache/nsDiskCacheDevice.cpp +++ b/netwerk/cache/nsDiskCacheDevice.cpp @@ -370,11 +370,11 @@ nsDiskCache::Truncate(PRFileDesc * fd, uint32_t newEOF) * nsDiskCacheDevice *****************************************************************************/ -class NetworkDiskCacheReporter MOZ_FINAL : public MemoryReporterBase +class NetworkDiskCacheReporter MOZ_FINAL : public MemoryUniReporter { public: NetworkDiskCacheReporter(nsDiskCacheDevice* aDevice) - : MemoryReporterBase( + : MemoryUniReporter( "explicit/network/disk-cache", KIND_HEAP, UNITS_BYTES, diff --git a/netwerk/cache/nsMemoryCacheDevice.cpp b/netwerk/cache/nsMemoryCacheDevice.cpp index 02b7b8dc199b..e0e9c9656027 100644 --- a/netwerk/cache/nsMemoryCacheDevice.cpp +++ b/netwerk/cache/nsMemoryCacheDevice.cpp @@ -29,11 +29,11 @@ const char *gMemoryDeviceID = "memory"; class NetworkMemoryCacheReporter MOZ_FINAL : - public mozilla::MemoryReporterBase + public mozilla::MemoryUniReporter { public: NetworkMemoryCacheReporter(nsMemoryCacheDevice* aDevice) - : MemoryReporterBase( + : MemoryUniReporter( "explicit/network/memory-cache", KIND_HEAP, UNITS_BYTES, diff --git a/netwerk/dns/nsEffectiveTLDService.cpp b/netwerk/dns/nsEffectiveTLDService.cpp index 71dd332ba730..3389f63af018 100644 --- a/netwerk/dns/nsEffectiveTLDService.cpp +++ b/netwerk/dns/nsEffectiveTLDService.cpp @@ -61,11 +61,11 @@ nsDomainEntry::FuncForStaticAsserts(void) static nsEffectiveTLDService *gService = nullptr; -class EffectiveTLDServiceReporter MOZ_FINAL : public MemoryReporterBase +class EffectiveTLDServiceReporter MOZ_FINAL : public MemoryUniReporter { public: EffectiveTLDServiceReporter() - : MemoryReporterBase("explicit/xpcom/effective-TLD-service", + : MemoryUniReporter("explicit/xpcom/effective-TLD-service", KIND_HEAP, UNITS_BYTES, "Memory used by the effective TLD service.") {} diff --git a/startupcache/StartupCache.cpp b/startupcache/StartupCache.cpp index 14021ccb4eea..2889dd326207 100644 --- a/startupcache/StartupCache.cpp +++ b/startupcache/StartupCache.cpp @@ -53,11 +53,11 @@ namespace mozilla { namespace scache { -class StartupCacheMappingReporter MOZ_FINAL : public MemoryReporterBase +class StartupCacheMappingReporter MOZ_FINAL : public MemoryUniReporter { public: StartupCacheMappingReporter() - : MemoryReporterBase("explicit/startup-cache/mapping", + : MemoryUniReporter("explicit/startup-cache/mapping", KIND_NONHEAP, UNITS_BYTES, "Memory used to hold the mapping of the startup cache from file. This memory " "is likely to be swapped out shortly after start-up.") @@ -71,11 +71,11 @@ private: } }; -class StartupCacheDataReporter MOZ_FINAL : public MemoryReporterBase +class StartupCacheDataReporter MOZ_FINAL : public MemoryUniReporter { public: StartupCacheDataReporter() - : MemoryReporterBase("explicit/startup-cache/data", KIND_HEAP, UNITS_BYTES, + : MemoryUniReporter("explicit/startup-cache/data", KIND_HEAP, UNITS_BYTES, "Memory used by the startup cache for things other than the file mapping.") {} private: diff --git a/storage/src/mozStorageService.cpp b/storage/src/mozStorageService.cpp index 9b0b31948319..4e6118f033e6 100644 --- a/storage/src/mozStorageService.cpp +++ b/storage/src/mozStorageService.cpp @@ -57,18 +57,18 @@ namespace storage { // the multi-reporter provides reports that add up to the total. But it's // useful to have the total in the "Other Measurements" list in about:memory, // and more importantly, we also gather the total via telemetry. -class StorageSQLiteReporter MOZ_FINAL : public MemoryReporterBase +class StorageSQLiteUniReporter MOZ_FINAL : public MemoryUniReporter { public: - StorageSQLiteReporter() - : MemoryReporterBase("storage-sqlite", KIND_OTHER, UNITS_BYTES, + StorageSQLiteUniReporter() + : MemoryUniReporter("storage-sqlite", KIND_OTHER, UNITS_BYTES, "Memory used by SQLite.") {} private: int64_t Amount() MOZ_OVERRIDE { return ::sqlite3_memory_used(); } }; -class StorageSQLiteMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter +class StorageSQLiteMultiReporter MOZ_FINAL : public nsIMemoryReporter { private: Service *mService; // a weakref because Service contains a strongref to this @@ -97,7 +97,7 @@ public: NS_IMETHOD GetName(nsACString &aName) { - aName.AssignLiteral("storage-sqlite"); + aName.AssignLiteral("storage-sqlite-multi"); return NS_OK; } @@ -107,7 +107,7 @@ public: // main thread! But at the time of writing this function is only called when // about:memory is loaded (not, for example, when telemetry pings occur) and // any delays in that case aren't so bad. - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCb, + NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb, nsISupports *aClosure) { nsresult rv; @@ -164,8 +164,7 @@ public: private: /** - * Passes a single SQLite memory statistic to a memory multi-reporter - * callback. + * Passes a single SQLite memory statistic to a memory reporter callback. * * @param aCallback * The callback. @@ -185,7 +184,7 @@ private: * @param aTotal * The accumulator for the measurement. */ - nsresult reportConn(nsIMemoryMultiReporterCallback *aCb, + nsresult reportConn(nsIMemoryReporterCallback *aCb, nsISupports *aClosure, sqlite3 *aConn, const nsACString &aPathHead, @@ -216,7 +215,7 @@ private: NS_IMPL_ISUPPORTS1( StorageSQLiteMultiReporter, - nsIMemoryMultiReporter + nsIMemoryReporter ) //////////////////////////////////////////////////////////////////////////////// @@ -308,8 +307,8 @@ Service::Service() Service::~Service() { - (void)::NS_UnregisterMemoryReporter(mStorageSQLiteReporter); - (void)::NS_UnregisterMemoryMultiReporter(mStorageSQLiteMultiReporter); + (void)::NS_UnregisterMemoryReporter(mStorageSQLiteUniReporter); + (void)::NS_UnregisterMemoryReporter(mStorageSQLiteMultiReporter); int rc = sqlite3_vfs_unregister(mSqliteVFS); if (rc != SQLITE_OK) @@ -541,10 +540,10 @@ Service::initialize() // Create and register our SQLite memory reporters. Registration can only // happen on the main thread (otherwise you'll get cryptic crashes). - mStorageSQLiteReporter = new StorageSQLiteReporter(); + mStorageSQLiteUniReporter = new StorageSQLiteUniReporter(); mStorageSQLiteMultiReporter = new StorageSQLiteMultiReporter(this); - (void)::NS_RegisterMemoryReporter(mStorageSQLiteReporter); - (void)::NS_RegisterMemoryMultiReporter(mStorageSQLiteMultiReporter); + (void)::NS_RegisterMemoryReporter(mStorageSQLiteUniReporter); + (void)::NS_RegisterMemoryReporter(mStorageSQLiteMultiReporter); return NS_OK; } diff --git a/storage/src/mozStorageService.h b/storage/src/mozStorageService.h index 18a70a220795..f0625af5067d 100644 --- a/storage/src/mozStorageService.h +++ b/storage/src/mozStorageService.h @@ -17,7 +17,6 @@ #include "mozIStorageService.h" class nsIMemoryReporter; -class nsIMemoryMultiReporter; class nsIXPConnect; struct sqlite3_vfs; @@ -173,8 +172,8 @@ private: nsCOMPtr mProfileStorageFile; - nsCOMPtr mStorageSQLiteReporter; - nsCOMPtr mStorageSQLiteMultiReporter; + nsCOMPtr mStorageSQLiteUniReporter; + nsCOMPtr mStorageSQLiteMultiReporter; static Service *gService; diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js index cb9170734d2c..6e5320911ec3 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -166,49 +166,32 @@ function onUnload() //--------------------------------------------------------------------------- /** - * Iterates over each reporter and multi-reporter. + * Iterates over each reporter. * - * @param aIgnoreSingle - * Function that indicates if we should skip a single reporter, based - * on its path. - * @param aIgnoreMulti - * Function that indicates if we should skip a multi-reporter, based on - * its name. + * @param aIgnoreReporter + * Function that indicates if we should skip an entire reporter, based + * on its name. + * @param aIgnoreReport + * Function that indicates if we should skip a single report from a + * reporter, based on its path. * @param aHandleReport - * The function that's called for each report. + * The function that's called for each non-skipped report. */ -function processMemoryReporters(aIgnoreSingle, aIgnoreMulti, aHandleReport) +function processMemoryReporters(aIgnoreReporter, aIgnoreReport, aHandleReport) { - // Process each memory reporter with aHandleReport. - // - // - Note that copying rOrig.amount (which calls a C++ function under the - // IDL covers) to r._amount for every reporter now means that the - // results as consistent as possible -- measurements are made all at - // once before most of the memory required to generate this page is - // allocated. - // - // - After this point we never use the original memory report again. - - let e = gMgr.enumerateReporters(); - while (e.hasMoreElements()) { - let rOrig = e.getNext().QueryInterface(Ci.nsIMemoryReporter); - let unsafePath = rOrig.path; - if (!aIgnoreSingle(unsafePath)) { - aHandleReport(rOrig.process, unsafePath, rOrig.kind, rOrig.units, - rOrig.amount, rOrig.description); + let handleReport = function(aProcess, aUnsafePath, aKind, aUnits, + aAmount, aDescription) { + if (!aIgnoreReport(aUnsafePath)) { + aHandleReport(aProcess, aUnsafePath, aKind, aUnits, aAmount, + aDescription, /* presence = */ undefined); } } - let e = gMgr.enumerateMultiReporters(); + let e = gMgr.enumerateReporters(); while (e.hasMoreElements()) { - let mr = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter); - if (!aIgnoreMulti(mr.name)) { + let mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter); + if (!aIgnoreReporter(mr.name)) { // |collectReports| never passes in a |presence| argument. - let handleReport = function(aProcess, aUnsafePath, aKind, aUnits, - aAmount, aDescription) { - aHandleReport(aProcess, aUnsafePath, aKind, aUnits, aAmount, - aDescription, /* presence = */ undefined); - } mr.collectReports(handleReport, null); } } @@ -219,19 +202,19 @@ function processMemoryReporters(aIgnoreSingle, aIgnoreMulti, aHandleReport) * * @param aReports * Array of reports, read from a file or the clipboard. - * @param aIgnoreSingle - * Function that indicates if we should skip a single reporter, based + * @param aIgnoreReport + * Function that indicates if we should skip a single report, based * on its path. * @param aHandleReport * The function that's called for each report. */ -function processMemoryReportsFromFile(aReports, aIgnoreSingle, aHandleReport) +function processMemoryReportsFromFile(aReports, aIgnoreReport, aHandleReport) { // Process each memory reporter with aHandleReport. for (let i = 0; i < aReports.length; i++) { let r = aReports[i]; - if (!aIgnoreSingle(r.path)) { + if (!aIgnoreReport(r.path)) { aHandleReport(r.process, r.path, r.kind, r.units, r.amount, r.description, r._presence); } @@ -591,10 +574,7 @@ function updateAboutMemoryFromReporters() try { // Process the reports from the memory reporters. - let process = function(aIgnoreSingle, aIgnoreMulti, aHandleReport) { - processMemoryReporters(aIgnoreSingle, aIgnoreMulti, aHandleReport); - } - appendAboutMemoryMain(process, gMgr.hasMozMallocUsableSize, + appendAboutMemoryMain(processMemoryReporters, gMgr.hasMozMallocUsableSize, /* forceShowSmaps = */ false); } catch (ex) { @@ -621,8 +601,8 @@ function updateAboutMemoryFromJSONObject(aObj) "missing 'hasMozMallocUsableSize' property"); assertInput(aObj.reports && aObj.reports instanceof Array, "missing or non-array 'reports' property"); - let process = function(aIgnoreSingle, aIgnoreMulti, aHandleReport) { - processMemoryReportsFromFile(aObj.reports, aIgnoreSingle, aHandleReport); + let process = function(aIgnoreReporter, aIgnoreReport, aHandleReport) { + processMemoryReportsFromFile(aObj.reports, aIgnoreReport, aHandleReport); } appendAboutMemoryMain(process, aObj.hasMozMallocUsableSize, /* forceShowSmaps = */ true); @@ -973,7 +953,7 @@ function PColl() * Processes reports (whether from reporters or from a file) and append the * main part of the page. * - * @param aProcess + * @param aProcessReports * Function that extracts the memory reports from the reporters or from * file. * @param aHasMozMallocUsableSize @@ -982,10 +962,10 @@ function PColl() * True if we should show the smaps memory reporters even if we're not * in verbose mode. */ -function appendAboutMemoryMain(aProcess, aHasMozMallocUsableSize, +function appendAboutMemoryMain(aProcessReports, aHasMozMallocUsableSize, aForceShowSmaps) { - let pcollsByProcess = getPCollsByProcess(aProcess, aForceShowSmaps); + let pcollsByProcess = getPCollsByProcess(aProcessReports, aForceShowSmaps); // Sort the processes. let processes = Object.keys(pcollsByProcess); @@ -1043,7 +1023,7 @@ function appendAboutMemoryMain(aProcess, aHasMozMallocUsableSize, * This function reads all the memory reports, and puts that data in structures * that will be used to generate the page. * - * @param aProcessMemoryReports + * @param aProcessReports * Function that extracts the memory reports from the reporters or from * file. * @param aForceShowSmaps @@ -1051,7 +1031,7 @@ function appendAboutMemoryMain(aProcess, aHasMozMallocUsableSize, * in verbose mode. * @return The table of PColls by process. */ -function getPCollsByProcess(aProcessMemoryReports, aForceShowSmaps) +function getPCollsByProcess(aProcessReports, aForceShowSmaps) { let pcollsByProcess = {}; @@ -1060,23 +1040,28 @@ function getPCollsByProcess(aProcessMemoryReports, aForceShowSmaps) // be in parentheses, so a ')' might appear after the '.'.) const gSentenceRegExp = /^[A-Z].*\.\)?$/m; - // Ignore the "smaps" multi-reporter in non-verbose mode unless we're reading - // from a file or the clipboard, and ignore the "compartments" and - // "ghost-windows" multi-reporters all the time. (Note that reports from - // these multi-reporters can reach here as single reports if they were in the - // child process.) + // Ignore the "smaps" reporter in non-verbose mode unless we're reading from + // a file or the clipboard, and ignore the "compartments" and "ghost-windows" + // reporters all the time. (Note that reports from these reporters can reach + // here via a "content-child" reporter if they were in a child process.) // - // Also ignore the resident-fast reporter; we use the vanilla resident + // Also ignore the "resident-fast" reporter; we use the vanilla "resident" // reporter because it's more important that we get accurate results than // that we avoid the (small) possibility of a long pause when loading - // about:memory. - // - // We don't show both resident and resident-fast because running the resident - // reporter can purge pages on MacOS, which affects the results of the - // resident-fast reporter. We don't want about:memory's results to be - // affected by the order of memory reporter execution. + // about:memory. Furthermore, the "resident" reporter can purge pages on + // MacOS, which affects the results of the "resident-fast" reporter, and we + // don't want the measurements shown in about:memory to be affected by the + // (arbitrary) order of memory reporter execution. - function ignoreSingle(aUnsafePath) + function ignoreReporter(aName) + { + return (aName === "smaps" && !gVerbose.checked && !aForceShowSmaps) || + aName === "compartments" || + aName === "ghost-windows" || + aName === "resident-fast"; + } + + function ignoreReport(aUnsafePath) { return (isSmapsPath(aUnsafePath) && !gVerbose.checked && !aForceShowSmaps) || aUnsafePath.startsWith("compartments/") || @@ -1084,13 +1069,6 @@ function getPCollsByProcess(aProcessMemoryReports, aForceShowSmaps) aUnsafePath == "resident-fast"; } - function ignoreMulti(aMRName) - { - return (aMRName === "smaps" && !gVerbose.checked && !aForceShowSmaps) || - aMRName === "compartments" || - aMRName === "ghost-windows"; - } - function handleReport(aProcess, aUnsafePath, aKind, aUnits, aAmount, aDescription, aPresence) { @@ -1171,7 +1149,7 @@ function getPCollsByProcess(aProcessMemoryReports, aForceShowSmaps) } } - aProcessMemoryReports(ignoreSingle, ignoreMulti, handleReport); + aProcessReports(ignoreReporter, ignoreReport, handleReport); return pcollsByProcess; } @@ -2107,18 +2085,18 @@ Compartment.prototype = { function getCompartmentsByProcess() { - // Ignore anything that didn't come from the "compartments" multi-reporter. - // (Note that some such reports can reach here as single reports if they were - // in the child process.) + // Ignore anything that didn't come from the "compartments" reporter. (Note + // reports from this reporter can reach here via a "content-child" reporter + // if they were in a child process.) - function ignoreSingle(aUnsafePath) + function ignoreReporter(aName) { - return !aUnsafePath.startsWith("compartments/"); + return !(aName == "compartments" || aName == "content-child"); } - function ignoreMulti(aMRName) + function ignoreReport(aUnsafePath) { - return aMRName !== "compartments"; + return !aUnsafePath.startsWith("compartments/"); } let compartmentsByProcess = {}; @@ -2169,7 +2147,7 @@ function getCompartmentsByProcess() } } - processMemoryReporters(ignoreSingle, ignoreMulti, handleReport); + processMemoryReporters(ignoreReporter, ignoreReport, handleReport); return compartmentsByProcess; } @@ -2191,14 +2169,14 @@ GhostWindow.prototype = { function getGhostWindowsByProcess() { - function ignoreSingle(aUnsafePath) + function ignoreReporter(aName) { - return !aUnsafePath.startsWith('ghost-windows/') + return !(aName == "ghost-windows" || aName == "content-child"); } - function ignoreMulti(aName) + function ignoreReport(aUnsafePath) { - return aName !== "ghost-windows"; + return !aUnsafePath.startsWith('ghost-windows/') } let ghostWindowsByProcess = {}; @@ -2230,7 +2208,7 @@ function getGhostWindowsByProcess() } } - processMemoryReporters(ignoreSingle, ignoreMulti, handleReport); + processMemoryReporters(ignoreReporter, ignoreReport, handleReport); return ghostWindowsByProcess; } diff --git a/toolkit/components/aboutmemory/tests/test_aboutcompartments.xul b/toolkit/components/aboutmemory/tests/test_aboutcompartments.xul index aaab20563058..160a673bd664 100644 --- a/toolkit/components/aboutmemory/tests/test_aboutcompartments.xul +++ b/toolkit/components/aboutmemory/tests/test_aboutcompartments.xul @@ -24,8 +24,7 @@ let mgr = Cc["@mozilla.org/memory-reporter-manager;1"]. getService(Ci.nsIMemoryReporterManager); - // Remove all the real reporters and multi-reporters; save them to - // restore at the end. + // Remove all the real reporters; save them to restore at the end. mgr.blockRegistration(); var e = mgr.enumerateReporters(); var realReporters = []; @@ -34,13 +33,6 @@ mgr.unregisterReporter(r); realReporters.push(r); } - e = mgr.enumerateMultiReporters(); - var realMultiReporters = []; - while (e.hasMoreElements()) { - var r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter); - mgr.unregisterMultiReporter(r); - realMultiReporters.push(r); - } // Setup various fake-but-deterministic reporters. const KB = 1024; @@ -52,41 +44,39 @@ const BYTES = Ci.nsIMemoryReporter.UNITS_BYTES; const COUNT = Ci.nsIMemoryReporter.UNITS_COUNT; - function f(aProcess, aPath, aKind, aUnits, aAmount) { - return { - process: aProcess, - path: aPath, - kind: aKind, - units: aUnits, - description: "", - amount: aAmount - }; - } - var fakeReporters = [ - // These should be ignored. - f("", "explicit/a", HEAP, BYTES, 222 * MB), - f("", "explicit/b/a", HEAP, BYTES, 85 * MB), - f("", "explicit/b/b", NONHEAP, BYTES, 85 * MB), - f("", "other1", OTHER, BYTES, 111 * MB), - f("", "other2", OTHER, COUNT, 888), - - f("2nd", "explicit/c", HEAP, BYTES, 333 * MB), - f("2nd", "compartments/user/child-user-compartment", OTHER, COUNT, 1), - f("2nd", "compartments/system/child-system-compartment", OTHER, COUNT, 1) - ]; - - var fakeMultiReporters = [ - // These shouldn't show up. - { name: "fake", + { name: "fake1", + collectReports: function(aCbObj, aClosure) { + function f(aP1, aP2, aK, aU, aA) { + aCbObj.callback(aP1, aP2, aK, aU, aA, "Desc.", aClosure); + } + // These should be ignored. + f("", "explicit/a", HEAP, BYTES, 222 * MB); + f("", "explicit/b/a", HEAP, BYTES, 85 * MB); + f("", "explicit/b/b", NONHEAP, BYTES, 85 * MB); + f("", "other1", OTHER, BYTES, 111 * MB); + f("", "other2", OTHER, COUNT, 888); + } + }, + { name: "fake2", collectReports: function(aCbObj, aClosure) { function f(aP, aK, aU, aA) { aCbObj.callback("", aP, aK, aU, aA, "Desc.", aClosure); } + // These shouldn't show up. f("explicit/a/d", HEAP, BYTES, 13 * MB); f("explicit/b/c", NONHEAP, BYTES, 10 * MB); - }, - explicitNonHeap: 10*MB + } + }, + { name: "content-child", + collectReports: function(aCbObj, aClosure) { + function f(aP1, aP2, aK, aU, aA, aD) { + aCbObj.callback(aP1, aP2, aK, aU, aA, aD, aClosure); + } + f("2nd", "explicit/c", HEAP, BYTES, 333 * MB, "Desc."); + f("2nd", "compartments/user/child-user-compartment", OTHER, COUNT, 1, ""); + f("2nd", "compartments/system/child-system-compartment", OTHER, COUNT, 1, ""); + } }, { name: "compartments", collectReports: function(aCbObj, aClosure) { @@ -104,8 +94,7 @@ f("compartments/system/[System Principal]"); f("compartments/system/[System Principal]"); f("compartments/system/atoms"); - }, - explicitNonHeap: 0 + } }, { name: "ghost-windows", collectReports: function(aCbObj, aClosure) { @@ -114,8 +103,7 @@ } f("ghost-windows/https:\\\\very-long-url.com\\very-long\\oh-so-long\\really-quite-long.html?a=2&b=3&c=4&d=5&e=abcdefghijklmnopqrstuvwxyz&f=123456789123456789123456789"); f("ghost-windows/http:\\\\foobar.com\\foo?bar#baz"); - }, - explicitNonHeap: 0 + } }, // These shouldn't show up. { name: "smaps", @@ -126,17 +114,13 @@ } f("smaps/vsize/a", 24); f("smaps/swap/a", 1); - }, - explicitNonHeap: 0 + } } ]; for (var i = 0; i < fakeReporters.length; i++) { mgr.registerReporterEvenIfBlocked(fakeReporters[i]); } - for (var i = 0; i < fakeMultiReporters.length; i++) { - mgr.registerMultiReporterEvenIfBlocked(fakeMultiReporters[i]); - } ]]> @@ -180,21 +164,14 @@ Ghost Windows\n\ function finish() { - // Unregister fake reporters and multi-reporters, re-register the real - // reporters and multi-reporters, just in case subsequent tests rely on - // them. + // Unregister fake reporters and re-register the real reporters, just in + // case subsequent tests rely on them. for (var i = 0; i < fakeReporters.length; i++) { mgr.unregisterReporter(fakeReporters[i]); } - for (var i = 0; i < fakeMultiReporters.length; i++) { - mgr.unregisterMultiReporter(fakeMultiReporters[i]); - } for (var i = 0; i < realReporters.length; i++) { mgr.registerReporterEvenIfBlocked(realReporters[i]); } - for (var i = 0; i < realMultiReporters.length; i++) { - mgr.registerMultiReporterEvenIfBlocked(realMultiReporters[i]); - } mgr.unblockRegistration(); SimpleTest.finish(); diff --git a/toolkit/components/aboutmemory/tests/test_aboutmemory.xul b/toolkit/components/aboutmemory/tests/test_aboutmemory.xul index 84fe972f206f..cf1b9421b7c4 100644 --- a/toolkit/components/aboutmemory/tests/test_aboutmemory.xul +++ b/toolkit/components/aboutmemory/tests/test_aboutmemory.xul @@ -27,8 +27,7 @@ let mgr = Cc["@mozilla.org/memory-reporter-manager;1"]. getService(Ci.nsIMemoryReporterManager); - // Remove all the real reporters and multi-reporters; save them to - // restore at the end. + // Remove all the real reporters; save them to restore at the end. mgr.blockRegistration(); let e = mgr.enumerateReporters(); let realReporters = []; @@ -37,13 +36,6 @@ mgr.unregisterReporter(r); realReporters.push(r); } - e = mgr.enumerateMultiReporters(); - let realMultiReporters = []; - while (e.hasMoreElements()) { - let r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter); - mgr.unregisterMultiReporter(r); - realMultiReporters.push(r); - } // Setup various fake-but-deterministic reporters. const KB = 1024; @@ -57,71 +49,60 @@ const COUNT_CUMULATIVE = Ci.nsIMemoryReporter.UNITS_COUNT_CUMULATIVE; const PERCENTAGE = Ci.nsIMemoryReporter.UNITS_PERCENTAGE; - function f2(aProcess, aPath, aKind, aUnits, aAmount) { - return { - process: aProcess, - path: aPath, - kind: aKind, - units: aUnits, - description: "Desc.", - amount: aAmount - }; - } - - function f(aProcess, aPath, aKind, aAmount) { - return f2(aProcess, aPath, aKind, BYTES, aAmount); - } - let fakeReporters = [ - f("", "heap-allocated", OTHER, 500 * MB), - f("", "heap-unallocated", OTHER, 100 * MB), - f("", "explicit/a", HEAP, 222 * MB), - f("", "explicit/b/a", HEAP, 85 * MB), - f("", "explicit/b/b", HEAP, 75 * MB), - f("", "explicit/b/c/a", HEAP, 70 * MB), - f("", "explicit/b/c/b", HEAP, 2 * MB), // omitted - f("", "explicit/g/a", HEAP, 6 * MB), - f("", "explicit/g/b", HEAP, 5 * MB), - f("", "explicit/g/other", HEAP, 4 * MB), - // A degenerate tree with the same name as a non-degenerate tree should - // work ok. - f("", "explicit", OTHER, 888 * MB), - f("", "other1/a/b", OTHER, 111 * MB), - f("", "other1/c/d", OTHER, 22 * MB), - f("", "other1/c/e", OTHER, 33 * MB), - f2("", "other4", OTHER, COUNT_CUMULATIVE, 777), - f2("", "other4", OTHER, COUNT_CUMULATIVE, 111), - f2("", "other3/a/b/c/d/e", OTHER, PERCENTAGE, 2000), - f2("", "other3/a/b/c/d/f", OTHER, PERCENTAGE, 10), - f2("", "other3/a/b/c/d/g", OTHER, PERCENTAGE, 5), - f2("", "other3/a/b/c/d/g", OTHER, PERCENTAGE, 5), - // Check that a rounded-up-to-100.00% value is shown as "100.0%" (i.e. one - // decimal point). - f2("", "other6/big", OTHER, COUNT, 99999), - f2("", "other6/small", OTHER, COUNT, 1), - // Check that a 0 / 0 is handled correctly. - f("", "other7/zero", OTHER, 0), - // These compartments ones shouldn't be displayed. - f2("", "compartments/user/foo", OTHER, COUNT, 1), - f2("", "compartments/system/foo", OTHER, COUNT, 1) - ]; - let fakeMultiReporters = [ + { name: "fake0", + collectReports: function(aCbObj, aClosure) { + function f(aP, aK, aU, aA) { + aCbObj.callback("", aP, aK, aU, aA, "Desc.", aClosure); + } + f("heap-allocated", OTHER, BYTES, 500 * MB); + f("heap-unallocated", OTHER, BYTES, 100 * MB); + f("explicit/a", HEAP, BYTES, 222 * MB); + f("explicit/b/a", HEAP, BYTES, 85 * MB); + f("explicit/b/b", HEAP, BYTES, 75 * MB); + f("explicit/b/c/a", HEAP, BYTES, 70 * MB); + f("explicit/b/c/b", HEAP, BYTES, 2 * MB); // omitted + f("explicit/g/a", HEAP, BYTES, 6 * MB); + f("explicit/g/b", HEAP, BYTES, 5 * MB); + f("explicit/g/other", HEAP, BYTES, 4 * MB); + // A degenerate tree with the same name as a non-degenerate tree should + // work ok. + f("explicit", OTHER, BYTES, 888 * MB); + f("other1/a/b", OTHER, BYTES, 111 * MB); + f("other1/c/d", OTHER, BYTES, 22 * MB); + f("other1/c/e", OTHER, BYTES, 33 * MB); + f("other4", OTHER, COUNT_CUMULATIVE, 777); + f("other4", OTHER, COUNT_CUMULATIVE, 111); + f("other3/a/b/c/d/e", OTHER, PERCENTAGE, 2000); + f("other3/a/b/c/d/f", OTHER, PERCENTAGE, 10); + f("other3/a/b/c/d/g", OTHER, PERCENTAGE, 5); + f("other3/a/b/c/d/g", OTHER, PERCENTAGE, 5); + // Check that a rounded-up-to-100.00% value is shown as "100.0%" (i.e. one + // decimal point). + f("other6/big", OTHER, COUNT, 99999); + f("other6/small", OTHER, COUNT, 1); + // Check that a 0 / 0 is handled correctly. + f("other7/zero", OTHER, BYTES, 0); + // These compartments ones shouldn't be displayed. + f("compartments/user/foo", OTHER, COUNT, 1); + f("compartments/system/foo", OTHER, COUNT, 1); + } + }, { name: "fake1", collectReports: function(aCbObj, aClosure) { function f(aP, aK, aU, aA) { aCbObj.callback("", aP, aK, aU, aA, "Desc.", aClosure); } - f("explicit/c/d", NONHEAP, BYTES, 13 * MB), - f("explicit/c/d", NONHEAP, BYTES, 10 * MB), // dup - f("explicit/c/other", NONHEAP, BYTES, 77 * MB), + f("explicit/c/d", NONHEAP, BYTES, 13 * MB); + f("explicit/c/d", NONHEAP, BYTES, 10 * MB); // dup + f("explicit/c/other", NONHEAP, BYTES, 77 * MB); f("explicit/cc", NONHEAP, BYTES, 13 * MB); f("explicit/cc", NONHEAP, BYTES, 10 * MB); // dup f("explicit/d", NONHEAP, BYTES, 499 * KB); // omitted f("explicit/e", NONHEAP, BYTES, 100 * KB); // omitted f("explicit/f/g/h/i", HEAP, BYTES, 10 * MB); f("explicit/f/g/h/j", HEAP, BYTES, 10 * MB); - }, - explicitNonHeap: (100 + 13 + 10)*MB + (499 + 100)*KB + } }, { name: "fake2", collectReports: function(aCbObj, aClosure) { @@ -132,8 +113,7 @@ f("other2", OTHER, BYTES, 222 * MB); f("perc2", OTHER, PERCENTAGE, 10000); f("perc1", OTHER, PERCENTAGE, 4567); - }, - explicitNonHeap: 0 + } }, { name: "smaps", collectReports: function(aCbObj, aClosure) { @@ -148,8 +128,7 @@ f("swap/b/c", 10); f("rss/a", 42); f("pss/a", 43); - }, - explicitNonHeap: 0 + } }, { name: "compartments", collectReports: function(aCbObj, aClosure) { @@ -158,16 +137,12 @@ } f("compartments/user/bar"); f("compartments/system/bar"); - }, - explicitNonHeap: 0 + } } ]; for (let i = 0; i < fakeReporters.length; i++) { mgr.registerReporterEvenIfBlocked(fakeReporters[i]); } - for (let i = 0; i < fakeMultiReporters.length; i++) { - mgr.registerMultiReporterEvenIfBlocked(fakeMultiReporters[i]); - } // mgr.explicit sums "heap-allocated" and all the appropriate NONHEAP ones: // - "explicit/c", "explicit/cc" x 2, "explicit/d", "explicit/e" @@ -189,59 +164,74 @@ // the largest). Processes without a |resident| memory reporter are saved // for the end. let fakeReporters2 = [ - f("2nd", "heap-allocated", OTHER, 1000 * MB), - f("2nd", "heap-unallocated",OTHER, 100 * MB), - f("2nd", "explicit/a/b/c", HEAP, 497 * MB), - f("2nd", "explicit/a/b/c", HEAP, 1 * MB), // dup: merge - f("2nd", "explicit/a/b/c", HEAP, 1 * MB), // dup: merge - f("2nd", "explicit/flip\\the\\backslashes", - HEAP, 200 * MB), - f("2nd", "explicit/compartment(compartment-url)", - HEAP, 200 * MB), - f("2nd", "other0", OTHER, 666 * MB), - f("2nd", "other1", OTHER, 111 * MB), - // Even though the "smaps" reporter is a multi-reporter, if its in a - // child process it'll be passed to the main process as single reports. - // The fact that we skip the "smaps" multi-reporter in the main - // process won't cause these to be skipped; the fall-back skipping will - // be hit instead. - f("2nd", "size/e", NONHEAP, 24*4*KB), - f("2nd", "size/f", NONHEAP, 24*4*KB), + { name: "resident-fast", + collectReports: function(aCbObj, aClosure) { + // Shouldn't reach here; aboutMemory.js should skip the reporter. + // (Nb: this must come after |mgr.explicit| is accessed, otherwise it + // *will* be run by nsMemoryReporterManager::GetExplicit()). + ok(false, "'resident-fast' reporter was run"); + } + }, + { name: "fake3", + collectReports: function(aCbObj, aClosure) { + function f(aP1, aP2, aK, aU, aA) { + aCbObj.callback(aP1, aP2, aK, aU, aA, "Desc.", aClosure); + } + f("2nd", "heap-allocated", OTHER, BYTES,1000* MB); + f("2nd", "heap-unallocated",OTHER, BYTES,100 * MB); + f("2nd", "explicit/a/b/c", HEAP, BYTES,497 * MB); + f("2nd", "explicit/a/b/c", HEAP, BYTES, 1 * MB); // dup: merge + f("2nd", "explicit/a/b/c", HEAP, BYTES, 1 * MB); // dup: merge + f("2nd", "explicit/flip\\the\\backslashes", + HEAP, BYTES,200 * MB); + f("2nd", "explicit/compartment(compartment-url)", + HEAP, BYTES,200 * MB); + f("2nd", "other0", OTHER, BYTES,666 * MB); + f("2nd", "other1", OTHER, BYTES,111 * MB); + // If the "smaps" reporter is in a child process it'll be passed to + // the main process under a different name. The fact that we skip + // the "smaps" reporter in the main process won't cause these + // to be skipped; the report-level skipping will be hit instead. + f("2nd", "size/e", NONHEAP, BYTES,24*4*KB); + f("2nd", "size/f", NONHEAP, BYTES,24*4*KB); + f("2nd", "resident-fast", NONHEAP, BYTES,24*4*KB); // ignored! - // Check that we can handle "heap-allocated" not being present. - f("3rd", "explicit/a/b", HEAP, 333 * MB), - f("3rd", "explicit/a/c", HEAP, 444 * MB), - f("3rd", "other1", OTHER, 1 * MB), - f("3rd", "resident", OTHER, 100 * MB), + // Check that we can handle "heap-allocated" not being present. + f("3rd", "explicit/a/b", HEAP, BYTES,333 * MB); + f("3rd", "explicit/a/c", HEAP, BYTES,444 * MB); + f("3rd", "other1", OTHER, BYTES, 1 * MB); + f("3rd", "resident", OTHER, BYTES,100 * MB); - // Invalid values (negative, too-big) should be identified. - f("4th", "heap-allocated", OTHER, 100 * MB), - f("4th", "resident", OTHER, 200 * MB), - f("4th", "explicit/js/compartment(http:\\\\too-big.com\\)/stuff", - HEAP, 150 * MB), - f("4th", "explicit/ok", HEAP, 5 * MB), - f("4th", "explicit/neg1", NONHEAP, -2 * MB), - // -111 becomes "-0.00MB" in non-verbose mode, and getting the negative - // sign in there correctly is non-trivial. - f("4th", "other1", OTHER, -111), - f("4th", "other2", OTHER, -222 * MB), - f2("4th", "other3", OTHER, COUNT, -333), - f2("4th", "other4", OTHER, COUNT_CUMULATIVE, -444), - f2("4th", "other5", OTHER, PERCENTAGE, -555), - f2("4th", "other6", OTHER, PERCENTAGE, 66666), + // Invalid values (negative, too-big) should be identified. + f("4th", "heap-allocated", OTHER, BYTES,100 * MB); + f("4th", "resident", OTHER, BYTES,200 * MB); + f("4th", "explicit/js/compartment(http:\\\\too-big.com\\)/stuff", + HEAP, BYTES,150 * MB); + f("4th", "explicit/ok", HEAP, BYTES, 5 * MB); + f("4th", "explicit/neg1", NONHEAP, BYTES, -2 * MB); + // -111 becomes "-0.00MB" in non-verbose mode, and getting the negative + // sign in there correctly is non-trivial. + f("4th", "other1", OTHER, BYTES,-111); + f("4th", "other2", OTHER, BYTES,-222 * MB); + f("4th", "other3", OTHER, COUNT, -333); + f("4th", "other4", OTHER, COUNT_CUMULATIVE, -444); + f("4th", "other5", OTHER, PERCENTAGE, -555); + f("4th", "other6", OTHER, PERCENTAGE, 66666); - // If a negative value is within a collapsed sub-tree in non-verbose mode, - // we should get the warning at the top and the relevant sub-trees should - // be expanded, even in non-verbose mode. - f("5th", "heap-allocated", OTHER, 100 * MB), - f("5th", "explicit/big", HEAP, 99 * MB), - f("5th", "explicit/a/pos", HEAP, 40 * KB), - f("5th", "explicit/a/neg1", NONHEAP, -20 * KB), - f("5th", "explicit/a/neg2", NONHEAP, -10 * KB), - f("5th", "explicit/b/c/d/e", NONHEAP, 20 * KB), - f("5th", "explicit/b/c/d/f", NONHEAP, -60 * KB), - f("5th", "explicit/b/c/g/h", NONHEAP, 10 * KB), - f("5th", "explicit/b/c/i/j", NONHEAP, 5 * KB) + // If a negative value is within a collapsed sub-tree in non-verbose mode, + // we should get the warning at the top and the relevant sub-trees should + // be expanded, even in non-verbose mode. + f("5th", "heap-allocated", OTHER, BYTES,100 * MB); + f("5th", "explicit/big", HEAP, BYTES, 99 * MB); + f("5th", "explicit/a/pos", HEAP, BYTES, 40 * KB); + f("5th", "explicit/a/neg1", NONHEAP, BYTES,-20 * KB); + f("5th", "explicit/a/neg2", NONHEAP, BYTES,-10 * KB); + f("5th", "explicit/b/c/d/e", NONHEAP, BYTES, 20 * KB); + f("5th", "explicit/b/c/d/f", NONHEAP, BYTES,-60 * KB); + f("5th", "explicit/b/c/g/h", NONHEAP, BYTES, 10 * KB); + f("5th", "explicit/b/c/i/j", NONHEAP, BYTES, 5 * KB); + } + } ]; for (let i = 0; i < fakeReporters2.length; i++) { mgr.registerReporterEvenIfBlocked(fakeReporters2[i]); @@ -586,21 +576,14 @@ Other Measurements\n\ function finish() { - // Unregister fake reporters and multi-reporters, re-register the real - // reporters and multi-reporters, just in case subsequent tests rely on - // them. + // Unregister fake reporters and re-register the real reporters, just in + // case subsequent tests rely on them. for (let i = 0; i < fakeReporters.length; i++) { mgr.unregisterReporter(fakeReporters[i]); } - for (let i = 0; i < fakeMultiReporters.length; i++) { - mgr.unregisterMultiReporter(fakeMultiReporters[i]); - } for (let i = 0; i < realReporters.length; i++) { mgr.registerReporterEvenIfBlocked(realReporters[i]); } - for (let i = 0; i < realMultiReporters.length; i++) { - mgr.registerMultiReporterEvenIfBlocked(realMultiReporters[i]); - } mgr.unblockRegistration(); SimpleTest.finish(); diff --git a/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul b/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul index 830e1e3c02e1..d899bd4ad58c 100644 --- a/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul +++ b/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul @@ -22,8 +22,7 @@ let mgr = Cc["@mozilla.org/memory-reporter-manager;1"]. getService(Ci.nsIMemoryReporterManager); - // Remove all the real reporters and multi-reporters; save them to - // restore at the end. + // Remove all the real reporters; save them to restore at the end. mgr.blockRegistration(); let e = mgr.enumerateReporters(); let realReporters = []; @@ -32,13 +31,6 @@ mgr.unregisterReporter(r); realReporters.push(r); } - e = mgr.enumerateMultiReporters(); - let realMultiReporters = []; - while (e.hasMoreElements()) { - let r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter); - mgr.unregisterMultiReporter(r); - realMultiReporters.push(r); - } // Setup various fake-but-deterministic reporters. const KB = 1024; @@ -47,35 +39,31 @@ const OTHER = Ci.nsIMemoryReporter.KIND_OTHER; const BYTES = Ci.nsIMemoryReporter.UNITS_BYTES; - function f(aPath, aKind, aAmount) { - return { - process: "", - path: aPath, - kind: aKind, - units: BYTES, - description: "Desc.", - amount: aAmount - }; - } - - let hiReport = f("explicit/h/i", HEAP, 10 * MB); - let hi2Report = f("explicit/h/i2", HEAP, 9 * MB); - let jkReport = f("explicit/j/k", HEAP, 0.5 * MB); - let jk2Report = f("explicit/j/k2", HEAP, 0.3 * MB); + let hiPath = "explicit/h/i"; + let hi2Path = "explicit/h/i2"; + let jkPath = "explicit/j/k"; + let jk2Path = "explicit/j/k2"; let fakeReporters = [ - f("heap-allocated", OTHER, 250 * MB), - f("explicit/a/b", HEAP, 50 * MB), - f("explicit/a/c/d", HEAP, 25 * MB), - f("explicit/a/c/e", HEAP, 15 * MB), - f("explicit/a/f", HEAP, 30 * MB), - f("explicit/g", HEAP, 100 * MB), - hiReport, - hi2Report, - jkReport, - jk2Report, - f("explicit/a/l/m", HEAP, 0.1 * MB), - f("explicit/a/l/n", HEAP, 0.1 * MB), + { name: "fake1", + collectReports: function(aCbObj, aClosure) { + function f(aP, aK, aA) { + aCbObj.callback("", aP, aK, BYTES, aA, "Desc.", aClosure); + } + f("heap-allocated", OTHER, 250 * MB); + f("explicit/a/b", HEAP, 50 * MB); + f("explicit/a/c/d", HEAP, 25 * MB); + f("explicit/a/c/e", HEAP, 15 * MB); + f("explicit/a/f", HEAP, 30 * MB); + f("explicit/g", HEAP, 100 * MB); + f(hiPath, HEAP, 10 * MB); + f(hi2Path, HEAP, 9 * MB); + f(jkPath, HEAP, 0.5 * MB); + f(jk2Path, HEAP, 0.3 * MB); + f("explicit/a/l/m", HEAP, 0.1 * MB); + f("explicit/a/l/n", HEAP, 0.1 * MB); + } + } ]; for (let i = 0; i < fakeReporters.length; i++) { @@ -91,18 +79,14 @@ mMozillaLibraries; }; -NS_IMPL_ISUPPORTS1(MapsReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(MapsReporter, nsIMemoryReporter) MapsReporter::MapsReporter() : mSearchedForLibxul(false) @@ -173,7 +173,7 @@ MapsReporter::MapsReporter() } NS_IMETHODIMP -MapsReporter::CollectReports(nsIMemoryMultiReporterCallback *aCb, +MapsReporter::CollectReports(nsIMemoryReporterCallback *aCb, nsISupports *aClosure) { CategoriesSeen categoriesSeen; @@ -258,7 +258,7 @@ MapsReporter::FindLibxul() nsresult MapsReporter::ParseMapping( FILE *aFile, - nsIMemoryMultiReporterCallback *aCb, + nsIMemoryReporterCallback *aCb, nsISupports *aClosure, CategoriesSeen *aCategoriesSeen) { @@ -461,7 +461,7 @@ MapsReporter::ParseMapBody( FILE *aFile, const nsACString &aName, const nsACString &aDescription, - nsIMemoryMultiReporterCallback *aCb, + nsIMemoryReporterCallback *aCb, nsISupports *aClosure, CategoriesSeen *aCategoriesSeen) { @@ -520,11 +520,11 @@ MapsReporter::ParseMapBody( return NS_OK; } -class ResidentUniqueReporter MOZ_FINAL : public MemoryReporterBase +class ResidentUniqueReporter MOZ_FINAL : public MemoryUniReporter { public: ResidentUniqueReporter() - : MemoryReporterBase("resident-unique", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("resident-unique", KIND_OTHER, UNITS_BYTES, "Memory mapped by the process that is present in physical memory and not " "shared with any other processes. This is also known as the process's unique " "set size (USS). This is the amount of RAM we'd expect to be freed if we " @@ -540,9 +540,9 @@ private: // little to do with whether the pages are actually shared. smaps on the // other hand appears to give us the correct information. // - // We could calculate this data during the smaps multi-reporter, but the - // overhead of the smaps reporter is considerable (we don't even run the - // smaps reporter in normal about:memory operation). Hopefully this + // We could calculate this data within the smaps reporter, but the overhead + // of the smaps reporter is considerable (we don't even run the smaps + // reporter in normal about:memory operation). Hopefully this // implementation is fast enough not to matter. *aAmount = 0; @@ -568,8 +568,8 @@ private: void Init() { - nsCOMPtr reporter = new MapsReporter(); - NS_RegisterMemoryMultiReporter(reporter); + nsCOMPtr reporter = new MapsReporter(); + NS_RegisterMemoryReporter(reporter); NS_RegisterMemoryReporter(new ResidentUniqueReporter()); } diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index c1cf5784fddd..e4cbfbbbb394 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -917,7 +917,7 @@ private: CC_BeforeUnlinkCallback mBeforeUnlinkCB; CC_ForgetSkippableCallback mForgetSkippableCB; - nsCOMPtr mReporter; + nsCOMPtr mReporter; nsPurpleBuffer mPurpleBuf; @@ -2398,10 +2398,10 @@ nsCycleCollector::CollectWhite(nsICycleCollectorListener *aListener) // Memory reporter //////////////////////// -class CycleCollectorMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter +class CycleCollectorReporter MOZ_FINAL : public nsIMemoryReporter { public: - CycleCollectorMultiReporter(nsCycleCollector* aCollector) + CycleCollectorReporter(nsCycleCollector* aCollector) : mCollector(aCollector) {} @@ -2413,7 +2413,7 @@ class CycleCollectorMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter return NS_OK; } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback* aCb, + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { size_t objectSize, graphNodesSize, graphEdgesSize, whiteNodesSize, @@ -2465,7 +2465,7 @@ class CycleCollectorMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter nsCycleCollector* mCollector; }; -NS_IMPL_ISUPPORTS1(CycleCollectorMultiReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(CycleCollectorReporter, nsIMemoryReporter) //////////////////////////////////////////////////////////////////////// @@ -2492,7 +2492,7 @@ nsCycleCollector::nsCycleCollector() : nsCycleCollector::~nsCycleCollector() { - NS_UnregisterMemoryMultiReporter(mReporter); + NS_UnregisterMemoryReporter(mReporter); } void @@ -2508,7 +2508,7 @@ nsCycleCollector::RegisterJSRuntime(CycleCollectedJSRuntime *aJSRuntime) // instead. static bool registered = false; if (!registered) { - NS_RegisterMemoryMultiReporter(new CycleCollectorMultiReporter(this)); + NS_RegisterMemoryReporter(new CycleCollectorReporter(this)); registered = true; } } diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl index 615232b782a0..206adf12356e 100644 --- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -17,55 +17,22 @@ interface nsICancelableRunnable; * reporter. */ -/* - * An nsIMemoryReporter reports a single memory measurement as an object. - * Use this when it makes sense to gather this measurement without gathering - * related measurements at the same time. - * - * Note that the |amount| field may be implemented as a function, and so - * accessing it can trigger significant computation; the other fields can - * be accessed without triggering this computation. (Compare and contrast - * this with nsIMemoryMultiReporter.) - * - * aboutMemory.js is the most important consumer of memory reports. It - * places the following constraints on reports. - * - * - There must be an "explicit" tree. It represents non-overlapping - * regions of memory that have been explicitly allocated with an - * OS-level allocation (e.g. mmap/VirtualAlloc/vm_allocate) or a - * heap-level allocation (e.g. malloc/calloc/operator new). Reporters - * in this tree must have kind HEAP or NONHEAP, units BYTES, and a - * description that is a sentence (i.e. starts with a capital letter and - * ends with a period, or similar). - * - * - The "size", "rss", "pss" and "swap" trees are optional. They - * represent regions of virtual memory that the process has mapped. - * Reporters in this category must have kind NONHEAP, units BYTES, and a - * non-empty description. - * - * - The "compartments" and "ghost-windows" trees are optional. They are - * used by about:compartments. Reporters in these trees must have kind - * OTHER, units COUNT, an amount of 1, and a description that's an empty - * string. - * - * - All other reports are unconstrained except that they must have a - * description that is a sentence. - */ -[scriptable, uuid(b2c39f65-1799-4b92-a806-ab3cf6af3cfa)] -interface nsIMemoryReporter : nsISupports +[scriptable, function, uuid(3a61be3b-b93b-461a-a4f8-388214f558b1)] +interface nsIMemoryReporterCallback : nsISupports { /* - * The name of the process containing this reporter. Each reporter initially - * has "" in this field, indicating that it applies to the current process. - * (This is true even for reporters in a child process.) When a reporter - * from a child process is copied into the main process, the copy has its - * 'process' field set appropriately. - */ - readonly attribute ACString process; - - /* - * The path that this memory usage should be reported under. Paths are - * '/'-delimited, eg. "a/b/c". + * The arguments to the callback are as follows. + * + * + * |process| The name of the process containing this reporter. Each + * reporter initially has "" in this field, indicating that it applies to the + * current process. (This is true even for reporters in a child process.) + * When a reporter from a child process is copied into the main process, the + * copy has its 'process' field set appropriately. + * + * + * |path| The path that this memory usage should be reported under. Paths + * are '/'-delimited, eg. "a/b/c". * * Each reporter can be viewed as representing a leaf node in a tree. * Internal nodes of the tree don't have reporters. So, for example, the @@ -98,11 +65,9 @@ interface nsIMemoryReporter : nsISupports * * The paths of all reporters form a set of trees. Trees can be * "degenerate", i.e. contain a single entry with no '/'. - */ - readonly attribute AUTF8String path; - - /* - * There are three kinds of memory reporters. + * + * + * |kind| There are three kinds of memory reporters. * * - HEAP: reporters measuring memory allocated by the heap allocator, * e.g. by calling malloc, calloc, realloc, memalign, operator new, or @@ -120,19 +85,9 @@ interface nsIMemoryReporter : nsISupports * * The kind only matters for reporters in the "explicit" tree; * aboutMemory.js uses it to calculate "heap-unclassified". - */ - const int32_t KIND_NONHEAP = 0; - const int32_t KIND_HEAP = 1; - const int32_t KIND_OTHER = 2; - - /* - * The reporter kind. See KIND_* above. - */ - readonly attribute int32_t kind; - - /* - * The amount reported by a memory reporter must have one of the following - * units, but you may of course add new units as necessary: + * + * + * |units| The units on the reporter's amount. One of the following. * * - BYTES: The amount contains a number of bytes. * @@ -156,67 +111,84 @@ interface nsIMemoryReporter : nsISupports * be 1234. * * Values greater than 100% are allowed. + * + * + * |amount| The numeric value reported by this memory reporter. Accesses + * can fail if something goes wrong when getting the amount. + * + * + * |description| A human-readable description of this memory usage report. */ - const int32_t UNITS_BYTES = 0; - const int32_t UNITS_COUNT = 1; - const int32_t UNITS_COUNT_CUMULATIVE = 2; - const int32_t UNITS_PERCENTAGE = 3; - - /* - * The units on the reporter's amount. See UNITS_* above. - */ - readonly attribute int32_t units; - - /* - * The numeric value reported by this memory reporter. Accesses can fail if - * something goes wrong when getting the amount. - */ - readonly attribute int64_t amount; - - /* - * A human-readable description of this memory usage report. - */ - readonly attribute AUTF8String description; -}; - -[scriptable, function, uuid(5b15f3fa-ba15-443c-8337-7770f5f0ce5d)] -interface nsIMemoryMultiReporterCallback : nsISupports -{ void callback(in ACString process, in AUTF8String path, in int32_t kind, in int32_t units, in int64_t amount, in AUTF8String description, in nsISupports closure); }; /* - * An nsIMemoryMultiReporter reports multiple memory measurements via a - * callback function which is called once for each measurement. Use this - * when you want to gather multiple measurements in a single operation (eg. - * a single traversal of a large data structure). + * An nsIMemoryReporter reports one or more memory measurements via a + * callback function which is called once for each measurement. * - * The arguments to the callback deliberately match the fields in - * nsIMemoryReporter, but note that seeing any of these arguments requires - * calling collectReports which will trigger all relevant computation. - * (Compare and contrast this with nsIMemoryReporter, which allows all - * fields except |amount| to be accessed without triggering computation.) + * An nsIMemoryReporter that reports a single measurement is sometimes called a + * "uni-reporter". One that reports multiple measurements is sometimes called + * a "multi-reporter". + * + * aboutMemory.js is the most important consumer of memory reports. It + * places the following constraints on reports. + * + * - There must be an "explicit" tree. It represents non-overlapping + * regions of memory that have been explicitly allocated with an + * OS-level allocation (e.g. mmap/VirtualAlloc/vm_allocate) or a + * heap-level allocation (e.g. malloc/calloc/operator new). Reporters + * in this tree must have kind HEAP or NONHEAP, units BYTES, and a + * description that is a sentence (i.e. starts with a capital letter and + * ends with a period, or similar). + * + * - The "size", "rss", "pss" and "swap" trees are optional. They + * represent regions of virtual memory that the process has mapped. + * Reporters in this category must have kind NONHEAP, units BYTES, and a + * non-empty description. + * + * - The "compartments" and "ghost-windows" trees are optional. They are + * used by about:compartments. Reporters in these trees must have kind + * OTHER, units COUNT, an amount of 1, and a description that's an empty + * string. + * + * - All other reports are unconstrained except that they must have a + * description that is a sentence. */ -[scriptable, uuid(24d61ead-237b-4969-a6bd-73fd8fed1d99)] -interface nsIMemoryMultiReporter : nsISupports +[scriptable, uuid(53248304-124b-43cd-99dc-6e5797b91618)] +interface nsIMemoryReporter : nsISupports { /* - * The name of the multi-reporter. Useful when only one multi-reporter - * needs to be run. Must be unique; if multi-reporters share names it's - * likely the wrong one will be called in certain circumstances. + * The name of the reporter. Useful when only one reporter needs to be run. + * Must be unique; if reporters share names it's likely the wrong one will + * be called in certain circumstances. */ readonly attribute ACString name; /* - * Run the multi-reporter. + * Run the reporter. */ - void collectReports(in nsIMemoryMultiReporterCallback callback, + void collectReports(in nsIMemoryReporterCallback callback, in nsISupports closure); + + /* + * Kinds. See the |kind| comment in nsIMemoryReporterCallback. + */ + const int32_t KIND_NONHEAP = 0; + const int32_t KIND_HEAP = 1; + const int32_t KIND_OTHER = 2; + + /* + * Units. See the |units| comment in nsIMemoryReporterCallback. + */ + const int32_t UNITS_BYTES = 0; + const int32_t UNITS_COUNT = 1; + const int32_t UNITS_COUNT_CUMULATIVE = 2; + const int32_t UNITS_PERCENTAGE = 3; }; -[scriptable, builtinclass, uuid(70b0e608-8dbf-4dc7-b88f-f1c745c1b48c)] +[scriptable, builtinclass, uuid(4db7040a-16f9-4249-879b-fe72729c7ef5)] interface nsIMemoryReporterManager : nsISupports { /* @@ -224,12 +196,6 @@ interface nsIMemoryReporterManager : nsISupports */ nsISimpleEnumerator enumerateReporters (); - /* - * Return an enumerator of nsIMemoryMultiReporters that are currently - * registered. - */ - nsISimpleEnumerator enumerateMultiReporters (); - /* * Register the given nsIMemoryReporter. After a reporter is registered, * it will be available via enumerateReporters(). The Manager service @@ -237,31 +203,17 @@ interface nsIMemoryReporterManager : nsISupports */ void registerReporter (in nsIMemoryReporter reporter); - /* - * Register the given nsIMemoryMultiReporter. After a multi-reporter is - * registered, it will be available via enumerateMultiReporters(). The - * Manager service will hold a strong reference to the given - * multi-reporter. - */ - void registerMultiReporter (in nsIMemoryMultiReporter reporter); - /* * Unregister the given memory reporter. */ void unregisterReporter (in nsIMemoryReporter reporter); - /* - * Unregister the given memory multi-reporter. - */ - void unregisterMultiReporter (in nsIMemoryMultiReporter reporter); - /** * These functions should only be used for testing purposes. */ void blockRegistration(); void unblockRegistration(); void registerReporterEvenIfBlocked(in nsIMemoryReporter aReporter); - void registerMultiReporterEvenIfBlocked(in nsIMemoryMultiReporter aReporter); /* * Initialize. @@ -280,8 +232,8 @@ interface nsIMemoryReporterManager : nsISupports * (eg. via mmap, VirtualAlloc) and at the heap level (eg. via malloc, * calloc, operator new). (Nb: it covers all heap allocations, but will * miss any OS-level ones not covered by memory reporters.) This reporter - * is special-cased because it's interesting, and is moderately difficult - * to compute in JS. Accesses can fail. + * is special-cased because it's interesting, and is difficult to compute + * from JavaScript code. Accesses can fail. */ readonly attribute int64_t explicit; @@ -307,10 +259,7 @@ interface nsIMemoryReporterManager : nsISupports // instead of nsCOMPtr. XPCOM_API(nsresult) NS_RegisterMemoryReporter(nsIMemoryReporter* aReporter); -XPCOM_API(nsresult) NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter* aReporter); - XPCOM_API(nsresult) NS_UnregisterMemoryReporter(nsIMemoryReporter* aReporter); -XPCOM_API(nsresult) NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter* aReporter); #if defined(MOZ_DMD) namespace mozilla { @@ -375,10 +324,11 @@ void RunReporters(); namespace mozilla { // The following base class reduces the amount of boilerplate code required for -// memory reporters. You just need to provide the following. -// - The constant values: path, kind, units, and description. They are passed -// to the MemoryReporterBase constructor. -// - A (private) Amount() or (public) GetAmount() method. It can use the +// memory uni-reporters. You just need to provide the following. +// - The constant values: nameAndPath (which serves as both the reporters name, +// and the path in its single report), kind, units, and description. They +// are passed to the MemoryUniReporter constructor. +// - A (private) Amount() or (public) GetAmount() method. It can use the // MallocSizeOf method if necessary. (There is also // MallocSizeOfOn{Alloc,Free}, which can be useful.) Use Amount() if the // reporter is infallible, and GetAmount() otherwise. (If you fail to @@ -390,58 +340,45 @@ namespace mozilla { // - "explicit/dom/xyzzy" --> DOMXyzzyReporter // - "js-compartments/system" --> JSCompartmentsSystemReporter // -class MemoryReporterBase : public nsIMemoryReporter +class MemoryUniReporter : public nsIMemoryReporter { public: - MemoryReporterBase(const char* aPath, int32_t aKind, int32_t aUnits, - const char* aDescription) - : mPath(aPath) + MemoryUniReporter(const char* aNameAndPath, int32_t aKind, int32_t aUnits, + const char* aDescription) + : mNameAndPath(aNameAndPath) , mKind(aKind) , mUnits(aUnits) , mDescription(aDescription) {} - virtual ~MemoryReporterBase() {} + virtual ~MemoryUniReporter() {} NS_DECL_THREADSAFE_ISUPPORTS - NS_IMETHOD GetProcess(nsACString& aProcess) + NS_IMETHOD GetName(nsACString& aName) { - aProcess.Truncate(); + aName.Assign(mNameAndPath); return NS_OK; } - NS_IMETHOD GetPath(nsACString& aPath) + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCallback, + nsISupports* aClosure) { - aPath.Assign(mPath); - return NS_OK; - } - - NS_IMETHOD GetKind(int32_t* aKind) - { - *aKind = mKind; - return NS_OK; - } - - NS_IMETHOD GetUnits(int32_t* aUnits) - { - *aUnits = mUnits; - return NS_OK; + int64_t amount; + nsresult rv = GetAmount(&amount); + NS_ENSURE_SUCCESS(rv, rv); + + return aCallback->Callback(EmptyCString(), mNameAndPath, mKind, mUnits, + amount, mDescription, aClosure); } +protected: NS_IMETHOD GetAmount(int64_t* aAmount) { *aAmount = Amount(); return NS_OK; } - NS_IMETHOD GetDescription(nsACString& aDescription) - { - aDescription.Assign(mDescription); - return NS_OK; - } - -protected: virtual int64_t Amount() { // We only reach here if neither GetAmount() nor Amount() was overridden. @@ -453,7 +390,7 @@ protected: NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(MallocSizeOfOnAlloc) NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(MallocSizeOfOnFree) - const nsCString mPath; + const nsCString mNameAndPath; const int32_t mKind; const int32_t mUnits; const nsCString mDescription; diff --git a/xpcom/base/nsMemoryInfoDumper.cpp b/xpcom/base/nsMemoryInfoDumper.cpp index d6716918ecbd..b8ea0f6d1233 100644 --- a/xpcom/base/nsMemoryInfoDumper.cpp +++ b/xpcom/base/nsMemoryInfoDumper.cpp @@ -672,32 +672,35 @@ DumpReport(nsIGZFileWriter *aWriter, bool aIsFirst, return NS_OK; } -class DumpMultiReporterCallback MOZ_FINAL : public nsIMemoryMultiReporterCallback +class DumpReporterCallback MOZ_FINAL : public nsIMemoryReporterCallback { - public: - NS_DECL_ISUPPORTS +public: + NS_DECL_ISUPPORTS - NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath, - int32_t aKind, int32_t aUnits, int64_t aAmount, - const nsACString &aDescription, - nsISupports *aData) - { - nsCOMPtr writer = do_QueryInterface(aData); - NS_ENSURE_TRUE(writer, NS_ERROR_FAILURE); + DumpReporterCallback(bool* aIsFirstPtr) : mIsFirstPtr(aIsFirstPtr) {} - // The |isFirst = false| assumes that at least one single reporter is - // present and so will have been processed in - // DumpProcessMemoryReportsToGZFileWriter() below. - return DumpReport(writer, /* isFirst = */ false, aProcess, aPath, - aKind, aUnits, aAmount, aDescription); - return NS_OK; - } + NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath, + int32_t aKind, int32_t aUnits, int64_t aAmount, + const nsACString &aDescription, + nsISupports *aData) + { + nsCOMPtr writer = do_QueryInterface(aData); + NS_ENSURE_TRUE(writer, NS_ERROR_FAILURE); + + // The |isFirst = false| assumes that at least one single reporter is + // present and so will have been processed in + // DumpProcessMemoryReportsToGZFileWriter() below. + bool isFirst = *mIsFirstPtr; + *mIsFirstPtr = false; + return DumpReport(writer, isFirst, aProcess, aPath, aKind, aUnits, aAmount, + aDescription); + } + +private: + bool* mIsFirstPtr; }; -NS_IMPL_ISUPPORTS1( - DumpMultiReporterCallback - , nsIMemoryMultiReporterCallback - ) +NS_IMPL_ISUPPORTS1(DumpReporterCallback, nsIMemoryReporterCallback) } // namespace mozilla @@ -795,8 +798,6 @@ DMDWrite(void* aState, const char* aFmt, va_list ap) static nsresult DumpProcessMemoryReportsToGZFileWriter(nsIGZFileWriter *aWriter) { - nsresult rv; - // Increment this number if the format changes. // // This is the first write to the file, and it causes |aWriter| to allocate @@ -814,53 +815,15 @@ DumpProcessMemoryReportsToGZFileWriter(nsIGZFileWriter *aWriter) DUMP(aWriter, ",\n"); DUMP(aWriter, " \"reports\": "); - // Process single reporters. + // Process reporters. bool isFirst = true; bool more; nsCOMPtr e; mgr->EnumerateReporters(getter_AddRefs(e)); + nsRefPtr cb = new DumpReporterCallback(&isFirst); while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { nsCOMPtr r; e->GetNext(getter_AddRefs(r)); - - nsCString process; - rv = r->GetProcess(process); - NS_ENSURE_SUCCESS(rv, rv); - - nsCString path; - rv = r->GetPath(path); - NS_ENSURE_SUCCESS(rv, rv); - - int32_t kind; - rv = r->GetKind(&kind); - NS_ENSURE_SUCCESS(rv, rv); - - int32_t units; - rv = r->GetUnits(&units); - NS_ENSURE_SUCCESS(rv, rv); - - int64_t amount; - rv = r->GetAmount(&amount); - NS_ENSURE_SUCCESS(rv, rv); - - nsCString description; - rv = r->GetDescription(description); - NS_ENSURE_SUCCESS(rv, rv); - - rv = DumpReport(aWriter, isFirst, process, path, kind, units, amount, - description); - NS_ENSURE_SUCCESS(rv, rv); - - isFirst = false; - } - - // Process multi-reporters. - nsCOMPtr e2; - mgr->EnumerateMultiReporters(getter_AddRefs(e2)); - nsRefPtr cb = new DumpMultiReporterCallback(); - while (NS_SUCCEEDED(e2->HasMoreElements(&more)) && more) { - nsCOMPtr r; - e2->GetNext(getter_AddRefs(r)); r->CollectReports(cb, aWriter); } diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index b1b0d407db59..85a6cac78fda 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -327,11 +327,11 @@ static nsresult GetResidentFast(int64_t* aN) } #define HAVE_PRIVATE_REPORTER -class PrivateReporter MOZ_FINAL : public MemoryReporterBase +class PrivateReporter MOZ_FINAL : public MemoryUniReporter { public: PrivateReporter() - : MemoryReporterBase("private", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("private", KIND_OTHER, UNITS_BYTES, "Memory that cannot be shared with other processes, including memory that is " "committed and marked MEM_PRIVATE, data that is not mapped, and executable " "pages that have been written to.") @@ -356,11 +356,11 @@ public: #endif // XP_ #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS -class VsizeReporter MOZ_FINAL : public MemoryReporterBase +class VsizeReporter MOZ_FINAL : public MemoryUniReporter { public: VsizeReporter() - : MemoryReporterBase("vsize", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("vsize", KIND_OTHER, UNITS_BYTES, "Memory mapped by the process, including code and data segments, the heap, " "thread stacks, memory explicitly mapped by the process via mmap and similar " "operations, and memory shared with other processes. This is the vsize figure " @@ -373,11 +373,11 @@ public: NS_IMETHOD GetAmount(int64_t* aAmount) { return GetVsize(aAmount); } }; -class ResidentReporter MOZ_FINAL : public MemoryReporterBase +class ResidentReporter MOZ_FINAL : public MemoryUniReporter { public: ResidentReporter() - : MemoryReporterBase("resident", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("resident", KIND_OTHER, UNITS_BYTES, "Memory mapped by the process that is present in physical memory, also known " "as the resident set size (RSS). This is the best single figure to use when " "considering the memory resources used by the process, but it depends both on " @@ -389,11 +389,11 @@ public: NS_IMETHOD GetAmount(int64_t* aAmount) { return GetResident(aAmount); } }; -class ResidentFastReporter MOZ_FINAL : public MemoryReporterBase +class ResidentFastReporter MOZ_FINAL : public MemoryUniReporter { public: ResidentFastReporter() - : MemoryReporterBase("resident-fast", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("resident-fast", KIND_OTHER, UNITS_BYTES, "This is the same measurement as 'resident', but it tries to be as fast as " "possible at the expense of accuracy. On most platforms this is identical to " "the 'resident' measurement, but on Mac it may over-count. You should use " @@ -412,11 +412,11 @@ public: #define HAVE_PAGE_FAULT_REPORTERS 1 -class PageFaultsSoftReporter MOZ_FINAL : public MemoryReporterBase +class PageFaultsSoftReporter MOZ_FINAL : public MemoryUniReporter { public: PageFaultsSoftReporter() - : MemoryReporterBase("page-faults-soft", KIND_OTHER, + : MemoryUniReporter("page-faults-soft", KIND_OTHER, UNITS_COUNT_CUMULATIVE, "The number of soft page faults (also known as 'minor page faults') that " "have occurred since the process started. A soft page fault occurs when the " @@ -441,11 +441,11 @@ public: } }; -class PageFaultsHardReporter MOZ_FINAL : public MemoryReporterBase +class PageFaultsHardReporter MOZ_FINAL : public MemoryUniReporter { public: PageFaultsHardReporter() - : MemoryReporterBase("page-faults-hard", KIND_OTHER, + : MemoryUniReporter("page-faults-hard", KIND_OTHER, UNITS_COUNT_CUMULATIVE, "The number of hard page faults (also known as 'major page faults') that have " "occurred since the process started. A hard page fault occurs when a process " @@ -479,11 +479,11 @@ public: #ifdef HAVE_JEMALLOC_STATS -class HeapAllocatedReporter MOZ_FINAL : public MemoryReporterBase +class HeapAllocatedReporter MOZ_FINAL : public MemoryUniReporter { public: HeapAllocatedReporter() - : MemoryReporterBase("heap-allocated", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("heap-allocated", KIND_OTHER, UNITS_BYTES, "Memory mapped by the heap allocator that is currently allocated to the " "application. This may exceed the amount of memory requested by the " "application because the allocator regularly rounds up request sizes. (The " @@ -498,14 +498,14 @@ private: } }; -class HeapOverheadWasteReporter MOZ_FINAL : public MemoryReporterBase +class HeapOverheadWasteReporter MOZ_FINAL : public MemoryUniReporter { public: // We mark this and the other heap-overhead reporters as KIND_NONHEAP // because KIND_HEAP memory means "counted in heap-allocated", which this // is not. HeapOverheadWasteReporter() - : MemoryReporterBase("explicit/heap-overhead/waste", + : MemoryUniReporter("explicit/heap-overhead/waste", KIND_NONHEAP, UNITS_BYTES, "Committed bytes which do not correspond to an active allocation and which the " "allocator is not intentionally keeping alive (i.e., not 'heap-bookkeeping' or " @@ -522,11 +522,11 @@ private: } }; -class HeapOverheadBookkeepingReporter MOZ_FINAL : public MemoryReporterBase +class HeapOverheadBookkeepingReporter MOZ_FINAL : public MemoryUniReporter { public: HeapOverheadBookkeepingReporter() - : MemoryReporterBase("explicit/heap-overhead/bookkeeping", + : MemoryUniReporter("explicit/heap-overhead/bookkeeping", KIND_NONHEAP, UNITS_BYTES, "Committed bytes which the heap allocator uses for internal data structures.") {} @@ -539,11 +539,11 @@ private: } }; -class HeapOverheadPageCacheReporter MOZ_FINAL : public MemoryReporterBase +class HeapOverheadPageCacheReporter MOZ_FINAL : public MemoryUniReporter { public: HeapOverheadPageCacheReporter() - : MemoryReporterBase("explicit/heap-overhead/page-cache", + : MemoryUniReporter("explicit/heap-overhead/page-cache", KIND_NONHEAP, UNITS_BYTES, "Memory which the allocator could return to the operating system, but hasn't. " "The allocator keeps this memory around as an optimization, so it doesn't " @@ -559,11 +559,11 @@ private: } }; -class HeapCommittedReporter MOZ_FINAL : public MemoryReporterBase +class HeapCommittedReporter MOZ_FINAL : public MemoryUniReporter { public: HeapCommittedReporter() - : MemoryReporterBase("heap-committed", KIND_OTHER, UNITS_BYTES, + : MemoryUniReporter("heap-committed", KIND_OTHER, UNITS_BYTES, "Memory mapped by the heap allocator that is committed, i.e. in physical " "memory or paged to disk. This value corresponds to 'heap-allocated' + " "'heap-waste' + 'heap-bookkeeping' + 'heap-page-cache', but because " @@ -580,11 +580,11 @@ private: } }; -class HeapOverheadRatioReporter MOZ_FINAL : public MemoryReporterBase +class HeapOverheadRatioReporter MOZ_FINAL : public MemoryUniReporter { public: HeapOverheadRatioReporter() - : MemoryReporterBase("heap-overhead-ratio", KIND_OTHER, + : MemoryUniReporter("heap-overhead-ratio", KIND_OTHER, UNITS_PERCENTAGE, "Ratio of committed, unused bytes to allocated bytes; i.e., " "'heap-overhead' / 'heap-allocated'. This measures the overhead of " @@ -607,11 +607,11 @@ private: // However, the obvious time to register it is when the table is initialized, // and that happens before XPCOM components are initialized, which means the // NS_RegisterMemoryReporter call fails. So instead we do it here. -class AtomTablesReporter MOZ_FINAL : public MemoryReporterBase +class AtomTablesReporter MOZ_FINAL : public MemoryUniReporter { public: AtomTablesReporter() - : MemoryReporterBase("explicit/atom-tables", KIND_HEAP, UNITS_BYTES, + : MemoryUniReporter("explicit/atom-tables", KIND_HEAP, UNITS_BYTES, "Memory used by the dynamic and static atoms tables.") {} private: @@ -623,10 +623,10 @@ private: namespace mozilla { namespace dmd { -class DMDMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter +class DMDReporter MOZ_FINAL : public nsIMemoryReporter { public: - DMDMultiReporter() + DMDReporter() {} NS_DECL_ISUPPORTS @@ -637,7 +637,7 @@ public: return NS_OK; } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback* aCallback, + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCallback, nsISupports* aClosure) { dmd::Sizes sizes; @@ -677,7 +677,7 @@ public: } }; -NS_IMPL_ISUPPORTS1(DMDMultiReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(DMDReporter, nsIMemoryReporter) } // namespace dmd } // namespace mozilla @@ -725,7 +725,7 @@ nsMemoryReporterManager::Init() RegisterReporter(new AtomTablesReporter); #ifdef MOZ_DMD - RegisterMultiReporter(new mozilla::dmd::DMDMultiReporter); + RegisterReporter(new mozilla::dmd::DMDReporter); #endif #if defined(XP_LINUX) @@ -803,7 +803,6 @@ nsMemoryReporterManager::nsMemoryReporterManager() mIsRegistrationBlocked(false) { mReporters.Init(); - mMultiReporters.Init(); } nsMemoryReporterManager::~nsMemoryReporterManager() @@ -827,23 +826,6 @@ nsMemoryReporterManager::EnumerateReporters(nsISimpleEnumerator** aResult) return NS_OK; } -NS_IMETHODIMP -nsMemoryReporterManager::EnumerateMultiReporters(nsISimpleEnumerator** aResult) -{ - // Memory multi-reporters are not necessarily threadsafe, so - // EnumerateMultiReporters() must be called from the main thread. - if (!NS_IsMainThread()) { - MOZ_CRASH(); - } - - mozilla::MutexAutoLock autoLock(mMutex); - - nsRefPtr enumerator = - new HashtableEnumerator(mMultiReporters); - enumerator.forget(aResult); - return NS_OK; -} - static void DebugAssertRefcountIsNonZero(nsISupports* aObj) { @@ -899,41 +881,6 @@ nsMemoryReporterManager::RegisterReporterEvenIfBlocked( return RegisterReporterHelper(aReporter, /* force = */ true); } -nsresult -nsMemoryReporterManager::RegisterMultiReporterHelper( - nsIMemoryMultiReporter* aReporter, bool aForce) -{ - // This method is thread-safe. - mozilla::MutexAutoLock autoLock(mMutex); - - if ((mIsRegistrationBlocked && !aForce) || - mMultiReporters.Contains(aReporter)) { - return NS_ERROR_FAILURE; - } - - { - nsCOMPtr kungFuDeathGrip = aReporter; - mMultiReporters.PutEntry(aReporter); - } - - DebugAssertRefcountIsNonZero(aReporter); - - return NS_OK; -} - -NS_IMETHODIMP -nsMemoryReporterManager::RegisterMultiReporter(nsIMemoryMultiReporter* aReporter) -{ - return RegisterMultiReporterHelper(aReporter, /* force = */ false); -} - -NS_IMETHODIMP -nsMemoryReporterManager::RegisterMultiReporterEvenIfBlocked( - nsIMemoryMultiReporter* aReporter) -{ - return RegisterMultiReporterHelper(aReporter, /* force = */ true); -} - NS_IMETHODIMP nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter* aReporter) { @@ -948,20 +895,6 @@ nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter* aReporter) return NS_OK; } -NS_IMETHODIMP -nsMemoryReporterManager::UnregisterMultiReporter(nsIMemoryMultiReporter* aReporter) -{ - // This method is thread-safe. - mozilla::MutexAutoLock autoLock(mMutex); - - if (!mMultiReporters.Contains(aReporter)) { - return NS_ERROR_FAILURE; - } - - mMultiReporters.RemoveEntry(aReporter); - return NS_OK; -} - NS_IMETHODIMP nsMemoryReporterManager::BlockRegistration() { @@ -998,7 +931,7 @@ nsMemoryReporterManager::GetResident(int64_t* aResident) } // This is just a wrapper for int64_t that implements nsISupports, so it can be -// passed to nsIMemoryMultiReporter::CollectReports. +// passed to nsIMemoryReporter::CollectReports. class Int64Wrapper MOZ_FINAL : public nsISupports { public: NS_DECL_ISUPPORTS @@ -1007,7 +940,7 @@ public: }; NS_IMPL_ISUPPORTS0(Int64Wrapper) -class ExplicitNonHeapCountingCallback MOZ_FINAL : public nsIMemoryMultiReporterCallback +class ExplicitCallback MOZ_FINAL : public nsIMemoryReporterCallback { public: NS_DECL_ISUPPORTS @@ -1015,23 +948,20 @@ public: NS_IMETHOD Callback(const nsACString& aProcess, const nsACString& aPath, int32_t aKind, int32_t aUnits, int64_t aAmount, const nsACString& aDescription, - nsISupports* aWrappedExplicitNonHeap) + nsISupports* aWrappedExplicit) { - if (aKind == nsIMemoryReporter::KIND_NONHEAP && - PromiseFlatCString(aPath).Find("explicit") == 0 && - aAmount != int64_t(-1)) + if (aPath.Equals("heap-allocated") || + (aKind == nsIMemoryReporter::KIND_NONHEAP && + PromiseFlatCString(aPath).Find("explicit") == 0)) { - Int64Wrapper* wrappedPRInt64 = - static_cast(aWrappedExplicitNonHeap); - wrappedPRInt64->mValue += aAmount; + Int64Wrapper* wrappedInt64 = + static_cast(aWrappedExplicit); + wrappedInt64->mValue += aAmount; } return NS_OK; } }; -NS_IMPL_ISUPPORTS1( - ExplicitNonHeapCountingCallback -, nsIMemoryMultiReporterCallback -) +NS_IMPL_ISUPPORTS1(ExplicitCallback, nsIMemoryReporterCallback) NS_IMETHODIMP nsMemoryReporterManager::GetExplicit(int64_t* aExplicit) @@ -1044,63 +974,25 @@ nsMemoryReporterManager::GetExplicit(int64_t* aExplicit) nsresult rv; bool more; - // Get "heap-allocated" and all the KIND_NONHEAP measurements from normal - // (i.e. non-multi) "explicit" reporters. - int64_t heapAllocated = int64_t(-1); - int64_t explicitNonHeapNormalSize = 0; + // For each reporter we call CollectReports and filter out the + // non-explicit, non-NONHEAP measurements (except for "heap-allocated"). + // That's lots of wasted work, and we used to have a GetExplicitNonHeap() + // method which did this more efficiently, but it ended up being more + // trouble than it was worth. + + nsRefPtr cb = new ExplicitCallback(); + nsRefPtr wrappedExplicitSize = new Int64Wrapper(); + nsCOMPtr e; EnumerateReporters(getter_AddRefs(e)); while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { nsCOMPtr r; e->GetNext(getter_AddRefs(r)); - - int32_t kind; - rv = r->GetKind(&kind); - NS_ENSURE_SUCCESS(rv, rv); - - nsCString path; - rv = r->GetPath(path); - NS_ENSURE_SUCCESS(rv, rv); - - // We're only interested in NONHEAP explicit reporters and - // the 'heap-allocated' reporter. - if (kind == nsIMemoryReporter::KIND_NONHEAP && - path.Find("explicit") == 0) - { - // Just skip any NONHEAP reporters that fail, because - // "heap-allocated" is the most important one. - int64_t amount; - rv = r->GetAmount(&amount); - if (NS_SUCCEEDED(rv)) { - explicitNonHeapNormalSize += amount; - } - } else if (path.Equals("heap-allocated")) { - // If we don't have "heap-allocated", give up, because the result - // would be horribly inaccurate. - rv = r->GetAmount(&heapAllocated); - NS_ENSURE_SUCCESS(rv, rv); - } + r->CollectReports(cb, wrappedExplicitSize); } - // For each multi-reporter we call CollectReports and filter out the - // non-explicit, non-NONHEAP measurements. That's lots of wasted work, - // and we used to have a GetExplicitNonHeap() method which did this more - // efficiently, but it ended up being more trouble than it was worth. + *aExplicit = wrappedExplicitSize->mValue; - nsRefPtr cb = - new ExplicitNonHeapCountingCallback(); - nsRefPtr wrappedExplicitNonHeapMultiSize = - new Int64Wrapper(); - nsCOMPtr e2; - EnumerateMultiReporters(getter_AddRefs(e2)); - while (NS_SUCCEEDED(e2->HasMoreElements(&more)) && more) { - nsCOMPtr r; - e2->GetNext(getter_AddRefs(r)); - r->CollectReports(cb, wrappedExplicitNonHeapMultiSize); - } - int64_t explicitNonHeapMultiSize = wrappedExplicitNonHeapMultiSize->mValue; - - *aExplicit = heapAllocated + explicitNonHeapNormalSize + explicitNonHeapMultiSize; return NS_OK; #endif // HAVE_JEMALLOC_STATS } @@ -1205,7 +1097,7 @@ nsMemoryReporterManager::MinimizeMemoryUsage(nsIRunnable* aCallback, // Most memory reporters don't need thread safety, but some do. Make them all // thread-safe just to be safe. Memory reporters are created and destroyed // infrequently enough that the performance cost should be negligible. -NS_IMPL_ISUPPORTS1(MemoryReporterBase, nsIMemoryReporter) +NS_IMPL_ISUPPORTS1(MemoryUniReporter, nsIMemoryReporter) nsresult NS_RegisterMemoryReporter(nsIMemoryReporter* aReporter) @@ -1217,16 +1109,6 @@ NS_RegisterMemoryReporter(nsIMemoryReporter* aReporter) return mgr->RegisterReporter(aReporter); } -nsresult -NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter* aReporter) -{ - nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); - if (!mgr) { - return NS_ERROR_FAILURE; - } - return mgr->RegisterMultiReporter(aReporter); -} - nsresult NS_UnregisterMemoryReporter(nsIMemoryReporter* aReporter) { @@ -1237,22 +1119,12 @@ NS_UnregisterMemoryReporter(nsIMemoryReporter* aReporter) return mgr->UnregisterReporter(aReporter); } -nsresult -NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter* aReporter) -{ - nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); - if (!mgr) { - return NS_ERROR_FAILURE; - } - return mgr->UnregisterMultiReporter(aReporter); -} - #if defined(MOZ_DMD) namespace mozilla { namespace dmd { -class NullMultiReporterCallback : public nsIMemoryMultiReporterCallback +class NullReporterCallback : public nsIMemoryReporterCallback { public: NS_DECL_ISUPPORTS @@ -1267,8 +1139,8 @@ public: } }; NS_IMPL_ISUPPORTS1( - NullMultiReporterCallback -, nsIMemoryMultiReporterCallback + NullReporterCallback +, nsIMemoryReporterCallback ) void @@ -1277,48 +1149,15 @@ RunReporters() nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); - // Do vanilla reporters. + nsRefPtr cb = new NullReporterCallback(); + + bool more; nsCOMPtr e; mgr->EnumerateReporters(getter_AddRefs(e)); - bool more; while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { nsCOMPtr r; e->GetNext(getter_AddRefs(r)); - - int32_t kind; - nsresult rv = r->GetKind(&kind); - if (NS_FAILED(rv)) { - continue; - } - nsCString path; - rv = r->GetPath(path); - if (NS_FAILED(rv)) { - continue; - } - - // We're only interested in HEAP explicit reporters. (In particular, - // some heap blocks are deliberately measured once inside an "explicit" - // reporter and once outside, which isn't a problem. This condition - // prevents them being reported as double-counted. See bug 811018 - // comment 2.) - if (kind == nsIMemoryReporter::KIND_HEAP && - path.Find("explicit") == 0) - { - // Just getting the amount is enough for the reporter to report to - // DMD. - int64_t amount; - (void)r->GetAmount(&amount); - } - } - - // Do multi-reporters. - nsCOMPtr e2; - mgr->EnumerateMultiReporters(getter_AddRefs(e2)); - nsRefPtr cb = new NullMultiReporterCallback(); - while (NS_SUCCEEDED(e2->HasMoreElements(&more)) && more) { - nsCOMPtr r; - e2->GetNext(getter_AddRefs(r)); - r->CollectReports(cb, nullptr); + r->CollectReports(cb, nullptr); } } diff --git a/xpcom/base/nsMemoryReporterManager.h b/xpcom/base/nsMemoryReporterManager.h index 3b22ce011b65..baa1e30343aa 100644 --- a/xpcom/base/nsMemoryReporterManager.h +++ b/xpcom/base/nsMemoryReporterManager.h @@ -24,11 +24,8 @@ public: private: nsresult RegisterReporterHelper(nsIMemoryReporter *reporter, bool aForce); - nsresult RegisterMultiReporterHelper(nsIMemoryMultiReporter *reporter, - bool aForce); nsTHashtable mReporters; - nsTHashtable mMultiReporters; Mutex mMutex; bool mIsRegistrationBlocked; }; diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp index d4dc96da432f..a56b668807f7 100644 --- a/xpcom/build/nsXPComInit.cpp +++ b/xpcom/build/nsXPComInit.cpp @@ -334,11 +334,11 @@ NS_InitXPCOM(nsIServiceManager* *result, return NS_InitXPCOM2(result, binDirectory, nullptr); } -class ICUReporter MOZ_FINAL : public MemoryReporterBase +class ICUReporter MOZ_FINAL : public MemoryUniReporter { public: ICUReporter() - : MemoryReporterBase("explicit/icu", KIND_HEAP, UNITS_BYTES, + : MemoryUniReporter("explicit/icu", KIND_HEAP, UNITS_BYTES, "Memory used by ICU, a Unicode and globalization support library.") { #ifdef DEBUG diff --git a/xpcom/components/nsCategoryManager.cpp b/xpcom/components/nsCategoryManager.cpp index 7765add9feab..7ca0a1906544 100644 --- a/xpcom/components/nsCategoryManager.cpp +++ b/xpcom/components/nsCategoryManager.cpp @@ -402,11 +402,11 @@ CategoryEnumerator::enumfunc_createenumerator(const char* aStr, CategoryNode* aN NS_IMPL_QUERY_INTERFACE1(nsCategoryManager, nsICategoryManager) -class XPCOMCategoryManagerReporter MOZ_FINAL : public MemoryReporterBase +class XPCOMCategoryManagerReporter MOZ_FINAL : public MemoryUniReporter { public: XPCOMCategoryManagerReporter() - : MemoryReporterBase("explicit/xpcom/category-manager", + : MemoryUniReporter("explicit/xpcom/category-manager", KIND_HEAP, UNITS_BYTES, "Memory used for the XPCOM category manager.") {} diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp index e9cf03a9c70c..aa4487f7249e 100644 --- a/xpcom/components/nsComponentManager.cpp +++ b/xpcom/components/nsComponentManager.cpp @@ -280,11 +280,11 @@ CloneAndAppend(nsIFile* aBase, const nsACString& append) // nsComponentManagerImpl //////////////////////////////////////////////////////////////////////////////// -class XPCOMComponentManagerReporter MOZ_FINAL : public MemoryReporterBase +class XPCOMComponentManagerReporter MOZ_FINAL : public MemoryUniReporter { public: XPCOMComponentManagerReporter() - : MemoryReporterBase("explicit/xpcom/component-manager", + : MemoryUniReporter("explicit/xpcom/component-manager", KIND_HEAP, UNITS_BYTES, "Memory used for the XPCOM component manager.") {} diff --git a/xpcom/ds/nsObserverService.cpp b/xpcom/ds/nsObserverService.cpp index 4b8448eb6d85..0c3ca7ee65be 100644 --- a/xpcom/ds/nsObserverService.cpp +++ b/xpcom/ds/nsObserverService.cpp @@ -48,18 +48,18 @@ GetObserverServiceLog() namespace mozilla { -class ObserverServiceReporter MOZ_FINAL : public nsIMemoryMultiReporter +class ObserverServiceReporter MOZ_FINAL : public nsIMemoryReporter { public: NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYMULTIREPORTER + NS_DECL_NSIMEMORYREPORTER protected: static const size_t kSuspectReferentCount = 1000; static PLDHashOperator CountReferents(nsObserverList* aObserverList, void* aClosure); }; -NS_IMPL_ISUPPORTS1(ObserverServiceReporter, nsIMemoryMultiReporter) +NS_IMPL_ISUPPORTS1(ObserverServiceReporter, nsIMemoryReporter) NS_IMETHODIMP ObserverServiceReporter::GetName(nsACString& aName) @@ -128,7 +128,7 @@ ObserverServiceReporter::CountReferents(nsObserverList* aObserverList, } NS_IMETHODIMP -ObserverServiceReporter::CollectReports(nsIMemoryMultiReporterCallback* cb, +ObserverServiceReporter::CollectReports(nsIMemoryReporterCallback* cb, nsISupports* aClosure) { nsCOMPtr os = mozilla::services::GetObserverService(); @@ -220,14 +220,14 @@ void nsObserverService::RegisterReporter() { mReporter = new ObserverServiceReporter(); - NS_RegisterMemoryMultiReporter(mReporter); + NS_RegisterMemoryReporter(mReporter); } void nsObserverService::Shutdown() { if (mReporter) { - NS_UnregisterMemoryMultiReporter(mReporter); + NS_UnregisterMemoryReporter(mReporter); } mShuttingDown = true; diff --git a/xpcom/ds/nsObserverService.h b/xpcom/ds/nsObserverService.h index 0c559a8a1ec3..1b3ff959194a 100644 --- a/xpcom/ds/nsObserverService.h +++ b/xpcom/ds/nsObserverService.h @@ -15,7 +15,7 @@ #define NS_OBSERVERSERVICE_CID \ { 0xd07f5195, 0xe3d1, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } } -class nsIMemoryMultiReporter; +class nsIMemoryReporter; namespace mozilla { class ObserverServiceReporter; @@ -47,7 +47,7 @@ private: bool mShuttingDown; nsTHashtable mObserverTopicTable; - nsCOMPtr mReporter; + nsCOMPtr mReporter; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsObserverService, NS_OBSERVERSERVICE_CID) diff --git a/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp b/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp index c34c36b907ca..0a0546e9dfe2 100644 --- a/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp +++ b/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp @@ -40,11 +40,11 @@ XPTInterfaceInfoManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) return n; } -class XPTIWorkingSetReporter MOZ_FINAL : public MemoryReporterBase +class XPTIWorkingSetReporter MOZ_FINAL : public MemoryUniReporter { public: XPTIWorkingSetReporter() - : MemoryReporterBase("explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, + : MemoryUniReporter("explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, "Memory used by the XPCOM typelib system.") {} private: From 2529248891c10b91a72903732260015e0ce6e572 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 21:16:07 -0700 Subject: [PATCH 76/86] Bug 885169 - Spidermonkey: Fix ARM trampoline code to inform its RegisterSet of its use of a context register. r=nbp --- js/src/jit/arm/Trampoline-arm.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/js/src/jit/arm/Trampoline-arm.cpp b/js/src/jit/arm/Trampoline-arm.cpp index b5ca00421ea0..374f13b44efe 100644 --- a/js/src/jit/arm/Trampoline-arm.cpp +++ b/js/src/jit/arm/Trampoline-arm.cpp @@ -651,6 +651,7 @@ IonRuntime::generateVMWrapper(JSContext *cx, const VMFunction &f) // The context is the first argument; r0 is the first argument register. Register cxreg = r0; + regs.take(cxreg); // Stack is: // ... frame ... From 9f96e589c94cdf6d275a2bfebc0202017acd0369 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 21:16:07 -0700 Subject: [PATCH 77/86] Bug 885169 - Spidermonkey: Alleviate register allocation constraints in ICGetElem_Arguments::Compiler::generateStubCode. r=nbp --- js/src/jit/BaselineIC.cpp | 3 ++- js/src/jit/arm/MacroAssembler-arm.h | 30 +++++++++++++++++++++++------ js/src/jit/x86/MacroAssembler-x86.h | 26 +++++++++++++++++++------ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index ca883d1c2bba..bdfb5e857952 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -3970,7 +3970,7 @@ ICGetElem_Arguments::Compiler::generateStubCode(MacroAssembler &masm) regs = availableGeneralRegs(0); regs.takeUnchecked(objReg); regs.takeUnchecked(idxReg); - regs.takeUnchecked(scratchReg); + regs.take(scratchReg); Register argData = regs.takeAny(); Register tempReg = regs.takeAny(); @@ -3992,6 +3992,7 @@ ICGetElem_Arguments::Compiler::generateStubCode(MacroAssembler &masm) masm.addPtr(Imm32(ArgumentsData::offsetOfArgs()), argData); regs.add(scratchReg); regs.add(tempReg); + regs.add(argData); ValueOperand tempVal = regs.takeAnyValue(); masm.loadValue(BaseIndex(argData, idxReg, ScaleFromElemWidth(sizeof(Value))), tempVal); diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index 5c8e52159d48..5cd54627f98b 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -954,12 +954,30 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM void moveValue(const Value &val, const ValueOperand &dest); void moveValue(const ValueOperand &src, const ValueOperand &dest) { - JS_ASSERT(src.typeReg() != dest.payloadReg()); - JS_ASSERT(src.payloadReg() != dest.typeReg()); - if (src.typeReg() != dest.typeReg()) - ma_mov(src.typeReg(), dest.typeReg()); - if (src.payloadReg() != dest.payloadReg()) - ma_mov(src.payloadReg(), dest.payloadReg()); + Register s0 = src.typeReg(), d0 = dest.typeReg(), + s1 = src.payloadReg(), d1 = dest.payloadReg(); + + // Either one or both of the source registers could be the same as a + // destination register. + if (s1 == d0) { + if (s0 == d1) { + // If both are, this is just a swap of two registers. + JS_ASSERT(d1 != ScratchRegister); + JS_ASSERT(d0 != ScratchRegister); + ma_mov(d1, ScratchRegister); + ma_mov(d0, d1); + ma_mov(ScratchRegister, d0); + return; + } + // If only one is, copy that source first. + mozilla::Swap(s0, s1); + mozilla::Swap(d0, d1); + } + + if (s0 != d0) + ma_mov(s0, d0); + if (s1 != d1) + ma_mov(s1, d1); } void storeValue(ValueOperand val, Operand dst); diff --git a/js/src/jit/x86/MacroAssembler-x86.h b/js/src/jit/x86/MacroAssembler-x86.h index 5b3d579562fa..dcb8673f5fb9 100644 --- a/js/src/jit/x86/MacroAssembler-x86.h +++ b/js/src/jit/x86/MacroAssembler-x86.h @@ -113,12 +113,26 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared moveValue(val, dest.typeReg(), dest.payloadReg()); } void moveValue(const ValueOperand &src, const ValueOperand &dest) { - JS_ASSERT(src.typeReg() != dest.payloadReg()); - JS_ASSERT(src.payloadReg() != dest.typeReg()); - if (src.typeReg() != dest.typeReg()) - movl(src.typeReg(), dest.typeReg()); - if (src.payloadReg() != dest.payloadReg()) - movl(src.payloadReg(), dest.payloadReg()); + Register s0 = src.typeReg(), d0 = dest.typeReg(), + s1 = src.payloadReg(), d1 = dest.payloadReg(); + + // Either one or both of the source registers could be the same as a + // destination register. + if (s1 == d0) { + if (s0 == d1) { + // If both are, this is just a swap of two registers. + xchgl(d0, d1); + return; + } + // If only one is, copy that source first. + mozilla::Swap(s0, s1); + mozilla::Swap(d0, d1); + } + + if (s0 != d0) + movl(s0, d0); + if (s1 != d1) + movl(s1, d1); } ///////////////////////////////////////////////////////////////// From 1e180cb5c9cca2d48a86d04c21a5cf297faacfaa Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 4 Sep 2013 21:16:07 -0700 Subject: [PATCH 78/86] Bug 885169 - Reverse the default register allocation order so that low registers like eax on x86/x64 are preferred over high registers. r=h4writer --- js/src/jit/RegisterSets.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/js/src/jit/RegisterSets.h b/js/src/jit/RegisterSets.h index b19d422c3fcc..251fac45f805 100644 --- a/js/src/jit/RegisterSets.h +++ b/js/src/jit/RegisterSets.h @@ -400,8 +400,12 @@ class TypedRegisterSet #endif } T getAny() const { - JS_ASSERT(!empty()); - return T::FromCode(mozilla::FloorLog2(bits_)); + // The choice of first or last here is mostly arbitrary, as they are + // about the same speed on popular architectures. We choose first, as + // it has the advantage of using the "lower" registers more often. These + // registers are sometimes more efficient (e.g. optimized encodings for + // EAX on x86). + return getFirst(); } T getFirst() const { JS_ASSERT(!empty()); From 95e80fd9544e49837eb4da3d682ebe4d9b870238 Mon Sep 17 00:00:00 2001 From: Shane Tully Date: Fri, 23 Aug 2013 16:36:01 -0700 Subject: [PATCH 79/86] Bug 880118 - Integrate the GeckoView library into the build system r=cpeterson --- mobile/android/geckoview_library/.classpath | 13 ++++++ mobile/android/geckoview_library/.project | 33 ++++++++++++++ .../geckoview_library/AndroidManifest.xml | 17 +++++++ mobile/android/geckoview_library/Makefile.in | 45 +++++++++++++++++++ mobile/android/geckoview_library/moz.build | 5 +++ .../geckoview_library/project.properties | 15 +++++++ mobile/android/moz.build | 1 + toolkit/mozapps/installer/packager.mk | 7 ++- 8 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 mobile/android/geckoview_library/.classpath create mode 100644 mobile/android/geckoview_library/.project create mode 100644 mobile/android/geckoview_library/AndroidManifest.xml create mode 100644 mobile/android/geckoview_library/Makefile.in create mode 100644 mobile/android/geckoview_library/moz.build create mode 100644 mobile/android/geckoview_library/project.properties diff --git a/mobile/android/geckoview_library/.classpath b/mobile/android/geckoview_library/.classpath new file mode 100644 index 000000000000..46d9cf7cbb2f --- /dev/null +++ b/mobile/android/geckoview_library/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/mobile/android/geckoview_library/.project b/mobile/android/geckoview_library/.project new file mode 100644 index 000000000000..6ed69354e958 --- /dev/null +++ b/mobile/android/geckoview_library/.project @@ -0,0 +1,33 @@ + + + GeckoView + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/mobile/android/geckoview_library/AndroidManifest.xml b/mobile/android/geckoview_library/AndroidManifest.xml new file mode 100644 index 000000000000..12aed5b1bc5a --- /dev/null +++ b/mobile/android/geckoview_library/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/mobile/android/geckoview_library/Makefile.in b/mobile/android/geckoview_library/Makefile.in new file mode 100644 index 000000000000..129832a1f478 --- /dev/null +++ b/mobile/android/geckoview_library/Makefile.in @@ -0,0 +1,45 @@ +# 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/. + +DEPTH = @DEPTH@ +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +INSTALL_TARGETS += GECKOVIEW_LIBRARY +GECKOVIEW_LIBRARY_DEST = $(CURDIR) +GECKOVIEW_LIBRARY_FILES := \ + .classpath \ + .project \ + AndroidManifest.xml \ + project.properties \ + $(NULL) + +include $(topsrcdir)/config/rules.mk + +package: + # Make directory for the zips + $(MKDIR) -p $(DIST)/geckoview_library + + # Zip the assets + cd $(DIST)/fennec; \ + $(ZIP) -r ../geckoview_library/geckoview_assets.zip assets + + # Make empty directories to fit an Android project structure + $(MKDIR) -p bin gen libs/$(ABI_DIR) src + + # Copy the JARs + cp ../base/jars/* libs/ + + # Copy the SOs + cp $(DIST)/bin/libmozglue.so $(DIST)/bin/lib/libplugin-container.so libs/$(ABI_DIR)/ + + # Copy the resources + cp -R ../base/res . + + # Zip the directory + cd ..; \ + $(ZIP) -r ../../dist/geckoview_library/geckoview_library.zip geckoview_library --exclude geckoview_library/backend.mk geckoview_library/Makefile diff --git a/mobile/android/geckoview_library/moz.build b/mobile/android/geckoview_library/moz.build new file mode 100644 index 000000000000..c271ec3908ce --- /dev/null +++ b/mobile/android/geckoview_library/moz.build @@ -0,0 +1,5 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. diff --git a/mobile/android/geckoview_library/project.properties b/mobile/android/geckoview_library/project.properties new file mode 100644 index 000000000000..484dab07534a --- /dev/null +++ b/mobile/android/geckoview_library/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-17 +android.library=true diff --git a/mobile/android/moz.build b/mobile/android/moz.build index 9d4352980971..d2c29326d7a6 100644 --- a/mobile/android/moz.build +++ b/mobile/android/moz.build @@ -16,6 +16,7 @@ DIRS += [ 'themes/core', 'app', 'fonts', + 'geckoview_library', ] if not CONFIG['LIBXUL_SDK']: diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk index 2acb734bf901..b344809899bc 100644 --- a/toolkit/mozapps/installer/packager.mk +++ b/toolkit/mozapps/installer/packager.mk @@ -344,6 +344,10 @@ else INNER_ROBOCOP_PACKAGE=echo 'Testing is disabled - No Robocop for you' endif +# Create geckoview_library/geckoview_{assets,library}.zip for third-party GeckoView consumers. +INNER_MAKE_GECKOVIEW_LIBRARY= \ + $(MAKE) -C ../mobile/android/geckoview_library package ABI_DIR=$(ABI_DIR) + ifdef MOZ_OMX_PLUGIN DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginfroyo.so endif @@ -394,7 +398,8 @@ INNER_MAKE_PACKAGE = \ cp $(_ABS_DIST)/gecko.apk $(_ABS_DIST)/gecko-unsigned-unaligned.apk && \ $(RELEASE_JARSIGNER) $(_ABS_DIST)/gecko.apk && \ $(ZIPALIGN) -f -v 4 $(_ABS_DIST)/gecko.apk $(PACKAGE) && \ - $(INNER_ROBOCOP_PACKAGE) + $(INNER_ROBOCOP_PACKAGE) && \ + $(INNER_MAKE_GECKOVIEW_LIBRARY) # Language repacks root the resources contained in assets/omni.ja # under assets/, but the repacks expect them to be rooted at /. From a3499c335b597f212705116bc661e548772bc054 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 5 Sep 2013 00:26:26 -0400 Subject: [PATCH 80/86] Bug 880118 - Add support for disabling geckoview packaging r=glandium --- configure.in | 1 + toolkit/mozapps/installer/packager.mk | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/configure.in b/configure.in index 0054bf9d702b..a7412ab73ab2 100644 --- a/configure.in +++ b/configure.in @@ -8447,6 +8447,7 @@ AC_SUBST(MOZ_METRO) AC_SUBST(MOZ_ANDROID_HISTORY) AC_SUBST(MOZ_WEBSMS_BACKEND) AC_SUBST(MOZ_ANDROID_BEAM) +AC_SUBST(MOZ_DISABLE_GECKOVIEW) AC_SUBST(ENABLE_STRIP) AC_SUBST(PKG_SKIP_STRIP) AC_SUBST(STRIP_FLAGS) diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk index b344809899bc..0fe7c54919bb 100644 --- a/toolkit/mozapps/installer/packager.mk +++ b/toolkit/mozapps/installer/packager.mk @@ -345,8 +345,12 @@ INNER_ROBOCOP_PACKAGE=echo 'Testing is disabled - No Robocop for you' endif # Create geckoview_library/geckoview_{assets,library}.zip for third-party GeckoView consumers. +ifndef MOZ_DISABLE_GECKOVIEW INNER_MAKE_GECKOVIEW_LIBRARY= \ $(MAKE) -C ../mobile/android/geckoview_library package ABI_DIR=$(ABI_DIR) +else +INNER_MAKE_GECKOVIEW_LIBRARY=echo 'GeckoView library packaging is disabled' +endif ifdef MOZ_OMX_PLUGIN DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginfroyo.so From 6d8ac130b9cb09fb3f2396b235157edc104b9796 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 5 Sep 2013 00:26:30 -0400 Subject: [PATCH 81/86] Bug 880118 - Disable geckoview packaging in l10n builds r=glandium --- mobile/android/config/mozconfigs/android-armv6/l10n-nightly | 1 + mobile/android/config/mozconfigs/android-armv6/l10n-release | 1 + mobile/android/config/mozconfigs/android-x86/l10n-nightly | 1 + mobile/android/config/mozconfigs/android-x86/l10n-release | 1 + mobile/android/config/mozconfigs/android/l10n-nightly | 1 + mobile/android/config/mozconfigs/android/l10n-release | 1 + 6 files changed, 6 insertions(+) diff --git a/mobile/android/config/mozconfigs/android-armv6/l10n-nightly b/mobile/android/config/mozconfigs/android-armv6/l10n-nightly index 04fbfac0c332..3bbac064ff35 100644 --- a/mobile/android/config/mozconfigs/android-armv6/l10n-nightly +++ b/mobile/android/config/mozconfigs/android-armv6/l10n-nightly @@ -34,6 +34,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 export MOZ_PKG_SPECIAL=armv6 +export MOZ_DISABLE_GECKOVIEW=1 ac_add_options --with-branding=mobile/android/branding/nightly diff --git a/mobile/android/config/mozconfigs/android-armv6/l10n-release b/mobile/android/config/mozconfigs/android-armv6/l10n-release index a369cde177ff..2b493db2664d 100644 --- a/mobile/android/config/mozconfigs/android-armv6/l10n-release +++ b/mobile/android/config/mozconfigs/android-armv6/l10n-release @@ -31,6 +31,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 export MOZ_PKG_SPECIAL=armv6 +export MOZ_DISABLE_GECKOVIEW=1 ac_add_options --enable-official-branding ac_add_options --with-branding=mobile/android/branding/beta diff --git a/mobile/android/config/mozconfigs/android-x86/l10n-nightly b/mobile/android/config/mozconfigs/android-x86/l10n-nightly index a03e4099e958..80e4328bc00e 100644 --- a/mobile/android/config/mozconfigs/android-x86/l10n-nightly +++ b/mobile/android/config/mozconfigs/android-x86/l10n-nightly @@ -32,6 +32,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 +export MOZ_DISABLE_GECKOVIEW=1 ac_add_options --with-branding=mobile/android/branding/nightly diff --git a/mobile/android/config/mozconfigs/android-x86/l10n-release b/mobile/android/config/mozconfigs/android-x86/l10n-release index 4064f8503775..3f717c3a6984 100644 --- a/mobile/android/config/mozconfigs/android-x86/l10n-release +++ b/mobile/android/config/mozconfigs/android-x86/l10n-release @@ -29,6 +29,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 +export MOZ_DISABLE_GECKOVIEW=1 ac_add_options --enable-official-branding ac_add_options --with-branding=mobile/android/branding/beta diff --git a/mobile/android/config/mozconfigs/android/l10n-nightly b/mobile/android/config/mozconfigs/android/l10n-nightly index ad3f99d0b3a1..021712335fa8 100644 --- a/mobile/android/config/mozconfigs/android/l10n-nightly +++ b/mobile/android/config/mozconfigs/android/l10n-nightly @@ -32,6 +32,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 +export MOZ_DISABLE_GECKOVIEW=1 ac_add_options --with-branding=mobile/android/branding/nightly diff --git a/mobile/android/config/mozconfigs/android/l10n-release b/mobile/android/config/mozconfigs/android/l10n-release index 0143c6b1478d..671c52604a26 100644 --- a/mobile/android/config/mozconfigs/android/l10n-release +++ b/mobile/android/config/mozconfigs/android/l10n-release @@ -29,6 +29,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} export JAVA_HOME=/tools/jdk6 export MOZILLA_OFFICIAL=1 +export MOZ_DISABLE_GECKOVIEW=1 ac_add_options --enable-official-branding ac_add_options --with-branding=mobile/android/branding/beta From 8b7d6d5ca2f831e4093e348f6adf0b5cee595594 Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 5 Sep 2013 00:29:29 -0400 Subject: [PATCH 82/86] Bug 880118 - Dynamically pull resource IDs to avoid R.java reordering r=kats --- mobile/android/base/gfx/LayerView.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/gfx/LayerView.java b/mobile/android/base/gfx/LayerView.java index 842395a2bcf9..c3aa8a4bb32a 100644 --- a/mobile/android/base/gfx/LayerView.java +++ b/mobile/android/base/gfx/LayerView.java @@ -443,18 +443,20 @@ public class LayerView extends FrameLayout { return mGLController; } - private Bitmap getDrawable(int resId) { + private Bitmap getDrawable(String name) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; - return BitmapUtils.decodeResource(getContext(), resId, options); + Context context = getContext(); + int resId = context.getResources().getIdentifier(name, "drawable", context.getPackageName()); + return BitmapUtils.decodeResource(context, resId, options); } Bitmap getShadowPattern() { - return getDrawable(R.drawable.shadow); + return getDrawable("shadow"); } Bitmap getScrollbarImage() { - return getDrawable(R.drawable.scrollbar); + return getDrawable("scrollbar"); } /* When using a SurfaceView (mSurfaceView != null), resizing happens in two From af28e043e97aa5cc8dab9522ebc9be27cae7e02c Mon Sep 17 00:00:00 2001 From: Mark Finkle Date: Thu, 5 Sep 2013 00:33:11 -0400 Subject: [PATCH 83/86] Bug 911018 - Call HardwareUtils.init in GeckoView r=bnicholson --- mobile/android/base/GeckoView.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mobile/android/base/GeckoView.java b/mobile/android/base/GeckoView.java index 5bd8c57d6af1..fa6eb551e484 100644 --- a/mobile/android/base/GeckoView.java +++ b/mobile/android/base/GeckoView.java @@ -9,6 +9,7 @@ import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.gfx.LayerView; import org.mozilla.gecko.mozglue.GeckoLoader; import org.mozilla.gecko.util.Clipboard; +import org.mozilla.gecko.util.HardwareUtils; import org.mozilla.gecko.util.GeckoEventListener; import org.mozilla.gecko.util.ThreadUtils; @@ -53,6 +54,8 @@ public class GeckoView extends LayerView } Clipboard.init(context); + HardwareUtils.init(context); + GeckoLoader.loadMozGlue(); BrowserDB.setEnableContentProviders(false); } From 51f479662d78fc9ecc4bac3d2052b6fa4dd3dcca Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Wed, 4 Sep 2013 21:49:16 -0700 Subject: [PATCH 84/86] Back out e46601eb7279:533dc9ea3301 (bug 912322) for Android reftest bustage --- content/base/crashtests/308120-1.xul | 2 +- content/base/crashtests/330925-1.xhtml | 2 +- content/base/crashtests/401993-1.html | 2 +- content/base/test/test_base.xhtml | 2 +- content/base/test/test_bug330925.xhtml | 9 +++-- content/base/test/test_bug372086.html | 4 +-- content/base/test/test_bug444030.xhtml | 2 +- .../html/content/crashtests/465466-1.xhtml | 2 +- content/xbl/crashtests/472260-1.xhtml | 2 +- content/xbl/test/file_bug379959_cross.html | 4 +-- content/xbl/test/file_bug379959_data.html | 2 +- content/xbl/test/file_bug591198_inner.html | 2 +- content/xbl/test/test_bug378866.xhtml | 2 +- content/xbl/test/test_bug468210.xhtml | 2 +- .../xslt/tests/mochitest/test_bug319374.xhtml | 9 ++--- content/xul/content/crashtests/326864-1.xul | 10 ++---- content/xul/content/crashtests/384740-1.xul | 2 +- dom/base/crashtests/404869-1.xul | 2 +- dom/indexedDB/test/head.js | 2 +- dom/webidl/Document.webidl | 5 +-- js/xpconnect/crashtests/471366-1.html | 2 +- js/xpconnect/src/XPCWrappedNativeScope.cpp | 9 ----- js/xpconnect/src/nsXPConnect.cpp | 12 ++----- js/xpconnect/src/xpcprivate.h | 17 +++++---- js/xpconnect/tests/mochitest/Makefile.in | 1 - .../tests/mochitest/test_bug912322.html | 35 ------------------- layout/base/crashtests/379105-1.xhtml | 2 +- layout/inspector/tests/test_bug522601.xhtml | 2 +- layout/reftests/bugs/495385-2f.xhtml | 18 +++------- layout/reftests/bugs/reftest.list | 2 +- .../test_selectors_on_anonymous_content.html | 2 +- layout/xul/base/src/crashtests/328135-1.xul | 2 +- layout/xul/base/src/crashtests/329477-1.xhtml | 4 +-- .../tests/widgets/test_popupanchor.xul | 2 +- 34 files changed, 55 insertions(+), 124 deletions(-) delete mode 100644 js/xpconnect/tests/mochitest/test_bug912322.html diff --git a/content/base/crashtests/308120-1.xul b/content/base/crashtests/308120-1.xul index 55963d758e44..dc8a21c3e906 100644 --- a/content/base/crashtests/308120-1.xul +++ b/content/base/crashtests/308120-1.xul @@ -1,3 +1,3 @@ - +