Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Sat, 31 Aug 2013 16:21:43 -0400
changeset 145196 b6c29e43451900744de9db867fc175f120d5a6bb
parent 145195 29d3273e03a9d5cf0aaf274f0ba9cd8e0a0c9179 (current diff)
parent 145193 aef6bbfe9db3b5f150806ef530879082e669aae3 (diff)
child 145197 36d12ef42b436d58e833a5b80042ad715bc0f1a2
child 145205 1179318fb5aa7a95793361c69b21c4897d9c1874
push id33186
push userryanvm@gmail.com
push dateSat, 31 Aug 2013 20:52:27 +0000
treeherdermozilla-inbound@b6c29e434519 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone26.0a1
first release with
nightly linux32
b6c29e434519 / 26.0a1 / 20130901030218 / files
nightly linux64
b6c29e434519 / 26.0a1 / 20130901030218 / files
nightly mac
b6c29e434519 / 26.0a1 / 20130901030218 / files
nightly win32
b6c29e434519 / 26.0a1 / 20130901030218 / files
nightly win64
b6c29e434519 / 26.0a1 / 20130901030218 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c.
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -410,16 +410,20 @@ SettingsListener.observe('device.storage
   Services.prefs.setCharPref('device.storage.writable.name', value);
 });
 
 // =================== Privacy ====================
 SettingsListener.observe('privacy.donottrackheader.enabled', false, function(value) {
   Services.prefs.setBoolPref('privacy.donottrackheader.enabled', value);
 });
 
+SettingsListener.observe('privacy.donottrackheader.value', 1, function(value) {
+  Services.prefs.setIntPref('privacy.donottrackheader.value', value);
+});
+
 // =================== Crash Reporting ====================
 SettingsListener.observe('app.reportCrashes', 'ask', function(value) {
   if (value == 'always') {
     Services.prefs.setBoolPref('app.reportCrashes', true);
   } else if (value == 'never') {
     Services.prefs.setBoolPref('app.reportCrashes', false);
   } else {
     Services.prefs.clearUserPref('app.reportCrashes');
--- a/browser/branding/aurora/content/aboutDialog.css
+++ b/browser/branding/aurora/content/aboutDialog.css
@@ -6,16 +6,17 @@
   background-image: url("chrome://branding/content/about-background.png");
   background-repeat: no-repeat;
   background-color: rgb(19,8,36);
   color: #fff;
 }
 
 .text-link {
   color: #fff !important;
+  text-decoration: underline;
 }
 
 .text-link:-moz-focusring {
   border-color: #fff;
 }
 
 #rightBox {
   /* this margin prevents text from overlapping the planet image */
--- a/browser/branding/nightly/content/aboutDialog.css
+++ b/browser/branding/nightly/content/aboutDialog.css
@@ -6,16 +6,17 @@
   background-image: url("chrome://branding/content/about-background.png");
   background-repeat: no-repeat;
   background-color: rgb(10,17,37);
   color: #fff;
 }
 
 .text-link {
   color: #fff !important;
+  text-decoration: underline;
 }
 
 .text-link:-moz-focusring {
   border-color: #fff;
 }
 
 #rightBox {
   /* this margin prevents text from overlapping the planet image */
--- a/browser/branding/unofficial/content/aboutDialog.css
+++ b/browser/branding/unofficial/content/aboutDialog.css
@@ -6,16 +6,17 @@
   background-image: url("chrome://branding/content/about-background.png");
   background-repeat: no-repeat;
   background-color: #000;
   color: #fff;
 }
 
 .text-link {
   color: #fff !important;
+  text-decoration: underline;
 }
 
 #rightBox {
   /* this margin prevents text from overlapping the planet image */
   margin-left: 280px;
   margin-right: 20px;
 }
 
--- a/browser/components/sessionstore/test/browser_sessionStorage.js
+++ b/browser/components/sessionstore/test/browser_sessionStorage.js
@@ -39,48 +39,55 @@ function waitForStorageChange(aTab) {
 
 function test() {
 
   waitForExplicitFinish();
 
   let tab;
   Task.spawn(function() {
     try {
+      let SESSION_STORAGE_KEY = "SESSION_STORAGE_KEY " + Math.random();
+      let SESSION_STORAGE_VALUE = "SESSION_STORAGE_VALUE " + Math.random();
+      let LOCAL_STORAGE_KEY = "LOCAL_STORAGE_KEY " + Math.random();
+      let LOCAL_STORAGE_VALUE = "LOCAL_STORAGE_VALUE " + Math.random();
+
       tab = gBrowser.addTab("http://example.com");
       // about:home supports sessionStorage and localStorage
 
       let win = tab.linkedBrowser.contentWindow;
 
       // Flush loading and next save, call getBrowserState()
       // a few times to ensure that everything is cached.
       yield promiseBrowserLoaded(tab.linkedBrowser);
       yield forceWriteState();
       info("Calling getBrowserState() to populate cache");
       ss.getBrowserState();
 
       info("Change sessionStorage, ensure that state is saved");
-      win.sessionStorage["SESSION_STORAGE_KEY"] = "SESSION_STORAGE_VALUE";
-      let storageChanged = yield waitForStorageChange(tab);
+      let storageChangedPromise = waitForStorageChange(tab);
+      win.sessionStorage[SESSION_STORAGE_KEY] = SESSION_STORAGE_VALUE;
+      let storageChanged = yield storageChangedPromise;
       ok(storageChanged, "Changing sessionStorage triggered the right message");
       yield forceWriteState();
 
       let state = ss.getBrowserState();
-      ok(state.indexOf("SESSION_STORAGE_KEY") != -1, "Key appears in state");
-      ok(state.indexOf("SESSION_STORAGE_VALUE") != -1, "Value appears in state");
+      ok(state.indexOf(SESSION_STORAGE_KEY) != -1, "Key appears in state");
+      ok(state.indexOf(SESSION_STORAGE_VALUE) != -1, "Value appears in state");
 
 
       info("Change localStorage, ensure that state is not saved");
-      win.localStorage["LOCAL_STORAGE_KEY"] = "LOCAL_STORAGE_VALUE";
-      storageChanged = yield waitForStorageChange(tab);
+      storageChangedPromise = waitForStorageChange(tab);
+      win.localStorage[LOCAL_STORAGE_KEY] = LOCAL_STORAGE_VALUE;
+      storageChanged = yield storageChangedPromise;
       ok(!storageChanged, "Changing localStorage did not trigger a message");
       yield forceWriteState();
 
       state = ss.getBrowserState();
-      ok(state.indexOf("LOCAL_STORAGE_KEY") == -1, "Key does not appear in state");
-      ok(state.indexOf("LOCAL_STORAGE_VALUE") == -1, "Value does not appear in state");
+      ok(state.indexOf(LOCAL_STORAGE_KEY) == -1, "Key does not appear in state");
+      ok(state.indexOf(LOCAL_STORAGE_VALUE) == -1, "Value does not appear in state");
     } catch (ex) {
       ok(false, ex);
       info(ex.stack);
     } finally {
       // clean up
       if (tab) {
         gBrowser.removeTab(tab);
       }
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -547,16 +547,19 @@ MOCHITEST_FILES_C= \
 		test_bug707142.html \
 		file_bug707142_baseline.json \
 		file_bug707142_bom.json \
 		file_bug707142_utf-16.json \
 		test_reentrant_flush.html \
 		test_bug708620.html \
 		file_bug708620.html \
 		file_bug708620-2.html \
+		test_XHR_timeout.html \
+		test_XHR_timeout.js \
+		file_XHR_timeout.sjs \
 		test_bug717511.html \
 		file_bug717511.html \
 		file_bug717511.html^headers^ \
 		file_bug717511_2.html \
 		file_bug717511_2.html^headers^ \
 		test_bug726364.html \
 		test_bug698381.html \
 		test_bug711047.html \
@@ -696,20 +699,15 @@ MOCHITEST_FILES_PARTS = $(foreach s,A B 
 # Disabled for now. Mochitest isn't reliable enough for these.
 # test_bug444546.html \
 # bug444546.sjs \
 
 # Disabled due to making the harness time out
 #		test_bug503473.html \
 #		file_bug503473-frame.sjs \
 
-# Disabled for frequent failures (bug 841505, bug 842344, etc)
-#		test_XHR_timeout.html \
-#		test_XHR_timeout.js \
-#		file_XHR_timeout.sjs \
-
 MOCHITEST_BROWSER_FILES = \
 		browser_bug593387.js \
 		browser_bug902350.js \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -75,54 +75,62 @@ var ecmaGlobals =
 var interfaceNamesInGlobalScope =
   [
     "AnalyserNode",
     "AnimationEvent",
     "ArchiveRequest",
     "Attr",
     "Audio",
     "AudioBuffer",
+    {name: "AudioChannelManager", b2g: true},
     "AudioContext",
     "AudioBufferSourceNode",
     "AudioDestinationNode",
     "AudioListener",
     "AudioNode",
     "AudioParam",
     "AudioProcessingEvent",
     "AudioStreamTrack",
     "BarProp",
     "BatteryManager",
     "BeforeUnloadEvent",
     "BiquadFilterNode",
     "Blob",
     "BlobEvent",
+    {name: "BluetoothAdapter", b2g: true},
+    {name: "BluetoothDevice", b2g: true},
+    {name: "BluetoothDeviceEvent", b2g: true},
+    {name: "BluetoothManager", b2g: true},
+    {name: "BluetoothStatusChangedEvent", b2g: true},
     {name: "BoxObject", xbl: true},
-    {name: "BrowserFeedWriter", android: false},
+    {name: "BrowserFeedWriter", desktop: true},
+    {name: "CallEvent", b2g: true},
     "CameraCapabilities",
     "CameraControl",
     "CameraManager",
     "CanvasGradient",
     "CanvasPattern",
     "CanvasRenderingContext2D",
     "CaretPosition",
     "CDATASection",
+    {name: "CFStateChangeEvent", b2g: true},
     "ChannelMergerNode",
     "ChannelSplitterNode",
     "CharacterData",
     {name: "ChromeWindow", xbl: true},
     "ClientRect",
     "ClientRectList",
     "ClipboardEvent",
     "CloseEvent",
     "CommandEvent",
     "Comment",
     "CompositionEvent",
     "Controllers",
     "ConvolverNode",
-    {name: "CRMFObject", android: false},
+    {name: "CRMFObject", desktop: true},
     "Crypto",
     "CSS",
     "CSS2Properties",
     "CSSCharsetRule",
     "CSSConditionRule",
     "CSSFontFaceRule",
     {name: "CSSFontFeatureValuesRule", release: false},
     "CSSGroupingRule",
@@ -139,16 +147,17 @@ var interfaceNamesInGlobalScope =
     "CSSStyleRule",
     "CSSStyleSheet",
     "CSSSupportsRule",
     "CSSValue",
     "CSSValueList",
     "CustomEvent",
     "DataChannel",
     "DataContainerEvent",
+    {name: "DataErrorEvent", b2g: true},
     "DataTransfer",
     "DelayNode",
     "DesktopNotification",
     "DesktopNotificationCenter",
     "DeviceAcceleration",
     "DeviceLightEvent",
     "DeviceMotionEvent",
     "DeviceOrientationEvent",
@@ -180,23 +189,24 @@ var interfaceNamesInGlobalScope =
     "EventListenerInfo",
     "EventSource",
     "EventTarget",
     "File",
     "FileHandle",
     "FileList",
     "FileReader",
     "FileRequest",
+    {name: "FMRadio", b2g: true},
     "FocusEvent",
     "FormData",
     "GainNode",
-    {name: "Gamepad", android: false},
-    {name: "GamepadAxisMoveEvent", android: false},
-    {name: "GamepadButtonEvent", android: false},
-    {name: "GamepadEvent", android: false},
+    {name: "Gamepad", desktop: true},
+    {name: "GamepadAxisMoveEvent", desktop: true},
+    {name: "GamepadButtonEvent", desktop: true},
+    {name: "GamepadEvent", desktop: true},
     "HashChangeEvent",
     "History",
     "HTMLAnchorElement",
     "HTMLAppletElement",
     "HTMLAreaElement",
     "HTMLAudioElement",
     "HTMLBaseElement",
     "HTMLBodyElement",
@@ -260,31 +270,32 @@ var interfaceNamesInGlobalScope =
     "HTMLTableSectionElement",
     "HTMLTemplateElement",
     "HTMLTextAreaElement",
     "HTMLTimeElement",
     "HTMLTitleElement",
     "HTMLUListElement",
     "HTMLUnknownElement",
     "HTMLVideoElement",
+    {name: "IccCardLockErrorEvent", b2g: true},
     "IDBCursor",
     "IDBCursorWithValue",
     "IDBDatabase",
     "IDBFactory",
     "IDBFileHandle",
     "IDBIndex",
     "IDBKeyRange",
     "IDBObjectStore",
     "IDBOpenDBRequest",
     "IDBRequest",
     "IDBTransaction",
     "IDBVersionChangeEvent",
     "Image",
     "ImageData",
-    {name: "InstallTrigger", xbl: false},
+    {name: "InstallTrigger", b2g: false, xbl: false},
     "KeyEvent",
     "KeyboardEvent",
     "LoadStatus",
     "LocalMediaStream",
     "Location",
     "LockedFile",
     "MediaElementAudioSourceNode",
     "MediaError",
@@ -297,38 +308,54 @@ var interfaceNamesInGlobalScope =
     "MediaStreamEvent",
     "MediaStreamTrack",
     "MessageEvent",
     "MimeType",
     "MimeTypeArray",
     "ModalContentWindow",
     "MouseEvent",
     "MouseScrollEvent",
+    {name: "MozActivity", b2g: true},
     "MozApplicationEvent",
     "MozCanvasPrintState",
+    {name: "MozCellBroadcast", b2g: true},
+    {name: "MozCellBroadcastEvent", b2g: true},
     "MozConnection",
     "mozContact",
     "MozContactChangeEvent",
     "MozCSSKeyframeRule",
     "MozCSSKeyframesRule",
+    {name: "MozEmergencyCbModeEvent", b2g: true},
+    {name: "MozIccManager", b2g: true},
+    {name: "MozInputContext", b2g: true},
+    {name: "MozInputMethod", b2g: true},
+    {name: "MozInputMethodManager", b2g: true},
     "MozMmsEvent",
     "MozMmsMessage",
+    {name: "MozMobileConnection", b2g: true},
     "MozMobileMessageManager",
     "MozMobileMessageThread",
     "MozNamedAttrMap",
+    {name: "MozOtaStatusEvent", b2g: true},
     "MozPowerManager",
     "mozRTCIceCandidate",
     "mozRTCPeerConnection",
     "mozRTCSessionDescription",
     "MozSettingsEvent",
     "MozSmsEvent",
     "MozSmsFilter",
     "MozSmsMessage",
     "MozSmsSegmentInfo",
+    {name: "MozStkCommandEvent", b2g: true},
+    {name: "MozTimeManager", b2g: true},
+    {name: "MozVoicemail", b2g: true},
+    {name: "MozVoicemailEvent", b2g: true},
     "MozWakeLock",
+    {name: "MozWifiConnectionInfoEvent", b2g: true},
+    {name: "MozWifiStatusChangeEvent", b2g: true},
     "MutationEvent",
     "MutationObserver",
     "MutationRecord",
     "Navigator",
     "Node",
     "NodeFilter",
     "NodeIterator",
     "NodeList",
@@ -350,18 +377,18 @@ var interfaceNamesInGlobalScope =
     "PeriodicWave",
     "PhoneNumberService",
     "Plugin",
     "PluginArray",
     "PopStateEvent",
     "PopupBlockedEvent",
     "ProcessingInstruction",
     "ProgressEvent",
-    {name: "Promise", release: false},
-    {name: "PromiseResolver", release: false},
+    {name: "Promise", b2g: false, release: false},
+    {name: "PromiseResolver", b2g: false, release: false},
     "PropertyNodeList",
     "Range",
     "RecordErrorEvent",
     "Rect",
     "RGBColor",
     "RTCDataChannelEvent",
     "RTCPeerConnectionIceEvent",
     "Screen",
@@ -499,16 +526,19 @@ var interfaceNamesInGlobalScope =
     "SVGTransform",
     "SVGTransformList",
     "SVGTSpanElement",
     "SVGUnitTypes",
     "SVGUseElement",
     "SVGViewElement",
     "SVGZoomAndPan",
     "SVGZoomEvent",
+    {name: "Telephony", b2g: true},
+    {name: "TelephonyCall", b2g: true},
+    {name: "TelephonyCallGroup", b2g: true},
     "Text",
     "TextDecoder",
     "TextEncoder",
     "TextMetrics",
     "TimeEvent",
     "TimeRanges",
     "Touch",
     "TouchEvent",
@@ -519,16 +549,17 @@ var interfaceNamesInGlobalScope =
     {name: "TreeContentView", xbl: true},
     {name: "TreeSelection", xbl: true},
     "TreeWalker",
     "UIEvent",
     "UndoManager",
     "URL",
     {name: "UserDataHandler", xbl: true},
     "UserProximityEvent",
+    {name: "USSDReceivedEvent", b2g: true},
     "ValidityState",
     "VideoStreamTrack",
     "WaveShaperNode",
     "WebGLActiveInfo",
     "WebGLBuffer",
     "WebGLFramebuffer",
     "WebGLProgram",
     "WebGLRenderbuffer",
@@ -567,37 +598,39 @@ var interfaceNamesInGlobalScope =
     {name: "XULTreeBuilder", xbl: true},
   ]
 // IMPORTANT: Do not change this list without review from a DOM peer!
 
 function createInterfaceMap(isXBLScope) {
   var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
   var isNightly = version.endsWith("a1");
   var isRelease = !version.contains("a");
-  var isAndroid = navigator.userAgent.indexOf("Android") >= 0;
+  var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
+  var isB2G = !isDesktop && !navigator.userAgent.contains("Android");
   var interfaceMap = {};
   for (var entry of ecmaGlobals) {
     if (typeof(entry) === "string") {
       // Standard ECMAScript global objects are not defined on the XBL scope.
       interfaceMap[entry] = !isXBLScope;
     } else if (entry.nightly === isNightly) {
       interfaceMap[entry.name] = !isXBLScope;
     } else {
       interfaceMap[entry.name] = false;
     }
   }
   for (var entry of interfaceNamesInGlobalScope) {
     if (typeof(entry) === "string") {
       interfaceMap[entry] = true;
-    } else if (entry.xbl === isXBLScope ||
-               entry.android === isAndroid ||
-               entry.release === isRelease) {
+    } else if (entry.xbl === !isXBLScope ||
+               entry.desktop === !isDesktop ||
+               entry.b2g === !isB2G ||
+               entry.release === !isRelease) {
+      interfaceMap[entry.name] = false;
+    } else {
       interfaceMap[entry.name] = true;
-    } else {
-      interfaceMap[entry.name] = false;
     }
   }
   return interfaceMap;
 }
 
 function runTest(isXBLScope) {
   var interfaceMap = createInterfaceMap(isXBLScope);
   for (var name of Object.getOwnPropertyNames(window)) {
--- a/dom/workers/test/Makefile.in
+++ b/dom/workers/test/Makefile.in
@@ -88,34 +88,32 @@ MOCHITEST_FILES = \
   test_workersDisabled.html \
   workersDisabled_worker.js \
   test_xhr_implicit_cancel.html \
   xhr_implicit_cancel_worker.js \
   test_xhr_parameters.html \
   test_xhr_parameters.js \
   test_xhr_system.html \
   test_xhr_system.js \
+  test_xhr_timeout.html \
   test_blobConstructor.html \
   test_csp.html \
   test_csp.js \
   test_csp.html^headers^ \
   csp_worker.js \
   test_transferable.html \
   transferable_worker.js \
   test_errorwarning.html \
   errorwarning_worker.js \
   test_contentWorker.html \
   content_worker.js \
   test_url.html \
   url_worker.js \
   $(NULL)
 
-# Disabled for frequent failures (bug 841505, bug 842344, etc)
-#  test_xhr_timeout.html \
-
 MOCHITEST_CHROME_FILES = \
   test_chromeWorker.xul \
   test_chromeWorkerJSM.xul \
   test_extension.xul \
   test_extensionBootstrap.xul \
   test_file.xul \
   test_fileSlice.xul \
   test_fileBlobPosting.xul \
--- a/js/src/builtin/Profilers.cpp
+++ b/js/src/builtin/Profilers.cpp
@@ -208,18 +208,17 @@ struct RequiredStringArg {
         } else {
             mBytes = JS_EncodeString(cx, args[argi].toString());
         }
     }
     operator void*() {
         return (void*) mBytes;
     }
     ~RequiredStringArg() {
-        if (mBytes)
-            js_free(mBytes);
+        js_free(mBytes);
     }
 };
 
 static bool
 StartProfiling(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() == 0) {
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -293,18 +293,17 @@ struct ClosureInfo
     : rt(runtime)
     , errResult(NULL)
     , closure(NULL)
   {}
 
   ~ClosureInfo() {
     if (closure)
       ffi_closure_free(closure);
-    if (errResult)
-      js_free(errResult);
+    js_free(errResult);
   }
 };
 
 bool IsCTypesGlobal(JSObject* obj);
 
 JSCTypesCallbacks* GetCallbacks(JSObject* obj);
 
 /*******************************************************************************
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -3616,24 +3616,28 @@ EmitSingletonInitialiser(ExclusiveContex
 
     return EmitObjectOp(cx, objbox, JSOP_OBJECT, bce);
 }
 
 /* See the SRC_FOR source note offsetBias comments later in this file. */
 JS_STATIC_ASSERT(JSOP_NOP_LENGTH == 1);
 JS_STATIC_ASSERT(JSOP_POP_LENGTH == 1);
 
+namespace {
+
 class EmitLevelManager
 {
     BytecodeEmitter *bce;
   public:
     EmitLevelManager(BytecodeEmitter *bce) : bce(bce) { bce->emitLevel++; }
     ~EmitLevelManager() { bce->emitLevel--; }
 };
 
+} /* anonymous namespace */
+
 static bool
 EmitCatch(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
     ptrdiff_t guardJump;
 
     /*
      * Morph STMT_BLOCK to STMT_CATCH, note the block entry code offset,
      * and save the block object atom.
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -15,16 +15,18 @@
 #include "vm/StringBuffer.h"
 
 #include "jsfuninlines.h"
 #include "jsscriptinlines.h"
 
 using namespace js;
 using namespace js::frontend;
 
+namespace {
+
 class NameResolver
 {
     static const size_t MaxParents = 100;
 
     JSContext *cx;
     size_t nparents;                /* number of parents in the parents array */
     ParseNode *parents[MaxParents]; /* history of ParseNodes we've been looking at */
     StringBuffer *buf;              /* when resolving, buffer to append to */
@@ -320,15 +322,17 @@ class NameResolver
             for (ParseNode *nxt = cur->pn_head; nxt; nxt = nxt->pn_next)
                 resolve(nxt, prefix);
             break;
         }
         nparents--;
     }
 };
 
+} /* anonymous namespace */
+
 bool
 frontend::NameFunctions(JSContext *cx, ParseNode *pn)
 {
     NameResolver nr(cx);
     nr.resolve(pn);
     return true;
 }
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -65,16 +65,18 @@ ParseNodeAllocator::freeNode(ParseNode *
     /* Poison the node, to catch attempts to use it without initializing it. */
     memset(pn, 0xab, sizeof(*pn));
 #endif
 
     pn->pn_next = freelist;
     freelist = pn;
 }
 
+namespace {
+
 /*
  * A work pool of ParseNodes. The work pool is a stack, chained together
  * by nodes' pn_next fields. We use this to avoid creating deep C++ stacks
  * when recycling deep parse trees.
  *
  * Since parse nodes are probably allocated in something close to the order
  * they appear in a depth-first traversal of the tree, making the work pool
  * a stack should give us pretty good locality.
@@ -99,16 +101,18 @@ class NodeStack {
         ParseNode *hold = top; /* my kingdom for a prog1 */
         top = top->pn_next;
         return hold;
     }
   private:
     ParseNode *top;
 };
 
+} /* anonymous namespace */
+
 /*
  * Push the children of |pn| on |stack|. Return true if |pn| itself could be
  * safely recycled, or false if it must be cleaned later (pn_used and pn_defn
  * nodes, and all function nodes; see comments for CleanFunctionList in
  * SemanticAnalysis.cpp). Some callers want to free |pn|; others
  * (js::ParseNodeAllocator::prepareNodeForMutation) don't care about |pn|, and
  * just need to take care of its children.
  */
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -328,18 +328,17 @@ TokenStream::TokenStream(ExclusiveContex
 }
 
 #ifdef _MSC_VER
 #pragma warning(pop)
 #endif
 
 TokenStream::~TokenStream()
 {
-    if (sourceMap)
-        js_free(sourceMap);
+    js_free(sourceMap);
 
     JS_ASSERT_IF(originPrincipals, originPrincipals->refcount);
 }
 
 // Use the fastest available getc.
 #if defined(HAVE_GETC_UNLOCKED)
 # define fast_getc getc_unlocked
 #elif defined(HAVE__GETC_NOLOCK)
@@ -842,18 +841,17 @@ TokenStream::getSourceMappingURL(bool is
 
         if (tokenbuf.empty())
             // The source map's URL was missing, but not quite an exception that
             // we should stop and drop everything for, though.
             return true;
 
         size_t sourceMapLength = tokenbuf.length();
 
-        if (sourceMap)
-            js_free(sourceMap);
+        js_free(sourceMap);
         sourceMap = cx->pod_malloc<jschar>(sourceMapLength + 1);
         if (!sourceMap)
             return false;
 
         PodCopy(sourceMap, tokenbuf.begin(), sourceMapLength);
         sourceMap[sourceMapLength] = '\0';
     }
     return true;
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -618,16 +618,18 @@ operator<=(Type lhs, VarType rhs)
     MOZ_ASSUME_UNREACHABLE("Unexpected rhs type");
 }
 
 /*****************************************************************************/
 
 static inline MIRType ToMIRType(MIRType t) { return t; }
 static inline MIRType ToMIRType(VarType t) { return t.toMIRType(); }
 
