xpcom/tests/SizeTest01.cpp
author Nicholas Nethercote <nnethercote@mozilla.com>
Fri, 16 Feb 2018 17:54:16 +1100
changeset 407868 32d6774930e55be5c03e8d631fc067a995623c1e
parent 150399 ad59ee55f59606bb7d07bf0d442a9078041c20a1
child 420394 220898648f5f735a4372d824f74e45acb66907ae
permissions -rw-r--r--
Bug 1438678 - Pass early prefs via shared memory instead of the command line. r=bobowen,jld,glandium. This patch replaces the large -intPrefs/-boolPrefs/-stringPrefs flags with a short-lived, anonymous, shared memory segment that is used to pass the early prefs. Removing the bloat from the command line is nice, but more important is the fact that this will let us pass more prefs at content process start-up, which will allow us to remove the early/late prefs split (bug 1436911). Although this mechanism is only used for prefs, it's conceivable that it could be used for other data that must be received very early by children, and for which the command line isn't ideal. Notable details: - Much of the patch deals with the various platform-specific ways of passing handles/fds to children. - Linux and Mac: we use a fixed fd (8) in combination with the new GeckoChildProcessHost::AddFdToRemap() function (which ensures the child won't close the fd). - Android: like Linux and Mac, but the handles get passed via "parcels" and we use the new SetPrefsFd() function instead of the fixed fd. - Windows: there is no need to duplicate the handle because Windows handles are system-wide. But we do use the new GeckoChildProcessHost::AddHandleToShare() function to add it to the list of inheritable handles. We also ensure that list is processed on all paths (MOZ_SANDBOX with sandbox, MOZ_SANDBOX without sandbox, non-MOZ_SANDBOX) so that the handles are marked as inheritable. The handle is passed via the -prefsHandle flag. The -prefsLen flag is used on all platforms to indicate the size of the shared memory segment. - The patch also moves the serialization/deserialization of the prefs in/out of the shared memory into libpref, which is a better spot for it. (This means Preferences::MustSendToContentProcesses() can be removed.) MozReview-Commit-ID: 8fREEBiYFvc

// Test01.cpp

#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
#include "nsString.h"

NS_DEF_PTR(nsIDOMNode);

	/*
		This test file compares the generated code size of similar functions between raw
                COM interface pointers (|AddRef|ing and |Release|ing by hand) and |nsCOMPtr|s.

		Function size results were determined by examining dissassembly of the generated code.
		mXXX is the size of the generated code on the Macintosh.  wXXX is the size on Windows.
		For these tests, all reasonable optimizations were enabled and exceptions were
		disabled (just as we build for release).

		The tests in this file explore only the simplest functionality: assigning a pointer
                to be reference counted into a [raw, nsCOMPtr] object; ensuring that it is
		|AddRef|ed and |Release|d appropriately; calling through the pointer to a function
		supplied by the underlying COM interface.

		Windows:
			raw_optimized														 31 bytes
			raw, nsCOMPtr*													 34
			nsCOMPtr_optimized*											 38
			nsCOMPtr_optimized											 42
			nsCOMPtr																 46

		Macintosh:
			raw_optimized, nsCOMPtr_optimized				112 bytes 	(1.0000)
			nsCOMPtr																120					(1.0714)	i.e., 7.14% bigger than raw_optimized et al
			raw																			140 				(1.2500)

		The overall difference in size between Windows and Macintosh is caused by the
		the PowerPC RISC architecture where every instruction is 4 bytes.

                On Macintosh, nsCOMPtr generates out-of-line destructors which are
		not referenced, and which can be stripped by the linker.
	*/

void
Test01_raw( nsIDOMNode* aDOMNode, nsString* aResult )
		// m140, w34
	{
			/*
				This test is designed to be more like a typical large function where,
				because you are working with several resources, you don't just return when
				one of them is |nullptr|.  Similarly: |Test01_nsCOMPtr00|, and |Test01_nsIPtr00|.
			*/

		nsIDOMNode* node = aDOMNode;
		NS_IF_ADDREF(node);

		if ( node )
			node->GetNodeName(*aResult);

		NS_IF_RELEASE(node);
	}

void
Test01_raw_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
		// m112, w31
	{
			/*
				This test simulates smaller functions where you _do_ just return
				|nullptr| at the first sign of trouble.  Similarly: |Test01_nsCOMPtr01|,
				and |Test01_nsIPtr01|.
			*/

			/*
				This test produces smaller code that |Test01_raw| because it avoids
				the three tests: |NS_IF_...|, and |if ( node )|.
			*/

// -- the following code is assumed, but is commented out so we compare only
//		 the relevent generated code

//		if ( !aDOMNode )
//			return;

		nsIDOMNode* node = aDOMNode;
		NS_ADDREF(node);
		node->GetNodeName(*aResult);
		NS_RELEASE(node);
	}

void
Test01_nsCOMPtr( nsIDOMNode* aDOMNode, nsString* aResult )
		// m120, w46/34
	{
		nsCOMPtr<nsIDOMNode> node = aDOMNode;

		if ( node )
			node->GetNodeName(*aResult);
	}

void
Test01_nsCOMPtr_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
		// m112, w42/38
	{
//		if ( !aDOMNode )
//			return;

		nsCOMPtr<nsIDOMNode> node = aDOMNode;
		node->GetNodeName(*aResult);
	}