+namespace {
+
 template <class VecT>
 class ABIArgIter
 {
     ABIArgGenerator gen_;
     const VecT &types_;
     unsigned i_;
 
     void settle() { if (!done()) gen_.next(ToMIRType(types_[i_])); }
@@ -678,16 +680,18 @@ class Signature
     bool appendArg(VarType type) { return argTypes_.append(type); }
     VarType arg(unsigned i) const { return argTypes_[i]; }
     const VarTypeVector &args() const { return argTypes_; }
     MoveRef<VarTypeVector> extractArgs() { return OldMove(argTypes_); }
 
     RetType retType() const { return retType_; }
 };
 
+} /* namespace anonymous */
+
 static
 bool operator==(const Signature &lhs, const Signature &rhs)
 {
     if (lhs.retType() != rhs.retType())
         return false;
     if (lhs.args().length() != rhs.args().length())
         return false;
     for (unsigned i = 0; i < lhs.args().length(); i++) {
@@ -902,21 +906,21 @@ TypedArrayStoreType(ArrayBufferView::Vie
         return ArrayStore_Doublish;
       default:;
     }
     MOZ_ASSUME_UNREACHABLE("Unexpected array type");
 }
 
 /*****************************************************************************/
 
+namespace {
+
 typedef Vector<PropertyName*,1> LabelVector;
 typedef Vector<MBasicBlock*,8> BlockVector;
 
-namespace {
-
 // ModuleCompiler encapsulates the compilation of an entire asm.js module. Over
 // the course of an ModuleCompiler object's lifetime, many FunctionCompiler
 // objects will be created and destroyed in sequence, one for each function in
 // the module.
 //
 // *** asm.js FFI calls ***
 //
 // asm.js allows calling out to non-asm.js via "FFI calls". The asm.js type
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -91,18 +91,17 @@ struct BaselineStackBuilder
         buffer_(NULL),
         header_(NULL),
         framePushed_(0)
     {
         JS_ASSERT(bufferTotal_ >= HeaderSize());
     }
 
     ~BaselineStackBuilder() {
-        if (buffer_)
-            js_free(buffer_);
+        js_free(buffer_);
     }
 
     bool init() {
         JS_ASSERT(!buffer_);
         JS_ASSERT(bufferUsed_ == 0);
         buffer_ = reinterpret_cast<uint8_t *>(js_calloc(bufferTotal_));
         if (!buffer_)
             return false;
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -417,18 +417,18 @@ typedef bool (*ReportOverRecursedFn)(JSC
 static const VMFunction CheckOverRecursedInfo =
     FunctionInfo<ReportOverRecursedFn>(CheckOverRecursed);
 
 bool
 BaselineCompiler::emitStackCheck()
 {
     Label skipCall;
     uintptr_t *limitAddr = &cx->runtime()->mainThread.ionStackLimit;
-    masm.loadPtr(AbsoluteAddress(limitAddr), R0.scratchReg());
-    masm.branchPtr(Assembler::AboveOrEqual, BaselineStackReg, R0.scratchReg(), &skipCall);
+    masm.branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(limitAddr), BaselineStackReg,
+                   &skipCall);
 
     prepareVMCall();
     if (!callVM(CheckOverRecursedInfo))
         return false;
 
     masm.bind(&skipCall);
     return true;
 }
--- a/js/src/jit/EffectiveAddressAnalysis.cpp
+++ b/js/src/jit/EffectiveAddressAnalysis.cpp
@@ -27,17 +27,17 @@ AnalyzeLsh(MBasicBlock *block, MLsh *lsh
         return;
 
     Scale scale = ShiftToScale(shiftValue.toInt32());
 
     int32_t displacement = 0;
     MInstruction *last = lsh;
     MDefinition *base = NULL;
     while (true) {
-        if (last->useCount() != 1)
+        if (!last->hasOneUse())
             break;
 
         MUseIterator use = last->usesBegin();
         if (!use->consumer()->isDefinition() || !use->consumer()->toDefinition()->isAdd())
             break;
 
         MAdd *add = use->consumer()->toDefinition()->toAdd();
         if (add->specialization() != MIRType_Int32 || !add->isTruncated())
@@ -56,17 +56,17 @@ AnalyzeLsh(MBasicBlock *block, MLsh *lsh
         last = add;
     }
 
     if (!base) {
         uint32_t elemSize = 1 << ScaleToShift(scale);
         if (displacement % elemSize != 0)
             return;
 
-        if (last->useCount() != 1)
+        if (!last->hasOneUse())
             return;
 
         MUseIterator use = last->usesBegin();
         if (!use->consumer()->isDefinition() || !use->consumer()->toDefinition()->isBitAnd())
             return;
 
         MBitAnd *bitAnd = use->consumer()->toDefinition()->toBitAnd();
         MDefinition *other = bitAnd->getOperand(1 - use->index());
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -473,18 +473,17 @@ IonCompartment::IonCompartment(IonRuntim
     baselineSetPropReturnAddr_(NULL),
     stringConcatStub_(NULL),
     parallelStringConcatStub_(NULL)
 {
 }
 
 IonCompartment::~IonCompartment()
 {
-    if (stubCodes_)
-        js_delete(stubCodes_);
+    js_delete(stubCodes_);
 }
 
 bool
 IonCompartment::initialize(JSContext *cx)
 {
     stubCodes_ = cx->new_<ICStubCodeMap>(cx);
     if (!stubCodes_ || !stubCodes_->init())
         return false;
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1136,17 +1136,17 @@ IonBuilder::traverseBytecode()
         // Nothing in inspectOpcode() is allowed to advance the pc.
         JSOp op = JSOp(*pc);
         if (!inspectOpcode(op))
             return false;
 
 #ifdef DEBUG
         for (size_t i = 0; i < popped.length(); i++) {
             // Call instructions can discard PassArg instructions. Ignore them.
-            if (popped[i]->isPassArg() && popped[i]->useCount() == 0)
+            if (popped[i]->isPassArg() && !popped[i]->hasUses())
                 continue;
 
             switch (op) {
               case JSOP_POP:
               case JSOP_POPN:
               case JSOP_DUP:
               case JSOP_DUP2:
               case JSOP_PICK:
@@ -4033,23 +4033,24 @@ IonBuilder::getInlineableGetPropertyCach
         if (unbox->mode() != MUnbox::Infallible)
             return NULL;
         if (unbox->hasUses())
             return NULL;
         if (!unbox->input()->isTypeBarrier())
             return NULL;
 
         MTypeBarrier *barrier = unbox->input()->toTypeBarrier();
-        if (barrier->useCount() != 1)
+        // Test if usecount() > 1
+        if (!barrier->hasOneUse())
             return NULL;
         if (!barrier->input()->isGetPropertyCache())
             return NULL;
 
         MGetPropertyCache *cache = barrier->input()->toGetPropertyCache();
-        if (cache->useCount() > 1)
+        if (cache->hasUses() && !cache->hasOneUse())
             return NULL;
         if (!CanInlineGetPropertyCache(cache, thisDef))
             return NULL;
         return cache;
     }
 
     return NULL;
 }
@@ -4156,17 +4157,17 @@ IonBuilder::inlineTypeObjectFallback(Cal
     JS_ASSERT(callInfo.fun()->isGetPropertyCache() || callInfo.fun()->isUnbox());
 
     // 2. The MGetPropertyCache has inlineable cases by guarding on the TypeObject.
     JS_ASSERT(dispatch->numCases() > 0);
 
     // 3. The MGetPropertyCache (and, if applicable, MTypeBarrier and MUnbox) only
     //    have at most a single use.
     JS_ASSERT_IF(callInfo.fun()->isGetPropertyCache(), !cache->hasUses());
-    JS_ASSERT_IF(callInfo.fun()->isUnbox(), cache->useCount() == 1);
+    JS_ASSERT_IF(callInfo.fun()->isUnbox(), cache->hasOneUse());
 
     // This means that no resume points yet capture the MGetPropertyCache,
     // so everything from the MGetPropertyCache up until the call is movable.
     // We now move the MGetPropertyCache and friends into a fallback path.
 
     // Create a new CallInfo to track modified state within the fallback path.
     CallInfo fallbackInfo(cx, callInfo.constructing());
     if (!fallbackInfo.init(callInfo))
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -1802,18 +1802,17 @@ ParallelIonCache::reset()
     if (stubbedShapes_)
         stubbedShapes_->clear();
 }
 
 void
 ParallelIonCache::destroy()
 {
     DispatchIonCache::destroy();
-    if (stubbedShapes_)
-        js_delete(stubbedShapes_);
+    js_delete(stubbedShapes_);
 }
 
 void
 GetPropertyParIC::reset()
 {
     ParallelIonCache::reset();
     hasTypedArrayLengthStub_ = false;
 }
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -581,20 +581,18 @@ struct IonBlockCounts
             successors_ = (uint32_t *) js_calloc(numSuccessors * sizeof(uint32_t));
             if (!successors_)
                 return false;
         }
         return true;
     }
 
     void destroy() {
-        if (successors_)
-            js_free(successors_);
-        if (code_)
-            js_free(code_);
+        js_free(successors_);
+        js_free(code_);
     }
 
     uint32_t id() const {
         return id_;
     }
 
     uint32_t offset() const {
         return offset_;
@@ -668,18 +666,17 @@ struct IonScriptCounts
     IonScriptCounts() {
         mozilla::PodZero(this);
     }
 
     ~IonScriptCounts() {
         for (size_t i = 0; i < numBlocks_; i++)
             blocks_[i].destroy();
         js_free(blocks_);
-        if (previous_)
-            js_delete(previous_);
+        js_delete(previous_);
     }
 
     bool init(size_t numBlocks) {
         numBlocks_ = numBlocks;
         blocks_ = (IonBlockCounts *) js_calloc(numBlocks * sizeof(IonBlockCounts));
         return blocks_ != NULL;
     }
 
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -1007,17 +1007,18 @@ MacroAssembler::loadBaselineOrIonNoArgCh
 
         Pop(offset);
     }
 }
 
 void
 MacroAssembler::loadBaselineFramePtr(Register framePtr, Register dest)
 {
-    movePtr(framePtr, dest);
+    if (framePtr != dest)
+        movePtr(framePtr, dest);
     subPtr(Imm32(BaselineFrame::Size()), dest);
 }
 
 void
 MacroAssembler::loadForkJoinSlice(Register slice, Register scratch)
 {
     // Load the current ForkJoinSlice *. If we need a parallel exit frame,
     // chances are we are about to do something very slow anyways, so just
--- a/js/src/jit/IonSpewer.cpp
+++ b/js/src/jit/IonSpewer.cpp
@@ -254,16 +254,17 @@ jit::CheckLogging()
             "  snapshots  Snapshot information\n"
             "  codegen    Native code generation\n"
             "  bailouts   Bailouts\n"
             "  caches     Inline caches\n"
             "  osi        Invalidation\n"
             "  safepoints Safepoints\n"
             "  pools      Literal Pools (ARM only for now)\n"
             "  cacheflush Instruction Cache flushes (ARM only for now)\n"
+            "  range      Range Analysis\n"
             "  logs       C1 and JSON visualization logging\n"
             "  trace      Generate calls to js::jit::Trace() for effectful instructions\n"
             "  all        Everything\n"
             "\n"
             "  bl-aborts  Baseline compiler abort messages\n"
             "  bl-scripts Baseline script-compilation\n"
             "  bl-op      Baseline compiler detailed op-specific messages\n"
             "  bl-ic      Baseline inline-cache messages\n"
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -554,19 +554,24 @@ ReorderCommutative(MDefinition **lhsp, M
 
     // Ensure that if there is a constant, then it is in rhs.
     // In addition, since clobbering binary operations clobber the left
     // operand, prefer a non-constant lhs operand with no further uses.
 
     if (rhs->isConstant())
         return;
 
-    if (lhs->isConstant() ||
-        (rhs->defUseCount() == 1 && lhs->defUseCount() > 1))
-    {
+    // lhs and rhs are used by the commutative operator. If they have any
+    // *other* uses besides, try to reorder to avoid clobbering them. To
+    // be fully precise, we should check whether this is the *last* use,
+    // but checking hasOneDefUse() is a decent approximation which doesn't
+    // require any extra analysis.
+    JS_ASSERT(lhs->defUseCount() > 0);
+    JS_ASSERT(rhs->defUseCount() > 0);
+    if (lhs->isConstant() || (rhs->hasOneDefUse() && !lhs->hasOneDefUse())) {
         *rhsp = lhs;
         *lhsp = rhs;
     }
 }
 
 bool
 LIRGenerator::visitTest(MTest *test)
 {
@@ -1113,17 +1118,17 @@ LIRGenerator::visitAbs(MAbs *ins)
 }
 
 bool
 LIRGenerator::visitSqrt(MSqrt *ins)
 {
     MDefinition *num = ins->num();
     JS_ASSERT(num->type() == MIRType_Double);
     LSqrtD *lir = new LSqrtD(useRegisterAtStart(num));
-    return defineReuseInput(lir, ins, 0);
+    return define(lir, ins);
 }
 
 bool
 LIRGenerator::visitAtan2(MAtan2 *ins)
 {
     MDefinition *y = ins->y();
     JS_ASSERT(y->type() == MIRType_Double);
 
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -268,16 +268,45 @@ MDefinition::defUseCount() const
 {
     size_t count = 0;
     for (MUseIterator i(uses_.begin()); i != uses_.end(); i++)
         if ((*i)->consumer()->isDefinition())
             count++;
     return count;
 }
 
+bool
+MDefinition::hasOneUse() const
+{
+    MUseIterator i(uses_.begin());
+    if (i == uses_.end())
+        return false;
+    i++;
+    return i == uses_.end();
+}
+
+bool
+MDefinition::hasOneDefUse() const
+{
+    bool hasOneDefUse = false;
+    for (MUseIterator i(uses_.begin()); i != uses_.end(); i++) {
+        if (!(*i)->consumer()->isDefinition())
+            continue;
+
+        // We already have a definition use. So 1+
+        if (hasOneDefUse)
+            return false;
+
+        // We saw one definition. Loop to test if there is another.
+        hasOneDefUse = true;
+    }
+
+    return hasOneDefUse;
+}
+
 MUseIterator
 MDefinition::removeUse(MUseIterator use)
 {
     return uses_.removeAt(use);
 }
 
 MUseIterator
 MNode::replaceOperand(MUseIterator use, MDefinition *def)
@@ -851,17 +880,17 @@ MPhi::addInputSlow(MDefinition *ins, boo
     }
 
     return true;
 }
 
 uint32_t
 MPrepareCall::argc() const
 {
-    JS_ASSERT(useCount() == 1);
+    JS_ASSERT(hasOneUse());
     MCall *call = usesBegin()->consumer()->toDefinition()->toCall();
     return call->numStackArgs();
 }
 
 void
 MPassArg::printOpcode(FILE *fp) const
 {
     PrintOpcodeName(fp, op());
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -475,16 +475,23 @@ class MDefinition : public MNode
 
     // Number of uses of this instruction.
     size_t useCount() const;
 
     // Number of uses of this instruction.
     // (only counting MDefinitions, ignoring MResumePoints)
     size_t defUseCount() const;
 
+    // Test whether this MDefinition has exactly one use.
+    bool hasOneUse() const;
+
+    // Test whether this MDefinition has exactly one use.
+    // (only counting MDefinitions, ignoring MResumePoints)
+    bool hasOneDefUse() const;
+
     bool hasUses() const {
         return !uses_.empty();
     }
 
     virtual bool isControlInstruction() const {
         return false;
     }
 
@@ -3941,21 +3948,19 @@ class MPhi MOZ_FINAL : public MDefinitio
 };
 
 // The goal of a Beta node is to split a def at a conditionally taken
 // branch, so that uses dominated by it have a different name.
 class MBeta : public MUnaryInstruction
 {
   private:
     const Range *comparison_;
-    MDefinition *val_;
     MBeta(MDefinition *val, const Range *comp)
         : MUnaryInstruction(val),
-          comparison_(comp),
-          val_(val)
+          comparison_(comp)
     {
         setResultType(val->type());
         setResultTypeSet(val->resultTypeSet());
     }
 
   public:
     INSTRUCTION_HEADER(Beta)
     void printOpcode(FILE *fp) const;
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -353,22 +353,22 @@ void
 Range::unionWith(const Range *other)
 {
    bool decimal = decimal_ | other->decimal_;
    uint16_t max_exponent = Max(max_exponent_, other->max_exponent_);
 
    if (lower_infinite_ || other->lower_infinite_)
        makeLowerInfinite();
    else
-       setLower(Min(lower_, other->lower_));
+       setLowerInit(Min(lower_, other->lower_));
 
    if (upper_infinite_ || other->upper_infinite_)
        makeUpperInfinite();
    else
-       setUpper(Max(upper_, other->upper_));
+       setUpperInit(Max(upper_, other->upper_));
 
    decimal_ = decimal;
    max_exponent_ = max_exponent;
 }
 
 static const int64_t RANGE_INF_MAX = int64_t(JSVAL_INT_MAX) + 1;
 static const int64_t RANGE_INF_MIN = int64_t(JSVAL_INT_MIN) - 1;
 
@@ -795,17 +795,17 @@ MPhi::computeRange()
     setRange(range);
 }
 
 void
 MBeta::computeRange()
 {
     bool emptyRange = false;
 
-    Range *range = Range::intersect(val_->range(), comparison_, &emptyRange);
+    Range *range = Range::intersect(getOperand(0)->range(), comparison_, &emptyRange);
     if (emptyRange) {
         IonSpew(IonSpew_Range, "Marking block for inst %d unexitable", id());
         block()->setEarlyAbort();
     } else {
         setRange(range);
     }
 }
 
--- a/js/src/jit/UnreachableCodeElimination.cpp
+++ b/js/src/jit/UnreachableCodeElimination.cpp
@@ -292,17 +292,17 @@ UnreachableCodeElimination::removeUnmark
             // in the graph. Since lowering will fail. Replace it with the
             // argument for the exceptional case when it is kept alive in a
             // ResumePoint. DCE will remove the unused MPassArg instruction.
             for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++) {
                 if (iter->isCall()) {
                     MCall *call = iter->toCall();
                     for (size_t i = 0; i < call->numStackArgs(); i++) {
                         JS_ASSERT(call->getArg(i)->isPassArg());
-                        JS_ASSERT(call->getArg(i)->defUseCount() == 1);
+                        JS_ASSERT(call->getArg(i)->hasOneDefUse());
                         MPassArg *arg = call->getArg(i)->toPassArg();
                         arg->replaceAllUsesWith(arg->getArgument());
                     }
                 }
             }
 
             graph_.removeBlock(block);
         }
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -338,18 +338,18 @@ CodeGeneratorARM::visitAbsD(LAbsD *ins)
     masm.ma_vabs(input, input);
     return true;
 }
 
 bool
 CodeGeneratorARM::visitSqrtD(LSqrtD *ins)
 {
     FloatRegister input = ToFloatRegister(ins->input());
-    JS_ASSERT(input == ToFloatRegister(ins->output()));
-    masm.ma_vsqrt(input, input);
+    FloatRegister output = ToFloatRegister(ins->output());
+    masm.ma_vsqrt(input, output);
     return true;
 }
 
 bool
 CodeGeneratorARM::visitAddI(LAddI *ins)
 {
     const LAllocation *lhs = ins->getOperand(0);
     const LAllocation *rhs = ins->getOperand(1);
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -14,17 +14,20 @@
 #include "jit/ParallelFunctions.h"
 #include "jit/RangeAnalysis.h"
 
 #include "jit/shared/CodeGenerator-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
+using mozilla::DoubleSignificandBits;
 using mozilla::FloorLog2;
+using mozilla::NegativeInfinity;
+using mozilla::SpecificNaN;
 
 namespace js {
 namespace jit {
 
 CodeGeneratorX86Shared::CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
   : CodeGeneratorShared(gen, graph, masm)
 {
 }
@@ -415,44 +418,41 @@ CodeGeneratorX86Shared::visitMinMaxD(LMi
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitAbsD(LAbsD *ins)
 {
     FloatRegister input = ToFloatRegister(ins->input());
     JS_ASSERT(input == ToFloatRegister(ins->output()));
-    masm.xorpd(ScratchFloatReg, ScratchFloatReg);
-    masm.subsd(input, ScratchFloatReg); // negate the sign bit.
-    masm.andpd(ScratchFloatReg, input); // s & ~s
+    // Load a value which is all ones except for the sign bit.
+    masm.loadConstantDouble(SpecificNaN(0, DoubleSignificandBits), ScratchFloatReg);
+    masm.andpd(ScratchFloatReg, input);
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitSqrtD(LSqrtD *ins)
 {
     FloatRegister input = ToFloatRegister(ins->input());
-    JS_ASSERT(input == ToFloatRegister(ins->output()));
-    masm.sqrtsd(input, input);
+    FloatRegister output = ToFloatRegister(ins->output());
+    masm.sqrtsd(input, output);
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitPowHalfD(LPowHalfD *ins)
 {
     FloatRegister input = ToFloatRegister(ins->input());
-    Register scratch = ToRegister(ins->temp());
     JS_ASSERT(input == ToFloatRegister(ins->output()));
 
-    const uint32_t NegInfinityFloatBits = 0xFF800000;
     Label done, sqrt;
 
     // Branch if not -Infinity.
-    masm.move32(Imm32(NegInfinityFloatBits), scratch);
-    masm.loadFloatAsDouble(scratch, ScratchFloatReg);
+    masm.loadConstantDouble(NegativeInfinity(), ScratchFloatReg);
     masm.branchDouble(Assembler::DoubleNotEqualOrUnordered, input, ScratchFloatReg, &sqrt);
 
     // Math.pow(-Infinity, 0.5) == Infinity.
     masm.xorpd(input, input);
     masm.subsd(ScratchFloatReg, input);
     masm.jump(&done);
 
     // Math.pow(-0, 0.5) == 0 == Math.pow(0, 0.5). Adding 0 converts any -0 to 0.
--- a/js/src/jit/shared/LIR-x86-shared.h
+++ b/js/src/jit/shared/LIR-x86-shared.h
@@ -152,31 +152,27 @@ class LModPowTwoI : public LInstructionH
         return getDef(0);
     }
     MMod *mir() const {
         return mir_->toMod();
     }
 };
 
 // Double raised to a half power.
-class LPowHalfD : public LInstructionHelper<1, 1, 1>
+class LPowHalfD : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(PowHalfD)
-    LPowHalfD(const LAllocation &input, const LDefinition &temp) {
+    LPowHalfD(const LAllocation &input) {
         setOperand(0, input);
-        setTemp(0, temp);
     }
 
     const LAllocation *input() {
         return getOperand(0);
     }
-    const LDefinition *temp() {
-        return getTemp(0);
-    }
     const LDefinition *output() {
         return getDef(0);
     }
 };
 
 // Takes a tableswitch with an integer to decide
 class LTableSwitch : public LInstructionHelper<0, 1, 2>
 {
--- a/js/src/jit/shared/Lowering-x86-shared.cpp
+++ b/js/src/jit/shared/Lowering-x86-shared.cpp
@@ -57,17 +57,17 @@ LIRGeneratorX86Shared::visitGuardObjectT
     return redefine(ins, ins->obj());
 }
 
 bool
 LIRGeneratorX86Shared::visitPowHalf(MPowHalf *ins)
 {
     MDefinition *input = ins->input();
     JS_ASSERT(input->type() == MIRType_Double);
-    LPowHalfD *lir = new LPowHalfD(useRegisterAtStart(input), temp());
+    LPowHalfD *lir = new LPowHalfD(useRegisterAtStart(input));
     return defineReuseInput(lir, ins, 0);
 }
 
 bool
 LIRGeneratorX86Shared::lowerForShift(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir,
                                      MDefinition *lhs, MDefinition *rhs)
 {
     ins->setOperand(0, useRegisterAtStart(lhs));
--- a/js/src/jit/x64/BaselineIC-x64.cpp
+++ b/js/src/jit/x64/BaselineIC-x64.cpp
@@ -23,19 +23,19 @@ ICCompare_Int32::Compiler::generateStubC
 {
     // Guard that R0 is an integer and R1 is an integer.
     Label failure;
     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
 
     // Directly compare the int32 payload of R0 and R1.
     Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
+    masm.xorl(ScratchReg, ScratchReg);
     masm.cmpl(R0.valueReg(), R1.valueReg());
     masm.setCC(cond, ScratchReg);
-    masm.movzxbl(ScratchReg, ScratchReg);
 
     // Box the result and return
     masm.boxValue(JSVAL_TYPE_BOOLEAN, ScratchReg, R0.valueReg());
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -309,11 +309,11 @@ MacroAssemblerX64::handleFailureWithHand
     movl(Imm32(BAILOUT_RETURN_OK), rax);
     jmp(Operand(rsp, offsetof(ResumeFromException, target)));
 }
 
 Assembler::Condition
 MacroAssemblerX64::testNegativeZero(const FloatRegister &reg, const Register &scratch)
 {
     movq(reg, scratch);
-    subq(Imm32(1), scratch);
+    cmpq(scratch, Imm32(1));
     return Overflow;
 }
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -343,39 +343,32 @@ IonRuntime::generateArgumentsRectifier(J
 
     // Push undefined.
     {
         Label undefLoopTop;
         masm.bind(&undefLoopTop);
 
         masm.push(r10);
         masm.subl(Imm32(1), rcx);
-
-        masm.testl(rcx, rcx);
         masm.j(Assembler::NonZero, &undefLoopTop);
     }
 
     // Get the topmost argument.
     BaseIndex b = BaseIndex(r9, r8, TimesEight, sizeof(IonRectifierFrameLayout));
     masm.lea(Operand(b), rcx);
 
     // Push arguments, |nargs| + 1 times (to include |this|).
+    masm.addl(Imm32(1), r8);
     {
-        Label copyLoopTop, initialSkip;
-
-        masm.jump(&initialSkip);
+        Label copyLoopTop;
 
         masm.bind(&copyLoopTop);
+        masm.push(Operand(rcx, 0x0));
         masm.subq(Imm32(sizeof(Value)), rcx);
         masm.subl(Imm32(1), r8);
-        masm.bind(&initialSkip);
-
-        masm.push(Operand(rcx, 0x0));
-
-        masm.testl(r8, r8);
         masm.j(Assembler::NonZero, &copyLoopTop);
     }
 
     // Construct descriptor.
     masm.subq(rsp, r9);
     masm.makeFrameDescriptor(r9, IonFrame_Rectifier);
 
     // Construct IonJSFrameLayout.
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -337,42 +337,35 @@ IonRuntime::generateArgumentsRectifier(J
     // Push undefined.
     {
         Label undefLoopTop;
         masm.bind(&undefLoopTop);
 
         masm.push(ebx); // type(undefined);
         masm.push(edi); // payload(undefined);
         masm.subl(Imm32(1), ecx);
-
-        masm.testl(ecx, ecx);
         masm.j(Assembler::NonZero, &undefLoopTop);
     }
 
     // Get the topmost argument. We did a push of %ebp earlier, so be sure to
     // account for this in the offset
     BaseIndex b = BaseIndex(FramePointer, esi, TimesEight,
                             sizeof(IonRectifierFrameLayout) + sizeof(void*));
     masm.lea(Operand(b), ecx);
 
     // Push arguments, |nargs| + 1 times (to include |this|).
+    masm.addl(Imm32(1), esi);
     {
-        Label copyLoopTop, initialSkip;
-
-        masm.jump(&initialSkip);
+        Label copyLoopTop;
 
         masm.bind(&copyLoopTop);
+        masm.push(Operand(ecx, sizeof(Value)/2));
+        masm.push(Operand(ecx, 0x0));
         masm.subl(Imm32(sizeof(Value)), ecx);
         masm.subl(Imm32(1), esi);
-        masm.bind(&initialSkip);
-
-        masm.push(Operand(ecx, sizeof(Value)/2));
-        masm.push(Operand(ecx, 0x0));
-
-        masm.testl(esi, esi);
         masm.j(Assembler::NonZero, &copyLoopTop);
     }
 
     // Construct descriptor, accounting for pushed frame pointer above
     masm.lea(Operand(FramePointer, sizeof(void*)), ebx);
     masm.subl(esp, ebx);
     masm.makeFrameDescriptor(ebx, IonFrame_Rectifier);
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2870,16 +2870,18 @@ JS_PUBLIC_API(bool)
 JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
 {
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, obj);
     *idp = OBJECT_TO_JSID(obj);
     return true;
 }
 
+namespace {
+
 class AutoHoldZone
 {
   public:
     explicit AutoHoldZone(Zone *zone
                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : holdp(&zone->hold)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
@@ -2890,16 +2892,18 @@ class AutoHoldZone
         *holdp = false;
     }
 
   private:
     bool *holdp;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
+} /* anonymous namespace */
+
 JS_PUBLIC_API(JSObject *)
 JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals,
                    JS::OnNewGlobalHookOption hookOption,
                    const JS::CompartmentOptions &options)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
@@ -4708,16 +4712,18 @@ ReadCompleteFile(JSContext *cx, FILE *fp
             break;
         if (!buffer.append(c))
             return false;
     }
 
     return true;
 }
 
+namespace {
+
 class AutoFile
 {
     FILE *fp_;
   public:
     AutoFile()
       : fp_(NULL)
     {}
     ~AutoFile()
@@ -4729,16 +4735,18 @@ class AutoFile
     bool open(JSContext *cx, const char *filename);
     bool readAll(JSContext *cx, FileContents &buffer)
     {
         JS_ASSERT(fp_);
         return ReadCompleteFile(cx, fp_, buffer);
     }
 };
 
+} /* anonymous namespace */
+
 /*
  * Open a source file for reading. Supports "-" and NULL to mean stdin. The
  * return value must be fclosed unless it is stdin.
  */
 bool
 AutoFile::open(JSContext *cx, const char *filename)
 {
     if (!filename || strcmp(filename, "-") == 0) {
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -826,32 +826,30 @@ js_ReportErrorNumberVA(JSContext *cx, un
 
     if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
                                  &message, &report, argumentsType, ap)) {
         return false;
     }
 
     ReportError(cx, message, &report, callback, userRef);
 
-    if (message)
-        js_free(message);
+    js_free(message);
     if (report.messageArgs) {
         /*
          * js_ExpandErrorArguments owns its messageArgs only if it had to
          * inflate the arguments (from regular |char *|s).
          */
         if (argumentsType == ArgumentsAreASCII) {
             int i = 0;
             while (report.messageArgs[i])
                 js_free((void *)report.messageArgs[i++]);
         }
         js_free((void *)report.messageArgs);
     }
-    if (report.ucmessage)
-        js_free((void *)report.ucmessage);
+    js_free((void *)report.ucmessage);
 
     return warning;
 }
 
 bool
 js_ReportErrorNumberUCArray(JSContext *cx, unsigned flags, JSErrorCallback callback,
                             void *userRef, const unsigned errorNumber,
                             const jschar **args)
@@ -871,20 +869,18 @@ js_ReportErrorNumberUCArray(JSContext *c
     va_list dummy;
     if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
                                  &message, &report, ArgumentsAreUnicode, dummy)) {
         return false;
     }
 
     ReportError(cx, message, &report, callback, userRef);
 
-    if (message)
-        js_free(message);
-    if (report.ucmessage)
-        js_free((void *)report.ucmessage);
+    js_free(message);
+    js_free((void *)report.ucmessage);
 
     return warning;
 }
 
 JS_FRIEND_API(void)
 js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
 {
     JSErrorReporter onError;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -4018,23 +4018,27 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocat
     }
 #endif
 
     FinishMarkingValidation(rt);
 
     rt->gcLastGCTime = PRMJ_Now();
 }
 
+namespace {
+
 /* ...while this class is to be used only for garbage collection. */
 class AutoGCSession : AutoTraceSession {
   public:
     explicit AutoGCSession(JSRuntime *rt);
     ~AutoGCSession();
 };
 
+} /* anonymous namespace */
+
 /* Start a new heap session. */
 AutoTraceSession::AutoTraceSession(JSRuntime *rt, js::HeapState heapState)
   : runtime(rt),
     prevState(rt->heapState),
     pause(rt)
 {
     JS_ASSERT(!rt->noGCOrAllocationCheck);
     JS_ASSERT(!rt->isHeapBusy());
@@ -4168,25 +4172,29 @@ ResetIncrementalGC(JSRuntime *rt, const 
     for (ZonesIter zone(rt); !zone.done(); zone.next()) {
         JS_ASSERT(!zone->needsBarrier());
         for (unsigned i = 0; i < FINALIZE_LIMIT; ++i)
             JS_ASSERT(!zone->allocator.arenas.arenaListsToSweep[i]);
     }
 #endif
 }
 
+namespace {
+
 class AutoGCSlice {
   public:
     AutoGCSlice(JSRuntime *rt);
     ~AutoGCSlice();
 
   private:
     JSRuntime *runtime;
 };
 
+} /* anonymous namespace */
+
 AutoGCSlice::AutoGCSlice(JSRuntime *rt)
   : runtime(rt)
 {
     /*
      * During incremental GC, the compartment's active flag determines whether
      * there are stack frames active for any of its scripts. Normally this flag
      * is set at the beginning of the mark phase. During incremental GC, we also
      * set it at the start of every phase.
@@ -4500,16 +4508,18 @@ ShouldCleanUpEverything(JSRuntime *rt, J
     // has changed; debug mode affects the results of bytecode analysis, so
     // we need to clear everything away.
     return !rt->hasContexts() ||
            reason == JS::gcreason::SHUTDOWN_CC ||
            reason == JS::gcreason::DEBUG_MODE_GC ||
            gckind == GC_SHRINK;
 }
 
+namespace {
+
 #ifdef JSGC_GENERATIONAL
 class AutoDisableStoreBuffer
 {
     JSRuntime *runtime;
     bool prior;
 
   public:
     AutoDisableStoreBuffer(JSRuntime *rt) : runtime(rt) {
@@ -4523,16 +4533,18 @@ class AutoDisableStoreBuffer
 };
 #else
 struct AutoDisableStoreBuffer
 {
     AutoDisableStoreBuffer(JSRuntime *) {}
 };
 #endif
 
+} /* anonymous namespace */
+
 static void
 Collect(JSRuntime *rt, bool incremental, int64_t budget,
         JSGCInvocationKind gckind, JS::gcreason::Reason reason)
 {
     /* GC shouldn't be running in parallel execution mode */
     JS_ASSERT(!InParallelSection());
 
     JS_AbortIfWrongThread(rt);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -563,16 +563,18 @@ TypeSet::unionSets(TypeSet *a, TypeSet *
 
     return res;
 }
 
 /////////////////////////////////////////////////////////////////////
 // TypeSet constraints
 /////////////////////////////////////////////////////////////////////
 
+namespace {
+
 /* Standard subset constraint, propagate all types from one set to another. */
 class TypeConstraintSubset : public TypeConstraint
 {
   public:
     TypeSet *target;
 
     TypeConstraintSubset(TypeSet *target)
         : target(target)
@@ -584,29 +586,33 @@ class TypeConstraintSubset : public Type
 
     void newType(JSContext *cx, TypeSet *source, Type type)
     {
         /* Basic subset constraint, move all types to the target. */
         target->addType(cx, type);
     }
 };
 
+} /* anonymous namespace */
+
 void
 StackTypeSet::addSubset(JSContext *cx, TypeSet *target)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintSubset>(target));
 }
 
 void
 HeapTypeSet::addSubset(JSContext *cx, TypeSet *target)
 {
     JS_ASSERT(!target->purged());
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintSubset>(target));
 }
 
+namespace {
+
 enum PropertyAccessKind {
     PROPERTY_WRITE,
     PROPERTY_READ,
     PROPERTY_READ_EXISTING
 };
 
 /* Constraints for reads/writes on object properties. */
 template <PropertyAccessKind access>
@@ -636,16 +642,18 @@ class TypeConstraintProp : public TypeCo
 
     void newType(JSContext *cx, TypeSet *source, Type type);
 };
 
 typedef TypeConstraintProp<PROPERTY_WRITE> TypeConstraintSetProperty;
 typedef TypeConstraintProp<PROPERTY_READ>  TypeConstraintGetProperty;
 typedef TypeConstraintProp<PROPERTY_READ_EXISTING> TypeConstraintGetPropertyExisting;
 
+} /* anonymous namespace */
+
 void
 StackTypeSet::addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
                              StackTypeSet *target, jsid id)
 {
     /*
      * GetProperty constraints are normally used with property read input type
      * sets, except for array_pop/array_shift special casing.
      */
@@ -664,16 +672,18 @@ StackTypeSet::addSetProperty(JSContext *
 void
 HeapTypeSet::addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
                             StackTypeSet *target, jsid id)
 {
     JS_ASSERT(!target->purged());
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintGetProperty>(script, pc, target, id));
 }
 
+namespace {
+
 /*
  * Constraints for updating the 'this' types of callees on CALLPROP/CALLELEM.
  * These are derived from the types on the properties themselves, rather than
  * those pushed in the 'this' slot at the call site, which allows us to retain
  * correlations between the type of the 'this' object and the associated
  * callee scripts at polymorphic call sites.
  */
 template <PropertyAccessKind access>
@@ -696,31 +706,35 @@ class TypeConstraintCallProp : public Ty
     const char *kind() { return "callprop"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
 };
 
 typedef TypeConstraintCallProp<PROPERTY_READ> TypeConstraintCallProperty;
 typedef TypeConstraintCallProp<PROPERTY_READ_EXISTING> TypeConstraintCallPropertyExisting;
 
+} /* anonymous namespace */
+
 void
 HeapTypeSet::addCallProperty(JSContext *cx, JSScript *script, jsbytecode *pc, jsid id)
 {
     /*
      * For calls which will go through JSOP_NEW, don't add any constraints to
      * modify the 'this' types of callees. The initial 'this' value will be
      * outright ignored.
      */
     jsbytecode *callpc = script->analysis()->getCallPC(pc);
     if (JSOp(*callpc) == JSOP_NEW)
         return;
 
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintCallProperty>(script, callpc, id));
 }
 
+namespace {
+
 /*
  * Constraints for generating 'set' property constraints on a SETELEM only if
  * the element type may be a number. For SETELEM we only account for integer
  * indexes, and if the element cannot be an integer (e.g. it must be a string)
  * then we lose precision by treating it like one.
  */
 class TypeConstraintSetElement : public TypeConstraint
 {
@@ -740,24 +754,28 @@ class TypeConstraintSetElement : public 
         JS_ASSERT(script && pc);
     }
 
     const char *kind() { return "setelement"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
 };
 
+} /* anonymous namespace */
+
 void
 StackTypeSet::addSetElement(JSContext *cx, JSScript *script, jsbytecode *pc,
                             StackTypeSet *objectTypes, StackTypeSet *valueTypes)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintSetElement>(script, pc, objectTypes,
                                                                    valueTypes));
 }
 
+namespace {
+
 /*
  * Constraints for watching call edges as they are discovered and invoking native
  * function handlers, adding constraints for arguments, receiver objects and the
  * return value, and updating script foundOffsets.
  */
 class TypeConstraintCall : public TypeConstraint
 {
   public:
@@ -768,22 +786,26 @@ class TypeConstraintCall : public TypeCo
         : callsite(callsite)
     {}
 
     const char *kind() { return "call"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
 };
 
+} /* anonymous namespace */
+
 void
 StackTypeSet::addCall(JSContext *cx, TypeCallsite *site)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintCall>(site));
 }
 
+namespace {
+
 /* Constraints for arithmetic operations. */
 class TypeConstraintArith : public TypeConstraint
 {
     JSScript *script_;
 
   public:
     jsbytecode *pc;
 
@@ -799,23 +821,27 @@ class TypeConstraintArith : public TypeC
         JS_ASSERT(target);
     }
 
     const char *kind() { return "arith"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
 };
 
+} /* anonymous namespace */
+
 void
 StackTypeSet::addArith(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target,
                        TypeSet *other)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintArith>(script, pc, target, other));
 }
 
+namespace {
+
 /* Subset constraint which transforms primitive values into appropriate objects. */
 class TypeConstraintTransformThis : public TypeConstraint
 {
     JSScript *script_;
 
   public:
     TypeSet *target;
 
@@ -823,22 +849,26 @@ class TypeConstraintTransformThis : publ
         : script_(script), target(target)
     {}
 
     const char *kind() { return "transformthis"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
 };
 
+} /* anonymous namespace */
+
 void
 StackTypeSet::addTransformThis(JSContext *cx, JSScript *script, TypeSet *target)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintTransformThis>(script, target));
 }
 
+namespace {
+
 /*
  * Constraint which adds a particular type to the 'this' types of all
  * discovered scripted functions.
  */
 class TypeConstraintPropagateThis : public TypeConstraint
 {
     JSScript *script_;
 
@@ -851,23 +881,27 @@ class TypeConstraintPropagateThis : publ
         : script_(script), callpc(callpc), type(type), types(types)
     {}
 
     const char *kind() { return "propagatethis"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
 };
 
+} /* anonymous namespace */
+
 void
 StackTypeSet::addPropagateThis(JSContext *cx, JSScript *script, jsbytecode *pc,
                                Type type, StackTypeSet *types)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintPropagateThis>(script, pc, type, types));
 }
 
+namespace {
+
 /* Subset constraint which filters out primitive types. */
 class TypeConstraintFilterPrimitive : public TypeConstraint
 {
   public:
     TypeSet *target;
 
     TypeConstraintFilterPrimitive(TypeSet *target)
         : target(target)
@@ -879,16 +913,18 @@ class TypeConstraintFilterPrimitive : pu
     {
         if (type.isPrimitive())
             return;
 
         target->addType(cx, type);
     }
 };
 
+} /* anonymous namespace */
+
 void
 HeapTypeSet::addFilterPrimitives(JSContext *cx, TypeSet *target)
 {
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintFilterPrimitive>(target));
 }
 
 /* If id is a normal slotful 'own' property of an object, get its shape. */
 static inline Shape *
@@ -989,16 +1025,18 @@ void ScriptAnalysis::breakTypeBarriersSS
 
     uint32_t offset = v.pushedOffset();
     if (JSOp(script_->code[offset]) == JSOP_GETPROP)
         breakTypeBarriersSSA(cx, poppedValue(offset, 0));
 
     breakTypeBarriers(cx, offset, true);
 }
 
+namespace {
+
 /*
  * Subset constraint for property reads and argument passing which can add type
  * barriers on the read instead of passing types along.
  */
 class TypeConstraintSubsetBarrier : public TypeConstraint
 {
   public:
     JSScript *script;
@@ -1016,16 +1054,18 @@ class TypeConstraintSubsetBarrier : publ
         if (!target->hasType(type)) {
             if (!script->ensureRanAnalysis(cx))
                 return;
             script->analysis()->addTypeBarrier(cx, pc, target, type);
         }
     }
 };
 
+} /* anonymous namespace */
+
 void
 StackTypeSet::addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintSubsetBarrier>(script, pc, target));
 }
 
 void
 HeapTypeSet::addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target)
@@ -1629,16 +1669,18 @@ TypeConstraintTransformThis::newType(JSC
 
     target->addType(cx, Type::ObjectType(object));
 }
 
 /////////////////////////////////////////////////////////////////////
 // Freeze constraints
 /////////////////////////////////////////////////////////////////////
 
+namespace {
+
 /* Constraint which triggers recompilation of a script if any type is added to a type set. */
 class TypeConstraintFreeze : public TypeConstraint
 {
   public:
     RecompileInfo info;
 
     /* Whether a new type has already been added, triggering recompilation. */
     bool typeAdded;
@@ -1654,16 +1696,18 @@ class TypeConstraintFreeze : public Type
         if (typeAdded)
             return;
 
         typeAdded = true;
         cx->compartment()->types.addPendingRecompile(cx, info);
     }
 };
 
+} /* anonymous namespace */
+
 void
 HeapTypeSet::addFreeze(JSContext *cx)
 {
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreeze>(
                 cx->compartment()->types.compiledInfo), false);
 }
 
 static inline JSValueType
@@ -1749,16 +1793,18 @@ StackTypeSet::mightBeType(JSValueType ty
         return true;
 
     if (type == JSVAL_TYPE_OBJECT)
         return unknownObject() || baseObjectCount() != 0;
 
     return baseFlags() & PrimitiveTypeFlag(type);
 }
 
+namespace {
+
 /* Constraint which triggers recompilation if an object acquires particular flags. */
 class TypeConstraintFreezeObjectFlags : public TypeConstraint
 {
   public:
     RecompileInfo info;
 
     /* Flags we are watching for on this object. */
     TypeObjectFlags flags;
@@ -1779,16 +1825,18 @@ class TypeConstraintFreezeObjectFlags : 
     {
         if (!marked && (object->hasAnyFlags(flags) || (!flags && force))) {
             marked = true;
             cx->compartment()->types.addPendingRecompile(cx, info);
         }
     }
 };
 
+} /* anonymous namespace */
+
 bool
 StackTypeSet::hasObjectFlags(JSContext *cx, TypeObjectFlags flags)
 {
     if (unknownObject())
         return true;
 
     /*
      * Treat type sets containing no objects as having all object flags,
@@ -1876,16 +1924,18 @@ HeapTypeSet::WatchObjectStateChange(JSCo
      * Use a constraint which triggers recompilation when markStateChange is
      * called, which will set 'force' to true.
      */
     types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeObjectFlags>(
                      cx->compartment()->types.compiledInfo,
                      0));
 }
 
+namespace {
+
 class TypeConstraintFreezeOwnProperty : public TypeConstraint
 {
   public:
     RecompileInfo info;
 
     bool updated;
     bool configurable;
 
@@ -1903,16 +1953,18 @@ class TypeConstraintFreezeOwnProperty : 
             return;
         if (source->ownProperty(configurable)) {
             updated = true;
             cx->compartment()->types.addPendingRecompile(cx, info);
         }
     }
 };
 
+} /* anonymous namespace */
+
 static void
 CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, HandleFunction fun);
 
 bool
 HeapTypeSet::isOwnProperty(JSContext *cx, TypeObject *object, bool configurable)
 {
     /*
      * Everywhere compiled code depends on definite properties associated with
@@ -2212,16 +2264,18 @@ StackTypeSet::propertyNeedsBarrier(JSCon
  * which this script was inlined into.
  */
 static inline void
 AddPendingRecompile(JSContext *cx, JSScript *script)
 {
     cx->compartment()->types.addPendingRecompile(cx, script);
 }
 
+namespace {
+
 /*
  * As for TypeConstraintFreeze, but describes an implicit freeze constraint
  * added for stack types within a script. Applies to all compilations of the
  * script, not just a single one.
  */
 class TypeConstraintFreezeStack : public TypeConstraint
 {
     JSScript *script_;
@@ -2238,16 +2292,18 @@ class TypeConstraintFreezeStack : public
         /*
          * Unlike TypeConstraintFreeze, triggering this constraint once does
          * not disable it on future changes to the type set.
          */
         AddPendingRecompile(cx, script_);
     }
 };
 
+} /* anonymous namespace */
+
 /////////////////////////////////////////////////////////////////////
 // TypeCompartment
 /////////////////////////////////////////////////////////////////////
 
 TypeCompartment::TypeCompartment()
 {
     PodZero(this);
     compiledInfo.outputIndex = RecompileInfo::NoCompilerRunning;
@@ -4740,16 +4796,18 @@ ScriptAnalysis::analyzeTypes(JSContext *
             state.forTypes->addType(cx, Type::UnknownType());
         }
         result = result->next;
     }
 
     TypeScript::AddFreezeConstraints(cx, script_);
 }
 
+namespace {
+
 /*
  * Persistent constraint clearing out newScript and definite properties from
  * an object should a property on another object get a getter or setter.
  */
 class TypeConstraintClearDefiniteGetterSetter : public TypeConstraint
 {
   public:
     TypeObject *object;
@@ -4772,16 +4830,18 @@ class TypeConstraintClearDefiniteGetterS
          */
         if (!(object->flags & OBJECT_FLAG_ADDENDUM_CLEARED) && source->ownProperty(true))
             object->clearAddendum(cx);
     }
 
     void newType(JSContext *cx, TypeSet *source, Type type) {}
 };
 
+} /* anonymous namespace */
+
 static bool
 AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, TypeObject *type, jsid id)
 {
     /*
      * Ensure that if the properties named here could have a getter, setter or
      * a permanent property in any transitive prototype, the definite
      * properties get cleared from the shape.
      */
@@ -4794,16 +4854,18 @@ AddClearDefiniteGetterSetterForPrototype
         if (!parentTypes || parentTypes->ownProperty(true))
             return false;
         parentTypes->add(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(type));
         parent = parent->getProto();
     }
     return true;
 }
 
+namespace {
+
 /*
  * Constraint which clears definite properties on an object should a type set
  * contain any types other than a single object.
  */
 class TypeConstraintClearDefiniteSingle : public TypeConstraint
 {
   public:
     TypeObject *object;
@@ -4830,16 +4892,18 @@ struct NewScriptPropertiesState
     Vector<TypeNewScript::Initializer> initializerList;
     Vector<jsid> accessedProperties;
 
     NewScriptPropertiesState(JSContext *cx)
       : thisFunction(cx), baseobj(cx), initializerList(cx), accessedProperties(cx)
     {}
 };
 
+} /* anonymous namespace */
+
 static bool
 AnalyzePoppedThis(JSContext *cx, SSAUseChain *use,
                   TypeObject *type, JSFunction *fun, NewScriptPropertiesState &state);
 
 static bool
 AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, HandleFunction fun,
                            NewScriptPropertiesState &state)
 {
@@ -6381,27 +6445,20 @@ JSCompartment::sweepNewTypeObjectTable(T
             else if (type != e.front())
                 e.rekeyFront(TypeObjectSet::Lookup(type->clasp, type->proto.get()), type);
         }
     }
 }
 
 TypeCompartment::~TypeCompartment()
 {
-    if (pendingArray)
-        js_free(pendingArray);
-
-    if (arrayTypeTable)
-        js_delete(arrayTypeTable);
-
-    if (objectTypeTable)
-        js_delete(objectTypeTable);
-
-    if (allocationSiteTable)
-        js_delete(allocationSiteTable);
+    js_free(pendingArray);
+    js_delete(arrayTypeTable);
+    js_delete(objectTypeTable);
+    js_delete(allocationSiteTable);
 }
 
 /* static */ void
 TypeScript::Sweep(FreeOp *fop, JSScript *script)
 {
     JSCompartment *compartment = script->compartment();
     JS_ASSERT(compartment->zone()->isGCSweeping());
     JS_ASSERT(compartment->zone()->types.inferenceEnabled);
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1161,25 +1161,29 @@ SuppressDeletedPropertyHelper(JSContext 
                 }
             }
         }
         ni = ni->next();
     }
     return true;
 }
 
+namespace {
+
 class SingleStringPredicate {
     Handle<JSFlatString*> str;
 public:
     SingleStringPredicate(Handle<JSFlatString*> str) : str(str) {}
 
     bool operator()(JSFlatString *str) { return EqualStrings(str, this->str); }
     bool matchesAtMostOne() { return true; }
 };
 
+} /* anonymous namespace */
+
 bool
 js_SuppressDeletedProperty(JSContext *cx, HandleObject obj, jsid id)
 {
     Rooted<JSFlatString*> str(cx, IdToString(cx, id));
     if (!str)
         return false;
     return SuppressDeletedPropertyHelper(cx, obj, SingleStringPredicate(str));
 }
@@ -1188,30 +1192,34 @@ bool
 js_SuppressDeletedElement(JSContext *cx, HandleObject obj, uint32_t index)
 {
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return js_SuppressDeletedProperty(cx, obj, id);
 }
 
+namespace {
+
 class IndexRangePredicate {
     uint32_t begin, end;
 
   public:
     IndexRangePredicate(uint32_t begin, uint32_t end) : begin(begin), end(end) {}
 
     bool operator()(JSFlatString *str) {
         uint32_t index;
         return str->isIndex(&index) && begin <= index && index < end;
     }
 
     bool matchesAtMostOne() { return false; }
 };
 
+} /* anonymous namespace */
+
 bool
 js_SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end)
 {
     return SuppressDeletedPropertyHelper(cx, obj, IndexRangePredicate(begin, end));
 }
 
 static inline bool
 IsStopIteration(const js::Value &v)
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -80,16 +80,18 @@ ComputeAccurateDecimalInteger(ThreadSafe
         return false;
     }
     if (err == JS_DTOA_ERANGE && *dp == HUGE_VAL)
         *dp = js_PositiveInfinity;
     js_free(cstr);
     return true;
 }
 
+namespace {
+
 class BinaryDigitReader
 {
     const int base;      /* Base of number; must be a power of 2 */
     int digit;           /* Current digit value in radix given by base */
     int digitMask;       /* Mask to extract the next bit from digit */
     const jschar *start; /* Pointer to the remaining digits */
     const jschar *end;   /* Pointer to first non-digit */
 
@@ -117,16 +119,18 @@ class BinaryDigitReader
         }
 
         int bit = (digit & digitMask) != 0;
         digitMask >>= 1;
         return bit;
     }
 };
 
+} /* anonymous namespace */
+
 /*
  * The fast result might also have been inaccurate for power-of-two bases. This
  * happens if the addition in value * 2 + digit causes a round-down to an even
  * least significant mantissa bit when the first dropped bit is a one.  If any
  * of the following digits in the number (which haven't been added in yet) are
  * nonzero, then the correct action would have been to round up instead of
  * down.  An example occurs when reading the number 0x1000000000000081, which
  * rounds to 0x1000000000000000 instead of 0x1000000000000100.
@@ -527,18 +531,17 @@ num_toSource(JSContext *cx, unsigned arg
 
 ToCStringBuf::ToCStringBuf() :dbuf(NULL)
 {
     JS_STATIC_ASSERT(sbufSize >= DTOSTR_STANDARD_BUFFER_SIZE);
 }
 
 ToCStringBuf::~ToCStringBuf()
 {
-    if (dbuf)
-        js_free(dbuf);
+    js_free(dbuf);
 }
 
 template <AllowGC allowGC>
 JSFlatString *
 js::Int32ToString(ThreadSafeContext *cx, int32_t si)
 {
     uint32_t ui;
     if (si >= 0) {
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1863,20 +1863,18 @@ struct JSObject::TradeGutsReserved {
         : avals(cx), bvals(cx),
           newafixed(0), newbfixed(0),
           newashape(cx), newbshape(cx),
           newaslots(NULL), newbslots(NULL)
     {}
 
     ~TradeGutsReserved()
     {
-        if (newaslots)
-            js_free(newaslots);
-        if (newbslots)
-            js_free(newbslots);
+        js_free(newaslots);
+        js_free(newbslots);
     }
 };
 
 bool
 JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *aArg, JSObject *bArg,
                               TradeGutsReserved &reserved)
 {
     /*
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -110,16 +110,18 @@ Quote(JSContext *cx, StringBuffer &sb, J
                 return false;
         }
     }
 
     /* Steps 3-4. */
     return sb.append('"');
 }
 
+namespace {
+
 class StringifyContext
 {
   public:
     StringifyContext(JSContext *cx, StringBuffer &sb, const StringBuffer &gap,
                      HandleObject replacer, const AutoIdVector &propertyList)
       : sb(sb),
         gap(gap),
         replacer(cx, replacer),
@@ -129,16 +131,18 @@ class StringifyContext
 
     StringBuffer &sb;
     const StringBuffer &gap;
     RootedObject replacer;
     const AutoIdVector &propertyList;
     uint32_t depth;
 };
 
+} /* anonymous namespace */
+
 static bool Str(JSContext *cx, const Value &v, StringifyContext *scx);
 
 static bool
 WriteIndent(JSContext *cx, StringifyContext *scx, uint32_t limit)
 {
     if (!scx->gap.empty()) {
         if (!scx->sb.append('\n'))
             return false;
@@ -146,16 +150,18 @@ WriteIndent(JSContext *cx, StringifyCont
             if (!scx->sb.append(scx->gap.begin(), scx->gap.end()))
                 return false;
         }
     }
 
     return true;
 }
 
+namespace {
+
 template<typename KeyType>
 class KeyStringifier {
 };
 
 template<>
 class KeyStringifier<uint32_t> {
   public:
     static JSString *toString(JSContext *cx, uint32_t index) {
@@ -166,16 +172,18 @@ class KeyStringifier<uint32_t> {
 template<>
 class KeyStringifier<HandleId> {
   public:
     static JSString *toString(JSContext *cx, HandleId id) {
         return IdToString(cx, id);
     }
 };
 
+} /* anonymous namespace */
+
 /*
  * ES5 15.12.3 Str, steps 2-4, extracted to enable preprocessing of property
  * values when stringifying objects in JO.
  */
 template<typename KeyType>
 static bool
 PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleValue vp, StringifyContext *scx)
 {
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -1082,29 +1082,33 @@ GetBlockChainAtPC(JSContext *cx, JSScrip
           default:
             break;
         }
     }
 
     return blockChain;
 }
 
+namespace {
+
 class PCStack
 {
     jsbytecode **stack;
     int depth_;
 
   public:
     PCStack() : stack(NULL), depth_(0) {}
     ~PCStack();
     bool init(JSContext *cx, JSScript *script, jsbytecode *pc);
     int depth() const { return depth_; }
     jsbytecode *operator[](int i) const;
 };
 
+} /* anonymous namespace */
+
 PCStack::~PCStack()
 {
     js_free(stack);
 }
 
 bool
 PCStack::init(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
--- a/js/src/jsprf.cpp
+++ b/js/src/jsprf.cpp
@@ -1048,21 +1048,17 @@ static int GrowStuff(SprintfState *ss, c
     ptrdiff_t off;
     char *newbase;
     uint32_t newlen;
 
     off = ss->cur - ss->base;
     if (off + len >= ss->maxlen) {
         /* Grow the buffer */
         newlen = ss->maxlen + ((len > 32) ? len : 32);
-        if (ss->base) {
-            newbase = (char*) js_realloc(ss->base, newlen);
-        } else {
-            newbase = (char*) js_malloc(newlen);
-        }
+        newbase = (char*) js_realloc(ss->base, newlen);
         if (!newbase) {
             /* Ran out of memory */
             return -1;
         }
         ss->base = newbase;
         ss->maxlen = newlen;
         ss->cur = ss->base + off;
     }
@@ -1104,19 +1100,17 @@ JS_PUBLIC_API(char *) JS_vsmprintf(const
     int rv;
 
     ss.stuff = GrowStuff;
     ss.base = 0;
     ss.cur = 0;
     ss.maxlen = 0;
     rv = dosprintf(&ss, fmt, ap);
     if (rv < 0) {
-        if (ss.base) {
-            js_free(ss.base);
-        }
+        js_free(ss.base);
         return 0;
     }
     return ss.base;
 }
 
 /*
 ** Stuff routine that discards overflow data
 */
@@ -1203,16 +1197,14 @@ JS_PUBLIC_API(char *) JS_vsprintf_append
         ss.maxlen = lastlen;
     } else {
         ss.base = 0;
         ss.cur = 0;
         ss.maxlen = 0;
     }
     rv = dosprintf(&ss, fmt, ap);
     if (rv < 0) {
-        if (ss.base) {
-            js_free(ss.base);
-        }
+        js_free(ss.base);
         return 0;
     }
     return ss.base;
 }
 
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -741,16 +741,18 @@ FunctionProxyObject::construct()
 inline Value
 FunctionProxyObject::constructOrUndefined() const
 {
     if (slotSpan() <= CONSTRUCT_SLOT)
         return UndefinedValue();
     return getSlot(CONSTRUCT_SLOT);
 }
 
+namespace {
+
 /* Derived class for all scripted indirect proxy handlers. */
 class ScriptedIndirectProxyHandler : public BaseProxyHandler
 {
   public:
     ScriptedIndirectProxyHandler();
     virtual ~ScriptedIndirectProxyHandler();
 
     /* ES5 Harmony fundamental proxy traps. */
@@ -786,16 +788,18 @@ class ScriptedIndirectProxyHandler : pub
                             CallArgs args) MOZ_OVERRIDE;
     virtual JSString *fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) MOZ_OVERRIDE;
     virtual bool defaultValue(JSContext *cx, HandleObject obj, JSType hint,
                               MutableHandleValue vp) MOZ_OVERRIDE;
 
     static ScriptedIndirectProxyHandler singleton;
 };
 
+} /* anonymous namespace */
+
 static int sScriptedIndirectProxyHandlerFamily = 0;
 
 ScriptedIndirectProxyHandler::ScriptedIndirectProxyHandler()
         : BaseProxyHandler(&sScriptedIndirectProxyHandlerFamily)
 {
 }
 
 ScriptedIndirectProxyHandler::~ScriptedIndirectProxyHandler()
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -115,16 +115,18 @@ typedef AutoValueVector NodeVector;
 
 #define LOCAL_NOT_REACHED(expr)                                                        \
     JS_BEGIN_MACRO                                                                     \
         MOZ_ASSERT(false);                                                             \
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PARSE_NODE);      \
         return false;                                                                  \
     JS_END_MACRO
 
+namespace {
+
 /*
  * Builder class that constructs JavaScript AST node objects. See:
  *
  *     https://developer.mozilla.org/en/SpiderMonkey/Parser_API
  *
  * Bug 569487: generalize builder interface
  */
 class NodeBuilder
@@ -610,16 +612,18 @@ class NodeBuilder
 
     bool arrayPattern(NodeVector &elts, TokenPos *pos, MutableHandleValue dst);
 
     bool objectPattern(NodeVector &elts, TokenPos *pos, MutableHandleValue dst);
 
     bool propertyPattern(HandleValue key, HandleValue patt, TokenPos *pos, MutableHandleValue dst);
 };
 
+} /* anonymous namespace */
+
 bool
 NodeBuilder::newNode(ASTType type, TokenPos *pos, MutableHandleObject dst)
 {
     JS_ASSERT(type > AST_ERROR && type < AST_LIMIT);
 
     RootedValue tv(cx);
     RootedObject node(cx, NewBuiltinClassInstance(cx, &JSObject::class_));
     if (!node ||
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2974,16 +2974,18 @@ DebuggerScript_getOffsetLine(JSContext *
     size_t offset;
     if (!ScriptOffset(cx, script, args[0], &offset))
         return false;
     unsigned lineno = JS_PCToLineNumber(cx, script, script->code + offset);
     args.rval().setNumber(lineno);
     return true;
 }
 
+namespace {
+
 class BytecodeRangeWithPosition : private BytecodeRange
 {
   public:
     using BytecodeRange::empty;
     using BytecodeRange::frontPC;
     using BytecodeRange::frontOpcode;
     using BytecodeRange::frontOffset;
 
@@ -3202,16 +3204,18 @@ class FlowGraphSummary {
             entries_[targetOffset] = Entry::createWithMultipleEdgesFromMultipleLines();
         else if (entries_[targetOffset].column() != sourceColumn)
             entries_[targetOffset] = Entry::createWithMultipleEdgesFromSingleLine(sourceLineno);
     }
 
     Vector<Entry> entries_;
 };
 
+} /* anonymous namespace */
+
 static bool
 DebuggerScript_getAllOffsets(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "getAllOffsets", args, obj, script);
 
     /*
      * First pass: determine which offsets in this script are jump targets and
      * which line numbers jump to them.
--- a/js/src/vm/OldDebugAPI.cpp
+++ b/js/src/vm/OldDebugAPI.cpp
@@ -999,16 +999,18 @@ JS::DescribeStack(JSContext *cx, unsigne
 
 JS_PUBLIC_API(void)
 JS::FreeStackDescription(JSContext *cx, JS::StackDescription *desc)
 {
     js_delete(desc->frames);
     js_delete(desc);
 }
 
+namespace {
+
 class AutoPropertyDescArray
 {
     JSContext *cx_;
     JSPropertyDescArray descArray_;
 
   public:
     AutoPropertyDescArray(JSContext *cx)
       : cx_(cx)
@@ -1027,16 +1029,18 @@ class AutoPropertyDescArray
             descArray_.array = NULL;
     }
 
     JSPropertyDescArray * operator ->() {
         return &descArray_;
     }
 };
 
+} /* anonymous namespace */
+
 static const char *
 FormatValue(JSContext *cx, const Value &vArg, JSAutoByteString &bytes)
 {
     RootedValue v(cx, vArg);
     JSString *str = ToString<CanGC>(cx, v);
     if (!str)
         return NULL;
     const char *buf = bytes.encodeLatin1(cx, str);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -388,18 +388,17 @@ RegExpShared::RegExpShared(JSAtom *sourc
     bytecode(NULL), activeUseCount(0), gcNumberWhenUsed(gcNumber)
 {}
 
 RegExpShared::~RegExpShared()
 {
 #if ENABLE_YARR_JIT
     codeBlock.release();
 #endif
-    if (bytecode)
-        js_delete<BytecodePattern>(bytecode);
+    js_delete<BytecodePattern>(bytecode);
 }
 
 void
 RegExpShared::reportYarrError(ExclusiveContext *cx, TokenStream *ts, ErrorCode error)
 {
     switch (error) {
       case JSC::Yarr::NoError:
         MOZ_ASSUME_UNREACHABLE("Called reportYarrError with value for no error");
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -385,18 +385,17 @@ JSRuntime::init(uint32_t maxbytes)
     return true;
 }
 
 JSRuntime::~JSRuntime()
 {
     mainThread.removeFromThreadList();
 
 #ifdef JS_WORKER_THREADS
-    if (workerThreadState)
-        js_delete(workerThreadState);
+    js_delete(workerThreadState);
 
     JS_ASSERT(!exclusiveAccessOwner);
     if (exclusiveAccessLock)
         PR_DestroyLock(exclusiveAccessLock);
 
     JS_ASSERT(!numExclusiveThreads);
 
     // Avoid bogus asserts during teardown.
@@ -446,18 +445,17 @@ JSRuntime::~JSRuntime()
 
     js_delete(bumpAlloc_);
     js_delete(mathCache_);
 #ifdef JS_ION
     js_delete(ionRuntime_);
 #endif
     js_delete(execAlloc_);  /* Delete after ionRuntime_. */
 
-    if (ionPcScriptCache)
-        js_delete(ionPcScriptCache);
+    js_delete(ionPcScriptCache);
 
 #ifdef JSGC_GENERATIONAL
     gcStoreBuffer.disable();
     gcNursery.disable();
 #endif
 
     DebugOnly<size_t> oldCount = liveRuntimesCount--;
     JS_ASSERT(oldCount > 0);
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -1133,16 +1133,18 @@ ScopeIterKey::match(ScopeIterKey si1, Sc
            (!si1.frame_ ||
             (si1.cur_   == si2.cur_   &&
              si1.block_ == si2.block_ &&
              si1.type_  == si2.type_));
 }
 
 /*****************************************************************************/
 
+namespace {
+
 /*
  * DebugScopeProxy is the handler for DebugScopeObject proxy objects. Having a
  * custom handler (rather than trying to reuse js::Wrapper) gives us several
  * important abilities:
  *  - We want to pass the ScopeObject as the receiver to forwarded scope
  *    property ops on aliased variables so that Call/Block/With ops do not all
  *    require a 'normalization' step.
  *  - The debug scope proxy can directly manipulate the stack frame to allow
@@ -1527,16 +1529,18 @@ class DebugScopeProxy : public BaseProxy
     bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE
     {
         RootedValue idval(cx, IdToValue(id));
         return js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_CANT_DELETE,
                                         JSDVG_IGNORE_STACK, idval, NullPtr(), NULL, NULL);
     }
 };
 
+} /* anonymous namespace */
+
 int DebugScopeProxy::family = 0;
 DebugScopeProxy DebugScopeProxy::singleton;
 
 /* static */ DebugScopeObject *
 DebugScopeObject::create(JSContext *cx, ScopeObject &scope, HandleObject enclosing)
 {
     JS_ASSERT(scope.compartment() == cx->compartment());
     RootedValue priv(cx, ObjectValue(scope));
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -961,37 +961,41 @@ JSStructuredCloneReader::checkDouble(dou
     if (!JSVAL_IS_DOUBLE_IMPL(l)) {
         JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL,
                              JSMSG_SC_BAD_SERIALIZED_DATA, "unrecognized NaN");
         return false;
     }
     return true;
 }
 
+namespace {
+
 class Chars {
     JSContext *cx;
     jschar *p;
   public:
     Chars(JSContext *cx) : cx(cx), p(NULL) {}
-    ~Chars() { if (p) js_free(p); }
+    ~Chars() { js_free(p); }
 
     bool allocate(size_t len) {
         JS_ASSERT(!p);
         // We're going to null-terminate!
         p = cx->pod_malloc<jschar>(len + 1);
         if (p) {
             p[len] = jschar(0);
             return true;
         }
         return false;
     }
     jschar *get() { return p; }
     void forget() { p = NULL; }
 };
 
+} /* anonymous namespace */
+
 JSString *
 JSStructuredCloneReader::readString(uint32_t nchars)
 {
     if (nchars > JSString::MAX_LENGTH) {
         JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA,
                              "string length");
         return NULL;
     }
--- a/js/src/vm/ThreadPool.cpp
+++ b/js/src/vm/ThreadPool.cpp
@@ -19,17 +19,17 @@ using namespace js;
 /////////////////////////////////////////////////////////////////////////////
 // ThreadPoolWorker
 //
 // Each |ThreadPoolWorker| just hangs around waiting for items to be added
 // to its |worklist_|.  Whenever something is added, it gets executed.
 // Once the worker's state is set to |TERMINATING|, the worker will
 // exit as soon as its queue is empty.
 
-const size_t WORKER_THREAD_STACK_SIZE = 1*1024*1024;
+static const size_t WORKER_THREAD_STACK_SIZE = 1*1024*1024;
 
 class js::ThreadPoolWorker : public Monitor
 {
     const size_t workerId_;
 
     // Current point in the worker's lifecycle.
     //
     // Modified only while holding the ThreadPoolWorker's lock.
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -1402,34 +1402,34 @@ template<> inline const int TypeIDOfType
 template<> inline const int TypeIDOfType<double>() { return ScalarTypeRepresentation::TYPE_FLOAT64; }
 template<> inline const int TypeIDOfType<uint8_clamped>() { return ScalarTypeRepresentation::TYPE_UINT8_CLAMPED; }
 
 template<typename NativeType> static inline const bool ElementTypeMayBeDouble() { return false; }
 template<> inline const bool ElementTypeMayBeDouble<uint32_t>() { return true; }
 template<> inline const bool ElementTypeMayBeDouble<float>() { return true; }
 template<> inline const bool ElementTypeMayBeDouble<double>() { return true; }
 
-template<typename NativeType> class TypedArrayObjectTemplate;
-
 template<typename ElementType>
 static inline JSObject *
 NewArray(JSContext *cx, uint32_t nelements);
 
 static inline void
 InitArrayBufferViewDataPointer(JSObject *obj, ArrayBufferObject *buffer, size_t byteOffset)
 {
     /*
      * N.B. The base of the array's data is stored in the object's
      * private data rather than a slot to avoid alignment restrictions
      * on private Values.
      */
     obj->initPrivate(buffer->dataPointer() + byteOffset);
     PostBarrierTypedArrayObject(obj);
 }
 
+namespace {
+
 template<typename NativeType>
 class TypedArrayObjectTemplate : public TypedArrayObject
 {
   public:
     typedef NativeType ThisType;
     typedef TypedArrayObjectTemplate<NativeType> ThisTypedArrayObject;
     static const int ArrayTypeID() { return TypeIDOfType<NativeType>(); }
     static const bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
@@ -2614,16 +2614,18 @@ class Float64ArrayObject : public TypedA
 };
 class Uint8ClampedArrayObject : public TypedArrayObjectTemplate<uint8_clamped> {
   public:
     enum { ACTUAL_TYPE = ScalarTypeRepresentation::TYPE_UINT8_CLAMPED };
     static const JSProtoKey key = JSProto_Uint8ClampedArray;
     static const JSFunctionSpec jsfuncs[];
 };
 
+} /* anonymous namespace */
+
 template<typename T>
 bool
 ArrayBufferObject::createTypedArrayFromBufferImpl(JSContext *cx, CallArgs args)
 {
     typedef TypedArrayObjectTemplate<T> ArrayType;
     JS_ASSERT(IsArrayBuffer(args.thisv()));
     JS_ASSERT(args.length() == 3);
 
@@ -2677,16 +2679,18 @@ void
 TypedArrayObjectTemplate<NativeType>::copyIndexToValue(JSObject *tarray, uint32_t index,
                                                        MutableHandleValue vp)
 {
     JS_STATIC_ASSERT(sizeof(NativeType) < 4);
 
     vp.setInt32(getIndex(tarray, index));
 }
 
+namespace {
+
 // and we need to specialize for 32-bit integers and floats
 template<>
 void
 TypedArrayObjectTemplate<int32_t>::copyIndexToValue(JSObject *tarray, uint32_t index,
                                                     MutableHandleValue vp)
 {
     int32_t val = getIndex(tarray, index);
     vp.setInt32(val);
@@ -2734,16 +2738,18 @@ TypedArrayObjectTemplate<double>::copyIn
      * could allow user code to break the engine-wide invariant that only
      * canonical nans are stored into jsvals, which means user code could
      * confuse the engine into interpreting a double-typed jsval as an
      * object-typed jsval.
      */
     vp.setDouble(JS_CANONICALIZE_NAN(val));
 }
 
+} /* anonymous namespace */
+
 static NewObjectKind
 DataViewNewObjectKind(JSContext *cx, uint32_t byteLength, JSObject *proto)
 {
     if (!proto && byteLength >= TypedArrayObject::SINGLETON_TYPE_BYTE_LENGTH)
         return SingletonObject;
     jsbytecode *pc;
     JSScript *script = cx->currentScript(&pc);
     if (!script)
--- a/js/src/yarr/wtfbridge.h
+++ b/js/src/yarr/wtfbridge.h
@@ -77,18 +77,17 @@ class PassOwnPtr {
 template<typename T>
 class OwnPtr {
     T *ptr;
   public:
     OwnPtr() : ptr(NULL) { }
     OwnPtr(PassOwnPtr<T> p) : ptr(p.get()) { }
 
     ~OwnPtr() {
-        if (ptr)
-            js_delete(ptr);
+        js_delete(ptr);
     }
 
     OwnPtr<T> &operator=(PassOwnPtr<T> p) {
         ptr = p.get();
         return *this;
     }
 
     T *operator ->() { return ptr; }
--- a/media/mtransport/nricectx.cpp
+++ b/media/mtransport/nricectx.cpp
@@ -313,22 +313,22 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const 
   RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer);
 
   // Initialize the crypto callbacks
   if (!initialized) {
     NR_reg_init(NR_REG_MODE_LOCAL);
     nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl;
     initialized = true;
 
-    // Set the priorites for candidate type preferences
-    NR_reg_set_uchar((char *)"ice.pref.type.srv_rflx",100);
-    NR_reg_set_uchar((char *)"ice.pref.type.peer_rflx",105);
-    NR_reg_set_uchar((char *)"ice.pref.type.prflx",99);
-    NR_reg_set_uchar((char *)"ice.pref.type.host",125);
-    NR_reg_set_uchar((char *)"ice.pref.type.relayed",126);
+    // Set the priorites for candidate type preferences.
+    // These numbers come from RFC 5245 S. 4.1.2.2
+    NR_reg_set_uchar((char *)"ice.pref.type.srv_rflx", 100);
+    NR_reg_set_uchar((char *)"ice.pref.type.peer_rflx", 110);
+    NR_reg_set_uchar((char *)"ice.pref.type.host", 126);
+    NR_reg_set_uchar((char *)"ice.pref.type.relayed", 0);
 
     if (set_interface_priorities) {
       NR_reg_set_uchar((char *)"ice.pref.interface.rl0", 255);
       NR_reg_set_uchar((char *)"ice.pref.interface.wi0", 254);
       NR_reg_set_uchar((char *)"ice.pref.interface.lo0", 253);
       NR_reg_set_uchar((char *)"ice.pref.interface.en1", 252);
       NR_reg_set_uchar((char *)"ice.pref.interface.en0", 251);
       NR_reg_set_uchar((char *)"ice.pref.interface.eth0", 252);
--- a/media/mtransport/nricemediastream.cpp
+++ b/media/mtransport/nricemediastream.cpp
@@ -41,16 +41,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 */
 
 
 #include <string>
 #include <vector>
 
 #include "logging.h"
 #include "nsError.h"
+#include "mozilla/Scoped.h"
 
 // nICEr includes
 extern "C" {
 #include "nr_api.h"
 #include "registry.h"
 #include "async_timer.h"
 #include "ice_util.h"
 #include "transport_addr.h"
@@ -67,16 +68,62 @@ extern "C" {
 // Local includes
 #include "nricectx.h"
 #include "nricemediastream.h"
 
 namespace mozilla {
 
 MOZ_MTLOG_MODULE("mtransport")
 
+// Make an NrIceCandidate from the candidate |cand|.
+// This is not a member fxn because we want to hide the
+// defn of nr_ice_candidate but we pass by reference.
+static NrIceCandidate* MakeNrIceCandidate(const nr_ice_candidate& candc) {
+  ScopedDeletePtr<NrIceCandidate> out(new NrIceCandidate());
+
+  int r;
+  // Const-cast because the internal nICEr code isn't const-correct.
+  nr_ice_candidate *cand = const_cast<nr_ice_candidate *>(&candc);
+  char addr[INET6_ADDRSTRLEN + 1];
+
+  r = nr_transport_addr_get_addrstring(&cand->addr, addr, sizeof(addr));
+  if (r)
+    return nullptr;
+
+  int port;
+  r=nr_transport_addr_get_port(&cand->addr, &port);
+  if (r)
+    return nullptr;
+
+  NrIceCandidate::Type type;
+
+  switch(cand->type) {
+    case HOST:
+      type = NrIceCandidate::ICE_HOST;
+      break;
+    case SERVER_REFLEXIVE:
+      type = NrIceCandidate::ICE_SERVER_REFLEXIVE;
+      break;
+    case PEER_REFLEXIVE:
+      type = NrIceCandidate::ICE_PEER_REFLEXIVE;
+      break;
+    case RELAYED:
+      type = NrIceCandidate::ICE_RELAYED;
+      break;
+    default:
+      return nullptr;
+  }
+
+  out->host = addr;
+  out->port = port;
+  out->type = type;
+
+  return out.forget();
+}
+
 // NrIceMediaStream
 RefPtr<NrIceMediaStream>
 NrIceMediaStream::Create(NrIceCtx *ctx,
                          const std::string& name,
                          int components) {
   RefPtr<NrIceMediaStream> stream =
     new NrIceMediaStream(ctx, name, components);
 
@@ -145,16 +192,48 @@ nsresult NrIceMediaStream::ParseTrickleC
                 << name_ << "'");
       return NS_ERROR_FAILURE;
     }
   }
 
   return NS_OK;
 }
 
+nsresult NrIceMediaStream::GetActivePair(int component,
+                                         NrIceCandidate **localp,
+                                         NrIceCandidate **remotep) {
+  int r;
+  nr_ice_candidate *local_int;
+  nr_ice_candidate *remote_int;
+
+  r = nr_ice_media_stream_get_active(ctx_->peer(),
+                                     stream_,
+                                     component,
+                                     &local_int, &remote_int);
+  if (r)
+    return NS_ERROR_FAILURE;
+
+  ScopedDeletePtr<NrIceCandidate> local(
+      MakeNrIceCandidate(*local_int));
+  if (!local)
+    return NS_ERROR_FAILURE;
+
+  ScopedDeletePtr<NrIceCandidate> remote(
+      MakeNrIceCandidate(*remote_int));
+  if (!remote)
+    return NS_ERROR_FAILURE;
+
+  if (localp)
+    *localp = local.forget();
+  if (remotep)
+    *remotep = remote.forget();
+
+  return NS_OK;
+}
+
 
 void NrIceMediaStream::EmitAllCandidates() {
   char **attrs = 0;
   int attrct;
   int r;
   r = nr_ice_media_stream_get_attributes(stream_,
                                          &attrs, &attrct);
   if (r) {
@@ -243,19 +322,26 @@ nsresult NrIceMediaStream::SendPacket(in
     return NS_BASE_STREAM_OSERROR;
   }
 
   return NS_OK;
 }
 
 
 void NrIceMediaStream::Ready() {
-  MOZ_MTLOG(ML_DEBUG, "Marking stream ready '" << name_ << "'");
-  state_ = ICE_OPEN;
-  SignalReady(this);
+  // This function is called whenever a stream becomes ready, but it
+  // gets fired multiple times when a stream gets nominated repeatedly.
+  if (state_ != ICE_OPEN) {
+    MOZ_MTLOG(ML_DEBUG, "Marking stream ready '" << name_ << "'");
+    state_ = ICE_OPEN;
+    SignalReady(this);
+  }
+  else {
+    MOZ_MTLOG(ML_DEBUG, "Stream ready callback fired again for '" << name_ << "'");
+  }
 }
 
 void NrIceMediaStream::Close() {
   MOZ_MTLOG(ML_DEBUG, "Marking stream closed '" << name_ << "'");
   state_ = ICE_CLOSED;
   stream_ = nullptr;
 }
 }  // close namespace
--- a/media/mtransport/nricemediastream.h
+++ b/media/mtransport/nricemediastream.h
@@ -58,16 +58,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
 
 namespace mozilla {
 
 typedef struct nr_ice_media_stream_ nr_ice_media_stream;
 
 class NrIceCtx;
 
+/* A summary of a candidate, for use in asking which candidate
+   pair is active */
+struct NrIceCandidate {
+  enum Type {
+    ICE_HOST,
+    ICE_SERVER_REFLEXIVE,
+    ICE_PEER_REFLEXIVE,
+    ICE_RELAYED
+  };
+
+  std::string host;
+  uint16_t port;
+  Type type;
+};
+
 class NrIceMediaStream {
  public:
   static RefPtr<NrIceMediaStream> Create(NrIceCtx *ctx,
                                          const std::string& name,
                                          int components);
   ~NrIceMediaStream();
 
   enum State { ICE_CONNECTING, ICE_OPEN, ICE_CLOSED};
@@ -84,16 +99,24 @@ class NrIceMediaStream {
   nsresult GetDefaultCandidate(int component, std::string *host, int *port);
 
   // Parse remote attributes
   nsresult ParseAttributes(std::vector<std::string>& candidates);
 
   // Parse trickle ICE candidate
   nsresult ParseTrickleCandidate(const std::string& candidate);
 
+  // Get the candidate pair currently active. It's the
+  // caller's responsibility to free these.
+  nsresult GetActivePair(int component,
+                         NrIceCandidate** local, NrIceCandidate** remote);
+
+  // The number of components
+  int components() const { return components_; }
+
   // The underlying nICEr stream
   nr_ice_media_stream *stream() { return stream_; }
   // Signals to indicate events. API users can (and should)
   // register for these.
 
   // Send a packet
   nsresult SendPacket(int component_id, const unsigned char *data, size_t len);
 
@@ -121,21 +144,17 @@ class NrIceMediaStream {
 
  private:
   NrIceMediaStream(NrIceCtx *ctx,  const std::string& name,
                    int components) :
       state_(ICE_CONNECTING),
       ctx_(ctx),
       name_(name),
       components_(components),
-      stream_(nullptr)
-  {
-    // XXX: components_ will be used eventually;  placate clang in the meantime.
-    (void)components_;
-  }
+      stream_(nullptr) {}
 
   DISALLOW_COPY_ASSIGN(NrIceMediaStream);
 
   State state_;
   NrIceCtx *ctx_;
   const std::string name_;
   const int components_;
   nr_ice_media_stream *stream_;
--- a/media/mtransport/test/ice_unittest.cpp
+++ b/media/mtransport/test/ice_unittest.cpp
@@ -72,17 +72,19 @@ class IceTestPeer : public sigslot::has_
       gathering_complete_(false),
       ready_ct_(0),
       ice_complete_(false),
       received_(0),
       sent_(0),
       fake_resolver_(),
       dns_resolver_(new NrIceResolver()),
       remote_(nullptr),
-      candidate_filter_(nullptr) {
+      candidate_filter_(nullptr),
+      expected_local_type_(NrIceCandidate::ICE_HOST),
+      expected_remote_type_(NrIceCandidate::ICE_HOST) {
     ice_ctx_->SignalGatheringCompleted.connect(this,
                                                &IceTestPeer::GatheringComplete);
     ice_ctx_->SignalCompleted.connect(this, &IceTestPeer::IceCompleted);
   }
 
   ~IceTestPeer() {
     test_utils->sts_target()->Dispatch(WrapRunnable(this,
                                                     &IceTestPeer::Shutdown),
@@ -175,16 +177,21 @@ class IceTestPeer : public sigslot::has_
         std::cerr << "Returning candidate: " << candidates_in[i] << std::endl;
         candidates.push_back(candidates_in[i]);
       }
     }
 
     return candidates;
   }
 
+  void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote) {
+    expected_local_type_ = local;
+    expected_remote_type_ = remote;
+  }
+
   bool gathering_complete() { return gathering_complete_; }
   int ready_ct() { return ready_ct_; }
   bool is_ready(size_t stream) {
     return streams_[stream]->state() == NrIceMediaStream::ICE_OPEN;
   }
   bool ice_complete() { return ice_complete_; }
   size_t received() { return received_; }
   size_t sent() { return sent_; }
@@ -250,16 +257,67 @@ class IceTestPeer : public sigslot::has_
                         &NrIceMediaStream::ParseTrickleCandidate,
                         candidates[j],
                         &res), NS_DISPATCH_SYNC);
 
       ASSERT_TRUE(NS_SUCCEEDED(res));
     }
   }
 
+  void DumpCandidate(std::string which, const NrIceCandidate& cand) {
+    std::string type;
+
+    switch(cand.type) {
+      case NrIceCandidate::ICE_HOST:
+        type = "host";
+        break;
+      case NrIceCandidate::ICE_SERVER_REFLEXIVE:
+        type = "srflx";
+        break;
+      case NrIceCandidate::ICE_PEER_REFLEXIVE:
+        type = "prflx";
+        break;
+      case NrIceCandidate::ICE_RELAYED:
+        type = "relay";
+        break;
+      default:
+        FAIL();
+    };
+
+    std::cerr << which
+              << " --> "
+              << type
+              << " "
+              << cand.host
+              << ":"
+              << cand.port
+              << std::endl;
+  }
+
+  void DumpAndCheckActiveCandidates() {
+    std::cerr << "Active candidates:" << std::endl;
+    for (size_t i=0; i < streams_.size(); ++i) {
+      for (int j=0; j < streams_[i]->components(); ++j) {
+        std::cerr << "Stream " << i << " component " << j+1 << std::endl;
+
+        NrIceCandidate *local;
+        NrIceCandidate *remote;
+
+        nsresult res = streams_[i]->GetActivePair(j+1, &local, &remote);
+        ASSERT_TRUE(NS_SUCCEEDED(res));
+        DumpCandidate("Local  ", *local);
+        ASSERT_EQ(expected_local_type_, local->type);
+        DumpCandidate("Remote ", *remote);
+        ASSERT_EQ(expected_remote_type_, remote->type);
+        delete local;
+        delete remote;
+      }
+    }
+  }
+
   void Close() {
     test_utils->sts_target()->Dispatch(
       WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx),
       NS_DISPATCH_SYNC);
   }
 
   void Shutdown() {
     ice_ctx_ = nullptr;
@@ -281,18 +339,18 @@ class IceTestPeer : public sigslot::has_
   }
 
   void GotCandidate(NrIceMediaStream *stream, const std::string &candidate) {
     std::cerr << "Got candidate " << candidate << std::endl;
     candidates_[stream->name()].push_back(candidate);
   }
 
   void StreamReady(NrIceMediaStream *stream) {
-    std::cerr << "Stream ready " << stream->name() << std::endl;
     ++ready_ct_;
+    std::cerr << "Stream ready " << stream->name() << " ct=" << ready_ct_ << std::endl;
   }
 
   void IceCompleted(NrIceCtx *ctx) {
     std::cerr << "ICE completed " << name_ << std::endl;
     ice_complete_ = true;
   }
 
   void PacketReceived(NrIceMediaStream *stream, int component, const unsigned char *data,
@@ -330,16 +388,18 @@ class IceTestPeer : public sigslot::has_
   int ready_ct_;
   bool ice_complete_;
   size_t received_;
   size_t sent_;
   NrIceResolverFake fake_resolver_;
   nsRefPtr<NrIceResolver> dns_resolver_;
   IceTestPeer *remote_;
   CandidateFilter candidate_filter_;
+  NrIceCandidate::Type expected_local_type_;
+  NrIceCandidate::Type expected_remote_type_;
 };
 
 class IceGatherTest : public ::testing::Test {
  public:
   void SetUp() {
     peer_ = new IceTestPeer("P1", true, false);
     peer_->AddStream(1);
   }
@@ -396,29 +456,44 @@ class IceConnectTest : public ::testing:
 
   void SetTurnServer(const std::string addr, uint16_t port,
                      const std::string username,
                      const std::string password) {
     p1_->SetTurnServer(addr, port, username, password);
     p2_->SetTurnServer(addr, port, username, password);
   }
 
-  void SetCandidateFilter(CandidateFilter filter) {
+  void SetCandidateFilter(CandidateFilter filter, bool both=true) {
     p1_->SetCandidateFilter(filter);
-    p2_->SetCandidateFilter(filter);
+    if (both) {
+      p2_->SetCandidateFilter(filter);
+    }
   }
 
   void Connect() {
     p1_->Connect(p2_, TRICKLE_NONE);
     p2_->Connect(p1_, TRICKLE_NONE);
 
     ASSERT_TRUE_WAIT(p1_->ready_ct() == 1 && p2_->ready_ct() == 1, 5000);
     ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(), 5000);
+
+    p1_->DumpAndCheckActiveCandidates();
+    p2_->DumpAndCheckActiveCandidates();
   }
 
+  void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote) {
+    p1_->SetExpectedTypes(local, remote);
+    p2_->SetExpectedTypes(local, remote);
+  }
+
+  void SetExpectedTypes(NrIceCandidate::Type local1, NrIceCandidate::Type remote1,
+                        NrIceCandidate::Type local2, NrIceCandidate::Type remote2) {
+    p1_->SetExpectedTypes(local1, remote1);
+    p2_->SetExpectedTypes(local2, remote2);
+  }
 
   void ConnectP1(TrickleMode mode = TRICKLE_NONE) {
     p1_->Connect(p2_, mode);
   }
 
   void ConnectP2(TrickleMode mode = TRICKLE_NONE) {
     p2_->Connect(p1_, mode);
   }
@@ -695,28 +770,32 @@ TEST_F(IceConnectTest, TestConnectTurnOn
   if (g_turn_server.empty())
     return;
 
   AddStream("first", 1);
   SetTurnServer(g_turn_server, kDefaultStunServerPort,
                 g_turn_user, g_turn_password);
   ASSERT_TRUE(Gather(true));
   SetCandidateFilter(IsRelayCandidate);
+  SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
+                   NrIceCandidate::Type::ICE_RELAYED);
   Connect();
 }
 
 TEST_F(IceConnectTest, TestSendReceiveTurnOnly) {
   if (g_turn_server.empty())
     return;
 
   AddStream("first", 1);
   SetTurnServer(g_turn_server, kDefaultStunServerPort,
                 g_turn_user, g_turn_password);
   ASSERT_TRUE(Gather(true));
   SetCandidateFilter(IsRelayCandidate);
+  SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
+                   NrIceCandidate::Type::ICE_RELAYED);
   Connect();
   SendReceive();
 }
 
 TEST_F(IceConnectTest, TestConnectShutdownOneSide) {
   AddStream("first", 1);
   ASSERT_TRUE(Gather(true));
   ConnectThenDelete();
--- a/media/mtransport/test/turn_unittest.cpp
+++ b/media/mtransport/test/turn_unittest.cpp
@@ -310,16 +310,20 @@ TEST_F(TurnClient, AllocateAndHold) {
   Allocate();
   PR_Sleep(20000);
 }
 
 TEST_F(TurnClient, SendToSelf) {
   Allocate();
   SendTo(relay_addr_);
   ASSERT_TRUE_WAIT(received() == 100, 1000);
+  PR_Sleep(10000); // Wait 10 seconds to make sure the
+                   // CreatePermission has time to complete/fail.
+  SendTo(relay_addr_);
+  ASSERT_TRUE_WAIT(received() == 200, 1000);
 }
 
 TEST_F(TurnClient, AllocateDummyServer) {
   turn_server_ = kDummyTurnServer;
   Allocate(false);
 }
 
 static std::string get_environment(const char *name) {
--- a/media/mtransport/third_party/nICEr/src/ice/ice_component.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.c
@@ -794,20 +794,23 @@ int nr_ice_component_nominated_pair(nr_i
     /* Set the new nominated pair */
     r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): nominated pair is %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,pair);
     comp->state=NR_ICE_COMPONENT_NOMINATED;
     comp->nominated=pair;
     comp->active=pair;
 
     r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling all pairs but %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,pair);
 
-    /* OK, we need to cancel off everything on this component */
+    /* Cancel checks in WAITING and FROZEN per ICE S 8.1.2 */
     p2=TAILQ_FIRST(&comp->stream->check_list);
     while(p2){
-      if((p2 != pair) && (p2->remote->component->component_id == comp->component_id)){
+      if((p2 != pair) &&
+         (p2->remote->component->component_id == comp->component_id) &&
+         ((p2->state == NR_ICE_PAIR_STATE_FROZEN) ||
+	  (p2->state == NR_ICE_PAIR_STATE_WAITING))) {
         r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling pair %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->as_string,p2);
 
         if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2))
           ABORT(r);
       }
 
       p2=TAILQ_NEXT(p2,entry);
     }
--- a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c
@@ -290,17 +290,16 @@ int nr_ice_media_stream_pair_candidates(
     return(_status);
   }
 
 int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, nr_ice_media_stream *pstream, int *serviced)
   {
     nr_ice_component *pcomp;
     int r,_status;
     char *user = 0;
-    char *lufrag, *rufrag;
 
     if (serviced)
       *serviced = 0;
 
     pcomp=STAILQ_FIRST(&pstream->components);
     while(pcomp){
       int serviced_inner=0;
 
@@ -693,44 +692,62 @@ int nr_ice_media_stream_find_component(n
 
     *compp=comp;
 
     _status=0;
   abort:
     return(_status);
   }
 
-
 int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, UCHAR *data, int len)
   {
     int r,_status;
     nr_ice_component *comp;
 
     /* First find the peer component */
     if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
       ABORT(r);
 
     /* Do we have an active pair yet? We should... */
     if(!comp->active)
-      ABORT(R_BAD_ARGS);
+      ABORT(R_NOT_FOUND);
 
     /* OK, write to that pair, which means:
        1. Use the socket on our local side.
        2. Use the address on the remote side
     */
     comp->keepalive_needed=0; /* Suppress keepalives */
     if(r=nr_socket_sendto(comp->active->local->osock,data,len,0,
-      &comp->active->remote->addr))
+                          &comp->active->remote->addr))
       ABORT(r);
 
     _status=0;
   abort:
     return(_status);
   }
 
+int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote)
+  {
+    int r,_status;
+    nr_ice_component *comp;
+
+    /* First find the peer component */
+    if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
+      ABORT(r);
+
+    if(!comp->active)
+      ABORT(R_NOT_FOUND);
+
+    if (local) *local = comp->active->local;
+    if (remote) *remote = comp->active->remote;
+
+    _status=0;
+  abort:
+    return(_status);
+  }
 
 int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_transport_addr *local, nr_transport_addr *remote)
   {
     int r,_status;
     nr_ice_component *comp;
 
     /* First find the peer component */
     if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
--- a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h
@@ -83,17 +83,18 @@ int nr_ice_media_stream_start_checks(nr_
 int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream, int *serviced);
 int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
 int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation);
 int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out);
 int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component);
 int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component);
 int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
 int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp);
-int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx,nr_ice_media_stream *str, int component, UCHAR *data, int len);
+int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, UCHAR *data, int len);
+int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote);
 int nr_ice_media_stream_find_component(nr_ice_media_stream *str, int comp_id, nr_ice_component **compp);
 int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_transport_addr *local, nr_transport_addr *remote);
 int
 nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr);
 
 
 #ifdef __cplusplus
 }
--- a/media/mtransport/third_party/nICEr/src/stun/stun_proc.c
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_proc.c
@@ -84,17 +84,17 @@ nr_stun_receive_message(nr_stun_message 
     else {
         if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_RESPONSE
          && NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_ERROR_RESPONSE) {
             r_log(NR_LOG_STUN,LOG_NOTICE,"Illegal message class: %03x", msg->header.type);
             ABORT(R_REJECTED);
         }
 
         if (NR_STUN_GET_TYPE_METHOD(req->header.type) != NR_STUN_GET_TYPE_METHOD(msg->header.type)) {
-            r_log(NR_LOG_STUN,LOG_NOTICE,"Inconsistent message method: %03x", msg->header.type);
+            r_log(NR_LOG_STUN,LOG_NOTICE,"Inconsistent message method: %03x expected %03x", msg->header.type, req->header.type);
             ABORT(R_REJECTED);
         }
 
         if (nr_stun_different_transaction(msg->buffer, msg->length, req)) {
             r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized STUN transaction");
             ABORT(R_REJECTED);
         }
     }
--- a/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c
+++ b/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c
@@ -171,16 +171,21 @@ static int nr_turn_stun_set_auth_params(
 
   assert(nonce);
   if (!nonce)
     ABORT(R_BAD_ARGS);
   ctx->nonce=r_strdup(nonce);
   if (!ctx->nonce)
     ABORT(R_NO_MEMORY);
 
+  RFREE(ctx->stun->realm);
+  ctx->stun->realm = r_strdup(ctx->realm);
+  if (!ctx->stun->realm)
+    ABORT(R_NO_MEMORY);
+
   ctx->stun->auth_params.realm = ctx->realm;
   ctx->stun->auth_params.nonce = ctx->nonce;
   ctx->stun->auth_params.authenticate = 1;  /* May already be 1 */
 
   _status=0;
 abort:
   return(_status);
 }
--- a/netwerk/base/src/nsSocketTransportService2.cpp
+++ b/netwerk/base/src/nsSocketTransportService2.cpp
@@ -1046,20 +1046,24 @@ nsSocketTransportService::DiscoverMaxCou
     gMaxCount = SOCKET_LIMIT_TARGET;
 #else
     // other platforms are harder to test - so leave at safe legacy value
 #endif
 
     return PR_SUCCESS;
 }
 
+
+// Used to return connection info to Dashboard.cpp
 void
 nsSocketTransportService::AnalyzeConnection(nsTArray<SocketInfo> *data,
         struct SocketContext *context, bool aActive)
 {
+    if (context->mHandler->mIsPrivate)
+        return;
     PRFileDesc *aFD = context->mFD;
     bool tcp = (PR_GetDescType(aFD) == PR_DESC_SOCKET_TCP);
 
     PRNetAddr peer_addr;
     PR_GetPeerName(aFD, &peer_addr);
 
     char host[64] = {0};
     PR_NetAddrToString(&peer_addr, host, sizeof(host));
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -24,16 +24,17 @@
 #include "prnetdb.h"
 #include "prmon.h"
 #include "prio.h"
 #include "plstr.h"
 #include "nsIOService.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsNetAddr.h"
 #include "nsProxyRelease.h"
+#include "nsIObserverService.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/VisualEventTracer.h"
 
 using namespace mozilla;
 using namespace mozilla::net;
 
 static const char kPrefDnsCacheEntries[]    = "network.dnsCacheEntries";
@@ -428,16 +429,23 @@ nsDNSService::Init()
             prefs->AddObserver(kPrefDnsLocalDomains, this, false);
             prefs->AddObserver(kPrefDisableIPv6, this, false);
             prefs->AddObserver(kPrefDisablePrefetch, this, false);
 
             // Monitor these to see if there is a change in proxy configuration
             // If a manual proxy is in use, disable prefetch implicitly
             prefs->AddObserver("network.proxy.type", this, false);
         }
+
+        nsresult rv;
+        nsCOMPtr<nsIObserverService> observerService =
+            do_GetService("@mozilla.org/observer-service;1", &rv);
+        if (NS_SUCCEEDED(rv)) {
+            observerService->AddObserver(this, "last-pb-context-exited", false);
+        }
     }
 
     nsDNSPrefetch::Initialize(this);
 
     // Don't initialize the resolver if we're in offline mode.
     // Later on, the IO service will reinitialize us when going online.
     if (gIOService->IsOffline() && !gIOService->IsComingOnline())
         return NS_OK;
@@ -777,17 +785,18 @@ nsDNSService::GetMyHostName(nsACString &
     }
     return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsDNSService::Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
 {
     // we are only getting called if a preference has changed. 
-    NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0,
+    NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0 ||
+        strcmp(topic, "last-pb-context-exited") == 0,
         "unexpected observe call");
 
     //
     // Shutdown and this function are both only called on the UI thread, so we don't
     // have to worry about mResolver being cleared out from under us.
     //
     // NOTE Shutting down and reinitializing the service like this is obviously
     // suboptimal if Observe gets called several times in a row, but we don't
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -3338,16 +3338,19 @@ nsConnectionEntry::MaxPipelineDepth(nsAH
     return mGreenDepth;
 }
 
 PLDHashOperator
 nsHttpConnectionMgr::ReadConnectionEntry(const nsACString &key,
                 nsAutoPtr<nsConnectionEntry> &ent,
                 void *aArg)
 {
+    if (ent->mConnInfo->GetPrivate())
+        return PL_DHASH_NEXT;
+
     nsTArray<HttpRetParams> *args = static_cast<nsTArray<HttpRetParams> *> (aArg);
     HttpRetParams data;
     data.host = ent->mConnInfo->Host();
     data.port = ent->mConnInfo->Port();
     for (uint32_t i = 0; i < ent->mActiveConns.Length(); i++) {
         HttpConnInfo info;
         info.ttl = ent->mActiveConns[i]->TimeToLive();
         info.rtt = ent->mActiveConns[i]->Rtt();
--- a/netwerk/protocol/websocket/WebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannel.cpp
@@ -947,16 +947,17 @@ WebSocketChannel::WebSocketChannel() :
   mFragmentAccumulator(0),
   mBuffered(0),
   mBufferSize(kIncomingBufferInitialSize),
   mCurrentOut(nullptr),
   mCurrentOutSent(0),
   mCompressor(nullptr),
   mDynamicOutputSize(0),
   mDynamicOutput(nullptr),
+  mPrivateBrowsing(false),
   mConnectionLogService(nullptr)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
 
   LOG(("WebSocketChannel::WebSocketChannel() %p\n", this));
 
   if (!sWebSocketAdmissions)
     sWebSocketAdmissions = new nsWSAdmissionManager();
@@ -1323,17 +1324,17 @@ WebSocketChannel::ProcessInput(uint8_t *
         // Section 8.1 says to fail connection if invalid utf-8 in text message
         if (!IsUTF8(utf8Data, false)) {
           LOG(("WebSocketChannel:: text frame invalid utf-8\n"));
           return NS_ERROR_CANNOT_CONVERT_DATA;
         }
 
         NS_DispatchToMainThread(new CallOnMessageAvailable(this, utf8Data, -1));
         nsresult rv;
-        if (mConnectionLogService) {
+        if (mConnectionLogService && !mPrivateBrowsing) {
           nsAutoCString host;
           rv = mURI->GetHostPort(host);
           if (NS_SUCCEEDED(rv)) {
             mConnectionLogService->NewMsgReceived(host, mSerial, count);
             LOG(("Added new msg received for %s",host.get()));
           }
         }
       }
@@ -1414,17 +1415,17 @@ WebSocketChannel::ProcessInput(uint8_t *
     } else if (opcode == kBinary) {
       LOG(("WebSocketChannel:: binary frame received\n"));
       if (mListener) {
         nsCString binaryData((const char *)payload, payloadLength);
         NS_DispatchToMainThread(new CallOnMessageAvailable(this, binaryData,
                                                            payloadLength));
         // To add the header to 'Networking Dashboard' log
         nsresult rv;
-        if (mConnectionLogService) {
+        if (mConnectionLogService && !mPrivateBrowsing) {
           nsAutoCString host;
           rv = mURI->GetHostPort(host);
           if (NS_SUCCEEDED(rv)) {
             mConnectionLogService->NewMsgReceived(host, mSerial, count);
             LOG(("Added new received msg for %s",host.get()));
           }
         }
       }
@@ -1839,17 +1840,17 @@ WebSocketChannel::CleanupConnection()
   if (mTransport) {
     mTransport->SetSecurityCallbacks(nullptr);
     mTransport->SetEventSink(nullptr, nullptr);
     mTransport->Close(NS_BASE_STREAM_CLOSED);
     mTransport = nullptr;
   }
 
   nsresult rv;
-  if (mConnectionLogService) {
+  if (mConnectionLogService && !mPrivateBrowsing) {
     nsAutoCString host;
     rv = mURI->GetHostPort(host);
     if (NS_SUCCEEDED(rv))
       mConnectionLogService->RemoveHost(host, mSerial);
   }
 
   DecrementSessionCount();
 }
@@ -2673,17 +2674,19 @@ WebSocketChannel::AsyncOpen(nsIURI *aURI
 
   mHttpChannel = do_QueryInterface(localChannel, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = SetupRequest();
   if (NS_FAILED(rv))
     return rv;
 
-  if (mConnectionLogService) {
+  mPrivateBrowsing = NS_UsePrivateBrowsing(localChannel);
+
+  if (mConnectionLogService && !mPrivateBrowsing) {
     nsAutoCString host;
     rv = mURI->GetHostPort(host);
     if (NS_SUCCEEDED(rv)) {
       mConnectionLogService->AddHost(host, mSerial, BaseWebSocketChannel::mEncrypted);
     }
   }
 
   rv = ApplyForAdmission();
@@ -2778,17 +2781,17 @@ WebSocketChannel::SendMsgCommon(const ns
 
   NS_ABORT_IF_FALSE(mMaxMessageSize >= 0, "max message size negative");
   if (aLength > static_cast<uint32_t>(mMaxMessageSize)) {
     LOG(("WebSocketChannel:: Error: message too big\n"));
     return NS_ERROR_FILE_TOO_BIG;
   }
 
   nsresult rv;
-  if (mConnectionLogService) {
+  if (mConnectionLogService && !mPrivateBrowsing) {
     nsAutoCString host;
     rv = mURI->GetHostPort(host);
     if (NS_SUCCEEDED(rv)) {
       mConnectionLogService->NewMsgSent(host, mSerial, aLength);
       LOG(("Added new msg sent for %s",host.get()));
     }
   }
 
--- a/netwerk/protocol/websocket/WebSocketChannel.h
+++ b/netwerk/protocol/websocket/WebSocketChannel.h
@@ -242,16 +242,17 @@ private:
   nsDeque                         mOutgoingPingMessages;
   nsDeque                         mOutgoingPongMessages;
   uint32_t                        mHdrOutToSend;
   uint8_t                        *mHdrOut;
   uint8_t                         mOutHeader[kCopyBreak + 16];
   nsWSCompression                *mCompressor;
   uint32_t                        mDynamicOutputSize;
   uint8_t                        *mDynamicOutput;
+  bool                            mPrivateBrowsing;
 
   nsCOMPtr<nsIDashboardEventNotifier> mConnectionLogService;
   uint32_t mSerial;
   static uint32_t sSerialSeed;
 };
 
 class WebSocketSSLChannel : public WebSocketChannel
 {
--- a/testing/mochitest/b2g.json
+++ b/testing/mochitest/b2g.json
@@ -327,17 +327,16 @@
     "dom/tests/mochitest/bugs/test_resize_move_windows.html": "Windows can't change size and position on B2G",
     "dom/tests/mochitest/bugs/test_window_bar.html":"",
 
     "dom/tests/mochitest/general/test_clipboard_events.html":"clipboard undefined",
     "content/base/test/test_copypaste.html":"clipboard undefined",
     "content/base/test/test_bug166235.html":"clipboard undefined",
 
     "dom/tests/mochitest/general/test_idleapi_permissions.html":"",
-    "dom/tests/mochitest/general/test_interfaces.html":"",
     "dom/tests/mochitest/general/test_paste_selection.html":"No clipboard",
 
     "dom/tests/mochitest/geolocation/test_allowCurrent.html":"Bug 910235 - Error: no message manager set when calling method: [nsIObserver::observe]",
     "dom/tests/mochitest/geolocation/test_allowWatch.html":"",
     "dom/tests/mochitest/geolocation/test_cachedPosition.html":"",
     "dom/tests/mochitest/geolocation/test_cancelCurrent.html":"",
     "dom/tests/mochitest/geolocation/test_cancelWatch.html":"",
     "dom/tests/mochitest/geolocation/test_clearWatch.html":"",