Merge inbound to m-c
authorWes Kocher <wkocher@mozilla.com>
Wed, 05 Mar 2014 18:08:47 -0800
changeset 189312 c7d401d189e0ea43a76e27bc909750331225cda9
parent 189244 21740ba59e60ab3b1c07395a6c95d54a3d454f10 (current diff)
parent 189311 9f57c9fd8d52e8b784e2e3fa3cdc3a1734f203f6 (diff)
child 189322 8122ffa9e1aaa473fcfef2a8daf093f79986aa1b
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c
testing/mochitest/tests/Makefile.in
testing/mochitest/tests/SpecialPowersLoadChromeScript.js
testing/mochitest/tests/file_SpecialPowersFrame1.html
testing/mochitest/tests/test_SimpleTestGetTestFileURL.html
testing/mochitest/tests/test_SpecialPowersExtension.html
testing/mochitest/tests/test_SpecialPowersExtension2.html
testing/mochitest/tests/test_SpecialPowersLoadChromeScript.html
testing/mochitest/tests/test_SpecialPowersPushPermissions.html
testing/mochitest/tests/test_SpecialPowersPushPrefEnv.html
testing/mochitest/tests/test_bug362788.xhtml
testing/mochitest/tests/test_bug816847.html
testing/mochitest/tests/test_sanity.html
testing/mochitest/tests/test_sanityEventUtils.html
testing/mochitest/tests/test_sanityException.html
testing/mochitest/tests/test_sanityException2.html
testing/mochitest/tests/test_sanitySimpletest.html
testing/mochitest/tests/test_sanityWindowSnapshot.html
testing/mochitest/tests/test_sanity_cleanup.html
testing/mochitest/tests/test_sanity_cleanup2.html
xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.s
xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc64_linux.s
--- a/browser/components/shell/src/nsWindowsShellService.cpp
+++ b/browser/components/shell/src/nsWindowsShellService.cpp
@@ -1,15 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "imgIContainer.h"
 #include "imgIRequest.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIImageLoadingContent.h"
 #include "nsIPrefService.h"
 #include "nsIPrefLocalizedString.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
 #include "nsNetUtil.h"
@@ -50,16 +52,18 @@
   (val == ERROR_SUCCESS)
 
 #define REG_FAILED(val) \
   (val != ERROR_SUCCESS)
 
 #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
 
 using mozilla::IsWin8OrLater;
+using namespace mozilla;
+using namespace mozilla::gfx;
 
 NS_IMPL_ISUPPORTS2(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
 
 static nsresult
 OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
 {
   const nsString &flatName = PromiseFlatString(aKeyName);
 
@@ -744,42 +748,51 @@ nsWindowsShellService::SetShouldCheckDef
   return prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
 }
 
 static nsresult
 WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
 {
   nsresult rv;
 
-  nsRefPtr<gfxASurface> surface =
+  nsRefPtr<gfxASurface> thebesSurface =
     aImage->GetFrame(imgIContainer::FRAME_FIRST,
                      imgIContainer::FLAG_SYNC_DECODE);
-  NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE);
 
-  nsRefPtr<gfxImageSurface> image(surface->GetAsReadableARGB32ImageSurface());
-  NS_ENSURE_TRUE(image, NS_ERROR_FAILURE);
+  nsRefPtr<gfxImageSurface> thebesImageSurface =
+    thebesSurface->GetAsReadableARGB32ImageSurface();
+  NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE);
+
+  RefPtr<DataSourceSurface> dataSurface =
+    thebesImageSurface->CopyToB8G8R8A8DataSourceSurface();
+  NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
 
-  int32_t width = image->Width();
-  int32_t height = image->Height();
+  DataSourceSurface::MappedSurface map;
+  dataSurface->Map(DataSourceSurface::MapType::READ, &map);
+  if (!map.mData) {
+    return NS_ERROR_FAILURE;
+  }
 
-  uint8_t* bits = image->Data();
-  uint32_t length = image->GetDataSize();
-  uint32_t bpr = uint32_t(image->Stride());
-  int32_t bitCount = bpr/width;
+  int32_t width = dataSurface->GetSize().width;
+  int32_t height = dataSurface->GetSize().height;
+  int32_t bytesPerPixel = 4 * sizeof(uint8_t);
+  uint32_t bytesPerRow = bytesPerPixel * width;
+  uint32_t length = map.mStride * height;
 
   // initialize these bitmap structs which we will later
   // serialize directly to the head of the bitmap file
   BITMAPINFOHEADER bmi;
   bmi.biSize = sizeof(BITMAPINFOHEADER);
   bmi.biWidth = width;
   bmi.biHeight = height;
   bmi.biPlanes = 1;
-  bmi.biBitCount = (WORD)bitCount*8;
+  bmi.biBitCount = (WORD)bytesPerPixel*8;
   bmi.biCompression = BI_RGB;
-  bmi.biSizeImage = length;
+  bmi.biSizeImage = bytesPerRow * height;
   bmi.biXPelsPerMeter = 0;
   bmi.biYPelsPerMeter = 0;
   bmi.biClrUsed = 0;
   bmi.biClrImportant = 0;
 
   BITMAPFILEHEADER bf;
   bf.bfType = 0x4D42; // 'BM'
   bf.bfReserved1 = 0;
@@ -799,19 +812,19 @@ WriteBitmap(nsIFile* aFile, imgIContaine
     stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
     if (written == sizeof(BITMAPFILEHEADER)) {
       stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written);
       if (written == sizeof(BITMAPINFOHEADER)) {
         // write out the image data backwards because the desktop won't
         // show bitmaps with negative heights for top-to-bottom
         uint32_t i = length;
         do {
-          i -= bpr;
-          stream->Write(((const char*)bits) + i, bpr, &written);
-          if (written == bpr) {
+          i -= map.mStride;
+          stream->Write(((const char*)map.mData) + i, bytesPerRow, &written);
+          if (written == bytesPerRow) {
             rv = NS_OK;
           } else {
             rv = NS_ERROR_FAILURE;
             break;
           }
         } while (i != 0);
       }
     }
--- a/build/autoconf/config.guess
+++ b/build/autoconf/config.guess
@@ -1,47 +1,41 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-#   Free Software Foundation, Inc.
+#   Copyright 1992-2014 Free Software Foundation, Inc.
 
-timestamp='2009-08-19'
+timestamp='2014-02-12'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful, but
 # WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner.  Please send patches (context
-# diff format) to <config-patches@gnu.org> and include a ChangeLog
-# entry.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
 #
-# This script attempts to guess a canonical system name similar to
-# config.sub.  If it succeeds, it prints the system name on stdout, and
-# exits with 0.  Otherwise, it exits with 1.
+# Originally written by Per Bothner.
 #
 # You can get the latest version of this script from:
 # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+
 
 me=`echo "$0" | sed -e 's,.*/,,'`
 
 usage="\
 Usage: $0 [OPTION]
 
 Output the configuration name of the system \`$me' is run on.
 
@@ -51,18 +45,17 @@ Operation modes:
   -v, --version      print version number, then exit
 
 Report bugs and patches to <config-patches@gnu.org>."
 
 version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+Copyright 1992-2014 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 
 help="
 Try \`$me --help' for more information."
 
 # Parse command line
@@ -134,22 +127,43 @@ if (test -f /.attbin/uname) >/dev/null 2
 	PATH=$PATH:/.attbin ; export PATH
 fi
 
 UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
 UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	;;
+esac
+
 # Note: order is significant - the case branches are not exclusive.
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:NetBSD:*:*)
 	# NetBSD (nbsd) targets should (where applicable) match one or
-	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
 	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
 	# switched to ELF, *-*-netbsd* would select the old
 	# object file format.  This provides both forward
 	# compatibility and a consistent mechanism for selecting the
 	# object file format.
 	#
 	# Note: NetBSD doesn't particularly care about the vendor
 	# portion of the name.  We always set it to "unknown".
@@ -175,17 +189,17 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$
 		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
 		    # Return netbsd for either.  FIX?
 		    os=netbsd
 		else
 		    os=netbsdelf
 		fi
 		;;
 	    *)
-	        os=netbsd
+		os=netbsd
 		;;
 	esac
 	# The OS release
 	# Debian GNU/NetBSD machines have a different userland, and
 	# thus, need a distinct triplet. However, they do not need
 	# kernel version information, so it can be replaced with a
 	# suitable tag, in the style of linux-gnu.
 	case "${UNAME_VERSION}" in
@@ -196,16 +210,20 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$
 		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
 		;;
 	esac
 	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
 	# contains redundant information, the shorter form:
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
 	echo "${machine}-${os}${release}"
 	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
     *:OpenBSD:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
 	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
 	exit ;;
     *:ekkoBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
 	exit ;;
     *:SolidBSD:*:*)
@@ -218,17 +236,17 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$
 	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
 	exit ;;
     alpha:OSF1:*:*)
 	case $UNAME_RELEASE in
 	*4.0)
 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
 		;;
 	*5.*)
-	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
 		;;
 	esac
 	# According to Compaq, /usr/sbin/psrinfo has been available on
 	# OSF/1 and Tru64 systems produced since 1995.  I hope that
 	# covers most systems running today.  This code pipes the CPU
 	# types through head -n 1, so we only detect the type of CPU 0.
 	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
 	case "$ALPHA_CPU_TYPE" in
@@ -264,17 +282,20 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$
 		UNAME_MACHINE="alphaev79" ;;
 	esac
 	# A Pn.n version is a patched version.
 	# A Vn.n version is a released version.
 	# A Tn.n version is a released field test version.
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
 	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	exit ;;
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
     Alpha\ *:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
 	# Should we change UNAME_MACHINE based on the output of uname instead
 	# of the specific Alpha model?
 	echo alpha-pc-interix
 	exit ;;
     21064:Windows_NT:50:3)
 	echo alpha-dec-winnt3.5
@@ -290,22 +311,22 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$
 	exit ;;
     *:OS/390:*:*)
 	echo i370-ibm-openedition
 	exit ;;
     *:z/VM:*:*)
 	echo s390-ibm-zvmoe
 	exit ;;
     *:OS400:*:*)
-        echo powerpc-ibm-os400
+	echo powerpc-ibm-os400
 	exit ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
 	exit ;;
-    arm:riscos:*:*|arm:RISCOS:*:*)
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
 	echo arm-unknown-riscos
 	exit ;;
     SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
 	echo hppa1.1-hitachi-hiuxmpp
 	exit ;;
     Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
 	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
 	if test "`(/bin/universe) 2>/dev/null`" = att ; then
@@ -328,16 +349,19 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$
 	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
     sun4H:SunOS:5.*:*)
 	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
 	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
     i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
 	eval $set_cc_for_build
 	SUN_ARCH="i386"
 	# If there is a compiler, see if it is configured for 64-bit objects.
 	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
 	# This test works for both compilers.
 	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
 	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
@@ -386,33 +410,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$
     # can be virtually everything (everything which is not
     # "atarist" or "atariste" at least should have a processor
     # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
     # to the lowercase version "mint" (or "freemint").  Finally
     # the system name "TOS" denotes a system which is actually not
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
 	echo m68k-atari-mint${UNAME_RELEASE}
-        exit ;;
+	exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-        echo m68k-milan-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-        echo m68k-hades-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-        echo m68k-unknown-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
     m68k:machten:*:*)
 	echo m68k-apple-machten${UNAME_RELEASE}
 	exit ;;
     powerpc:machten:*:*)
 	echo powerpc-apple-machten${UNAME_RELEASE}
 	exit ;;
     RISC*:Mach:*:*)
 	echo mips-dec-mach_bsd4.3
@@ -472,31 +496,31 @@ EOF
 	exit ;;
     m88k:*:4*:R4*)
 	echo m88k-motorola-sysv4
 	exit ;;
     m88k:*:3*:R3*)
 	echo m88k-motorola-sysv3
 	exit ;;
     AViiON:dgux:*:*)
-        # DG/UX returns AViiON for all architectures
-        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
 	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
 	then
 	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
 	       [ ${TARGET_BINARY_INTERFACE}x = x ]
 	    then
 		echo m88k-dg-dgux${UNAME_RELEASE}
 	    else
 		echo m88k-dg-dguxbcs${UNAME_RELEASE}
 	    fi
 	else
 	    echo i586-dg-dgux${UNAME_RELEASE}
 	fi
- 	exit ;;
+	exit ;;
     M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
 	echo m88k-dolphin-sysv3
 	exit ;;
     M88*:*:R3*:*)
 	# Delta 88k system running SVR3
 	echo m88k-motorola-sysv3
 	exit ;;
     XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
@@ -543,17 +567,17 @@ EOF
 			echo rs6000-ibm-aix3.2.5
 		fi
 	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
 		echo rs6000-ibm-aix3.2.4
 	else
 		echo rs6000-ibm-aix3.2
 	fi
 	exit ;;
-    *:AIX:*:[456])
+    *:AIX:*:[4567])
 	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
 	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
 		IBM_ARCH=rs6000
 	else
 		IBM_ARCH=powerpc
 	fi
 	if [ -x /usr/bin/oslevel ] ; then
 		IBM_REV=`/usr/bin/oslevel`
@@ -586,62 +610,62 @@ EOF
     9000/[34678]??:HP-UX:*:*)
 	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
 	case "${UNAME_MACHINE}" in
 	    9000/31? )            HP_ARCH=m68000 ;;
 	    9000/[34]?? )         HP_ARCH=m68k ;;
 	    9000/[678][0-9][0-9])
 		if [ -x /usr/bin/getconf ]; then
 		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
-                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-                    case "${sc_cpu_version}" in
-                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
-                      532)                      # CPU_PA_RISC2_0
-                        case "${sc_kernel_bits}" in
-                          32) HP_ARCH="hppa2.0n" ;;
-                          64) HP_ARCH="hppa2.0w" ;;
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
 			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
-                        esac ;;
-                    esac
+			esac ;;
+		    esac
 		fi
 		if [ "${HP_ARCH}" = "" ]; then
 		    eval $set_cc_for_build
-		    sed 's/^              //' << EOF >$dummy.c
+		    sed 's/^		//' << EOF >$dummy.c
 
-              #define _HPUX_SOURCE
-              #include <stdlib.h>
-              #include <unistd.h>
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
 
-              int main ()
-              {
-              #if defined(_SC_KERNEL_BITS)
-                  long bits = sysconf(_SC_KERNEL_BITS);
-              #endif
-                  long cpu  = sysconf (_SC_CPU_VERSION);
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
 
-                  switch (cpu)
-              	{
-              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-              	case CPU_PA_RISC2_0:
-              #if defined(_SC_KERNEL_BITS)
-              	    switch (bits)
-              		{
-              		case 64: puts ("hppa2.0w"); break;
-              		case 32: puts ("hppa2.0n"); break;
-              		default: puts ("hppa2.0"); break;
-              		} break;
-              #else  /* !defined(_SC_KERNEL_BITS) */
-              	    puts ("hppa2.0"); break;
-              #endif
-              	default: puts ("hppa1.0"); break;
-              	}
-                  exit (0);
-              }
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
 EOF
 		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
 		    test -z "$HP_ARCH" && HP_ARCH=hppa
 		fi ;;
 	esac
 	if [ ${HP_ARCH} = "hppa2.0w" ]
 	then
 	    eval $set_cc_for_build
@@ -722,32 +746,32 @@ EOF
 	    echo ${UNAME_MACHINE}-unknown-osf1
 	fi
 	exit ;;
     parisc*:Lites*:*:*)
 	echo hppa1.1-hp-lites
 	exit ;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
 	echo c1-convex-bsd
-        exit ;;
+	exit ;;
     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
 	if getsysinfo -f scalar_acc
 	then echo c32-convex-bsd
 	else echo c2-convex-bsd
 	fi
-        exit ;;
+	exit ;;
     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
 	echo c34-convex-bsd
-        exit ;;
+	exit ;;
     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
 	echo c38-convex-bsd
-        exit ;;
+	exit ;;
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
 	echo c4-convex-bsd
-        exit ;;
+	exit ;;
     CRAY*Y-MP:*:*:*)
 	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
     CRAY*[A-Z]90:*:*:*)
 	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
 	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
 	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
 	      -e 's/\.[^.]*$/.X/'
@@ -761,63 +785,68 @@ EOF
     CRAY*SV1:*:*:*)
 	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
     *:UNICOS/mp:*:*)
 	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit ;;
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
     5000:UNIX_System_V:4.*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
 	exit ;;
     sparc*:BSD/OS:*:*)
 	echo sparc-unknown-bsdi${UNAME_RELEASE}
 	exit ;;
     *:BSD/OS:*:*)
 	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
 	exit ;;
     *:FreeBSD:*:*)
-	case ${UNAME_MACHINE} in
-	    pc98)
-		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
 	    amd64)
 		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	    *)
-		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	esac
 	exit ;;
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
     *:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
+    i*:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
     i*:windows32*:*)
-    	# uname -m includes "-pc" on this system.
-    	echo ${UNAME_MACHINE}-mingw32
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
 	exit ;;
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit ;;
-    *:Interix*:[3456]*)
-    	case ${UNAME_MACHINE} in
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
 	    x86)
 		echo i586-pc-interix${UNAME_RELEASE}
 		exit ;;
-	    EM64T | authenticamd | genuineintel)
+	    authenticamd | genuineintel | EM64T)
 		echo x86_64-unknown-interix${UNAME_RELEASE}
 		exit ;;
 	    IA64)
 		echo ia64-unknown-interix${UNAME_RELEASE}
 		exit ;;
 	esac ;;
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
 	echo i${UNAME_MACHINE}-pc-mks
@@ -840,55 +869,91 @@ EOF
     p*:CYGWIN*:*)
 	echo powerpcle-unknown-cygwin
 	exit ;;
     prep*:SunOS:5.*:*)
 	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
     *:GNU:*:*)
 	# the GNU system
-	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
 	exit ;;
     *:GNU/*:*:*)
 	# other systems with GNU libc and userland
-	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
 	exit ;;
     i*86:Minix:*:*)
 	echo ${UNAME_MACHINE}-pc-minix
 	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
     arm*:Linux:*:*)
 	eval $set_cc_for_build
 	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
 	    | grep -q __ARM_EABI__
 	then
-	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	else
-	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+	    fi
 	fi
 	exit ;;
     avr32*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     cris:Linux:*:*)
-	echo cris-axis-linux-gnu
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
 	exit ;;
     crisv32:Linux:*:*)
-	echo crisv32-axis-linux-gnu
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
 	exit ;;
     frv:Linux:*:*)
-    	echo frv-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
 	exit ;;
     ia64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     m32r*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     m68*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     mips:Linux:*:* | mips64:Linux:*:*)
 	eval $set_cc_for_build
 	sed 's/^	//' << EOF >$dummy.c
 	#undef CPU
 	#undef ${UNAME_MACHINE}
 	#undef ${UNAME_MACHINE}el
 	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
@@ -896,145 +961,87 @@ EOF
 	#else
 	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
 	CPU=${UNAME_MACHINE}
 	#else
 	CPU=
 	#endif
 	#endif
 EOF
-	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-	    /^CPU/{
-		s: ::g
-		p
-	    }'`"
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
 	;;
-    or32:Linux:*:*)
-	echo or32-unknown-linux-gnu
-	exit ;;
-    ppc:Linux:*:*)
-	echo powerpc-unknown-linux-gnu
+    or1k:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
-    ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-gnu
-	exit ;;
-    alpha:Linux:*:*)
-	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
-	  EV5)   UNAME_MACHINE=alphaev5 ;;
-	  EV56)  UNAME_MACHINE=alphaev56 ;;
-	  PCA56) UNAME_MACHINE=alphapca56 ;;
-	  PCA57) UNAME_MACHINE=alphapca56 ;;
-	  EV6)   UNAME_MACHINE=alphaev6 ;;
-	  EV67)  UNAME_MACHINE=alphaev67 ;;
-	  EV68*) UNAME_MACHINE=alphaev68 ;;
-        esac
-	objdump --private-headers /bin/sh | grep -q ld.so.1
-	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
-	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+    or32:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     padre:Linux:*:*)
-	echo sparc-unknown-linux-gnu
+	echo sparc-unknown-linux-${LIBC}
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
 	exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
 	# Look for CPU level
 	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
-	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
-	  *)    echo hppa-unknown-linux-gnu ;;
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
 	esac
 	exit ;;
-    parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-gnu
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
 	exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
-	echo ${UNAME_MACHINE}-ibm-linux
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
 	exit ;;
     sh64*:Linux:*:*)
-    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     sh*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     vax:Linux:*:*)
-	echo ${UNAME_MACHINE}-dec-linux-gnu
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
 	exit ;;
     x86_64:Linux:*:*)
-	echo x86_64-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     xtensa*:Linux:*:*)
-    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
-    i*86:Linux:*:*)
-	# The BFD linker knows what the default object file format is, so
-	# first see if it will tell us. cd to the root directory to prevent
-	# problems with other programs or directories called `ld' in the path.
-	# Set LC_ALL=C to ensure ld outputs messages in English.
-	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
-			 | sed -ne '/supported targets:/!d
-				    s/[ 	][ 	]*/ /g
-				    s/.*supported targets: *//
-				    s/ .*//
-				    p'`
-        case "$ld_supported_targets" in
-	  elf32-i386)
-		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
-		;;
-	esac
-	# Determine whether the default compiler is a.out or elf
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#include <features.h>
-	#ifdef __ELF__
-	# ifdef __GLIBC__
-	#  if __GLIBC__ >= 2
-	LIBC=gnu
-	#  else
-	LIBC=gnulibc1
-	#  endif
-	# else
-	LIBC=gnulibc1
-	# endif
-	#else
-	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-	LIBC=gnu
-	#else
-	LIBC=gnuaout
-	#endif
-	#endif
-	#ifdef __dietlibc__
-	LIBC=dietlibc
-	#endif
-EOF
-	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
-	    /^LIBC/{
-		s: ::g
-		p
-	    }'`"
-	test x"${LIBC}" != x && {
-		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
-		exit
-	}
-	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
-	;;
     i*86:DYNIX/ptx:4*:*)
 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
 	# earlier versions are messed up and put the nodename in both
 	# sysname and nodename.
 	echo i386-sequent-sysv4
 	exit ;;
     i*86:UNIX_SV:4.2MP:2.*)
-        # Unixware is an offshoot of SVR4, but it has its own version
-        # number series starting with 2...
-        # I am not positive that other SVR4 systems won't match this,
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
 	# I just have to hope.  -- rms.
-        # Use sysv4.2uw... so that sysv4* matches it.
+	# Use sysv4.2uw... so that sysv4* matches it.
 	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
 	exit ;;
     i*86:OS/2:*:*)
 	# If we were able to find `uname', then EMX Unix compatibility
 	# is probably installed.
 	echo ${UNAME_MACHINE}-pc-os2-emx
 	exit ;;
     i*86:XTS-300:*:STOP)
@@ -1056,17 +1063,17 @@ EOF
 	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
 	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
 		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
 	else
 		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
 	fi
 	exit ;;
     i*86:*:5:[678]*)
-    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
 	case `/bin/uname -X | grep "^Machine"` in
 	    *486*)	     UNAME_MACHINE=i486 ;;
 	    *Pentium)	     UNAME_MACHINE=i586 ;;
 	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
 	esac
 	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
 	exit ;;
     i*86:*:3.2:*)
@@ -1084,23 +1091,23 @@ EOF
 			&& UNAME_MACHINE=i686
 		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
 	else
 		echo ${UNAME_MACHINE}-pc-sysv32
 	fi
 	exit ;;
     pc:*:*:*)
 	# Left here for compatibility:
-        # uname -m prints for DJGPP always 'pc', but it prints nothing about
-        # the processor, so we play safe by assuming i586.
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
 	# Note: whatever this is, it MUST be the same as what config.sub
 	# prints for the "djgpp" host, or else GDB configury will decide that
 	# this is a cross-build.
 	echo i586-pc-msdosdjgpp
-        exit ;;
+	exit ;;
     Intel:Mach:3*:*)
 	echo i386-pc-mach3
 	exit ;;
     paragon:*:*:*)
 	echo i860-intel-osf1
 	exit ;;
     i860:*:4.*:*) # i860-SVR4
 	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
@@ -1125,18 +1132,18 @@ EOF
 	OS_REL=''
 	test -r /etc/.relid \
 	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
 	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
 	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
 	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && { echo i486-ncr-sysv4; exit; } ;;
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
     NCR*:*:4.2:* | MPRAS*:*:4.2:*)
 	OS_REL='.3'
 	test -r /etc/.relid \
 	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
 	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
 	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
 	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
@@ -1169,20 +1176,20 @@ EOF
     *:SINIX-*:*:*)
 	if uname -p 2>/dev/null >/dev/null ; then
 		UNAME_MACHINE=`(uname -p) 2>/dev/null`
 		echo ${UNAME_MACHINE}-sni-sysv4
 	else
 		echo ns32k-sni-sysv
 	fi
 	exit ;;
-    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                      # says <Richard.M.Bartel@ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
     *:UNIX_System_V:4*:FTX*)
 	# From Gerald Hewes <hewes@openmarket.com>.
 	# How about differentiating between stratus architectures? -djm
 	echo hppa1.1-stratus-sysv4
 	exit ;;
     *:*:*:FTX*)
 	# From seanf@swdc.stratus.com.
 	echo i860-stratus-sysv4
@@ -1198,33 +1205,36 @@ EOF
     mc68*:A/UX:*:*)
 	echo m68k-apple-aux${UNAME_RELEASE}
 	exit ;;
     news*:NEWS-OS:6*:*)
 	echo mips-sony-newsos6
 	exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
 	if [ -d /usr/nec ]; then
-	        echo mips-nec-sysv${UNAME_RELEASE}
+		echo mips-nec-sysv${UNAME_RELEASE}
 	else
-	        echo mips-unknown-sysv${UNAME_RELEASE}
+		echo mips-unknown-sysv${UNAME_RELEASE}
 	fi
-        exit ;;
+	exit ;;
     BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
 	echo powerpc-be-beos
 	exit ;;
     BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
 	echo powerpc-apple-beos
 	exit ;;
     BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
 	echo i586-pc-beos
 	exit ;;
     BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
 	echo i586-pc-haiku
 	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
     SX-4:SUPER-UX:*:*)
 	echo sx4-nec-superux${UNAME_RELEASE}
 	exit ;;
     SX-5:SUPER-UX:*:*)
 	echo sx5-nec-superux${UNAME_RELEASE}
 	exit ;;
     SX-6:SUPER-UX:*:*)
 	echo sx6-nec-superux${UNAME_RELEASE}
@@ -1241,37 +1251,58 @@ EOF
     Power*:Rhapsody:*:*)
 	echo powerpc-apple-rhapsody${UNAME_RELEASE}
 	exit ;;
     *:Rhapsody:*:*)
 	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
 	exit ;;
     *:Darwin:*:*)
 	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-	case $UNAME_PROCESSOR in
-	    i386) eval $set_cc_for_build
-	          if $CC_FOR_BUILD -E -dM -x c /dev/null | grep __LP64__>/dev/null 2>&1 ; then
-	            UNAME_PROCESSOR=x86_64
-	          fi ;;
-	    unknown) UNAME_PROCESSOR=powerpc ;;
-	esac
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
 	exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
 	UNAME_PROCESSOR=`uname -p`
 	if test "$UNAME_PROCESSOR" = "x86"; then
 		UNAME_PROCESSOR=i386
 		UNAME_MACHINE=pc
 	fi
 	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
 	exit ;;
     *:QNX:*:4*)
 	echo i386-pc-qnx
 	exit ;;
-    NSE-?:NONSTOP_KERNEL:*:*)
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
 	echo nse-tandem-nsk${UNAME_RELEASE}
 	exit ;;
     NSR-?:NONSTOP_KERNEL:*:*)
 	echo nsr-tandem-nsk${UNAME_RELEASE}
 	exit ;;
     *:NonStop-UX:*:*)
 	echo mips-compaq-nonstopux
 	exit ;;
@@ -1306,23 +1337,23 @@ EOF
 	exit ;;
     *:TOPS-20:*:*)
 	echo pdp10-unknown-tops20
 	exit ;;
     *:ITS:*:*)
 	echo pdp10-unknown-its
 	exit ;;
     SEI:*:*:SEIUX)
-        echo mips-sei-seiux${UNAME_RELEASE}
+	echo mips-sei-seiux${UNAME_RELEASE}
 	exit ;;
     *:DragonFly:*:*)
 	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
 	exit ;;
     *:*VMS:*:*)
-    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
 	case "${UNAME_MACHINE}" in
 	    A*) echo alpha-dec-vms ; exit ;;
 	    I*) echo ia64-dec-vms ; exit ;;
 	    V*) echo vax-dec-vms ; exit ;;
 	esac ;;
     *:XENIX:*:SysV)
 	echo i386-pc-xenix
 	exit ;;
@@ -1330,169 +1361,21 @@ EOF
 	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
 	exit ;;
     i*86:rdos:*:*)
 	echo ${UNAME_MACHINE}-pc-rdos
 	exit ;;
     i*86:AROS:*:*)
 	echo ${UNAME_MACHINE}-pc-aros
 	exit ;;
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
+	exit ;;
 esac
 
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-          "4"
-#else
-	  ""
-#endif
-         ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-    struct utsname un;
-
-    uname(&un);
-
-    if (strncmp(un.version, "V2", 2) == 0) {
-	printf ("i386-sequent-ptx2\n"); exit (0);
-    }
-    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-	printf ("i386-sequent-ptx1\n"); exit (0);
-    }
-    printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-#  include <sys/param.h>
-#  if defined (BSD)
-#   if BSD == 43
-      printf ("vax-dec-bsd4.3\n"); exit (0);
-#   else
-#    if BSD == 199006
-      printf ("vax-dec-bsd4.3reno\n"); exit (0);
-#    else
-      printf ("vax-dec-bsd\n"); exit (0);
-#    endif
-#   endif
-#  else
-    printf ("vax-dec-bsd\n"); exit (0);
-#  endif
-# else
-    printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
-	{ echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
-    case `getsysinfo -f cpu_type` in
-    c1*)
-	echo c1-convex-bsd
-	exit ;;
-    c2*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-	exit ;;
-    c34*)
-	echo c34-convex-bsd
-	exit ;;
-    c38*)
-	echo c38-convex-bsd
-	exit ;;
-    c4*)
-	echo c4-convex-bsd
-	exit ;;
-    esac
-fi
-
 cat >&2 <<EOF
 $0: unable to guess system type
 
 This script, last modified $timestamp, has failed to recognize
 the operating system you are using. It is advised that you
 download the most up to date version of the config scripts from
 
   http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
--- a/build/autoconf/config.sub
+++ b/build/autoconf/config.sub
@@ -1,43 +1,36 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-#   Free Software Foundation, Inc.
+#   Copyright 1992-2014 Free Software Foundation, Inc.
 
-timestamp='2011-01-03'
+timestamp='2014-01-01'
 
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine.  It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 #
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
 
 
-# Please send patches to <config-patches@gnu.org>.  Submit a context
-# diff and a properly formatted GNU ChangeLog entry.
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
 #
 # Configuration subroutine to validate and canonicalize a configuration type.
 # Supply the specified configuration type as an argument.
 # If it is invalid, we print an error message on stderr and exit with code 1.
 # Otherwise, we print the canonical config type on stdout and succeed.
 
 # You can get the latest version of this script from:
 # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
@@ -70,18 +63,17 @@ Operation modes:
   -t, --time-stamp   print date of last modification, then exit
   -v, --version      print version number, then exit
 
 Report bugs and patches to <config-patches@gnu.org>."
 
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+Copyright 1992-2014 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 
 help="
 Try \`$me --help' for more information."
 
 # Parse command line
@@ -118,20 +110,21 @@ case $# in
  *) echo "$me: too many arguments$help" >&2
     exit 1;;
 esac
 
 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
-  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
   kopensolaris*-gnu* | \
-  storm-chaos* | os2-emx* | rtmk-nova* | wince-winmo*)
+  storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
   *)
     basic_machine=`echo $1 | sed 's/-[^-]*$//'`
     if [ $basic_machine != $1 ]
     then os=`echo $1 | sed 's/.*-/-/'`
     else os=; fi
@@ -147,41 +140,41 @@ case $os in
 		# Prevent following clause from handling this invalid input.
 		;;
 	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
 	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
 	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple | -axis | -knuth | -cray | -microblaze)
+	-apple | -axis | -knuth | -cray | -microblaze*)
 		os=
 		basic_machine=$1
 		;;
-        -bluegene*)
-	        os=-cnk
+	-bluegene*)
+		os=-cnk
 		;;
 	-sim | -cisco | -oki | -wec | -winbond)
 		os=
 		basic_machine=$1
 		;;
 	-scout)
 		;;
 	-wrs)
 		os=-vxworks
 		basic_machine=$1
 		;;
 	-chorusos*)
 		os=-chorusos
 		basic_machine=$1
 		;;
- 	-chorusrdb)
- 		os=-chorusrdb
+	-chorusrdb)
+		os=-chorusrdb
 		basic_machine=$1
- 		;;
+		;;
 	-hiux*)
 		os=-hiuxwe2
 		;;
 	-sco6)
 		os=-sco5v6
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
 	-sco5)
@@ -216,16 +209,22 @@ case $os in
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
 	-clix*)
 		basic_machine=clipper-intergraph
 		;;
 	-isc*)
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
 	-lynx*)
 		os=-lynxos
 		;;
 	-ptx*)
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
 		;;
 	-windowsnt*)
 		os=`echo $os | sed -e 's/windowsnt/winnt/'`
@@ -240,30 +239,38 @@ case $os in
 esac
 
 # Decode aliases for certain CPU-COMPANY combinations.
 case $basic_machine in
 	# Recognize the basic CPU types without company name.
 	# Some are omitted here because they have special meanings below.
 	1750a | 580 \
 	| a29k \
+	| aarch64 | aarch64_be \
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
-	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| be32 | be64 \
 	| bfin \
-	| c4x | clipper \
+	| c4x | c8051 | clipper \
 	| d10v | d30v | dlx | dsp16xx \
+	| epiphany \
 	| fido | fr30 | frv \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
 	| i370 | i860 | i960 | ia64 \
 	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
 	| lm32 \
 	| m32c | m32r | m32rle | m68000 | m68k | m88k \
-	| maxq | mb | microblaze | mcore | mep | metag \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
 	| mips64octeon | mips64octeonel \
 	| mips64orion | mips64orionel \
 	| mips64r5900 | mips64r5900el \
 	| mips64vr | mips64vrel \
 	| mips64vr4100 | mips64vr4100el \
@@ -271,84 +278,118 @@ case $basic_machine in
 	| mips64vr5000 | mips64vr5000el \
 	| mips64vr5900 | mips64vr5900el \
 	| mipsisa32 | mipsisa32el \
 	| mipsisa32r2 | mipsisa32r2el \
 	| mipsisa64 | mipsisa64el \
 	| mipsisa64r2 | mipsisa64r2el \
 	| mipsisa64sb1 | mipsisa64sb1el \
 	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
 	| mipstx39 | mipstx39el \
 	| mn10200 | mn10300 \
 	| moxie \
 	| mt \
 	| msp430 \
-	| nios | nios2 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
 	| ns16k | ns32k \
-	| or32 \
+	| open8 \
+	| or1k | or32 \
 	| pdp10 | pdp11 | pj | pjl \
-	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
 	| pyramid \
+	| rl78 | rx \
 	| score \
 	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
-	| spu | strongarm \
-	| tahoe | thumb | tic4x | tic80 | tron \
-	| v850 | v850e \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
 	| we32k \
-	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| x86 | xc16x | xstormy16 | xtensa \
 	| z8k | z80)
 		basic_machine=$basic_machine-unknown
 		;;
-	m6811 | m68hc11 | m6812 | m68hc12)
-		# Motorola 68HC11/12.
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
 		basic_machine=$basic_machine-unknown
 		os=-none
 		;;
 	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
 		;;
 	ms1)
 		basic_machine=mt-unknown
 		;;
 
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
 	# We use `pc' rather than `unknown'
 	# because (1) that's what they normally are, and
 	# (2) the word "unknown" tends to confuse beginning users.
 	i*86 | x86_64)
 	  basic_machine=$basic_machine-pc
 	  ;;
 	# Object if more than one company name word.
 	*-*-*)
 		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
 		exit 1
 		;;
 	# Recognize the basic CPU types with company name.
 	580-* \
 	| a29k-* \
+	| aarch64-* | aarch64_be-* \
 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
-	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* | avr32-* \
+	| be32-* | be64-* \
 	| bfin-* | bs2000-* \
-	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
-	| clipper-* | craynv-* | cydra-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
 	| elxsi-* \
 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
 	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
 	| lm32-* \
 	| m32c-* | m32r-* | m32rle-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 	| mips16-* \
 	| mips64-* | mips64el-* \
 	| mips64octeon-* | mips64octeonel-* \
 	| mips64orion-* | mips64orionel-* \
 	| mips64r5900-* | mips64r5900el-* \
 	| mips64vr-* | mips64vrel-* \
 	| mips64vr4100-* | mips64vr4100el-* \
@@ -356,38 +397,44 @@ case $basic_machine in
 	| mips64vr5000-* | mips64vr5000el-* \
 	| mips64vr5900-* | mips64vr5900el-* \
 	| mipsisa32-* | mipsisa32el-* \
 	| mipsisa32r2-* | mipsisa32r2el-* \
 	| mipsisa64-* | mipsisa64el-* \
 	| mipsisa64r2-* | mipsisa64r2el-* \
 	| mipsisa64sb1-* | mipsisa64sb1el-* \
 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
 	| mipstx39-* | mipstx39el-* \
 	| mmix-* \
 	| mt-* \
 	| msp430-* \
-	| nios-* | nios2-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
-	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
 	| pyramid-* \
-	| romp-* | rs6000-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
 	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
-	| tahoe-* | thumb-* \
-	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
 	| tron-* \
-	| v850-* | v850e-* | vax-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
 	| we32k-* \
-	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
 	| xstormy16-* | xtensa*-* \
 	| ymp-* \
 	| z8k-* | z80-*)
 		;;
 	# Recognize the basic CPU types without company name, with glob match.
 	xtensa*)
 		basic_machine=$basic_machine-unknown
 		;;
@@ -402,17 +449,17 @@ case $basic_machine in
 		;;
 	3b*)
 		basic_machine=we32k-att
 		;;
 	a29khif)
 		basic_machine=a29k-amd
 		os=-udi
 		;;
-    	abacus)
+	abacus)
 		basic_machine=abacus-unknown
 		;;
 	adobe68k)
 		basic_machine=m68010-adobe
 		os=-scout
 		;;
 	alliant | fx80)
 		basic_machine=fx80-alliant
@@ -472,21 +519,30 @@ case $basic_machine in
 	blackfin-*)
 		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
 		os=-linux
 		;;
 	bluegene*)
 		basic_machine=powerpc-ibm
 		os=-cnk
 		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	c90)
 		basic_machine=c90-cray
 		os=-unicos
 		;;
-        cegcc)
+	cegcc)
 		basic_machine=arm-unknown
 		os=-cegcc
 		;;
 	convex-c1)
 		basic_machine=c1-convex
 		os=-bsd
 		;;
 	convex-c2)
@@ -508,17 +564,17 @@ case $basic_machine in
 	cray | j90)
 		basic_machine=j90-cray
 		os=-unicos
 		;;
 	craynv)
 		basic_machine=craynv-cray
 		os=-unicosmp
 		;;
-	cr16)
+	cr16 | cr16-*)
 		basic_machine=cr16-unknown
 		os=-elf
 		;;
 	crds | unos)
 		basic_machine=m68k-crds
 		;;
 	crisv32 | crisv32-* | etraxfs*)
 		basic_machine=crisv32-axis
@@ -666,17 +722,16 @@ case $basic_machine in
 		;;
 	hppro)
 		basic_machine=hppa1.1-hp
 		os=-proelf
 		;;
 	i370-ibm* | ibm*)
 		basic_machine=i370-ibm
 		;;
-# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
 	i*86v32)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-sysv32
 		;;
 	i*86v4*)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-sysv4
 		;;
@@ -724,21 +779,25 @@ case $basic_machine in
 	magnum | m3230)
 		basic_machine=mips-mips
 		os=-sysv
 		;;
 	merlin)
 		basic_machine=ns32k-utek
 		os=-sysv
 		;;
-        microblaze)
+	microblaze*)
 		basic_machine=microblaze-xilinx
 		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
 	mingw32)
-		basic_machine=i386-pc
+		basic_machine=i686-pc
 		os=-mingw32
 		;;
 	mingw32ce)
 		basic_machine=arm-unknown
 		os=-mingw32ce
 		;;
 	miniframe)
 		basic_machine=m68000-convergent
@@ -763,20 +822,28 @@ case $basic_machine in
 		;;
 	msdos)
 		basic_machine=i386-pc
 		os=-msdos
 		;;
 	ms1-*)
 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
 		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
 	mvs)
 		basic_machine=i370-ibm
 		os=-mvs
 		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
 	ncr3000)
 		basic_machine=i486-ncr
 		os=-sysv4
 		;;
 	netbsd386)
 		basic_machine=i386-unknown
 		os=-netbsd
 		;;
@@ -831,16 +898,22 @@ case $basic_machine in
 		;;
 	nonstopux)
 		basic_machine=mips-compaq
 		os=-nonstopux
 		;;
 	np1)
 		basic_machine=np1-gould
 		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
 	nsr-tandem)
 		basic_machine=nsr-tandem
 		;;
 	op50n-* | op60c-*)
 		basic_machine=hppa1.1-oki
 		os=-proelf
 		;;
 	openrisc | openrisc-*)
@@ -913,19 +986,20 @@ case $basic_machine in
 	pentium4-*)
 		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	pn)
 		basic_machine=pn-gould
 		;;
 	power)	basic_machine=power-ibm
 		;;
-	ppc)	basic_machine=powerpc-unknown
+	ppc | ppcbe)	basic_machine=powerpc-unknown
 		;;
-	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppcle | powerpclittle | ppc-le | powerpc-little)
 		basic_machine=powerpcle-unknown
 		;;
 	ppcle-* | powerpclittle-*)
 		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppc64)	basic_machine=powerpc64-unknown
@@ -940,17 +1014,21 @@ case $basic_machine in
 		;;
 	ps2)
 		basic_machine=i386-ibm
 		;;
 	pw32)
 		basic_machine=i586-unknown
 		os=-pw32
 		;;
-	rdos)
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
 		basic_machine=i386-pc
 		os=-rdos
 		;;
 	rom68k)
 		basic_machine=m68k-rom68k
 		os=-coff
 		;;
 	rm[46]00)
@@ -1009,16 +1087,19 @@ case $basic_machine in
 		;;
 	st2000)
 		basic_machine=m68k-tandem
 		;;
 	stratus)
 		basic_machine=i860-stratus
 		os=-sysv4
 		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	sun2)
 		basic_machine=m68000-sun
 		;;
 	sun2os3)
 		basic_machine=m68000-sun
 		os=-sunos3
 		;;
 	sun2os4)
@@ -1065,30 +1146,18 @@ case $basic_machine in
 	t3e)
 		basic_machine=alphaev5-cray
 		os=-unicos
 		;;
 	t90)
 		basic_machine=t90-cray
 		os=-unicos
 		;;
-	tic54x | c54x*)
-		basic_machine=tic54x-unknown
-		os=-coff
-		;;
-	tic55x | c55x*)
-		basic_machine=tic55x-unknown
-		os=-coff
-		;;
-	tic6x | c6x*)
-		basic_machine=tic6x-unknown
-		os=-coff
-		;;
 	tile*)
-		basic_machine=tile-unknown
+		basic_machine=$basic_machine-unknown
 		os=-linux-gnu
 		;;
 	tx39)
 		basic_machine=mipstx39-unknown
 		;;
 	tx39el)
 		basic_machine=mipstx39el-unknown
 		;;
@@ -1148,16 +1217,19 @@ case $basic_machine in
 		;;
 	xbox)
 		basic_machine=i686-pc
 		os=-mingw32
 		;;
 	xps | xps100)
 		basic_machine=xps100-honeywell
 		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
 	ymp)
 		basic_machine=ymp-cray
 		os=-unicos
 		;;
 	z8k-*-coff)
 		basic_machine=z8k-unknown
 		os=-sim
 		;;
@@ -1245,19 +1317,22 @@ case $basic_machine in
 		;;
 esac
 
 # Decode manufacturer-specific aliases for certain operating systems.
 
 if [ x"$os" != x"" ]
 then
 case $os in
-        # First match some system type aliases
-        # that might get confused with valid system types.
+	# First match some system type aliases
+	# that might get confused with valid system types.
 	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
 	-solaris1 | -solaris1.*)
 		os=`echo $os | sed -e 's|solaris1|sunos4|'`
 		;;
 	-solaris)
 		os=-solaris2
 		;;
 	-svr4*)
 		os=-sysv4
@@ -1269,39 +1344,40 @@ case $os in
 		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
 		;;
 	# First accept the basic system types.
 	# The portable systems comes first.
 	# Each alternative MUST END IN A *, to match a version number.
 	# -sysv* is not here because it comes later, after sysvr4.
 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
 	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
-	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
-	      | -kopensolaris* \
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
 	      | -aos* | -aros* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-	      | -openbsd* | -solidbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* \
 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* | -cegcc* \
-	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -mingw64* | -linux-gnu* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -winmo*)
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
 		case $basic_machine in
 		    x86-* | i*86-*)
 			;;
 		    *)
 			os=-nto$os
@@ -1330,22 +1406,19 @@ case $os in
 		os=`echo $os | sed -e 's|sunos5|solaris2|'`
 		;;
 	-sunos6*)
 		os=`echo $os | sed -e 's|sunos6|solaris3|'`
 		;;
 	-opened*)
 		os=-openedition
 		;;
-        -os400*)
+	-os400*)
 		os=-os400
 		;;
-	-wince-winmo*)
-		os=-wince-winmo
-		;;
 	-wince*)
 		os=-wince
 		;;
 	-osfrose*)
 		os=-osfrose
 		;;
 	-osf*)
 		os=-osf
@@ -1382,17 +1455,17 @@ case $os in
 		;;
 	# Preserve the version number of sinix5.
 	-sinix5.*)
 		os=`echo $os | sed -e 's|sinix|sysv|'`
 		;;
 	-sinix*)
 		os=-sysv4
 		;;
-        -tpf*)
+	-tpf*)
 		os=-tpf
 		;;
 	-triton*)
 		os=-sysv3
 		;;
 	-oss*)
 		os=-sysv3
 		;;
@@ -1418,28 +1491,27 @@ case $os in
 		os=-xenix
 		;;
 	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
 		os=-mint
 		;;
 	-aros*)
 		os=-aros
 		;;
-	-kaos*)
-		os=-kaos
-		;;
 	-zvmoe)
 		os=-zvmoe
 		;;
 	-dicos*)
 		os=-dicos
 		;;
         -android*)
 	        os=-android
                 ;;
+	-nacl*)
+		;;
 	-none)
 		;;
 	*)
 		# Get rid of the `-' at the beginning of $os.
 		os=`echo $os | sed 's/[^-]*-//'`
 		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
 		exit 1
 		;;
@@ -1452,33 +1524,48 @@ else
 
 # Note that if you're going to try to match "-MANUFACTURER" here (say,
 # "-sun"), then you have to tell the case statement up towards the top
 # that MANUFACTURER isn't an operating system.  Otherwise, code above
 # will signal an error saying that MANUFACTURER isn't an operating
 # system, and we'll never get to this point.
 
 case $basic_machine in
-        score-*)
+	score-*)
 		os=-elf
 		;;
-        spu-*)
+	spu-*)
 		os=-elf
 		;;
 	*-acorn)
 		os=-riscix1.2
 		;;
 	arm*-rebel)
 		os=-linux
 		;;
 	arm*-semi)
 		os=-aout
 		;;
-        c4x-* | tic4x-*)
-        	os=-coff
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
 		;;
 	# This must come before the *-dec entry.
 	pdp10-*)
 		os=-tops20
 		;;
 	pdp11-*)
 		os=-none
 		;;
@@ -1488,32 +1575,32 @@ case $basic_machine in
 	m68*-apollo)
 		os=-domain
 		;;
 	i386-sun)
 		os=-sunos4.0.2
 		;;
 	m68000-sun)
 		os=-sunos3
-		# This also exists in the configure program, but was not the
-		# default.
-		# os=-sunos4
 		;;
 	m68*-cisco)
 		os=-aout
 		;;
-        mep-*)
+	mep-*)
 		os=-elf
 		;;
 	mips*-cisco)
 		os=-elf
 		;;
 	mips*-*)
 		os=-elf
 		;;
+	or1k-*)
+		os=-elf
+		;;
 	or32-*)
 		os=-coff
 		;;
 	*-tti)	# must be before sparc entry or we get the wrong os.
 		os=-sysv3
 		;;
 	sparc-* | *-sun)
 		os=-sunos4.1.1
@@ -1522,17 +1609,17 @@ case $basic_machine in
 		os=-beos
 		;;
 	*-haiku)
 		os=-haiku
 		;;
 	*-ibm)
 		os=-aix
 		;;
-    	*-knuth)
+	*-knuth)
 		os=-mmixware
 		;;
 	*-wec)
 		os=-proelf
 		;;
 	*-winbond)
 		os=-proelf
 		;;
--- a/configure.in
+++ b/configure.in
@@ -1139,17 +1139,17 @@ esac
 
 # Only set CPU_ARCH if we recognize the value of OS_TEST
 
 case "$OS_TEST" in
 *86 | i86pc)
     CPU_ARCH=x86
     ;;
 
-powerpc64 | ppc64)
+powerpc64 | ppc64 | powerpc64le | ppc64le)
     CPU_ARCH=ppc64
     ;;
 
 powerpc | ppc | rs6000)
     CPU_ARCH=ppc
     ;;
 
 Alpha | alpha | ALPHA)
--- a/content/media/gstreamer/GStreamerFunctionList.h
+++ b/content/media/gstreamer/GStreamerFunctionList.h
@@ -91,16 +91,17 @@ GST_FUNC(LIBGSTREAMER, gst_pad_set_buffe
 GST_FUNC(LIBGSTREAMER, gst_registry_get_default)
 GST_FUNC(LIBGSTREAMER, gst_segment_set_newsegment)
 GST_FUNC(LIBGSTVIDEO, gst_video_format_get_component_height)
 GST_FUNC(LIBGSTVIDEO, gst_video_format_get_component_offset)
 GST_FUNC(LIBGSTVIDEO, gst_video_format_get_component_width)
 GST_FUNC(LIBGSTVIDEO, gst_video_format_get_pixel_stride)
 GST_FUNC(LIBGSTVIDEO, gst_video_format_get_row_stride)
 GST_FUNC(LIBGSTVIDEO, gst_video_format_parse_caps)
+GST_FUNC(LIBGSTVIDEO, gst_video_parse_caps_pixel_aspect_ratio)
 #else
 
 GST_FUNC(LIBGSTAPP, gst_app_sink_pull_sample)
 GST_FUNC(LIBGSTREAMER, _gst_caps_any)
 GST_FUNC(LIBGSTREAMER, gst_allocator_get_type)
 GST_FUNC(LIBGSTREAMER, gst_buffer_copy_into)
 GST_FUNC(LIBGSTREAMER, gst_buffer_extract)
 GST_FUNC(LIBGSTREAMER, gst_buffer_get_meta)
--- a/content/media/gstreamer/GStreamerReader.cpp
+++ b/content/media/gstreamer/GStreamerReader.cpp
@@ -989,32 +989,52 @@ void GStreamerReader::AudioPreroll()
   gst_object_unref(sinkpad);
 }
 
 void GStreamerReader::VideoPreroll()
 {
   /* The first video buffer has reached the video sink. Get width and height */
   LOG(PR_LOG_DEBUG, "Video preroll");
   GstPad* sinkpad = gst_element_get_static_pad(GST_ELEMENT(mVideoAppSink), "sink");
+  int PARNumerator, PARDenominator;
 #if GST_VERSION_MAJOR >= 1
   GstCaps* caps = gst_pad_get_current_caps(sinkpad);
   memset (&mVideoInfo, 0, sizeof (mVideoInfo));
   gst_video_info_from_caps(&mVideoInfo, caps);
   mFormat = mVideoInfo.finfo->format;
   mPicture.width = mVideoInfo.width;
   mPicture.height = mVideoInfo.height;
+  PARNumerator = GST_VIDEO_INFO_PAR_N(&mVideoInfo);
+  PARDenominator = GST_VIDEO_INFO_PAR_D(&mVideoInfo);
 #else
   GstCaps* caps = gst_pad_get_negotiated_caps(sinkpad);
   gst_video_format_parse_caps(caps, &mFormat, &mPicture.width, &mPicture.height);
+  if (!gst_video_parse_caps_pixel_aspect_ratio(caps, &PARNumerator, &PARDenominator)) {
+    PARNumerator = 1;
+    PARDenominator = 1;
+  }
 #endif
-  GstStructure* structure = gst_caps_get_structure(caps, 0);
-  gst_structure_get_fraction(structure, "framerate", &fpsNum, &fpsDen);
   NS_ASSERTION(mPicture.width && mPicture.height, "invalid video resolution");
-  mInfo.mVideo.mDisplay = ThebesIntSize(mPicture.Size());
-  mInfo.mVideo.mHasVideo = true;
+
+  // Calculate display size according to pixel aspect ratio.
+  nsIntRect pictureRect(0, 0, mPicture.width, mPicture.height);
+  nsIntSize frameSize = nsIntSize(mPicture.width, mPicture.height);
+  nsIntSize displaySize = nsIntSize(mPicture.width, mPicture.height);
+  ScaleDisplayByAspectRatio(displaySize, float(PARNumerator) / float(PARDenominator));
+
+  // If video frame size is overflow, stop playing.
+  if (IsValidVideoRegion(frameSize, pictureRect, displaySize)) {
+    GstStructure* structure = gst_caps_get_structure(caps, 0);
+    gst_structure_get_fraction(structure, "framerate", &fpsNum, &fpsDen);
+    mInfo.mVideo.mDisplay = ThebesIntSize(displaySize.ToIntSize());
+    mInfo.mVideo.mHasVideo = true;
+  } else {
+    LOG(PR_LOG_DEBUG, "invalid video region");
+    Eos();
+  }
   gst_caps_unref(caps);
   gst_object_unref(sinkpad);
 }
 
 GstFlowReturn GStreamerReader::NewBufferCb(GstAppSink* aSink,
                                            gpointer aUserData)
 {
   GStreamerReader* reader = reinterpret_cast<GStreamerReader*>(aUserData);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1415,16 +1415,23 @@ DOMInterfaces = {
     'wrapperCache': False
 },
 
 'WebGLVertexArray': {
     'nativeType': 'mozilla::WebGLVertexArray',
     'headerFile': 'WebGLVertexArray.h'
 },
 
+'WebrtcGlobalInformation': {
+    'nativeType': 'mozilla::dom::WebrtcGlobalInformation',
+    'headerFile': 'WebrtcGlobalInformation.h',
+    'wrapperCache': False,
+    'concrete': False,
+},
+
 'WebSocket': {
     'headerFile': 'WebSocket.h',
 },
 
 'Window': {
     'nativeType': 'nsGlobalWindow',
     # When turning on Window, remember to drop the "'register': False"
     # from ChromeWindow.
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -629,21 +629,16 @@ TabChild::HandlePossibleViewportChange()
     CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom();
     MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom &&
                defaultZoom <= viewportInfo.GetMaxZoom());
     metrics.mZoom = defaultZoom;
 
     metrics.mScrollId = viewId;
   }
 
-  metrics.mDisplayPort = AsyncPanZoomController::CalculatePendingDisplayPort(
-    // The page must have been refreshed in some way such as a new document or
-    // new CSS viewport, so we know that there's no velocity, acceleration, and
-    // we have no idea how long painting will take.
-    metrics, ScreenPoint(0.0f, 0.0f), 0.0);
   metrics.mCumulativeResolution = metrics.mZoom / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
   // This is the root layer, so the cumulative resolution is the same
   // as the resolution.
   metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
   utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale);
 
   CSSSize scrollPort = metrics.CalculateCompositedRectInCssPixels().Size();
   utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);
@@ -654,16 +649,24 @@ TabChild::HandlePossibleViewportChange()
 
   CSSSize pageSize = GetPageSize(document, viewport);
   if (!pageSize.width) {
     // Return early rather than divide by 0.
     return;
   }
   metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize);
 
+  // Calculate a display port _after_ having a scrollable rect because the
+  // display port is clamped to the scrollable rect.
+  metrics.mDisplayPort = AsyncPanZoomController::CalculatePendingDisplayPort(
+    // The page must have been refreshed in some way such as a new document or
+    // new CSS viewport, so we know that there's no velocity, acceleration, and
+    // we have no idea how long painting will take.
+    metrics, ScreenPoint(0.0f, 0.0f), 0.0);
+
   // Force a repaint with these metrics. This, among other things, sets the
   // displayport, so we start with async painting.
   ProcessUpdateFrame(metrics);
 
   if (viewportInfo.IsZoomAllowed() && scrollIdentifiersValid) {
     // If the CSS viewport is narrower than the screen (i.e. width <= device-width)
     // then we disable double-tap-to-zoom behaviour.
     bool allowDoubleTapZoom = (viewport.width > screenW / metrics.mDevPixelsPerCSSPixel.scale);
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -9,26 +9,24 @@ const {classes: Cc, interfaces: Ci, util
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PopupNotifications.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PeerConnectionIdp",
   "resource://gre/modules/media/PeerConnectionIdp.jsm");
 
 const PC_CONTRACT = "@mozilla.org/dom/peerconnection;1";
-const WEBRTC_GLOBAL_CONTRACT = "@mozilla.org/dom/webrtcglobalinformation1";
 const PC_OBS_CONTRACT = "@mozilla.org/dom/peerconnectionobserver;1";
 const PC_ICE_CONTRACT = "@mozilla.org/dom/rtcicecandidate;1";
 const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
 const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
 const PC_STATS_CONTRACT = "@mozilla.org/dom/rtcstatsreport;1";
 const PC_IDENTITY_CONTRACT = "@mozilla.org/dom/rtcidentityassertion;1";
 
 const PC_CID = Components.ID("{00e0e20d-1494-4776-8e0e-0f0acbea3c79}");
-const WEBRTC_GLOBAL_CID = Components.ID("{f6063d11-f467-49ad-9765-e7923050dc08}");
 const PC_OBS_CID = Components.ID("{d1748d4c-7f6a-4dc5-add6-d55b7678537e}");
 const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
 const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
 const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
 const PC_STATS_CID = Components.ID("{7fe6e18b-0da3-4056-bf3b-440ef3809e06}");
 const PC_IDENTITY_CID = Components.ID("{1abc7499-3c54-43e0-bd60-686e2703f072}");
 
 // Global list of PeerConnection objects, so they can be cleaned up when
@@ -119,82 +117,19 @@ GlobalPCList.prototype = {
         // this._list shold be empty here
         this._networkdown = true;
       } else if (data == "online") {
         this._networkdown = false;
       }
     }
   },
 
-  getStatsForEachPC: function(callback, errorCallback) {
-    function getStatsFromPC(pcref) {
-      try {
-        pcref.get().getStatsInternal(null, callback, errorCallback);
-      } catch (e) {
-        errorCallback("Some error getting stats from PC: " + e.toString());
-      }
-    }
-
-    for (let winId in this._list) {
-      if (this._list.hasOwnProperty(winId)) {
-        this.removeNullRefs(winId);
-        if (this._list[winId]) {
-          this._list[winId].forEach(getStatsFromPC);
-        }
-      }
-    }
-  },
-
-  // TODO(bcampen@mozilla.com): Handle this with a global object in c++
-  // (Bug 958221)
-  getLoggingFromFirstPC: function(pattern, callback, errorCallback) {
-    for (let winId in this._list) {
-      this.removeNullRefs(winId);
-      if (this._list[winId]) {
-        // We expect removeNullRefs to not leave us with an empty array here
-        let pcref = this._list[winId][0];
-        pcref.get().getLogging(pattern, callback, errorCallback);
-        return;
-      }
-    }
-  },
 };
 let _globalPCList = new GlobalPCList();
 
-function WebrtcGlobalInformation() {
-}
-WebrtcGlobalInformation.prototype = {
-  classDescription: "WebrtcGlobalInformation",
-  classID: WEBRTC_GLOBAL_CID,
-  contractID: WEBRTC_GLOBAL_CONTRACT,
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
-
-  getAllStats: function(successCallback, failureCallback) {
-    // TODO(bcampen@mozilla.com): Move the work of fanout into c++, and
-    // only callback once. (Bug 958221)
-    if (_globalPCList) {
-      _globalPCList.getStatsForEachPC(successCallback, failureCallback);
-    } else {
-      failureCallback("No global PeerConnection list");
-    }
-  },
-
-  getLogs: function(pattern, callback, errorCallback) {
-    if (_globalPCList) {
-      _globalPCList.getLoggingFromFirstPC(pattern, callback, errorCallback);
-    } else {
-      errorCallback("No global PeerConnection list");
-    }
-  },
-
-  getCandPairLogs: function(candPairId, callback, errorCallback) {
-    this.getLogs('CAND-PAIR(' + candPairId + ')', callback, errorCallback);
-  },
-};
-
 function RTCIceCandidate() {
   this.candidate = this.sdpMid = this.sdpMLineIndex = null;
 }
 RTCIceCandidate.prototype = {
   classDescription: "mozRTCIceCandidate",
   classID: PC_ICE_CID,
   contractID: PC_ICE_CONTRACT,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
@@ -320,18 +255,16 @@ function RTCPeerConnection() {
   this._closed = false;
 
   this._onCreateOfferSuccess = null;
   this._onCreateOfferFailure = null;
   this._onCreateAnswerSuccess = null;
   this._onCreateAnswerFailure = null;
   this._onGetStatsSuccess = null;
   this._onGetStatsFailure = null;
-  this._onGetLoggingSuccess = null;
-  this._onGetLoggingFailure = null;
 
   this._pendingType = null;
   this._localType = null;
   this._remoteType = null;
   this._trickleIce = false;
   this._peerIdentity = null;
 
   /**
@@ -917,49 +850,26 @@ RTCPeerConnection.prototype = {
   changeIceConnectionState: function(state) {
     this._iceConnectionState = state;
     this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
   },
 
   getStats: function(selector, onSuccess, onError) {
     this._queueOrRun({
       func: this._getStats,
-      args: [selector, onSuccess, onError, false],
-      wait: true
-    });
-  },
-
-  getStatsInternal: function(selector, onSuccess, onError) {
-    this._queueOrRun({
-      func: this._getStats,
-      args: [selector, onSuccess, onError, true],
+      args: [selector, onSuccess, onError],
       wait: true
     });
   },
 
-  _getStats: function(selector, onSuccess, onError, internal) {
+  _getStats: function(selector, onSuccess, onError) {
     this._onGetStatsSuccess = onSuccess;
     this._onGetStatsFailure = onError;
 
-    this._impl.getStats(selector, internal);
-  },
-
-  getLogging: function(pattern, onSuccess, onError) {
-    this._queueOrRun({
-      func: this._getLogging,
-      args: [pattern, onSuccess, onError],
-      wait: true
-    });
-  },
-
-  _getLogging: function(pattern, onSuccess, onError) {
-    this._onGetLoggingSuccess = onSuccess;
-    this._onGetLoggingFailure = onError;
-
-    this._impl.getLogging(pattern);
+    this._impl.getStats(selector);
   },
 
   createDataChannel: function(label, dict) {
     this._checkClosed();
     if (dict == undefined) {
       dict = {};
     }
     if (dict.maxRetransmitNum != undefined) {
@@ -1301,26 +1211,16 @@ PeerConnectionObserver.prototype = {
     this._dompc._executeNext();
   },
 
   onGetStatsError: function(code, message) {
     this.callCB(this._dompc._onGetStatsFailure, new RTCError(code, message));
     this._dompc._executeNext();
   },
 
-  onGetLoggingSuccess: function(logs) {
-    this.callCB(this._dompc._onGetLoggingSuccess, logs);
-    this._dompc._executeNext();
-  },
-
-  onGetLoggingError: function(code, message) {
-    this.callCB(this._dompc._onGetLoggingFailure, new RTCError(code, message));
-    this._dompc._executeNext();
-  },
-
   onAddStream: function(stream) {
     this.dispatchEvent(new this._dompc._win.MediaStreamEvent("addstream",
                                                              { stream: stream }));
   },
 
   onRemoveStream: function(stream, type) {
     this.dispatchEvent(new this._dompc._win.MediaStreamEvent("removestream",
                                                              { stream: stream }));
@@ -1351,11 +1251,10 @@ PeerConnectionObserver.prototype = {
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
   [GlobalPCList,
    RTCIceCandidate,
    RTCSessionDescription,
    RTCPeerConnection,
    RTCStatsReport,
    RTCIdentityAssertion,
-   PeerConnectionObserver,
-   WebrtcGlobalInformation]
+   PeerConnectionObserver]
 );
--- a/dom/media/PeerConnection.manifest
+++ b/dom/media/PeerConnection.manifest
@@ -1,17 +1,15 @@
 component {00e0e20d-1494-4776-8e0e-0f0acbea3c79} PeerConnection.js
-component {f6063d11-f467-49ad-9765-e7923050dc08} PeerConnection.js
 component {d1748d4c-7f6a-4dc5-add6-d55b7678537e} PeerConnection.js
 component {02b9970c-433d-4cc2-923d-f7028ac66073} PeerConnection.js
 component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
 component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
 component {7fe6e18b-0da3-4056-bf3b-440ef3809e06} PeerConnection.js
 component {1abc7499-3c54-43e0-bd60-686e2703f072} PeerConnection.js
 
 contract @mozilla.org/dom/peerconnection;1 {00e0e20d-1494-4776-8e0e-0f0acbea3c79}
-contract @mozilla.org/dom/webrtcglobalinformation;1 {f6063d11-f467-49ad-9765-e7923050dc08}
 contract @mozilla.org/dom/peerconnectionobserver;1 {d1748d4c-7f6a-4dc5-add6-d55b7678537e}
 contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
 contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}
 contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}
 contract @mozilla.org/dom/rtcstatsreport;1 {7fe6e18b-0da3-4056-bf3b-440ef3809e06}
 contract @mozilla.org/dom/rtcidentityassertion;1 {1abc7499-3c54-43e0-bd60-686e2703f072}
--- a/dom/webidl/PeerConnectionImpl.webidl
+++ b/dom/webidl/PeerConnectionImpl.webidl
@@ -31,23 +31,17 @@ interface PeerConnectionImpl  {
   [Throws]
   void setLocalDescription(long action, DOMString sdp);
   [Throws]
   void setRemoteDescription(long action, DOMString sdp);
 
   /* Stats call, calls either |onGetStatsSuccess| or |onGetStatsError| on our
      observer. (see the |PeerConnectionObserver| interface) */
   [Throws]
-  void getStats(MediaStreamTrack? selector, boolean internalStats);
-
-  /* Scrapes the RLogRingbuffer, and calls either |onGetLoggingSuccess|
-     or |onGetLoggingError| on our observer.
-     (see the |PeerConnectionObserver| interface) */
-  [Throws]
-  void getLogging(DOMString pattern);
+  void getStats(MediaStreamTrack? selector);
 
   /* Adds the stream created by GetUserMedia */
   [Throws]
   void addStream(MediaStream stream,
                  optional MediaConstraintsInternal constraints);
   [Throws]
   void removeStream(MediaStream stream);
   [Throws]
--- a/dom/webidl/PeerConnectionObserver.webidl
+++ b/dom/webidl/PeerConnectionObserver.webidl
@@ -23,20 +23,16 @@ interface PeerConnectionObserver
   void onAddIceCandidateSuccess();
   void onAddIceCandidateError(unsigned long name, DOMString message);
   void onIceCandidate(unsigned short level, DOMString mid, DOMString candidate);
 
   /* Stats callbacks */
   void onGetStatsSuccess(optional RTCStatsReportInternal report);
   void onGetStatsError(unsigned long name, DOMString message);
 
-  /* Logging callbacks */
-  void onGetLoggingSuccess(sequence<DOMString> logs);
-  void onGetLoggingError(unsigned long name, DOMString message);
-
   /* Data channel callbacks */
   void notifyDataChannel(DataChannel channel);
   void notifyConnection();
   void notifyClosedConnection();
 
   /* Notification of one of several types of state changed */
   void onStateChange(PCObserverStateType state);
 
--- a/dom/webidl/RTCPeerConnection.webidl
+++ b/dom/webidl/RTCPeerConnection.webidl
@@ -130,40 +130,20 @@ interface mozRTCPeerConnection : EventTa
   attribute EventHandler onaddstream;
   attribute EventHandler onremovestream;
   attribute EventHandler oniceconnectionstatechange;
 
   void getStats (MediaStreamTrack? selector,
                  RTCStatsCallback successCallback,
                  RTCPeerConnectionErrorCallback failureCallback);
 
-  [ChromeOnly]
-  void getStatsInternal (MediaStreamTrack? selector,
-                         RTCStatsCallback successCallback,
-                         RTCPeerConnectionErrorCallback failureCallback);
-
   // Data channel.
   RTCDataChannel createDataChannel (DOMString label,
                                     optional RTCDataChannelInit dataChannelDict);
   attribute EventHandler ondatachannel;
   attribute EventHandler onconnection;
   attribute EventHandler onclosedconnection;
   [Pref="media.peerconnection.identity.enabled"]
   attribute EventHandler onidentityresult;
   [Pref="media.peerconnection.identity.enabled"]
   attribute EventHandler onpeeridentity;
 };
 
-callback RTCLogCallback = void (sequence<DOMString> logMessages);
-
-[JSImplementation="@mozilla.org/dom/webrtcglobalinformation;1",
- ChromeOnly,
- Constructor ()]
-interface WebrtcGlobalInformation {
-    void getAllStats(RTCStatsCallback callback,
-                     RTCPeerConnectionErrorCallback errorCallback);
-    void getCandPairLogs(DOMString candPairId,
-                         RTCLogCallback callback,
-                         RTCPeerConnectionErrorCallback errorCallback);
-    void getLogs(DOMString pattern,
-                 RTCLogCallback callback,
-                 RTCPeerConnectionErrorCallback errorCallback);
-};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/WebrtcGlobalInformation.webidl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+dictionary WebrtcGlobalStatisticsReport {
+  sequence<RTCStatsReportInternal> reports;
+};
+
+callback WebrtcGlobalStatisticsCallback = void (WebrtcGlobalStatisticsReport reports);
+callback WebrtcGlobalLoggingCallback = void (sequence<DOMString> logMessages);
+
+[ChromeOnly]
+interface WebrtcGlobalInformation {
+
+  [Throws]
+  static void getAllStats(WebrtcGlobalStatisticsCallback callback);
+
+  [Throws]
+  static void getLogging(DOMString pattern,
+                         WebrtcGlobalLoggingCallback callback);
+};
+
+
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -465,16 +465,17 @@ if CONFIG['MOZ_WEBGL']:
 if CONFIG['MOZ_WEBRTC']:
     WEBIDL_FILES += [
         'DataChannel.webidl',
         'MediaStreamList.webidl',
         'PeerConnectionImpl.webidl',
         'PeerConnectionImplEnums.webidl',
         'PeerConnectionObserver.webidl',
         'PeerConnectionObserverEnums.webidl',
+        'WebrtcGlobalInformation.webidl',
     ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     WEBIDL_FILES += [
         'SpeechGrammar.webidl',
         'SpeechGrammarList.webidl',
         'SpeechRecognition.webidl',
         'SpeechRecognitionAlternative.webidl',
--- a/gfx/2d/FilterNodeSoftware.cpp
+++ b/gfx/2d/FilterNodeSoftware.cpp
@@ -56,44 +56,55 @@ public:
   void CacheForExponent(Float aExponent)
   {
     mExponent = aExponent;
     int numPreSquares = 0;
     while (numPreSquares < 5 && mExponent > (1 << (numPreSquares + 2))) {
       numPreSquares++;
     }
     mNumPowTablePreSquares = numPreSquares;
-    for (int i = 0; i < sCacheSize; i++) {
-      Float a = i / Float(sCacheSize - 1);
+    for (size_t i = 0; i < sCacheSize; i++) {
+      // sCacheSize is chosen in such a way that a takes values
+      // from 0.0 to 1.0 inclusive.
+      Float a = i / Float(1 << sCacheIndexPrecisionBits);
+      MOZ_ASSERT(0.0f <= a && a <= 1.0f, "We only want to cache for bases between 0 and 1.");
+
       for (int j = 0; j < mNumPowTablePreSquares; j++) {
         a = sqrt(a);
       }
-      mPowTable[i] = uint16_t(pow(a, mExponent) * (1 << sOutputIntPrecisionBits));
+      uint32_t cachedInt = pow(a, mExponent) * (1 << sOutputIntPrecisionBits);
+      MOZ_ASSERT(cachedInt < (1 << (sizeof(mPowTable[i]) * 8)), "mPowCache integer type too small");
+
+      mPowTable[i] = cachedInt;
     }
   }
 
   uint16_t Pow(uint16_t aBase)
   {
     // Results should be similar to what the following code would produce:
-    // double x = double(aBase) / (1 << sInputIntPrecisionBits);
+    // Float x = Float(aBase) / (1 << sInputIntPrecisionBits);
     // return uint16_t(pow(x, mExponent) * (1 << sOutputIntPrecisionBits));
 
+    MOZ_ASSERT(aBase <= (1 << sInputIntPrecisionBits), "aBase needs to be between 0 and 1!");
+
     uint32_t a = aBase;
     for (int j = 0; j < mNumPowTablePreSquares; j++) {
       a = a * a >> sInputIntPrecisionBits;
     }
-    static_assert(sCacheSize == (1 << sInputIntPrecisionBits >> 7), "please fix index calculation below");
-    int i = a >> 7;
+    uint32_t i = a >> (sInputIntPrecisionBits - sCacheIndexPrecisionBits);
+    MOZ_ASSERT(i < sCacheSize, "out-of-bounds mPowTable access");
     return mPowTable[i];
   }
 
+  static const int sInputIntPrecisionBits = 15;
+  static const int sOutputIntPrecisionBits = 15;
+  static const int sCacheIndexPrecisionBits = 7;
+
 private:
-  static const int sCacheSize = 256;
-  static const int sInputIntPrecisionBits = 15;
-  static const int sOutputIntPrecisionBits = 8;
+  static const size_t sCacheSize = (1 << sCacheIndexPrecisionBits) + 1;
 
   Float mExponent;
   int mNumPowTablePreSquares;
   uint16_t mPowTable[sCacheSize];
 };
 
 class PointLightSoftware
 {
@@ -185,42 +196,81 @@ NS_lround(double x)
 void
 ClearDataSourceSurface(DataSourceSurface *aSurface)
 {
   size_t numBytes = aSurface->GetSize().height * aSurface->Stride();
   uint8_t* data = aSurface->GetData();
   PodZero(data, numBytes);
 }
 
-static ptrdiff_t
-DataOffset(DataSourceSurface* aSurface, IntPoint aPoint)
+// This check is safe against integer overflow.
+static bool
+SurfaceContainsPoint(SourceSurface* aSurface, const IntPoint& aPoint)
+{
+  IntSize size = aSurface->GetSize();
+  return aPoint.x >= 0 && aPoint.x < size.width &&
+         aPoint.y >= 0 && aPoint.y < size.height;
+}
+
+static uint8_t*
+DataAtOffset(DataSourceSurface* aSurface, IntPoint aPoint)
 {
-  return aPoint.y * aSurface->Stride() +
-         aPoint.x * BytesPerPixel(aSurface->GetFormat());
+  if (!SurfaceContainsPoint(aSurface, aPoint)) {
+    MOZ_CRASH("sample position needs to be inside surface!");
+  }
+
+  MOZ_ASSERT(Factory::CheckSurfaceSize(aSurface->GetSize()),
+             "surface size overflows - this should have been prevented when the surface was created");
+
+  uint8_t* data = aSurface->GetData() + aPoint.y * aSurface->Stride() +
+    aPoint.x * BytesPerPixel(aSurface->GetFormat());
+
+  if (data < aSurface->GetData()) {
+    MOZ_CRASH("out-of-range data access");
+  }
+
+  return data;
+}
+
+static bool
+IntRectOverflows(const IntRect& aRect)
+{
+  CheckedInt<int32_t> xMost = aRect.x;
+  xMost += aRect.width;
+  CheckedInt<int32_t> yMost = aRect.y;
+  yMost += aRect.height;
+  return !xMost.isValid() || !yMost.isValid();
 }
 
 /**
  * aSrcRect: Rect relative to the aSrc surface
  * aDestPoint: Point inside aDest surface
  */
 static void
 CopyRect(DataSourceSurface* aSrc, DataSourceSurface* aDest,
          IntRect aSrcRect, IntPoint aDestPoint)
 {
+  if (IntRectOverflows(aSrcRect) ||
+      IntRectOverflows(IntRect(aDestPoint, aSrcRect.Size()))) {
+    MOZ_CRASH("we should never be getting invalid rects at this point");
+  }
+
   MOZ_ASSERT(aSrc->GetFormat() == aDest->GetFormat(), "different surface formats");
   MOZ_ASSERT(IntRect(IntPoint(), aSrc->GetSize()).Contains(aSrcRect), "source rect too big for source surface");
   MOZ_ASSERT(IntRect(IntPoint(), aDest->GetSize()).Contains(aSrcRect - aSrcRect.TopLeft() + aDestPoint), "dest surface too small");
-  uint8_t* sourceData = aSrc->GetData();
+
+  if (aSrcRect.IsEmpty()) {
+    return;
+  }
+
+  uint8_t* sourceData = DataAtOffset(aSrc, aSrcRect.TopLeft());
   uint32_t sourceStride = aSrc->Stride();
-  uint8_t* destData = aDest->GetData();
+  uint8_t* destData = DataAtOffset(aDest, aDestPoint);
   uint32_t destStride = aDest->Stride();
 
-  sourceData += DataOffset(aSrc, aSrcRect.TopLeft());
-  destData += DataOffset(aDest, aDestPoint);
-
   if (BytesPerPixel(aSrc->GetFormat()) == 4) {
     for (int32_t y = 0; y < aSrcRect.height; y++) {
       PodCopy((int32_t*)destData, (int32_t*)sourceData, aSrcRect.width);
       sourceData += sourceStride;
       destData += destStride;
     }
   } else if (BytesPerPixel(aSrc->GetFormat()) == 1) {
     for (int32_t y = 0; y < aSrcRect.height; y++) {
@@ -240,20 +290,25 @@ CloneAligned(DataSourceSurface* aSource)
     CopyRect(aSource, copy, IntRect(IntPoint(), aSource->GetSize()), IntPoint());
   }
   return copy;
 }
 
 static void
 FillRectWithPixel(DataSourceSurface *aSurface, const IntRect &aFillRect, IntPoint aPixelPos)
 {
-  uint8_t* data = aSurface->GetData();
-  uint8_t* sourcePixelData = data + DataOffset(aSurface, aPixelPos);
+  MOZ_ASSERT(!IntRectOverflows(aFillRect));
+  MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aFillRect),
+             "aFillRect needs to be completely inside the surface");
+  MOZ_ASSERT(SurfaceContainsPoint(aSurface, aPixelPos),
+             "aPixelPos needs to be inside the surface");
+
   int32_t stride = aSurface->Stride();
-  data += DataOffset(aSurface, aFillRect.TopLeft());
+  uint8_t* sourcePixelData = DataAtOffset(aSurface, aPixelPos);
+  uint8_t* data = DataAtOffset(aSurface, aFillRect.TopLeft());
   int bpp = BytesPerPixel(aSurface->GetFormat());
 
   // Fill the first row by hand.
   if (bpp == 4) {
     uint32_t sourcePixel = *(uint32_t*)sourcePixelData;
     for (int32_t x = 0; x < aFillRect.width; x++) {
       *((uint32_t*)data + x) = sourcePixel;
     }
@@ -268,20 +323,26 @@ FillRectWithPixel(DataSourceSurface *aSu
   }
 }
 
 static void
 FillRectWithVerticallyRepeatingHorizontalStrip(DataSourceSurface *aSurface,
                                                const IntRect &aFillRect,
                                                const IntRect &aSampleRect)
 {
-  uint8_t* data = aSurface->GetData();
+  MOZ_ASSERT(!IntRectOverflows(aFillRect));
+  MOZ_ASSERT(!IntRectOverflows(aSampleRect));
+  MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aFillRect),
+             "aFillRect needs to be completely inside the surface");
+  MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aSampleRect),
+             "aSampleRect needs to be completely inside the surface");
+
   int32_t stride = aSurface->Stride();
-  uint8_t* sampleData = data + DataOffset(aSurface, aSampleRect.TopLeft());
-  data += DataOffset(aSurface, aFillRect.TopLeft());
+  uint8_t* sampleData = DataAtOffset(aSurface, aSampleRect.TopLeft());
+  uint8_t* data = DataAtOffset(aSurface, aFillRect.TopLeft());
   if (BytesPerPixel(aSurface->GetFormat()) == 4) {
     for (int32_t y = 0; y < aFillRect.height; y++) {
       PodCopy((uint32_t*)data, (uint32_t*)sampleData, aFillRect.width);
       data += stride;
     }
   } else if (BytesPerPixel(aSurface->GetFormat()) == 1) {
     for (int32_t y = 0; y < aFillRect.height; y++) {
       PodCopy(data, sampleData, aFillRect.width);
@@ -290,20 +351,26 @@ FillRectWithVerticallyRepeatingHorizonta
   }
 }
 
 static void
 FillRectWithHorizontallyRepeatingVerticalStrip(DataSourceSurface *aSurface,
                                                const IntRect &aFillRect,
                                                const IntRect &aSampleRect)
 {
-  uint8_t* data = aSurface->GetData();
+  MOZ_ASSERT(!IntRectOverflows(aFillRect));
+  MOZ_ASSERT(!IntRectOverflows(aSampleRect));
+  MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aFillRect),
+             "aFillRect needs to be completely inside the surface");
+  MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aSampleRect),
+             "aSampleRect needs to be completely inside the surface");
+
   int32_t stride = aSurface->Stride();
-  uint8_t* sampleData = data + DataOffset(aSurface, aSampleRect.TopLeft());
-  data += DataOffset(aSurface, aFillRect.TopLeft());
+  uint8_t* sampleData = DataAtOffset(aSurface, aSampleRect.TopLeft());
+  uint8_t* data = DataAtOffset(aSurface, aFillRect.TopLeft());
   if (BytesPerPixel(aSurface->GetFormat()) == 4) {
     for (int32_t y = 0; y < aFillRect.height; y++) {
       int32_t sampleColor = *((uint32_t*)sampleData);
       for (int32_t x = 0; x < aFillRect.width; x++) {
         *((uint32_t*)data + x) = sampleColor;
       }
       data += stride;
       sampleData += stride;
@@ -316,16 +383,20 @@ FillRectWithHorizontallyRepeatingVertica
       sampleData += stride;
     }
   }
 }
 
 static void
 DuplicateEdges(DataSourceSurface* aSurface, const IntRect &aFromRect)
 {
+  MOZ_ASSERT(!IntRectOverflows(aFromRect));
+  MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aFromRect),
+             "aFromRect needs to be completely inside the surface");
+
   IntSize size = aSurface->GetSize();
   IntRect fill;
   IntRect sampleRect;
   for (int32_t ix = 0; ix < 3; ix++) {
     switch (ix) {
       case 0:
         fill.x = 0;
         fill.width = aFromRect.x;
@@ -419,16 +490,23 @@ TileSurface(DataSourceSurface* aSource, 
 
 static TemporaryRef<DataSourceSurface>
 GetDataSurfaceInRect(SourceSurface *aSurface,
                      const IntRect &aSurfaceRect,
                      const IntRect &aDestRect,
                      ConvolveMatrixEdgeMode aEdgeMode)
 {
   MOZ_ASSERT(aSurface ? aSurfaceRect.Size() == aSurface->GetSize() : aSurfaceRect.IsEmpty());
+
+  if (IntRectOverflows(aSurfaceRect) || IntRectOverflows(aDestRect)) {
+    // We can't rely on the intersection calculations below to make sense when
+    // XMost() or YMost() overflow. Bail out.
+    return nullptr;
+  }
+
   IntRect sourceRect = aSurfaceRect;
 
   if (sourceRect.IsEqualEdges(aDestRect)) {
     return aSurface ? aSurface->GetDataSurface() : nullptr;
   }
 
   IntRect intersect = sourceRect.Intersect(aDestRect);
   IntRect intersectInSourceSpace = intersect - sourceRect.TopLeft();
@@ -562,19 +640,33 @@ FilterNodeSoftware::Draw(DrawTarget* aDr
                          const DrawOptions &aOptions)
 {
 #ifdef DEBUG_DUMP_SURFACES
   printf("<style>section{margin:10px;}</style><pre>\nRendering filter %s...\n", GetName());
 #endif
 
   Rect renderRect = aSourceRect;
   renderRect.RoundOut();
-  IntRect renderIntRect(int32_t(renderRect.x), int32_t(renderRect.y),
-                        int32_t(renderRect.width), int32_t(renderRect.height));
-  IntRect outputRect = renderIntRect.Intersect(GetOutputRectInRect(renderIntRect));
+  IntRect renderIntRect;
+  if (!renderRect.ToIntRect(&renderIntRect)) {
+#ifdef DEBUG_DUMP_SURFACES
+    printf("render rect overflowed, not painting anything\n");
+    printf("</pre>\n");
+#endif
+    return;
+  }
+
+  IntRect outputRect = GetOutputRectInRect(renderIntRect);
+  if (IntRectOverflows(outputRect)) {
+#ifdef DEBUG_DUMP_SURFACES
+    printf("output rect overflowed, not painting anything\n");
+    printf("</pre>\n");
+#endif
+    return;
+  }
 
   RefPtr<DataSourceSurface> result;
   if (!outputRect.IsEmpty()) {
     result = GetOutput(outputRect);
   }
 
   if (!result) {
     // Null results are allowed and treated as transparent. Don't draw anything.
@@ -608,16 +700,21 @@ FilterNodeSoftware::Draw(DrawTarget* aDr
                              DrawSurfaceOptions(), aOptions);
   }
 }
 
 TemporaryRef<DataSourceSurface>
 FilterNodeSoftware::GetOutput(const IntRect &aRect)
 {
   MOZ_ASSERT(GetOutputRectInRect(aRect).Contains(aRect));
+
+  if (IntRectOverflows(aRect)) {
+    return nullptr;
+  }
+
   if (!mCachedRect.Contains(aRect)) {
     RequestRect(aRect);
     mCachedOutput = Render(mRequestedRect);
     if (!mCachedOutput) {
       mCachedRect = IntRect();
       mRequestedRect = IntRect();
       return nullptr;
     }
@@ -634,16 +731,20 @@ FilterNodeSoftware::RequestRect(const In
 {
   mRequestedRect = mRequestedRect.Union(aRect);
   RequestFromInputsForRect(aRect);
 }
 
 void
 FilterNodeSoftware::RequestInputRect(uint32_t aInputEnumIndex, const IntRect &aRect)
 {
+  if (IntRectOverflows(aRect)) {
+    return;
+  }
+
   int32_t inputIndex = InputIndex(aInputEnumIndex);
   if (inputIndex < 0 || (uint32_t)inputIndex >= NumberOfSetInputs()) {
     MOZ_CRASH();
   }
   if (mInputSurfaces[inputIndex]) {
     return;
   }
   RefPtr<FilterNodeSoftware> filter = mInputFilters[inputIndex];
@@ -663,16 +764,20 @@ FilterNodeSoftware::DesiredFormat(Surfac
 
 TemporaryRef<DataSourceSurface>
 FilterNodeSoftware::GetInputDataSourceSurface(uint32_t aInputEnumIndex,
                                               const IntRect& aRect,
                                               FormatHint aFormatHint,
                                               ConvolveMatrixEdgeMode aEdgeMode,
                                               const IntRect *aTransparencyPaddedSourceRect)
 {
+  if (IntRectOverflows(aRect)) {
+    return nullptr;
+  }
+
 #ifdef DEBUG_DUMP_SURFACES
   printf("<section><h1>GetInputDataSourceSurface with aRect: %d, %d, %d, %d</h1>\n",
          aRect.x, aRect.y, aRect.width, aRect.height);
 #endif
   int32_t inputIndex = InputIndex(aInputEnumIndex);
   if (inputIndex < 0 || (uint32_t)inputIndex >= NumberOfSetInputs()) {
     MOZ_CRASH();
     return nullptr;
@@ -761,16 +866,20 @@ FilterNodeSoftware::GetInputDataSourceSu
 
   return result;
 }
 
 IntRect
 FilterNodeSoftware::GetInputRectInRect(uint32_t aInputEnumIndex,
                                        const IntRect &aInRect)
 {
+  if (IntRectOverflows(aInRect)) {
+    return IntRect();
+  }
+
   int32_t inputIndex = InputIndex(aInputEnumIndex);
   if (inputIndex < 0 || (uint32_t)inputIndex >= NumberOfSetInputs()) {
     MOZ_CRASH();
     return IntRect();
   }
   if (mInputSurfaces[inputIndex]) {
     return aInRect.Intersect(IntRect(IntPoint(0, 0),
                                      mInputSurfaces[inputIndex]->GetSize()));
@@ -975,17 +1084,21 @@ FilterNodeTransformSoftware::SourceRectF
 
   Matrix inverted(mMatrix);
   if (!inverted.Invert()) {
     return IntRect();
   }
 
   Rect neededRect = inverted.TransformBounds(Rect(aRect));
   neededRect.RoundOut();
-  return GetInputRectInRect(IN_TRANSFORM_IN, RoundedToInt(neededRect));
+  IntRect neededIntRect;
+  if (!neededRect.ToIntRect(&neededIntRect)) {
+    return IntRect();
+  }
+  return GetInputRectInRect(IN_TRANSFORM_IN, neededIntRect);
 }
 
 TemporaryRef<DataSourceSurface>
 FilterNodeTransformSoftware::Render(const IntRect& aRect)
 {
   IntRect srcRect = SourceRectForOutputRect(aRect);
 
   RefPtr<DataSourceSurface> input =
@@ -1027,17 +1140,21 @@ FilterNodeTransformSoftware::GetOutputRe
 {
   IntRect srcRect = SourceRectForOutputRect(aRect);
   if (srcRect.IsEmpty()) {
     return IntRect();
   }
 
   Rect outRect = mMatrix.TransformBounds(Rect(srcRect));
   outRect.RoundOut();
-  return RoundedToInt(outRect).Intersect(aRect);
+  IntRect outIntRect;
+  if (!outRect.ToIntRect(&outIntRect)) {
+    return IntRect();
+  }
+  return outIntRect.Intersect(aRect);
 }
 
 FilterNodeMorphologySoftware::FilterNodeMorphologySoftware()
  : mOperator(MORPHOLOGY_OPERATOR_ERODE)
 {}
 
 int32_t
 FilterNodeMorphologySoftware::InputIndex(uint32_t aInputEnumIndex)
@@ -1086,39 +1203,36 @@ ApplyMorphology(const IntRect& aSourceRe
     tmp = aInput;
   } else {
     tmp = Factory::CreateDataSourceSurface(tmpRect.Size(), SurfaceFormat::B8G8R8A8);
     if (!tmp) {
       return nullptr;
     }
 
     int32_t sourceStride = aInput->Stride();
-    uint8_t* sourceData = aInput->GetData();
-    sourceData += DataOffset(aInput, destRect.TopLeft() - srcRect.TopLeft());
+    uint8_t* sourceData = DataAtOffset(aInput, destRect.TopLeft() - srcRect.TopLeft());
 
     int32_t tmpStride = tmp->Stride();
-    uint8_t* tmpData = tmp->GetData();
-    tmpData += DataOffset(tmp, destRect.TopLeft() - tmpRect.TopLeft());
+    uint8_t* tmpData = DataAtOffset(tmp, destRect.TopLeft() - tmpRect.TopLeft());
 
     FilterProcessing::ApplyMorphologyHorizontal(
       sourceData, sourceStride, tmpData, tmpStride, tmpRect, rx, aOperator);
   }
 
   RefPtr<DataSourceSurface> dest;
   if (ry == 0) {
     dest = tmp;
   } else {
     dest = Factory::CreateDataSourceSurface(destRect.Size(), SurfaceFormat::B8G8R8A8);
     if (!dest) {
       return nullptr;
     }
 
     int32_t tmpStride = tmp->Stride();
-    uint8_t* tmpData = tmp->GetData();
-    tmpData += DataOffset(tmp, destRect.TopLeft() - tmpRect.TopLeft());
+    uint8_t* tmpData = DataAtOffset(tmp, destRect.TopLeft() - tmpRect.TopLeft());
 
     int32_t destStride = dest->Stride();
     uint8_t* destData = dest->GetData();
 
     FilterProcessing::ApplyMorphologyVertical(
       tmpData, tmpStride, destData, destStride, destRect, ry, aOperator);
   }
 
@@ -2276,24 +2390,23 @@ FilterNodeConvolveMatrixSoftware::DoRend
 
   RefPtr<DataSourceSurface> target =
     Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8);
   if (!target) {
     return nullptr;
   }
   ClearDataSourceSurface(target);
 
-  uint8_t* sourceData = input->GetData();
+  IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
+
+  uint8_t* sourceData = DataAtOffset(input, offset);
   int32_t sourceStride = input->Stride();
   uint8_t* targetData = target->GetData();
   int32_t targetStride = target->Stride();
 
-  IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
-  sourceData += DataOffset(input, offset);
-
   // Why exactly are we reversing the kernel?
   std::vector<Float> kernel = ReversedVector(mKernelMatrix);
   kernel = ScaledVector(kernel, mDivisor);
   Float maxResultAbs = std::max(MaxVectorSum(kernel) + mBias,
                                 MaxVectorSum(ScaledVector(kernel, -1)) - mBias);
   maxResultAbs = std::max(maxResultAbs, 1.0f);
 
   double idealFactor = INT32_MAX / 2.0 / maxResultAbs / 255.0 * 0.999;
@@ -2423,26 +2536,25 @@ FilterNodeDisplacementMapSoftware::Rende
   RefPtr<DataSourceSurface> map =
     GetInputDataSourceSurface(IN_DISPLACEMENT_MAP_IN2, aRect, NEED_COLOR_CHANNELS);
   RefPtr<DataSourceSurface> target =
     Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8);
   if (!input || !map || !target) {
     return nullptr;
   }
 
-  uint8_t* sourceData = input->GetData();
+  IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
+
+  uint8_t* sourceData = DataAtOffset(input, offset);
   int32_t sourceStride = input->Stride();
   uint8_t* mapData = map->GetData();
   int32_t mapStride = map->Stride();
   uint8_t* targetData = target->GetData();
   int32_t targetStride = target->Stride();
 
-  IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
-  sourceData += DataOffset(input, offset);
-
   static const ptrdiff_t channelMap[4] = {
                              B8G8R8A8_COMPONENT_BYTEOFFSET_R,
                              B8G8R8A8_COMPONENT_BYTEOFFSET_G,
                              B8G8R8A8_COMPONENT_BYTEOFFSET_B,
                              B8G8R8A8_COMPONENT_BYTEOFFSET_A };
   uint16_t xChannel = channelMap[mChannelX];
   uint16_t yChannel = channelMap[mChannelY];
 
@@ -2892,18 +3004,19 @@ FilterNodeCropSoftware::InputIndex(uint3
 
 void
 FilterNodeCropSoftware::SetAttribute(uint32_t aIndex,
                                      const Rect &aSourceRect)
 {
   MOZ_ASSERT(aIndex == ATT_CROP_RECT);
   Rect srcRect = aSourceRect;
   srcRect.Round();
-  mCropRect = IntRect(int32_t(srcRect.x), int32_t(srcRect.y),
-                      int32_t(srcRect.width), int32_t(srcRect.height));
+  if (!srcRect.ToIntRect(&mCropRect)) {
+    mCropRect = IntRect();
+  }
   Invalidate();
 }
 
 TemporaryRef<DataSourceSurface>
 FilterNodeCropSoftware::Render(const IntRect& aRect)
 {
   return GetInputDataSourceSurface(IN_CROP_IN, aRect.Intersect(mCropRect));
 }
@@ -3147,18 +3260,17 @@ PointLightSoftware::GetColor(uint32_t aL
 {
   return aLightColor;
 }
 
 void
 SpotLightSoftware::Prepare()
 {
   mVectorFromFocusPointToLight = Normalized(mPointsAt - mPosition);
-  const float radPerDeg = static_cast<float>(M_PI/180.0);
-  mLimitingConeCos = std::max<double>(cos(mLimitingConeAngle * radPerDeg), 0.0);
+  mLimitingConeCos = std::max<double>(cos(mLimitingConeAngle * M_PI/180.0), 0.0);
   mPowCache.CacheForExponent(mSpecularFocus);
 }
 
 Point3D
 SpotLightSoftware::GetVectorToLight(const Point3D &aTargetPoint)
 {
   return Normalized(mPosition - aTargetPoint);
 }
@@ -3167,21 +3279,22 @@ uint32_t
 SpotLightSoftware::GetColor(uint32_t aLightColor, const Point3D &aVectorToLight)
 {
   union {
     uint32_t color;
     uint8_t colorC[4];
   };
   color = aLightColor;
   Float dot = -aVectorToLight.DotProduct(mVectorFromFocusPointToLight);
-  int16_t doti = dot * (255 << 7);
-  uint16_t tmp = mPowCache.Pow(doti) * (dot >= mLimitingConeCos);
-  colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_R] = uint8_t((colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_R] * tmp) >> 8);
-  colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_G] = uint8_t((colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_G] * tmp) >> 8);
-  colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_B] = uint8_t((colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_B] * tmp) >> 8);
+  uint16_t doti = dot * (dot >= 0) * (1 << PowCache::sInputIntPrecisionBits);
+  uint32_t tmp = mPowCache.Pow(doti) * (dot >= mLimitingConeCos);
+  MOZ_ASSERT(tmp <= (1 << PowCache::sOutputIntPrecisionBits), "pow() result must not exceed 1.0");
+  colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_R] = uint8_t((colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_R] * tmp) >> PowCache::sOutputIntPrecisionBits);
+  colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_G] = uint8_t((colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_G] * tmp) >> PowCache::sOutputIntPrecisionBits);
+  colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_B] = uint8_t((colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_B] * tmp) >> PowCache::sOutputIntPrecisionBits);
   colorC[B8G8R8A8_COMPONENT_BYTEOFFSET_A] = 255;
   return color;
 }
 
 void
 DistantLightSoftware::Prepare()
 {
   const double radPerDeg = M_PI / 180.0;
@@ -3288,24 +3401,23 @@ FilterNodeLightingSoftware<LightType, Li
   DebugOnlyAutoColorSamplingAccessControl accessControl(input);
 
   RefPtr<DataSourceSurface> target =
     Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8);
   if (!target) {
     return nullptr;
   }
 
-  uint8_t* sourceData = input->GetData();
+  IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
+
+  uint8_t* sourceData = DataAtOffset(input, offset);
   int32_t sourceStride = input->Stride();
   uint8_t* targetData = target->GetData();
   int32_t targetStride = target->Stride();
 
-  IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
-  sourceData += DataOffset(input, offset);
-
   uint32_t lightColor = ColorToBGRA(mColor);
   mLight.Prepare();
   mLighting.Prepare();
 
   for (int32_t y = 0; y < size.height; y++) {
     for (int32_t x = 0; x < size.width; x++) {
       int32_t sourceIndex = y * sourceStride + x;
       int32_t targetIndex = y * targetStride + 4 * x;
@@ -3399,32 +3511,32 @@ SpecularLightingSoftware::Prepare()
 uint32_t
 SpecularLightingSoftware::LightPixel(const Point3D &aNormal,
                                      const Point3D &aVectorToLight,
                                      uint32_t aColor)
 {
   Point3D vectorToEye(0, 0, 1);
   Point3D halfwayVector = Normalized(aVectorToLight + vectorToEye);
   Float dotNH = aNormal.DotProduct(halfwayVector);
-  uint16_t dotNHi = uint16_t(dotNH * (dotNH >= 0) * (255 << 7));
-  uint32_t specularNHi = mSpecularConstantInt * mPowCache.Pow(dotNHi);
+  uint16_t dotNHi = uint16_t(dotNH * (dotNH >= 0) * (1 << PowCache::sInputIntPrecisionBits));
+  uint32_t specularNHi = uint32_t(mSpecularConstantInt) * mPowCache.Pow(dotNHi) >> 8;
 
   union {
     uint32_t bgra;
     uint8_t components[4];
   } color = { aColor };
   color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_B] =
-    umin(FilterProcessing::FastDivideBy255<uint16_t>(
-      specularNHi * color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_B] >> 8), 255U);
+    umin(
+      (specularNHi * color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_B]) >> PowCache::sOutputIntPrecisionBits, 255U);
   color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_G] =
-    umin(FilterProcessing::FastDivideBy255<uint16_t>(
-      specularNHi * color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_G] >> 8), 255U);
+    umin(
+      (specularNHi * color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_G]) >> PowCache::sOutputIntPrecisionBits, 255U);
   color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_R] =
-    umin(FilterProcessing::FastDivideBy255<uint16_t>(
-      specularNHi * color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_R] >> 8), 255U);
+    umin(
+      (specularNHi * color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_R]) >> PowCache::sOutputIntPrecisionBits, 255U);
 
   color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_A] =
     umax(color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_B],
       umax(color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_G],
                color.components[B8G8R8A8_COMPONENT_BYTEOFFSET_R]));
   return color.bgra;
 }
 
--- a/gfx/cairo/cairo/src/moz.build
+++ b/gfx/cairo/cairo/src/moz.build
@@ -182,17 +182,17 @@ UNIFIED_SOURCES += [
     'cairo-user-font.c',
     'cairo-version.c',
     'cairo-wideint.c',
     'cairo.c',
 ]
 
 MSVC_ENABLE_PGO = True
 
-FINAL_LIBRARY = 'xul'
+FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['PACKAGE_VERSION'] = '"moz"'
 DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
 
 for var in ('CAIRO_HAS_PTHREAD', '_GNU_SOURCE'):
     DEFINES[var] = True
 
 for var in ('MOZ_TREE_CAIRO', 'MOZ_TREE_PIXMAN'):
--- a/gfx/cairo/libpixman/src/moz.build
+++ b/gfx/cairo/libpixman/src/moz.build
@@ -55,17 +55,17 @@ SOURCES += [
     'pixman-trap.c',
     'pixman-utils.c',
     'pixman-x86.c',
     'pixman.c',
 ]
 
 MSVC_ENABLE_PGO = True
 
-FINAL_LIBRARY = 'xul'
+FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     '../../cairo/src',
 ]
 
 
 if CONFIG['MOZ_USE_PTHREADS']:
     DEFINES['HAVE_PTHREAD_SETSPECIFIC'] = True
 
--- a/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp
+++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp
@@ -6,79 +6,59 @@
 
 #include "DecomposeIntoNoRepeatTriangles.h"
 #include "gfxMatrix.h"
 
 namespace mozilla {
 namespace gl {
 
 void
+RectTriangles::AppendRectToCoordArray(InfallibleTArray<coord>& array,
+                                      GLfloat x0, GLfloat y0,
+                                      GLfloat x1, GLfloat y1)
+{
+    coord* v = array.AppendElements(6);
+
+    v[0].x = x0; v[0].y = y0;
+    v[1].x = x1; v[1].y = y0;
+    v[2].x = x0; v[2].y = y1;
+    v[3].x = x0; v[3].y = y1;
+    v[4].x = x1; v[4].y = y0;
+    v[5].x = x1; v[5].y = y1;
+}
+
+void
 RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
                        GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
                        bool flip_y /* = false */)
 {
-    if (vertexCoords.IsEmpty() &&
-        x0 == 0.0f && y0 == 0.0f && x1 == 1.0f && y1 == 1.0f) {
-      mIsSimpleQuad = true;
-      if (flip_y) {
-        mTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty0 - ty1, tx0, ty1));
-      } else {
-        mTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty1 - ty0, tx0, ty0));
-      }
-    } else if (mIsSimpleQuad) {
-      mIsSimpleQuad = false;
-      mTextureTransform = gfx3DMatrix();
+    if (flip_y) {
+        std::swap(ty0, ty1);
     }
-
-    vert_coord v;
-    v.x = x0; v.y = y0;
-    vertexCoords.AppendElement(v);
-    v.x = x1; v.y = y0;
-    vertexCoords.AppendElement(v);
-    v.x = x0; v.y = y1;
-    vertexCoords.AppendElement(v);
-
-    v.x = x0; v.y = y1;
-    vertexCoords.AppendElement(v);
-    v.x = x1; v.y = y0;
-    vertexCoords.AppendElement(v);
-    v.x = x1; v.y = y1;
-    vertexCoords.AppendElement(v);
+    AppendRectToCoordArray(mVertexCoords, x0, y0, x1, y1);
+    AppendRectToCoordArray(mTexCoords, tx0, ty0, tx1, ty1);
+}
 
-    if (flip_y) {
-        tex_coord t;
-        t.u = tx0; t.v = ty1;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty1;
-        texCoords.AppendElement(t);
-        t.u = tx0; t.v = ty0;
-        texCoords.AppendElement(t);
-
-        t.u = tx0; t.v = ty0;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty1;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty0;
-        texCoords.AppendElement(t);
-    } else {
-        tex_coord t;
-        t.u = tx0; t.v = ty0;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty0;
-        texCoords.AppendElement(t);
-        t.u = tx0; t.v = ty1;
-        texCoords.AppendElement(t);
-
-        t.u = tx0; t.v = ty1;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty0;
-        texCoords.AppendElement(t);
-        t.u = tx1; t.v = ty1;
-        texCoords.AppendElement(t);
+bool
+RectTriangles::isSimpleQuad(gfx3DMatrix& aOutTextureTransform) const
+{
+    if (mVertexCoords.Length() == 6 &&
+        mVertexCoords[0].x == 0.0f &&
+        mVertexCoords[0].y == 0.0f &&
+        mVertexCoords[5].x == 1.0f &&
+        mVertexCoords[5].y == 1.0f)
+    {
+        GLfloat tx0 = mTexCoords[0].x;
+        GLfloat ty0 = mTexCoords[0].y;
+        GLfloat tx1 = mTexCoords[5].x;
+        GLfloat ty1 = mTexCoords[5].y;
+        aOutTextureTransform = gfx3DMatrix::From2D(gfxMatrix(tx1 - tx0, 0, 0, ty1 - ty0, tx0, ty0));
+        return true;
     }
+    return false;
 }
 
 static GLfloat
 WrapTexCoord(GLfloat v)
 {
     // fmodf gives negative results for negative numbers;
     // that is, fmodf(0.75, 1.0) == 0.75, but
     // fmodf(-0.75, 1.0) == -0.75.  For the negative case,
@@ -211,9 +191,9 @@ DecomposeIntoNoRepeatTriangles(const nsI
                        1.0f, 1.0f,
                        0.0f, 0.0f,
                        br[0], br[1],
                        aFlipY);
     }
 }
 
 }
-}
\ No newline at end of file
+}
--- a/gfx/gl/DecomposeIntoNoRepeatTriangles.h
+++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.h
@@ -14,60 +14,55 @@
 
 namespace mozilla {
 namespace gl {
 
 /** Helper for DecomposeIntoNoRepeatTriangles
   */
 class RectTriangles {
 public:
-    RectTriangles() : mIsSimpleQuad(false) { }
+    typedef struct { GLfloat x,y; } coord;
 
     // Always pass texture coordinates upright. If you want to flip the
     // texture coordinates emitted to the tex_coords array, set flip_y to
     // true.
     void addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
-                  GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
-                  bool flip_y = false);
+                 GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
+                 bool flip_y = false);
 
     // Returns whether this object is made of only one rect that can be drawn
     // with a pre-buffered unity quad which has 0,0,1,1 as both vertex
     // positions and texture coordinates.
     // aOutTextureTransform returns the transform that maps 0,0,1,1 texture
     // coordinates to the correct ones.
-    bool IsSimpleQuad(gfx3DMatrix& aOutTextureTransform) const {
-      aOutTextureTransform = mTextureTransform;
-      return mIsSimpleQuad;
-    }
+    bool isSimpleQuad(gfx3DMatrix& aOutTextureTransform) const;
 
     /**
       * these return a float pointer to the start of each array respectively.
       * Use it for glVertexAttribPointer calls.
       * We can return nullptr if we choose to use Vertex Buffer Objects here.
       */
-    float* vertexPointer() {
-        return &vertexCoords[0].x;
+    InfallibleTArray<coord>& vertCoords() {
+        return mVertexCoords;
     }
 
-    float* texCoordPointer() {
-        return &texCoords[0].u;
+    InfallibleTArray<coord>& texCoords() {
+        return mTexCoords;
     }
 
     unsigned int elements() {
-        return vertexCoords.Length();
+        return mVertexCoords.Length();
     }
-
-    typedef struct { GLfloat x,y; } vert_coord;
-    typedef struct { GLfloat u,v; } tex_coord;
 private:
-    // default is 4 rectangles, each made up of 2 triangles (3 coord vertices each)
-    nsAutoTArray<vert_coord, 6> vertexCoords;
-    nsAutoTArray<tex_coord, 6>  texCoords;
-    gfx3DMatrix mTextureTransform;
-    bool mIsSimpleQuad;
+    // Reserve inline storage for one quad (2 triangles, 3 coords).
+    nsAutoTArray<coord, 6> mVertexCoords;
+    nsAutoTArray<coord, 6> mTexCoords;
+
+    static void
+    AppendRectToCoordArray(InfallibleTArray<coord>& array, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1);
 };
 
 /**
   * Decompose drawing the possibly-wrapped aTexCoordRect rectangle
   * of a texture of aTexSize into one or more rectangles (represented
   * as 2 triangles) and associated tex coordinates, such that
   * we don't have to use the REPEAT wrap mode. If aFlipY is true, the
   * texture coordinates will be specified vertically flipped.
@@ -82,9 +77,9 @@ private:
 void DecomposeIntoNoRepeatTriangles(const nsIntRect& aTexCoordRect,
                                     const nsIntSize& aTexSize,
                                     RectTriangles& aRects,
                                     bool aFlipY = false);
 
 }
 }
 
-#endif // DecomposeIntoNoRepeatTriangles_h_
\ No newline at end of file
+#endif // DecomposeIntoNoRepeatTriangles_h_
--- a/gfx/gl/GLBlitTextureImageHelper.cpp
+++ b/gfx/gl/GLBlitTextureImageHelper.cpp
@@ -131,31 +131,31 @@ GLBlitTextureImageHelper::BlitTextureIma
                         srcSubRect.y / float(realTexSize.height),
                         srcSubRect.XMost() / float(realTexSize.width),
                         srcSubRect.YMost() / float(realTexSize.height));
             } else {
                 DecomposeIntoNoRepeatTriangles(srcSubRect, realTexSize, rects);
 
                 // now put the coords into the d[xy]0 .. d[xy]1 coordinate space
                 // from the 0..1 that it comes out of decompose
-                RectTriangles::vert_coord* v = (RectTriangles::vert_coord*)rects.vertexPointer();
+                InfallibleTArray<RectTriangles::coord>& coords = rects.vertCoords();
 
-                for (unsigned int i = 0; i < rects.elements(); ++i) {
-                    v[i].x = (v[i].x * (dx1 - dx0)) + dx0;
-                    v[i].y = (v[i].y * (dy1 - dy0)) + dy0;
+                for (unsigned int i = 0; i < coords.Length(); ++i) {
+                    coords[i].x = (coords[i].x * (dx1 - dx0)) + dx0;
+                    coords[i].y = (coords[i].y * (dy1 - dy0)) + dy0;
                 }
             }
 
             ScopedBindTextureUnit autoTexUnit(mGL, LOCAL_GL_TEXTURE0);
             ScopedBindTexture autoTex(mGL, aSrc->GetTextureID());
 
             mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
 
-            mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexPointer());
-            mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoordPointer());
+            mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertCoords().Elements());
+            mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoords().Elements());
 
             mGL->fEnableVertexAttribArray(0);
             mGL->fEnableVertexAttribArray(1);
 
             mGL->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
 
             mGL->fDisableVertexAttribArray(0);
             mGL->fDisableVertexAttribArray(1);
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -75,63 +75,63 @@ BindMaskForProgram(ShaderProgramOGL* aPr
 }
 
 // Draw the given quads with the already selected shader. Texture coordinates
 // are supplied if the shader requires them.
 static void
 DrawQuads(GLContext *aGLContext,
           VBOArena &aVBOs,
           ShaderProgramOGL *aProg,
+          GLenum aMode,
           RectTriangles &aRects)
 {
   NS_ASSERTION(aProg->HasInitialized(), "Shader program not correctly initialized");
   GLuint vertAttribIndex =
     aProg->AttribLocation(ShaderProgramOGL::VertexCoordAttrib);
   GLuint texCoordAttribIndex =
     aProg->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
   bool texCoords = (texCoordAttribIndex != GLuint(-1));
 
-  GLsizei elements = aRects.elements();
-  GLsizei bytes = elements * 2 * sizeof(GLfloat);
+  GLsizei bytes = aRects.elements() * 2 * sizeof(GLfloat);
 
   GLsizei total = bytes;
   if (texCoords) {
     total *= 2;
   }
 
   aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER,
                           aVBOs.Allocate(aGLContext));
   aGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER,
                           total,
                           nullptr,
                           LOCAL_GL_STREAM_DRAW);
 
   aGLContext->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
                              0,
                              bytes,
-                             aRects.vertexPointer());
+                             aRects.vertCoords().Elements());
   aGLContext->fEnableVertexAttribArray(vertAttribIndex);
   aGLContext->fVertexAttribPointer(vertAttribIndex,
                                    2, LOCAL_GL_FLOAT,
                                    LOCAL_GL_FALSE,
                                    0, BUFFER_OFFSET(0));
 
   if (texCoords) {
     aGLContext->fBufferSubData(LOCAL_GL_ARRAY_BUFFER,
                                bytes,
                                bytes,
-                               aRects.texCoordPointer());
+                               aRects.texCoords().Elements());
     aGLContext->fEnableVertexAttribArray(texCoordAttribIndex);
     aGLContext->fVertexAttribPointer(texCoordAttribIndex,
                                      2, LOCAL_GL_FLOAT,
                                      LOCAL_GL_FALSE,
                                      0, BUFFER_OFFSET(bytes));
   }
 
-  aGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, elements);
+  aGLContext->fDrawArrays(aMode, 0, aRects.elements());
 
   aGLContext->fDisableVertexAttribArray(vertAttribIndex);
   if (texCoords) {
     aGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
   }
 
   aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
 }
@@ -484,26 +484,26 @@ CompositorOGL::BindAndDrawQuadWithTextur
     nsIntRect tcRect(texCoordRect.x, texCoordRect.y,
                      texCoordRect.width, texCoordRect.height);
     DecomposeIntoNoRepeatTriangles(tcRect,
                                    nsIntSize(realTexSize.width, realTexSize.height),
                                    rects, flipped);
   }
 
   gfx3DMatrix textureTransform;
-  if (rects.IsSimpleQuad(textureTransform)) {
+  if (rects.isSimpleQuad(textureTransform)) {
     Matrix4x4 transform;
     ToMatrix4x4(aTextureTransform * textureTransform, transform);
     aProg->SetTextureTransform(transform);
     BindAndDrawQuad(aProg, false);
   } else {
     Matrix4x4 transform;
     ToMatrix4x4(aTextureTransform, transform);
     aProg->SetTextureTransform(transform);
-    DrawQuads(mGLContext, mVBOs, aProg, rects);
+    DrawQuads(mGLContext, mVBOs, aProg, LOCAL_GL_TRIANGLES, rects);
   }
 }
 
 void
 CompositorOGL::PrepareViewport(const gfx::IntSize& aSize,
                                const Matrix& aWorldTransform)
 {
   // Set the viewport correctly.
@@ -621,18 +621,21 @@ CalculatePOTSize(const IntSize& aSize, G
 
 void
 CompositorOGL::clearFBRect(const gfx::Rect* aRect)
 {
   if (!aRect) {
     return;
   }
 
+  // Map aRect to OGL coordinates, origin:bottom-left
+  GLint y = mHeight - (aRect->y + aRect->height);
+
   ScopedGLState scopedScissorTestState(mGLContext, LOCAL_GL_SCISSOR_TEST, true);
-  ScopedScissorRect autoScissorRect(mGLContext, aRect->x, aRect->y, aRect->width, aRect->height);
+  ScopedScissorRect autoScissorRect(mGLContext, aRect->x, y, aRect->width, aRect->height);
   mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
   mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
 }
 
 void
 CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
                           const Rect *aClipRectIn,
                           const gfx::Matrix& aTransform,
--- a/gfx/skia/generate_mozbuild.py
+++ b/gfx/skia/generate_mozbuild.py
@@ -15,17 +15,17 @@ footer = """
 # left out of UNIFIED_SOURCES for now; that's not C++ anyway, nothing else to unify it with
 if not CONFIG['INTEL_ARCHITECTURE'] and CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']:
     SOURCES += [
         'trunk/src/opts/memset.arm.S',
     ]
 
 MSVC_ENABLE_PGO = True
 
-FINAL_LIBRARY = 'xul'
+FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'trunk/include/config',
     'trunk/include/core',
     'trunk/include/effects',
     'trunk/include/gpu',
     'trunk/include/images',
     'trunk/include/lazy',
     'trunk/include/pathops',
@@ -61,16 +61,23 @@ if CONFIG['INTEL_ARCHITECTURE'] and CONF
     DEFINES['SK_BUILD_SSSE3'] = 1
 
 if (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android') or \
    (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa') or \
    (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk') or \
    CONFIG['MOZ_WIDGET_QT'] or \
    CONFIG['MOZ_WIDGET_GTK']:
     DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+    DEFINES['SKIA_DLL'] = 1
+    DEFINES['GR_DLL'] = 1
+
+DEFINES['SKIA_IMPLEMENTATION'] = 1
+DEFINES['GR_IMPLEMENTATION'] = 1
 """
 
 import json
 
 platforms = ['linux', 'mac', 'android', 'win']
 
 custom_includes = {
   'trunk/src/ports/SkAtomics_android.h': True,
--- a/gfx/skia/moz.build
+++ b/gfx/skia/moz.build
@@ -802,17 +802,17 @@ else:
 # left out of UNIFIED_SOURCES for now; that's not C++ anyway, nothing else to unify it with
 if not CONFIG['INTEL_ARCHITECTURE'] and CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']:
     SOURCES += [
         'trunk/src/opts/memset.arm.S',
     ]
 
 MSVC_ENABLE_PGO = True
 
-FINAL_LIBRARY = 'xul'
+FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'trunk/include/config',
     'trunk/include/core',
     'trunk/include/effects',
     'trunk/include/gpu',
     'trunk/include/images',
     'trunk/include/lazy',
     'trunk/include/pathops',
@@ -842,10 +842,20 @@ DEFINES['SK_G32_SHIFT'] = 8
 DEFINES['SK_B32_SHIFT'] = 0
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'qt', 'gonk', 'cocoa'):
     DEFINES['SK_USE_POSIX_THREADS'] = 1
 
 if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3']:
     DEFINES['SK_BUILD_SSSE3'] = 1
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+    DEFINES['SKIA_DLL'] = 1
+
 if (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android') or (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk') or    (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa') or    CONFIG['MOZ_WIDGET_GTK'] or    CONFIG['MOZ_WIDGET_QT']:
     DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+    DEFINES['SKIA_DLL'] = 1
+    DEFINES['GR_DLL'] = 1
+
+DEFINES['SKIA_IMPLEMENTATION'] = 1
+DEFINES['GR_IMPLEMENTATION'] = 1
--- a/gfx/thebes/gfxImageSurface.h
+++ b/gfx/thebes/gfxImageSurface.h
@@ -107,18 +107,19 @@ public:
     /**
      * Fast copy to a source surface; returns TRUE if successful, FALSE otherwise
      * Assumes that the format of this surface is compatible with aSurface
      */
     bool CopyTo (mozilla::gfx::SourceSurface *aSurface);
 
     /**
      * Copy to a Moz2D DataSourceSurface.
+     * Marked as virtual so that browsercomps can access this method.
      */
-    mozilla::TemporaryRef<mozilla::gfx::DataSourceSurface> CopyToB8G8R8A8DataSourceSurface();
+    virtual mozilla::TemporaryRef<mozilla::gfx::DataSourceSurface> CopyToB8G8R8A8DataSourceSurface();
 
     /* return new Subimage with pointing to original image starting from aRect.pos
      * and size of aRect.size. New subimage keeping current image reference
      */
     already_AddRefed<gfxSubimageSurface> GetSubimage(const gfxRect& aRect);
 
     virtual already_AddRefed<gfxImageSurface> GetAsImageSurface();
 
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -41,16 +41,22 @@ DisableFontActivation()
     // get the main bundle identifier
     CFBundleRef mainBundle = ::CFBundleGetMainBundle();
     CFStringRef mainBundleID = nullptr;
 
     if (mainBundle) {
         mainBundleID = ::CFBundleGetIdentifier(mainBundle);
     }
 
+    // bug 969388 and bug 922590 - mainBundlID as null is sometimes problematic
+    if (!mainBundleID) {
+        NS_WARNING("missing bundle ID, packaging set up incorrectly");
+        return;
+    }
+
     // if possible, fetch CTFontManagerSetAutoActivationSetting
     void (*CTFontManagerSetAutoActivationSettingPtr)
             (CFStringRef, AutoActivationSetting);
     CTFontManagerSetAutoActivationSettingPtr =
         (void (*)(CFStringRef, AutoActivationSetting))
         dlsym(RTLD_DEFAULT, "CTFontManagerSetAutoActivationSetting");
 
     // bug 567552 - disable auto-activation of fonts
--- a/js/src/assembler/wtf/Platform.h
+++ b/js/src/assembler/wtf/Platform.h
@@ -160,26 +160,32 @@
 /* WTF_CPU_PPC - PowerPC 32-bit */
 #if   defined(__ppc__)     \
     || defined(__PPC__)     \
     || defined(__powerpc__) \
     || defined(__powerpc)   \
     || defined(__POWERPC__) \
     || defined(_M_PPC)      \
     || defined(__PPC)
+#if !defined(__ppc64__) && !defined(__PPC64__)
 #define WTF_CPU_PPC 1
+#endif
+#if !defined(__LITTLE_ENDIAN__)
 #define WTF_CPU_BIG_ENDIAN 1
 #endif
+#endif
 
 /* WTF_CPU_PPC64 - PowerPC 64-bit */
 #if   defined(__ppc64__) \
     || defined(__PPC64__)
 #define WTF_CPU_PPC64 1
+#if !defined(__LITTLE_ENDIAN__)
 #define WTF_CPU_BIG_ENDIAN 1
 #endif
+#endif
 
 /* WTF_CPU_SH4 - SuperH SH-4 */
 #if defined(__SH4__)
 #define WTF_CPU_SH4 1
 #endif
 
 /* WTF_CPU_SPARC32 - SPARC 32-bit */
 #if defined(__sparc) && !defined(__arch64__) || defined(__sparcv8)
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -929,17 +929,17 @@ esac
 
 # Only set CPU_ARCH if we recognize the value of OS_TEST
 
 case "$OS_TEST" in
 *86 | i86pc)
     CPU_ARCH=x86
     ;;
 
-powerpc64 | ppc64)
+powerpc64 | ppc64 | powerpc64le | ppc64le)
     CPU_ARCH=ppc64
     ;;
 
 powerpc | ppc | rs6000)
     CPU_ARCH=ppc
     ;;
 
 Alpha | alpha | ALPHA)
--- a/js/src/ctypes/libffi/aclocal.m4
+++ b/js/src/ctypes/libffi/aclocal.m4
@@ -1277,31 +1277,34 @@ ia64-*-hpux*)
 	  LD="${LD-ld} -64"
 	  ;;
       esac
     fi
   fi
   rm -rf conftest*
   ;;
 
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
 s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
     case `/usr/bin/file conftest.o` in
       *32-bit*)
 	case $host in
 	  x86_64-*kfreebsd*-gnu)
 	    LD="${LD-ld} -m elf_i386_fbsd"
 	    ;;
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_i386"
 	    ;;
-	  ppc64-*linux*|powerpc64-*linux*)
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
 	    LD="${LD-ld} -m elf32ppclinux"
 	    ;;
 	  s390x-*linux*)
 	    LD="${LD-ld} -m elf_s390"
 	    ;;
 	  sparc64-*linux*)
 	    LD="${LD-ld} -m elf32_sparc"
 	    ;;
@@ -1310,17 +1313,20 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*
       *64-bit*)
 	case $host in
 	  x86_64-*kfreebsd*-gnu)
 	    LD="${LD-ld} -m elf_x86_64_fbsd"
 	    ;;
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_x86_64"
 	    ;;
-	  ppc*-*linux*|powerpc*-*linux*)
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
 	    LD="${LD-ld} -m elf64ppc"
 	    ;;
 	  s390*-*linux*|s390*-*tpf*)
 	    LD="${LD-ld} -m elf64_s390"
 	    ;;
 	  sparc*-*linux*)
 	    LD="${LD-ld} -m elf64_sparc"
 	    ;;
--- a/js/src/ctypes/libffi/configure
+++ b/js/src/ctypes/libffi/configure
@@ -6293,17 +6293,17 @@ ia64-*-hpux*)
 	  LD="${LD-ld} -64"
 	  ;;
       esac
     fi
   fi
   rm -rf conftest*
   ;;
 
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
 s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
@@ -6311,17 +6311,20 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*
       *32-bit*)
 	case $host in
 	  x86_64-*kfreebsd*-gnu)
 	    LD="${LD-ld} -m elf_i386_fbsd"
 	    ;;
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_i386"
 	    ;;
-	  ppc64-*linux*|powerpc64-*linux*)
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
 	    LD="${LD-ld} -m elf32ppclinux"
 	    ;;
 	  s390x-*linux*)
 	    LD="${LD-ld} -m elf_s390"
 	    ;;
 	  sparc64-*linux*)
 	    LD="${LD-ld} -m elf32_sparc"
 	    ;;
@@ -6330,17 +6333,20 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*
       *64-bit*)
 	case $host in
 	  x86_64-*kfreebsd*-gnu)
 	    LD="${LD-ld} -m elf_x86_64_fbsd"
 	    ;;
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_x86_64"
 	    ;;
-	  ppc*-*linux*|powerpc*-*linux*)
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
 	    LD="${LD-ld} -m elf64ppc"
 	    ;;
 	  s390*-*linux*|s390*-*tpf*)
 	    LD="${LD-ld} -m elf64_s390"
 	    ;;
 	  sparc*-*linux*)
 	    LD="${LD-ld} -m elf64_sparc"
 	    ;;
--- a/js/src/ctypes/libffi/m4/libtool.m4
+++ b/js/src/ctypes/libffi/m4/libtool.m4
@@ -1262,31 +1262,34 @@ ia64-*-hpux*)
 	  LD="${LD-ld} -64"
 	  ;;
       esac
     fi
   fi
   rm -rf conftest*
   ;;
 
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
 s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if AC_TRY_EVAL(ac_compile); then
     case `/usr/bin/file conftest.o` in
       *32-bit*)
 	case $host in
 	  x86_64-*kfreebsd*-gnu)
 	    LD="${LD-ld} -m elf_i386_fbsd"
 	    ;;
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_i386"
 	    ;;
-	  ppc64-*linux*|powerpc64-*linux*)
+	  powerpc64le-*linux*)
+	    LD="${LD-ld} -m elf32lppclinux"
+	    ;;
+	  powerpc64-*linux*)
 	    LD="${LD-ld} -m elf32ppclinux"
 	    ;;
 	  s390x-*linux*)
 	    LD="${LD-ld} -m elf_s390"
 	    ;;
 	  sparc64-*linux*)
 	    LD="${LD-ld} -m elf32_sparc"
 	    ;;
@@ -1295,17 +1298,20 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*
       *64-bit*)
 	case $host in
 	  x86_64-*kfreebsd*-gnu)
 	    LD="${LD-ld} -m elf_x86_64_fbsd"
 	    ;;
 	  x86_64-*linux*)
 	    LD="${LD-ld} -m elf_x86_64"
 	    ;;
-	  ppc*-*linux*|powerpc*-*linux*)
+	  powerpcle-*linux*)
+	    LD="${LD-ld} -m elf64lppc"
+	    ;;
+	  powerpc-*linux*)
 	    LD="${LD-ld} -m elf64ppc"
 	    ;;
 	  s390*-*linux*|s390*-*tpf*)
 	    LD="${LD-ld} -m elf64_s390"
 	    ;;
 	  sparc*-*linux*)
 	    LD="${LD-ld} -m elf64_sparc"
 	    ;;
--- a/js/src/ctypes/libffi/src/powerpc/ffi.c
+++ b/js/src/ctypes/libffi/src/powerpc/ffi.c
@@ -1,12 +1,14 @@
 /* -----------------------------------------------------------------------
-   ffi.c - Copyright (c) 1998 Geoffrey Keating
-   Copyright (C) 2007, 2008 Free Software Foundation, Inc
-   Copyright (C) 2008 Red Hat, Inc
+   ffi.c - Copyright (C) 2011 Anthony Green
+           Copyright (C) 2011 Kyle Moffett
+           Copyright (C) 2008 Red Hat, Inc
+           Copyright (C) 2007, 2008 Free Software Foundation, Inc
+	   Copyright (c) 1998 Geoffrey Keating
 
    PowerPC Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    ``Software''), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
@@ -34,42 +36,39 @@
 
 extern void ffi_closure_SYSV (void);
 extern void FFI_HIDDEN ffi_closure_LINUX64 (void);
 
 enum {
   /* The assembly depends on these exact flags.  */
   FLAG_RETURNS_SMST	= 1 << (31-31), /* Used for FFI_SYSV small structs.  */
   FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7 */
+#ifndef __NO_FPRS__
   FLAG_RETURNS_FP       = 1 << (31-29),
+#endif
   FLAG_RETURNS_64BITS   = 1 << (31-28),
 
   FLAG_RETURNS_128BITS  = 1 << (31-27), /* cr6  */
-  FLAG_SYSV_SMST_R4     = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
-					   structs.  */
-  FLAG_SYSV_SMST_R3     = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
-					   structs.  */
-  /* Bits (31-24) through (31-19) store shift value for SMST */
 
   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
+  FLAG_ARG_NEEDS_PSAVE  = FLAG_ARG_NEEDS_COPY, /* Used by ELFv2 */
+#ifndef __NO_FPRS__
   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
+#endif
   FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
   FLAG_RETVAL_REFERENCE = 1 << (31- 4)
 };
 
 /* About the SYSV ABI.  */
-unsigned int NUM_GPR_ARG_REGISTERS = 8;
+#define ASM_NEEDS_REGISTERS 4
+#define NUM_GPR_ARG_REGISTERS 8
 #ifndef __NO_FPRS__
-unsigned int NUM_FPR_ARG_REGISTERS = 8;
-#else
-unsigned int NUM_FPR_ARG_REGISTERS = 0;
+# define NUM_FPR_ARG_REGISTERS 8
 #endif
 
-enum { ASM_NEEDS_REGISTERS = 4 };
-
 /* ffi_prep_args_SYSV is called by the assembly routine once stack space
    has been allocated for the function's arguments.
 
    The stack layout we want looks like this:
 
    |   Return address from ffi_call_SYSV 4bytes	|	higher addresses
    |--------------------------------------------|
    |   Previous backchain pointer	4	|       stack pointer here
@@ -108,100 +107,119 @@ ffi_prep_args_SYSV (extended_cif *ecif, 
   /* 'stacktop' points at the previous backchain pointer.  */
   valp stacktop;
 
   /* 'gpr_base' points at the space for gpr3, and grows upwards as
      we use GPR registers.  */
   valp gpr_base;
   int intarg_count;
 
+#ifndef __NO_FPRS__
   /* 'fpr_base' points at the space for fpr1, and grows upwards as
      we use FPR registers.  */
   valp fpr_base;
   int fparg_count;
+#endif
 
   /* 'copy_space' grows down as we put structures in it.  It should
      stay 16-byte aligned.  */
   valp copy_space;
 
   /* 'next_arg' grows up as we put parameters in it.  */
   valp next_arg;
 
-  int i, ii MAYBE_UNUSED;
+  int i;
   ffi_type **ptr;
+#ifndef __NO_FPRS__
   double double_tmp;
+#endif
   union {
     void **v;
     char **c;
     signed char **sc;
     unsigned char **uc;
     signed short **ss;
     unsigned short **us;
     unsigned int **ui;
     long long **ll;
     float **f;
     double **d;
   } p_argv;
   size_t struct_copy_size;
   unsigned gprvalue;
 
-  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
-    NUM_FPR_ARG_REGISTERS = 0;
-
   stacktop.c = (char *) stack + bytes;
   gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
   intarg_count = 0;
+#ifndef __NO_FPRS__
   fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
   fparg_count = 0;
   copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
+#else
+  copy_space.c = gpr_base.c;
+#endif
   next_arg.u = stack + 2;
 
   /* Check that everything starts aligned properly.  */
-  FFI_ASSERT (((unsigned) (char *) stack & 0xF) == 0);
-  FFI_ASSERT (((unsigned) copy_space.c & 0xF) == 0);
-  FFI_ASSERT (((unsigned) stacktop.c & 0xF) == 0);
+  FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
+  FFI_ASSERT (((unsigned long) copy_space.c & 0xF) == 0);
+  FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
   FFI_ASSERT ((bytes & 0xF) == 0);
   FFI_ASSERT (copy_space.c >= next_arg.c);
 
   /* Deal with return values that are actually pass-by-reference.  */
   if (flags & FLAG_RETVAL_REFERENCE)
     {
       *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
       intarg_count++;
     }
 
   /* Now for the arguments.  */
   p_argv.v = ecif->avalue;
   for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
        i > 0;
        i--, ptr++, p_argv.v++)
     {
-      switch ((*ptr)->type)
-	{
+      unsigned short typenum = (*ptr)->type;
+
+      /* We may need to handle some values depending on ABI */
+      if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) {
+		if (typenum == FFI_TYPE_FLOAT)
+			typenum = FFI_TYPE_UINT32;
+		if (typenum == FFI_TYPE_DOUBLE)
+			typenum = FFI_TYPE_UINT64;
+		if (typenum == FFI_TYPE_LONGDOUBLE)
+			typenum = FFI_TYPE_UINT128;
+      } else if (ecif->cif->abi != FFI_LINUX) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+		if (typenum == FFI_TYPE_LONGDOUBLE)
+			typenum = FFI_TYPE_STRUCT;
+#endif
+      }
+
+      /* Now test the translated value */
+      switch (typenum) {
+#ifndef __NO_FPRS__
 	case FFI_TYPE_FLOAT:
 	  /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
-	  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
-	    goto soft_float_prep;
 	  double_tmp = **p_argv.f;
 	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
 	    {
 	      *next_arg.f = (float) double_tmp;
 	      next_arg.u += 1;
 	      intarg_count++;
 	    }
 	  else
 	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
 
 	case FFI_TYPE_DOUBLE:
 	  /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
-	  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
-	    goto soft_double_prep;
 	  double_tmp = **p_argv.d;
 
 	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
 	    {
 	      if (intarg_count >= NUM_GPR_ARG_REGISTERS
 		  && intarg_count % 2 != 0)
 		{
 		  intarg_count++;
@@ -213,53 +231,16 @@ ffi_prep_args_SYSV (extended_cif *ecif, 
 	  else
 	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
 
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	case FFI_TYPE_LONGDOUBLE:
-	  if ((ecif->cif->abi != FFI_LINUX)
-		&& (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
-	    goto do_struct;
-	  /* The soft float ABI for long doubles works like this,
-	     a long double is passed in four consecutive gprs if available.
-	     A maximum of 2 long doubles can be passed in gprs.
-	     If we do not have 4 gprs left, the long double is passed on the
-	     stack, 4-byte aligned.  */
-	  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
-	    {
-	      unsigned int int_tmp = (*p_argv.ui)[0];
-	      if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
-		{
-		  if (intarg_count < NUM_GPR_ARG_REGISTERS)
-		    intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
-		  *next_arg.u = int_tmp;
-		  next_arg.u++;
-		  for (ii = 1; ii < 4; ii++)
-		    {
-		      int_tmp = (*p_argv.ui)[ii];
-		      *next_arg.u = int_tmp;
-		      next_arg.u++;
-		    }
-		}
-	      else
-		{
-		  *gpr_base.u++ = int_tmp;
-		  for (ii = 1; ii < 4; ii++)
-		    {
-		      int_tmp = (*p_argv.ui)[ii];
-		      *gpr_base.u++ = int_tmp;
-		    }
-		}
-	      intarg_count +=4;
-	    }
-	  else
-	    {
 	      double_tmp = (*p_argv.d)[0];
 
 	      if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
 		{
 		  if (intarg_count >= NUM_GPR_ARG_REGISTERS
 		      && intarg_count % 2 != 0)
 		    {
 		      intarg_count++;
@@ -275,23 +256,50 @@ ffi_prep_args_SYSV (extended_cif *ecif, 
 		{
 		  *fpr_base.d++ = double_tmp;
 		  double_tmp = (*p_argv.d)[1];
 		  *fpr_base.d++ = double_tmp;
 		}
 
 	      fparg_count += 2;
 	      FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
-	    }
 	  break;
 #endif
+#endif /* have FPRs */
+
+	/*
+	 * The soft float ABI for long doubles works like this, a long double
+	 * is passed in four consecutive GPRs if available.  A maximum of 2
+	 * long doubles can be passed in gprs.  If we do not have 4 GPRs
+	 * left, the long double is passed on the stack, 4-byte aligned.
+	 */
+	case FFI_TYPE_UINT128: {
+		unsigned int int_tmp = (*p_argv.ui)[0];
+		unsigned int ii;
+		if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3) {
+			if (intarg_count < NUM_GPR_ARG_REGISTERS)
+				intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
+			*(next_arg.u++) = int_tmp;
+			for (ii = 1; ii < 4; ii++) {
+				int_tmp = (*p_argv.ui)[ii];
+				*(next_arg.u++) = int_tmp;
+			}
+		} else {
+			*(gpr_base.u++) = int_tmp;
+			for (ii = 1; ii < 4; ii++) {
+				int_tmp = (*p_argv.ui)[ii];
+				*(gpr_base.u++) = int_tmp;
+			}
+		}
+		intarg_count += 4;
+		break;
+	}
 
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_SINT64:
-	soft_double_prep:
 	  if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
 	    intarg_count++;
 	  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
 	    {
 	      if (intarg_count % 2 != 0)
 		{
 		  intarg_count++;
 		  next_arg.u++;
@@ -314,19 +322,16 @@ ffi_prep_args_SYSV (extended_cif *ecif, 
 		  gpr_base.u++;
 		}
 	      *gpr_base.ll++ = **p_argv.ll;
 	    }
 	  intarg_count += 2;
 	  break;
 
 	case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	do_struct:
-#endif
 	  struct_copy_size = ((*ptr)->size + 15) & ~0xF;
 	  copy_space.c -= struct_copy_size;
 	  memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
 
 	  gprvalue = (unsigned long) copy_space.c;
 
 	  FFI_ASSERT (copy_space.c > next_arg.c);
 	  FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
@@ -344,45 +349,91 @@ ffi_prep_args_SYSV (extended_cif *ecif, 
 	case FFI_TYPE_SINT16:
 	  gprvalue = **p_argv.ss;
 	  goto putgpr;
 
 	case FFI_TYPE_INT:
 	case FFI_TYPE_UINT32:
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_POINTER:
-	soft_float_prep:
 
 	  gprvalue = **p_argv.ui;
 
 	putgpr:
 	  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
 	    *next_arg.u++ = gprvalue;
 	  else
 	    *gpr_base.u++ = gprvalue;
 	  intarg_count++;
 	  break;
 	}
     }
 
   /* Check that we didn't overrun the stack...  */
   FFI_ASSERT (copy_space.c >= next_arg.c);
   FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
+  /* The assert below is testing that the number of integer arguments agrees
+     with the number found in ffi_prep_cif_machdep().  However, intarg_count
+     is incremented whenever we place an FP arg on the stack, so account for
+     that before our assert test.  */
+#ifndef __NO_FPRS__
+  if (fparg_count > NUM_FPR_ARG_REGISTERS)
+    intarg_count -= fparg_count - NUM_FPR_ARG_REGISTERS;
   FFI_ASSERT (fpr_base.u
 	      <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+#endif
   FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
 }
 
 /* About the LINUX64 ABI.  */
 enum {
   NUM_GPR_ARG_REGISTERS64 = 8,
   NUM_FPR_ARG_REGISTERS64 = 13
 };
 enum { ASM_NEEDS_REGISTERS64 = 4 };
 
+#if _CALL_ELF == 2
+static unsigned int
+discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
+{
+  switch (t->type)
+    {
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      *elnum = 1;
+      return (int) t->type;
+
+    case FFI_TYPE_STRUCT:;
+      {
+	unsigned int base_elt = 0, total_elnum = 0;
+	ffi_type **el = t->elements;
+	while (*el)
+	  {
+	    unsigned int el_elt, el_elnum = 0;
+	    el_elt = discover_homogeneous_aggregate (*el, &el_elnum);
+	    if (el_elt == 0
+		|| (base_elt && base_elt != el_elt))
+	      return 0;
+	    base_elt = el_elt;
+	    total_elnum += el_elnum;
+	    if (total_elnum > 8)
+	      return 0;
+	    el++;
+	  }
+	*elnum = total_elnum;
+	return base_elt;
+      }
+
+    default:
+      return 0;
+    }
+}
+#endif
+
+
 /* ffi_prep_args64 is called by the assembly routine once stack space
    has been allocated for the function's arguments.
 
    The stack layout we want looks like this:
 
    |   Ret addr from ffi_call_LINUX64	8bytes	|	higher addresses
    |--------------------------------------------|
    |   CR save area			8bytes	|
@@ -418,141 +469,216 @@ ffi_prep_args64 (extended_cif *ecif, uns
   const unsigned long bytes = ecif->cif->bytes;
   const unsigned long flags = ecif->cif->flags;
 
   typedef union {
     char *c;
     unsigned long *ul;
     float *f;
     double *d;
+    size_t p;
   } valp;
 
   /* 'stacktop' points at the previous backchain pointer.  */
   valp stacktop;
 
   /* 'next_arg' points at the space for gpr3, and grows upwards as
      we use GPR registers, then continues at rest.  */
   valp gpr_base;
   valp gpr_end;
   valp rest;
   valp next_arg;
 
   /* 'fpr_base' points at the space for fpr3, and grows upwards as
      we use FPR registers.  */
   valp fpr_base;
-  int fparg_count;
+  unsigned int fparg_count;
 
-  int i, words;
+  unsigned int i, words, nargs, nfixedargs;
   ffi_type **ptr;
   double double_tmp;
   union {
     void **v;
     char **c;
     signed char **sc;
     unsigned char **uc;
     signed short **ss;
     unsigned short **us;
     signed int **si;
     unsigned int **ui;
     unsigned long **ul;
     float **f;
     double **d;
   } p_argv;
   unsigned long gprvalue;
+#ifdef __STRUCT_PARM_ALIGN__
+  unsigned long align;
+#endif
 
   stacktop.c = (char *) stack + bytes;
   gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
   gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
+#if _CALL_ELF == 2
+  rest.ul = stack + 4 + NUM_GPR_ARG_REGISTERS64;
+#else
   rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
+#endif
   fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
   fparg_count = 0;
   next_arg.ul = gpr_base.ul;
 
   /* Check that everything starts aligned properly.  */
   FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
   FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
   FFI_ASSERT ((bytes & 0xF) == 0);
 
   /* Deal with return values that are actually pass-by-reference.  */
   if (flags & FLAG_RETVAL_REFERENCE)
     *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
 
   /* Now for the arguments.  */
   p_argv.v = ecif->avalue;
-  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
-       i > 0;
-       i--, ptr++, p_argv.v++)
+  nargs = ecif->cif->nargs;
+  nfixedargs = ecif->cif->nfixedargs;
+  for (ptr = ecif->cif->arg_types, i = 0;
+       i < nargs;
+       i++, ptr++, p_argv.v++)
     {
+      unsigned int elt, elnum;
+
       switch ((*ptr)->type)
 	{
 	case FFI_TYPE_FLOAT:
 	  double_tmp = **p_argv.f;
-	  *next_arg.f = (float) double_tmp;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    *fpr_base.d++ = double_tmp;
+	  else
+	    *next_arg.f = (float) double_tmp;
 	  if (++next_arg.ul == gpr_end.ul)
 	    next_arg.ul = rest.ul;
-	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
-	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
 
 	case FFI_TYPE_DOUBLE:
 	  double_tmp = **p_argv.d;
-	  *next_arg.d = double_tmp;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    *fpr_base.d++ = double_tmp;
+	  else
+	    *next_arg.d = double_tmp;
 	  if (++next_arg.ul == gpr_end.ul)
 	    next_arg.ul = rest.ul;
-	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
-	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
 
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	case FFI_TYPE_LONGDOUBLE:
 	  double_tmp = (*p_argv.d)[0];
-	  *next_arg.d = double_tmp;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    *fpr_base.d++ = double_tmp;
+	  else
+	    *next_arg.d = double_tmp;
 	  if (++next_arg.ul == gpr_end.ul)
 	    next_arg.ul = rest.ul;
-	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
-	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  double_tmp = (*p_argv.d)[1];
-	  *next_arg.d = double_tmp;
+	  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+	    *fpr_base.d++ = double_tmp;
+	  else
+	    *next_arg.d = double_tmp;
 	  if (++next_arg.ul == gpr_end.ul)
 	    next_arg.ul = rest.ul;
-	  if (fparg_count < NUM_FPR_ARG_REGISTERS64)
-	    *fpr_base.d++ = double_tmp;
 	  fparg_count++;
 	  FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
 	  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
 	  break;
 #endif
 
 	case FFI_TYPE_STRUCT:
-	  words = ((*ptr)->size + 7) / 8;
-	  if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
+#ifdef __STRUCT_PARM_ALIGN__
+	  align = (*ptr)->alignment;
+	  if (align > __STRUCT_PARM_ALIGN__)
+	    align = __STRUCT_PARM_ALIGN__;
+	  if (align > 1)
+	    next_arg.p = ALIGN (next_arg.p, align);
+#endif
+	  elt = 0;
+#if _CALL_ELF == 2
+	  elt = discover_homogeneous_aggregate (*ptr, &elnum);
+#endif
+	  if (elt)
 	    {
-	      size_t first = gpr_end.c - next_arg.c;
-	      memcpy (next_arg.c, *p_argv.c, first);
-	      memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
-	      next_arg.c = rest.c + words * 8 - first;
+	      union {
+		void *v;
+		float *f;
+		double *d;
+	      } arg;
+
+	      arg.v = *p_argv.v;
+	      if (elt == FFI_TYPE_FLOAT)
+		{
+		  do
+		    {
+		      double_tmp = *arg.f++;
+		      if (fparg_count < NUM_FPR_ARG_REGISTERS64
+			  && i < nfixedargs)
+			*fpr_base.d++ = double_tmp;
+		      else
+			*next_arg.f = (float) double_tmp;
+		      if (++next_arg.f == gpr_end.f)
+			next_arg.f = rest.f;
+		      fparg_count++;
+		    }
+		  while (--elnum != 0);
+		  if ((next_arg.p & 3) != 0)
+		    {
+		      if (++next_arg.f == gpr_end.f)
+			next_arg.f = rest.f;
+		    }
+		}
+	      else
+		do
+		  {
+		    double_tmp = *arg.d++;
+		    if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
+		      *fpr_base.d++ = double_tmp;
+		    else
+		      *next_arg.d = double_tmp;
+		    if (++next_arg.d == gpr_end.d)
+		      next_arg.d = rest.d;
+		    fparg_count++;
+		  }
+		while (--elnum != 0);
 	    }
 	  else
 	    {
-	      char *where = next_arg.c;
+	      words = ((*ptr)->size + 7) / 8;
+	      if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
+		{
+		  size_t first = gpr_end.c - next_arg.c;
+		  memcpy (next_arg.c, *p_argv.c, first);
+		  memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
+		  next_arg.c = rest.c + words * 8 - first;
+		}
+	      else
+		{
+		  char *where = next_arg.c;
 
-	      /* Structures with size less than eight bytes are passed
-		 left-padded.  */
-	      if ((*ptr)->size < 8)
-		where += 8 - (*ptr)->size;
-
-	      memcpy (where, *p_argv.c, (*ptr)->size);
-	      next_arg.ul += words;
-	      if (next_arg.ul == gpr_end.ul)
-		next_arg.ul = rest.ul;
+#ifndef __LITTLE_ENDIAN__
+		  /* Structures with size less than eight bytes are passed
+		     left-padded.  */
+		  if ((*ptr)->size < 8)
+		    where += 8 - (*ptr)->size;
+#endif
+		  memcpy (where, *p_argv.c, (*ptr)->size);
+		  next_arg.ul += words;
+		  if (next_arg.ul == gpr_end.ul)
+		    next_arg.ul = rest.ul;
+		}
 	    }
 	  break;
 
 	case FFI_TYPE_UINT8:
 	  gprvalue = **p_argv.uc;
 	  goto putgpr;
 	case FFI_TYPE_SINT8:
 	  gprvalue = **p_argv.sc;
@@ -586,53 +712,55 @@ ffi_prep_args64 (extended_cif *ecif, uns
   FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
 	      || (next_arg.ul >= gpr_base.ul
 		  && next_arg.ul <= gpr_base.ul + 4));
 }
 
 
 
 /* Perform machine dependent cif processing */
-ffi_status
-ffi_prep_cif_machdep (ffi_cif *cif)
+static ffi_status
+ffi_prep_cif_machdep_core (ffi_cif *cif)
 {
   /* All this is for the SYSV and LINUX64 ABI.  */
-  int i;
   ffi_type **ptr;
   unsigned bytes;
-  int fparg_count = 0, intarg_count = 0;
-  unsigned flags = 0;
+  unsigned i, fparg_count = 0, intarg_count = 0;
+  unsigned flags = cif->flags;
   unsigned struct_copy_size = 0;
   unsigned type = cif->rtype->type;
   unsigned size = cif->rtype->size;
 
-  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-    NUM_FPR_ARG_REGISTERS = 0;
-
+  /* The machine-independent calculation of cif->bytes doesn't work
+     for us.  Redo the calculation.  */
   if (cif->abi != FFI_LINUX64)
     {
-      /* All the machine-independent calculation of cif->bytes will be wrong.
-	 Redo the calculation for SYSV.  */
-
       /* Space for the frame pointer, callee's LR, and the asm's temp regs.  */
       bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
 
       /* Space for the GPR registers.  */
       bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
     }
   else
     {
       /* 64-bit ABI.  */
+#if _CALL_ELF == 2
+      /* Space for backchain, CR, LR, TOC and the asm's temp regs.  */
+      bytes = (4 + ASM_NEEDS_REGISTERS64) * sizeof (long);
 
+      /* Space for the general registers.  */
+      bytes += NUM_GPR_ARG_REGISTERS64 * sizeof (long);
+#else
       /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
 	 regs.  */
       bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
 
       /* Space for the mandatory parm save area and general registers.  */
       bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
+#endif
     }
 
   /* Return value handling.  The rules for SYSV are as follows:
      - 32-bit (or less) integer values are returned in gpr3;
      - Structures of size <= 4 bytes also returned in gpr3;
      - 64-bit integer values and structures between 5 and 8 bytes are returned
      in gpr3 and gpr4;
      - Single/double FP values are returned in fpr1;
@@ -641,71 +769,93 @@ ffi_prep_cif_machdep (ffi_cif *cif)
      - long doubles (if not equivalent to double) are returned in
      fpr1,fpr2 for Linux and as for large structs for SysV.
      For LINUX64:
      - integer values in gpr3;
      - Structures/Unions by reference;
      - Single/double FP values in fpr1, long double in fpr1,fpr2.
      - soft-float float/doubles are treated as UINT32/UINT64 respectivley.
      - soft-float long doubles are returned in gpr3-gpr6.  */
+  /* First translate for softfloat/nonlinux */
+  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+    {
+      if (type == FFI_TYPE_FLOAT)
+	type = FFI_TYPE_UINT32;
+      if (type == FFI_TYPE_DOUBLE)
+	type = FFI_TYPE_UINT64;
+      if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_UINT128;
+    }
+  else if (cif->abi != FFI_LINUX
+	   && cif->abi != FFI_LINUX64)
+    {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      if (type == FFI_TYPE_LONGDOUBLE)
+	type = FFI_TYPE_STRUCT;
+#endif
+    }
+
   switch (type)
     {
+#ifndef __NO_FPRS__
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
     case FFI_TYPE_LONGDOUBLE:
-      if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
-	&& cif->abi != FFI_LINUX_SOFT_FLOAT)
-	goto byref;
       flags |= FLAG_RETURNS_128BITS;
       /* Fall through.  */
 #endif
     case FFI_TYPE_DOUBLE:
       flags |= FLAG_RETURNS_64BITS;
       /* Fall through.  */
     case FFI_TYPE_FLOAT:
-      /* With FFI_LINUX_SOFT_FLOAT no fp registers are used.  */
-      if (cif->abi != FFI_LINUX_SOFT_FLOAT)
-	flags |= FLAG_RETURNS_FP;
+      flags |= FLAG_RETURNS_FP;
       break;
+#endif
 
+    case FFI_TYPE_UINT128:
+      flags |= FLAG_RETURNS_128BITS;
+      /* Fall through.  */
     case FFI_TYPE_UINT64:
     case FFI_TYPE_SINT64:
       flags |= FLAG_RETURNS_64BITS;
       break;
 
     case FFI_TYPE_STRUCT:
-      if (cif->abi == FFI_SYSV)
+      /*
+       * The final SYSV ABI says that structures smaller or equal 8 bytes
+       * are returned in r3/r4.  The FFI_GCC_SYSV ABI instead returns them
+       * in memory.
+       *
+       * NOTE: The assembly code can safely assume that it just needs to
+       *       store both r3 and r4 into a 8-byte word-aligned buffer, as
+       *       we allocate a temporary buffer in ffi_call() if this flag is
+       *       set.
+       */
+      if (cif->abi == FFI_SYSV && size <= 8)
 	{
-	  /* The final SYSV ABI says that structures smaller or equal 8 bytes
-	     are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
-	     in memory.  */
-
-	  /* Treat structs with size <= 8 bytes.  */
-	  if (size <= 8)
+	  flags |= FLAG_RETURNS_SMST;
+	  break;
+	}
+#if _CALL_ELF == 2
+      if (cif->abi == FFI_LINUX64)
+	{
+	  unsigned int elt, elnum;
+	  elt = discover_homogeneous_aggregate (cif->rtype, &elnum);
+	  if (elt)
+	    {
+	      if (elt == FFI_TYPE_DOUBLE)
+		flags |= FLAG_RETURNS_64BITS;
+	      flags |= FLAG_RETURNS_FP | FLAG_RETURNS_SMST;
+	      break;
+	    }
+	  if (size <= 16)
 	    {
 	      flags |= FLAG_RETURNS_SMST;
-	      /* These structs are returned in r3. We pack the type and the
-		 precalculated shift value (needed in the sysv.S) into flags.
-		 The same applies for the structs returned in r3/r4.  */
-	      if (size <= 4)
-		{
-		  flags |= FLAG_SYSV_SMST_R3;
-		  flags |= 8 * (4 - size) << 8;
-		  break;
-		}
-	      /* These structs are returned in r3 and r4. See above.   */
-	      if  (size <= 8)
-		{
-		  flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
-		  flags |= 8 * (8 - size) << 8;
-		  break;
-		}
+	      break;
 	    }
 	}
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-    byref:
 #endif
       intarg_count++;
       flags |= FLAG_RETVAL_REFERENCE;
       /* Fall through.  */
     case FFI_TYPE_VOID:
       flags |= FLAG_RETURNS_NOTHING;
       break;
 
@@ -717,218 +867,334 @@ ffi_prep_cif_machdep (ffi_cif *cif)
   if (cif->abi != FFI_LINUX64)
     /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
        first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
        goes on the stack.  Structures and long doubles (if not equivalent
        to double) are passed as a pointer to a copy of the structure.
        Stuff on the stack needs to keep proper alignment.  */
     for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
       {
-	switch ((*ptr)->type)
-	  {
+	unsigned short typenum = (*ptr)->type;
+
+	/* We may need to handle some values depending on ABI */
+	if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
+		if (typenum == FFI_TYPE_FLOAT)
+			typenum = FFI_TYPE_UINT32;
+		if (typenum == FFI_TYPE_DOUBLE)
+			typenum = FFI_TYPE_UINT64;
+		if (typenum == FFI_TYPE_LONGDOUBLE)
+			typenum = FFI_TYPE_UINT128;
+	} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+		if (typenum == FFI_TYPE_LONGDOUBLE)
+			typenum = FFI_TYPE_STRUCT;
+#endif
+	}
+
+	switch (typenum) {
+#ifndef __NO_FPRS__
 	  case FFI_TYPE_FLOAT:
-	    /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
-	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-	      goto soft_float_cif;
 	    fparg_count++;
 	    /* floating singles are not 8-aligned on stack */
 	    break;
 
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	  case FFI_TYPE_LONGDOUBLE:
-	    if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
-	      goto do_struct;
-	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-	      {
-		if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
-		  || intarg_count < NUM_GPR_ARG_REGISTERS)
-		  /* A long double in FFI_LINUX_SOFT_FLOAT can use only
-		     a set of four consecutive gprs. If we have not enough,
-		     we have to adjust the intarg_count value.  */
-		  intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
-		intarg_count += 4;
-		break;
-	      }
-	    else
-	      fparg_count++;
+	    fparg_count++;
 	    /* Fall thru */
 #endif
 	  case FFI_TYPE_DOUBLE:
-	    /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
-	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-	      goto soft_double_cif;
 	    fparg_count++;
 	    /* If this FP arg is going on the stack, it must be
 	       8-byte-aligned.  */
 	    if (fparg_count > NUM_FPR_ARG_REGISTERS
 		&& intarg_count >= NUM_GPR_ARG_REGISTERS
 		&& intarg_count % 2 != 0)
 	      intarg_count++;
 	    break;
+#endif
+	  case FFI_TYPE_UINT128:
+		/*
+		 * A long double in FFI_LINUX_SOFT_FLOAT can use only a set
+		 * of four consecutive gprs. If we do not have enough, we
+		 * have to adjust the intarg_count value.
+		 */
+		if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
+				&& intarg_count < NUM_GPR_ARG_REGISTERS)
+			intarg_count = NUM_GPR_ARG_REGISTERS;
+		intarg_count += 4;
+		break;
 
 	  case FFI_TYPE_UINT64:
 	  case FFI_TYPE_SINT64:
-	  soft_double_cif:
 	    /* 'long long' arguments are passed as two words, but
 	       either both words must fit in registers or both go
 	       on the stack.  If they go on the stack, they must
 	       be 8-byte-aligned.
 
 	       Also, only certain register pairs can be used for
 	       passing long long int -- specifically (r3,r4), (r5,r6),
 	       (r7,r8), (r9,r10).
 	    */
 	    if (intarg_count == NUM_GPR_ARG_REGISTERS-1
 		|| intarg_count % 2 != 0)
 	      intarg_count++;
 	    intarg_count += 2;
 	    break;
 
 	  case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	  do_struct:
-#endif
 	    /* We must allocate space for a copy of these to enforce
 	       pass-by-value.  Pad the space up to a multiple of 16
 	       bytes (the maximum alignment required for anything under
 	       the SYSV ABI).  */
 	    struct_copy_size += ((*ptr)->size + 15) & ~0xF;
 	    /* Fall through (allocate space for the pointer).  */
 
-	  default:
-	  soft_float_cif:
+	  case FFI_TYPE_POINTER:
+	  case FFI_TYPE_INT:
+	  case FFI_TYPE_UINT32:
+	  case FFI_TYPE_SINT32:
+	  case FFI_TYPE_UINT16:
+	  case FFI_TYPE_SINT16:
+	  case FFI_TYPE_UINT8:
+	  case FFI_TYPE_SINT8:
 	    /* Everything else is passed as a 4-byte word in a GPR, either
 	       the object itself or a pointer to it.  */
 	    intarg_count++;
 	    break;
+	  default:
+		FFI_ASSERT (0);
 	  }
       }
   else
     for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
       {
+	unsigned int elt, elnum;
+#ifdef __STRUCT_PARM_ALIGN__
+	unsigned int align;
+#endif
+
 	switch ((*ptr)->type)
 	  {
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	  case FFI_TYPE_LONGDOUBLE:
-	    if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-	      intarg_count += 4;
-	    else
-	      {
-		fparg_count += 2;
-		intarg_count += 2;
-	      }
+	    fparg_count += 2;
+	    intarg_count += 2;
+	    if (fparg_count > NUM_FPR_ARG_REGISTERS64)
+	      flags |= FLAG_ARG_NEEDS_PSAVE;
 	    break;
 #endif
 	  case FFI_TYPE_FLOAT:
 	  case FFI_TYPE_DOUBLE:
 	    fparg_count++;
 	    intarg_count++;
+	    if (fparg_count > NUM_FPR_ARG_REGISTERS64)
+	      flags |= FLAG_ARG_NEEDS_PSAVE;
 	    break;
 
 	  case FFI_TYPE_STRUCT:
+#ifdef __STRUCT_PARM_ALIGN__
+	    align = (*ptr)->alignment;
+	    if (align > __STRUCT_PARM_ALIGN__)
+	      align = __STRUCT_PARM_ALIGN__;
+	    align = align / 8;
+	    if (align > 1)
+	      intarg_count = ALIGN (intarg_count, align);
+#endif
 	    intarg_count += ((*ptr)->size + 7) / 8;
+	    elt = 0;
+#if _CALL_ELF == 2
+	    elt = discover_homogeneous_aggregate (*ptr, &elnum);
+#endif
+	    if (elt)
+	      {
+		fparg_count += elnum;
+		if (fparg_count > NUM_FPR_ARG_REGISTERS64)
+		  flags |= FLAG_ARG_NEEDS_PSAVE;
+	      }
+	    else
+	      {
+		if (intarg_count > NUM_GPR_ARG_REGISTERS64)
+		  flags |= FLAG_ARG_NEEDS_PSAVE;
+	      }
 	    break;
 
-	  default:
+	  case FFI_TYPE_POINTER:
+	  case FFI_TYPE_UINT64:
+	  case FFI_TYPE_SINT64:
+	  case FFI_TYPE_INT:
+	  case FFI_TYPE_UINT32:
+	  case FFI_TYPE_SINT32:
+	  case FFI_TYPE_UINT16:
+	  case FFI_TYPE_SINT16:
+	  case FFI_TYPE_UINT8:
+	  case FFI_TYPE_SINT8:
 	    /* Everything else is passed as a 8-byte word in a GPR, either
 	       the object itself or a pointer to it.  */
 	    intarg_count++;
+	    if (intarg_count > NUM_GPR_ARG_REGISTERS64)
+	      flags |= FLAG_ARG_NEEDS_PSAVE;
 	    break;
+	  default:
+	    FFI_ASSERT (0);
 	  }
       }
 
+#ifndef __NO_FPRS__
   if (fparg_count != 0)
     flags |= FLAG_FP_ARGUMENTS;
+#endif
   if (intarg_count > 4)
     flags |= FLAG_4_GPR_ARGUMENTS;
   if (struct_copy_size != 0)
     flags |= FLAG_ARG_NEEDS_COPY;
 
   if (cif->abi != FFI_LINUX64)
     {
+#ifndef __NO_FPRS__
       /* Space for the FPR registers, if needed.  */
       if (fparg_count != 0)
 	bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
+#endif
 
       /* Stack space.  */
       if (intarg_count > NUM_GPR_ARG_REGISTERS)
 	bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
+#ifndef __NO_FPRS__
       if (fparg_count > NUM_FPR_ARG_REGISTERS)
 	bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
+#endif
     }
   else
     {
+#ifndef __NO_FPRS__
       /* Space for the FPR registers, if needed.  */
       if (fparg_count != 0)
 	bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
+#endif
 
       /* Stack space.  */
+#if _CALL_ELF == 2
+      if ((flags & FLAG_ARG_NEEDS_PSAVE) != 0)
+	bytes += intarg_count * sizeof (long);
+#else
       if (intarg_count > NUM_GPR_ARG_REGISTERS64)
 	bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
+#endif
     }
 
   /* The stack space allocated needs to be a multiple of 16 bytes.  */
   bytes = (bytes + 15) & ~0xF;
 
   /* Add in the space for the copied structures.  */
   bytes += struct_copy_size;
 
   cif->flags = flags;
   cif->bytes = bytes;
 
   return FFI_OK;
 }
 
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  cif->nfixedargs = cif->nargs;
+  return ffi_prep_cif_machdep_core (cif);
+}
+
+ffi_status
+ffi_prep_cif_machdep_var (ffi_cif *cif,
+			  unsigned int nfixedargs,
+			  unsigned int ntotalargs MAYBE_UNUSED)
+{
+  cif->nfixedargs = nfixedargs;
+#if _CALL_ELF == 2
+  if (cif->abi == FFI_LINUX64)
+    cif->flags |= FLAG_ARG_NEEDS_PSAVE;
+#endif
+  return ffi_prep_cif_machdep_core (cif);
+}
+
 extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
 			  void (*fn)(void));
 extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
 					unsigned long, unsigned long *,
 					void (*fn)(void));
 
 void
 ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 {
+  /*
+   * The final SYSV ABI says that structures smaller or equal 8 bytes
+   * are returned in r3/r4.  The FFI_GCC_SYSV ABI instead returns them
+   * in memory.
+   *
+   * We bounce-buffer SYSV small struct return values so that sysv.S
+   * can write r3 and r4 to memory without worrying about struct size.
+   *
+   * For ELFv2 ABI, use a bounce buffer for homogeneous structs too,
+   * for similar reasons.
+   */
+  unsigned long smst_buffer[8];
   extended_cif ecif;
 
   ecif.cif = cif;
   ecif.avalue = avalue;
 
-  /* If the return value is a struct and we don't have a return	*/
-  /* value address then we need to make one		        */
-
-  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
-    {
-      ecif.rvalue = alloca(cif->rtype->size);
-    }
-  else
-    ecif.rvalue = rvalue;
-
+  ecif.rvalue = rvalue;
+  if ((cif->flags & FLAG_RETURNS_SMST) != 0)
+    ecif.rvalue = smst_buffer;
+  /* Ensure that we have a valid struct return value.
+     FIXME: Isn't this just papering over a user problem?  */
+  else if (!rvalue && cif->rtype->type == FFI_TYPE_STRUCT)
+    ecif.rvalue = alloca (cif->rtype->size);
 
   switch (cif->abi)
     {
 #ifndef POWERPC64
+# ifndef __NO_FPRS__
     case FFI_SYSV:
     case FFI_GCC_SYSV:
     case FFI_LINUX:
+# endif
     case FFI_LINUX_SOFT_FLOAT:
       ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
       break;
 #else
     case FFI_LINUX64:
       ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
       break;
 #endif
     default:
       FFI_ASSERT (0);
       break;
     }
+
+  /* Check for a bounce-buffered return value */
+  if (rvalue && ecif.rvalue == smst_buffer)
+    {
+      unsigned int rsize = cif->rtype->size;
+#ifndef __LITTLE_ENDIAN__
+      /* The SYSV ABI returns a structure of up to 4 bytes in size
+	 left-padded in r3.  */
+      if (cif->abi == FFI_SYSV && rsize <= 4)
+	memcpy (rvalue, (char *) smst_buffer + 4 - rsize, rsize);
+      /* The SYSV ABI returns a structure of up to 8 bytes in size
+	 left-padded in r3/r4, and the ELFv2 ABI similarly returns a
+	 structure of up to 8 bytes in size left-padded in r3.  */
+      else if (rsize <= 8)
+	memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize);
+      else
+#endif
+	memcpy (rvalue, smst_buffer, rsize);
+    }
 }
 
 
-#ifndef POWERPC64
+#if !defined POWERPC64 || _CALL_ELF == 2
 #define MIN_CACHE_LINE_SIZE 8
 
 static void
 flush_icache (char *wraddr, char *xaddr, int size)
 {
   int i;
   for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
     __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
@@ -942,26 +1208,48 @@ flush_icache (char *wraddr, char *xaddr,
 ffi_status
 ffi_prep_closure_loc (ffi_closure *closure,
 		      ffi_cif *cif,
 		      void (*fun) (ffi_cif *, void *, void **, void *),
 		      void *user_data,
 		      void *codeloc)
 {
 #ifdef POWERPC64
+# if _CALL_ELF == 2
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+
+  if (cif->abi != FFI_LINUX64)
+    return FFI_BAD_ABI;
+
+  tramp[0] = 0xe96c0018;	/* 0:	ld	11,2f-0b(12)	*/
+  tramp[1] = 0xe98c0010;	/*	ld	12,1f-0b(12)	*/
+  tramp[2] = 0x7d8903a6;	/*	mtctr	12		*/
+  tramp[3] = 0x4e800420;	/*	bctr			*/
+				/* 1:	.quad	function_addr	*/
+				/* 2:	.quad	context		*/
+  *(void **) &tramp[4] = (void *) ffi_closure_LINUX64;
+  *(void **) &tramp[6] = codeloc;
+  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
+# else
   void **tramp = (void **) &closure->tramp[0];
 
-  FFI_ASSERT (cif->abi == FFI_LINUX64);
+  if (cif->abi != FFI_LINUX64)
+    return FFI_BAD_ABI;
   /* Copy function address and TOC from ffi_closure_LINUX64.  */
   memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
   tramp[2] = codeloc;
+# endif
 #else
   unsigned int *tramp;
 
-  FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
+  if (! (cif->abi == FFI_GCC_SYSV 
+	 || cif->abi == FFI_SYSV
+	 || cif->abi == FFI_LINUX
+	 || cif->abi == FFI_LINUX_SOFT_FLOAT))
+    return FFI_BAD_ABI;
 
   tramp = (unsigned int *) &closure->tramp[0];
   tramp[0] = 0x7c0802a6;  /*   mflr    r0 */
   tramp[1] = 0x4800000d;  /*   bl      10 <trampoline_initial+0x10> */
   tramp[4] = 0x7d6802a6;  /*   mflr    r11 */
   tramp[5] = 0x7c0803a6;  /*   mtlr    r0 */
   tramp[6] = 0x800b0000;  /*   lwz     r0,0(r11) */
   tramp[7] = 0x816b0004;  /*   lwz     r11,4(r11) */
@@ -1006,110 +1294,215 @@ ffi_closure_helper_SYSV (ffi_closure *cl
   /* rvalue is the pointer to space for return value in closure assembly */
   /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
   /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV  */
   /* pst is the pointer to outgoing parameter stack in original caller */
 
   void **          avalue;
   ffi_type **      arg_types;
   long             i, avn;
-  long             nf;   /* number of floating registers already used */
-  long             ng;   /* number of general registers already used */
-  ffi_cif *        cif;
-  double           temp;
-  unsigned         size;
+#ifndef __NO_FPRS__
+  long             nf = 0;   /* number of floating registers already used */
+#endif
+  long             ng = 0;   /* number of general registers already used */
+
+  ffi_cif *cif = closure->cif;
+  unsigned       size     = cif->rtype->size;
+  unsigned short rtypenum = cif->rtype->type;
+
+  avalue = alloca (cif->nargs * sizeof (void *));
 
-  cif = closure->cif;
-  avalue = alloca (cif->nargs * sizeof (void *));
-  size = cif->rtype->size;
+  /* First translate for softfloat/nonlinux */
+  if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
+	if (rtypenum == FFI_TYPE_FLOAT)
+		rtypenum = FFI_TYPE_UINT32;
+	if (rtypenum == FFI_TYPE_DOUBLE)
+		rtypenum = FFI_TYPE_UINT64;
+	if (rtypenum == FFI_TYPE_LONGDOUBLE)
+		rtypenum = FFI_TYPE_UINT128;
+  } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	if (rtypenum == FFI_TYPE_LONGDOUBLE)
+		rtypenum = FFI_TYPE_STRUCT;
+#endif
+  }
 
-  nf = 0;
-  ng = 0;
 
   /* Copy the caller's structure return value address so that the closure
      returns the data directly to the caller.
      For FFI_SYSV the result is passed in r3/r4 if the struct size is less
      or equal 8 bytes.  */
-
-  if ((cif->rtype->type == FFI_TYPE_STRUCT
-       && !((cif->abi == FFI_SYSV) && (size <= 8)))
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-      || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
-	  && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
-#endif
-      )
-    {
+  if (rtypenum == FFI_TYPE_STRUCT && ((cif->abi != FFI_SYSV) || (size > 8))) {
       rvalue = (void *) *pgr;
       ng++;
       pgr++;
     }
 
   i = 0;
   avn = cif->nargs;
   arg_types = cif->arg_types;
 
   /* Grab the addresses of the arguments from the stack frame.  */
-  while (i < avn)
-    {
-      switch (arg_types[i]->type)
-	{
+  while (i < avn) {
+      unsigned short typenum = arg_types[i]->type;
+
+      /* We may need to handle some values depending on ABI */
+      if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
+		if (typenum == FFI_TYPE_FLOAT)
+			typenum = FFI_TYPE_UINT32;
+		if (typenum == FFI_TYPE_DOUBLE)
+			typenum = FFI_TYPE_UINT64;
+		if (typenum == FFI_TYPE_LONGDOUBLE)
+			typenum = FFI_TYPE_UINT128;
+      } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+		if (typenum == FFI_TYPE_LONGDOUBLE)
+			typenum = FFI_TYPE_STRUCT;
+#endif
+      }
+
+      switch (typenum) {
+#ifndef __NO_FPRS__
+	case FFI_TYPE_FLOAT:
+	  /* unfortunately float values are stored as doubles
+	   * in the ffi_closure_SYSV code (since we don't check
+	   * the type in that routine).
+	   */
+
+	  /* there are 8 64bit floating point registers */
+
+	  if (nf < 8)
+	    {
+	      double temp = pfr->d;
+	      pfr->f = (float) temp;
+	      avalue[i] = pfr;
+	      nf++;
+	      pfr++;
+	    }
+	  else
+	    {
+	      /* FIXME? here we are really changing the values
+	       * stored in the original calling routines outgoing
+	       * parameter stack.  This is probably a really
+	       * naughty thing to do but...
+	       */
+	      avalue[i] = pst;
+	      pst += 1;
+	    }
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  /* On the outgoing stack all values are aligned to 8 */
+	  /* there are 8 64bit floating point registers */
+
+	  if (nf < 8)
+	    {
+	      avalue[i] = pfr;
+	      nf++;
+	      pfr++;
+	    }
+	  else
+	    {
+	      if (((long) pst) & 4)
+		pst++;
+	      avalue[i] = pst;
+	      pst += 2;
+	    }
+	  break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+	  if (nf < 7)
+	    {
+	      avalue[i] = pfr;
+	      pfr += 2;
+	      nf += 2;
+	    }
+	  else
+	    {
+	      if (((long) pst) & 4)
+		pst++;
+	      avalue[i] = pst;
+	      pst += 4;
+	      nf = 8;
+	    }
+	  break;
+#endif
+#endif /* have FPRS */
+
+	case FFI_TYPE_UINT128:
+		/*
+		 * Test if for the whole long double, 4 gprs are available.
+		 * otherwise the stuff ends up on the stack.
+		 */
+		if (ng < 5) {
+			avalue[i] = pgr;
+			pgr += 4;
+			ng += 4;
+		} else {
+			avalue[i] = pst;
+			pst += 4;
+			ng = 8+4;
+		}
+		break;
+
 	case FFI_TYPE_SINT8:
 	case FFI_TYPE_UINT8:
+#ifndef __LITTLE_ENDIAN__
 	  /* there are 8 gpr registers used to pass values */
 	  if (ng < 8)
 	    {
 	      avalue[i] = (char *) pgr + 3;
 	      ng++;
 	      pgr++;
 	    }
 	  else
 	    {
 	      avalue[i] = (char *) pst + 3;
 	      pst++;
 	    }
 	  break;
+#endif
 
 	case FFI_TYPE_SINT16:
 	case FFI_TYPE_UINT16:
+#ifndef __LITTLE_ENDIAN__
 	  /* there are 8 gpr registers used to pass values */
 	  if (ng < 8)
 	    {
 	      avalue[i] = (char *) pgr + 2;
 	      ng++;
 	      pgr++;
 	    }
 	  else
 	    {
 	      avalue[i] = (char *) pst + 2;
 	      pst++;
 	    }
 	  break;
+#endif
 
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
 	case FFI_TYPE_POINTER:
-	soft_float_closure:
 	  /* there are 8 gpr registers used to pass values */
 	  if (ng < 8)
 	    {
 	      avalue[i] = pgr;
 	      ng++;
 	      pgr++;
 	    }
 	  else
 	    {
 	      avalue[i] = pst;
 	      pst++;
 	    }
 	  break;
 
 	case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	do_struct:
-#endif
 	  /* Structs are passed by reference. The address will appear in a
 	     gpr if it is one of the first 8 arguments.  */
 	  if (ng < 8)
 	    {
 	      avalue[i] = (void *) *pgr;
 	      ng++;
 	      pgr++;
 	    }
@@ -1117,17 +1510,16 @@ ffi_closure_helper_SYSV (ffi_closure *cl
 	    {
 	      avalue[i] = (void *) *pst;
 	      pst++;
 	    }
 	  break;
 
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
-	soft_double_closure:
 	  /* passing long long ints are complex, they must
 	   * be passed in suitable register pairs such as
 	   * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
 	   * and if the entire pair aren't available then the outgoing
 	   * parameter stack is used for both but an alignment of 8
 	   * must will be kept.  So we must either look in pgr
 	   * or pst to find the correct address for this type
 	   * of parameter.
@@ -1149,277 +1541,239 @@ ffi_closure_helper_SYSV (ffi_closure *cl
 	      if (((long) pst) & 4)
 		pst++;
 	      avalue[i] = pst;
 	      pst += 2;
 	      ng = 8;
 	    }
 	  break;
 
-	case FFI_TYPE_FLOAT:
-	  /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
-	  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-	    goto soft_float_closure;
-	  /* unfortunately float values are stored as doubles
-	   * in the ffi_closure_SYSV code (since we don't check
-	   * the type in that routine).
-	   */
-
-	  /* there are 8 64bit floating point registers */
-
-	  if (nf < 8)
-	    {
-	      temp = pfr->d;
-	      pfr->f = (float) temp;
-	      avalue[i] = pfr;
-	      nf++;
-	      pfr++;
-	    }
-	  else
-	    {
-	      /* FIXME? here we are really changing the values
-	       * stored in the original calling routines outgoing
-	       * parameter stack.  This is probably a really
-	       * naughty thing to do but...
-	       */
-	      avalue[i] = pst;
-	      pst += 1;
-	    }
-	  break;
-
-	case FFI_TYPE_DOUBLE:
-	  /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
-	  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-	    goto soft_double_closure;
-	  /* On the outgoing stack all values are aligned to 8 */
-	  /* there are 8 64bit floating point registers */
-
-	  if (nf < 8)
-	    {
-	      avalue[i] = pfr;
-	      nf++;
-	      pfr++;
-	    }
-	  else
-	    {
-	      if (((long) pst) & 4)
-		pst++;
-	      avalue[i] = pst;
-	      pst += 2;
-	    }
-	  break;
-
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	case FFI_TYPE_LONGDOUBLE:
-	  if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
-	    goto do_struct;
-	  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-	    { /* Test if for the whole long double, 4 gprs are available.
-		 otherwise the stuff ends up on the stack.  */
-	      if (ng < 5)
-		{
-		  avalue[i] = pgr;
-		  pgr += 4;
-		  ng += 4;
-		}
-	      else
-		{
-		  avalue[i] = pst;
-		  pst += 4;
-		  ng = 8;
-		}
-	      break;
-	    }
-	  if (nf < 7)
-	    {
-	      avalue[i] = pfr;
-	      pfr += 2;
-	      nf += 2;
-	    }
-	  else
-	    {
-	      if (((long) pst) & 4)
-		pst++;
-	      avalue[i] = pst;
-	      pst += 4;
-	      nf = 8;
-	    }
-	  break;
-#endif
-
 	default:
-	  FFI_ASSERT (0);
+		FFI_ASSERT (0);
 	}
 
       i++;
     }
 
 
   (closure->fun) (cif, rvalue, avalue, closure->user_data);
 
   /* Tell ffi_closure_SYSV how to perform return type promotions.
      Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4
      we have to tell ffi_closure_SYSV how to treat them. We combine the base
      type FFI_SYSV_TYPE_SMALL_STRUCT - 1  with the size of the struct.
      So a one byte struct gets the return type 16. Return type 1 to 15 are
      already used and we never have a struct with size zero. That is the reason
      for the subtraction of 1. See the comment in ffitarget.h about ordering.
   */
-  if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
-      && size <= 8)
+  if (cif->abi == FFI_SYSV && rtypenum == FFI_TYPE_STRUCT && size <= 8)
     return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-  else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
-	   && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
-    return FFI_TYPE_STRUCT;
-#endif
-  /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
-     respectivley UINT64.  */
-  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
-    {
-      switch (cif->rtype->type)
-	{
-	case FFI_TYPE_FLOAT:
-	  return FFI_TYPE_UINT32;
-	  break;
-	case FFI_TYPE_DOUBLE:
-	  return FFI_TYPE_UINT64;
-	  break;
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	case FFI_TYPE_LONGDOUBLE:
-	  return FFI_TYPE_UINT128;
-	  break;
-#endif
-	default:
-	  return cif->rtype->type;
-	}
-    }
-  else
-    {
-      return cif->rtype->type;
-    }
+  return rtypenum;
 }
 
 int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
 					   unsigned long *, ffi_dblfl *);
 
 int FFI_HIDDEN
 ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
 			    unsigned long *pst, ffi_dblfl *pfr)
 {
   /* rvalue is the pointer to space for return value in closure assembly */
   /* pst is the pointer to parameter save area
      (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
   /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
 
   void **avalue;
   ffi_type **arg_types;
-  long i, avn;
+  unsigned long i, avn, nfixedargs;
   ffi_cif *cif;
   ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
+#ifdef __STRUCT_PARM_ALIGN__
+  unsigned long align;
+#endif
 
   cif = closure->cif;
   avalue = alloca (cif->nargs * sizeof (void *));
 
-  /* Copy the caller's structure return value address so that the closure
-     returns the data directly to the caller.  */
-  if (cif->rtype->type == FFI_TYPE_STRUCT)
+  /* Copy the caller's structure return value address so that the
+     closure returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      && (cif->flags & FLAG_RETURNS_SMST) == 0)
     {
       rvalue = (void *) *pst;
       pst++;
     }
 
   i = 0;
   avn = cif->nargs;
+  nfixedargs = cif->nfixedargs;
   arg_types = cif->arg_types;
 
   /* Grab the addresses of the arguments from the stack frame.  */
   while (i < avn)
     {
+      unsigned int elt, elnum;
+
       switch (arg_types[i]->type)
 	{
 	case FFI_TYPE_SINT8:
 	case FFI_TYPE_UINT8:
+#ifndef __LITTLE_ENDIAN__
 	  avalue[i] = (char *) pst + 7;
 	  pst++;
 	  break;
+#endif
 
 	case FFI_TYPE_SINT16:
 	case FFI_TYPE_UINT16:
+#ifndef __LITTLE_ENDIAN__
 	  avalue[i] = (char *) pst + 6;
 	  pst++;
 	  break;
+#endif
 
 	case FFI_TYPE_SINT32:
 	case FFI_TYPE_UINT32:
+#ifndef __LITTLE_ENDIAN__
 	  avalue[i] = (char *) pst + 4;
 	  pst++;
 	  break;
+#endif
 
 	case FFI_TYPE_SINT64:
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_POINTER:
 	  avalue[i] = pst;
 	  pst++;
 	  break;
 
 	case FFI_TYPE_STRUCT:
-	  /* Structures with size less than eight bytes are passed
-	     left-padded.  */
-	  if (arg_types[i]->size < 8)
-	    avalue[i] = (char *) pst + 8 - arg_types[i]->size;
+#ifdef __STRUCT_PARM_ALIGN__
+	  align = arg_types[i]->alignment;
+	  if (align > __STRUCT_PARM_ALIGN__)
+	    align = __STRUCT_PARM_ALIGN__;
+	  if (align > 1)
+	    pst = (unsigned long *) ALIGN ((size_t) pst, align);
+#endif
+	  elt = 0;
+#if _CALL_ELF == 2
+	  elt = discover_homogeneous_aggregate (arg_types[i], &elnum);
+#endif
+	  if (elt)
+	    {
+	      union {
+		void *v;
+		unsigned long *ul;
+		float *f;
+		double *d;
+		size_t p;
+	      } to, from;
+
+	      /* Repackage the aggregate from its parts.  The
+		 aggregate size is not greater than the space taken by
+		 the registers so store back to the register/parameter
+		 save arrays.  */
+	      if (pfr + elnum <= end_pfr)
+		to.v = pfr;
+	      else
+		to.v = pst;
+
+	      avalue[i] = to.v;
+	      from.ul = pst;
+	      if (elt == FFI_TYPE_FLOAT)
+		{
+		  do
+		    {
+		      if (pfr < end_pfr && i < nfixedargs)
+			{
+			  *to.f = (float) pfr->d;
+			  pfr++;
+			}
+		      else
+			*to.f = *from.f;
+		      to.f++;
+		      from.f++;
+		    }
+		  while (--elnum != 0);
+		}
+	      else
+		{
+		  do
+		    {
+		      if (pfr < end_pfr && i < nfixedargs)
+			{
+			  *to.d = pfr->d;
+			  pfr++;
+			}
+		      else
+			*to.d = *from.d;
+		      to.d++;
+		      from.d++;
+		    }
+		  while (--elnum != 0);
+		}
+	    }
 	  else
-	    avalue[i] = pst;
+	    {
+#ifndef __LITTLE_ENDIAN__
+	      /* Structures with size less than eight bytes are passed
+		 left-padded.  */
+	      if (arg_types[i]->size < 8)
+		avalue[i] = (char *) pst + 8 - arg_types[i]->size;
+	      else
+#endif
+		avalue[i] = pst;
+	    }
 	  pst += (arg_types[i]->size + 7) / 8;
 	  break;
 
 	case FFI_TYPE_FLOAT:
 	  /* unfortunately float values are stored as doubles
 	   * in the ffi_closure_LINUX64 code (since we don't check
 	   * the type in that routine).
 	   */
 
 	  /* there are 13 64bit floating point registers */
 
-	  if (pfr < end_pfr)
+	  if (pfr < end_pfr && i < nfixedargs)
 	    {
 	      double temp = pfr->d;
 	      pfr->f = (float) temp;
 	      avalue[i] = pfr;
 	      pfr++;
 	    }
 	  else
 	    avalue[i] = pst;
 	  pst++;
 	  break;
 
 	case FFI_TYPE_DOUBLE:
 	  /* On the outgoing stack all values are aligned to 8 */
 	  /* there are 13 64bit floating point registers */
 
-	  if (pfr < end_pfr)
+	  if (pfr < end_pfr && i < nfixedargs)
 	    {
 	      avalue[i] = pfr;
 	      pfr++;
 	    }
 	  else
 	    avalue[i] = pst;
 	  pst++;
 	  break;
 
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 	case FFI_TYPE_LONGDOUBLE:
-	  if (pfr + 1 < end_pfr)
+	  if (pfr + 1 < end_pfr && i + 1 < nfixedargs)
 	    {
 	      avalue[i] = pfr;
 	      pfr += 2;
 	    }
 	  else
 	    {
-	      if (pfr < end_pfr)
+	      if (pfr < end_pfr && i < nfixedargs)
 		{
 		  /* Passed partly in f13 and partly on the stack.
 		     Move it all to the stack.  */
 		  *pst = *(unsigned long *) pfr;
 		  pfr++;
 		}
 	      avalue[i] = pst;
 	    }
@@ -1433,10 +1787,19 @@ ffi_closure_helper_LINUX64 (ffi_closure 
 
       i++;
     }
 
 
   (closure->fun) (cif, rvalue, avalue, closure->user_data);
 
   /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
+  if ((cif->flags & FLAG_RETURNS_SMST) != 0)
+    {
+      if ((cif->flags & FLAG_RETURNS_FP) == 0)
+	return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1;
+      else if ((cif->flags & FLAG_RETURNS_64BITS) != 0)
+	return FFI_V2_TYPE_DOUBLE_HOMOG;
+      else
+	return FFI_V2_TYPE_FLOAT_HOMOG;
+    }
   return cif->rtype->type;
 }
--- a/js/src/ctypes/libffi/src/powerpc/ffitarget.h
+++ b/js/src/ctypes/libffi/src/powerpc/ffitarget.h
@@ -1,11 +1,13 @@
 /* -----------------------------------------------------------------*-C-*-
-   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
-   Copyright (C) 2007, 2008 Free Software Foundation, Inc
+   ffitarget.h - Copyright (c) 2012  Anthony Green
+                 Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc
+                 Copyright (c) 1996-2003  Red Hat, Inc.
+
    Target configuration macros for PowerPC.
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    ``Software''), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
@@ -23,16 +25,20 @@
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
 
    ----------------------------------------------------------------------- */
 
 #ifndef LIBFFI_TARGET_H
 #define LIBFFI_TARGET_H
 
+#ifndef LIBFFI_H
+#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
+#endif
+
 /* ---- System specific configurations ----------------------------------- */
 
 #if defined (POWERPC) && defined (__powerpc64__)	/* linux64 */
 #ifndef POWERPC64
 #define POWERPC64
 #endif
 #elif defined (POWERPC_DARWIN) && defined (__ppc64__)	/* Darwin */
 #ifndef POWERPC64
@@ -52,28 +58,24 @@ typedef enum ffi_abi {
   FFI_FIRST_ABI = 0,
 
 #ifdef POWERPC
   FFI_SYSV,
   FFI_GCC_SYSV,
   FFI_LINUX64,
   FFI_LINUX,
   FFI_LINUX_SOFT_FLOAT,
-# ifdef POWERPC64
+# if defined(POWERPC64)
   FFI_DEFAULT_ABI = FFI_LINUX64,
-# else
-#  if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
+# elif defined(__NO_FPRS__)
+  FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
+# elif (__LDBL_MANT_DIG__ == 106)
   FFI_DEFAULT_ABI = FFI_LINUX,
-#  else
-#   ifdef __NO_FPRS__
-  FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
-#   else
+# else
   FFI_DEFAULT_ABI = FFI_GCC_SYSV,
-#   endif
-#  endif
 # endif
 #endif
 
 #ifdef POWERPC_AIX
   FFI_AIX,
   FFI_DARWIN,
   FFI_DEFAULT_ABI = FFI_AIX,
 #endif
@@ -96,32 +98,45 @@ typedef enum ffi_abi {
   FFI_LAST_ABI
 } ffi_abi;
 #endif
 
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
 #define FFI_NATIVE_RAW_API 0
+#if defined (POWERPC) || defined (POWERPC_FREEBSD)
+# define FFI_TARGET_SPECIFIC_VARIADIC 1
+# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs
+#endif
 
 /* For additional types like the below, take care about the order in
    ppc_closures.S. They must follow after the FFI_TYPE_LAST.  */
 
 /* Needed for soft-float long-double-128 support.  */
 #define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
 
 /* Needed for FFI_SYSV small structure returns.
    We use two flag bits, (FLAG_SYSV_SMST_R3, FLAG_SYSV_SMST_R4) which are
    defined in ffi.c, to determine the exact return type and its size.  */
 #define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
 
-#if defined(POWERPC64) || defined(POWERPC_AIX)
-#define FFI_TRAMPOLINE_SIZE 24
-#else /* POWERPC || POWERPC_AIX */
-#define FFI_TRAMPOLINE_SIZE 40
+/* Used by ELFv2 for homogenous structure returns.  */
+#define FFI_V2_TYPE_FLOAT_HOMOG		(FFI_TYPE_LAST + 1)
+#define FFI_V2_TYPE_DOUBLE_HOMOG	(FFI_TYPE_LAST + 2)
+#define FFI_V2_TYPE_SMALL_STRUCT	(FFI_TYPE_LAST + 3)
+
+#if _CALL_ELF == 2
+# define FFI_TRAMPOLINE_SIZE 32
+#else
+# if defined(POWERPC64) || defined(POWERPC_AIX)
+#  define FFI_TRAMPOLINE_SIZE 24
+# else /* POWERPC || POWERPC_AIX */
+#  define FFI_TRAMPOLINE_SIZE 40
+# endif
 #endif
 
 #ifndef LIBFFI_ASM
 #if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
 struct ffi_aix_trampoline_struct {
     void * code_pointer;	/* Pointer to ffi_closure_ASM */
     void * toc;			/* TOC */
     void * static_chain;	/* Pointer to closure */
--- a/js/src/ctypes/libffi/src/powerpc/linux64.S
+++ b/js/src/ctypes/libffi/src/powerpc/linux64.S
@@ -25,56 +25,86 @@
    DEALINGS IN THE SOFTWARE.
    ----------------------------------------------------------------------- */
 
 #define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
 
 #ifdef __powerpc64__
-	.hidden	ffi_call_LINUX64, .ffi_call_LINUX64
-	.globl	ffi_call_LINUX64, .ffi_call_LINUX64
+	.hidden	ffi_call_LINUX64
+	.globl	ffi_call_LINUX64
+# if _CALL_ELF == 2
+	.text
+ffi_call_LINUX64:
+	addis	%r2, %r12, .TOC.-ffi_call_LINUX64@ha
+	addi	%r2, %r2, .TOC.-ffi_call_LINUX64@l
+	.localentry ffi_call_LINUX64, . - ffi_call_LINUX64
+# else
 	.section	".opd","aw"
 	.align	3
 ffi_call_LINUX64:
+#  ifdef _CALL_LINUX
+	.quad	.L.ffi_call_LINUX64,.TOC.@tocbase,0
+	.type	ffi_call_LINUX64,@function
+	.text
+.L.ffi_call_LINUX64:
+#  else
+	.hidden	.ffi_call_LINUX64
+	.globl	.ffi_call_LINUX64
 	.quad	.ffi_call_LINUX64,.TOC.@tocbase,0
 	.size	ffi_call_LINUX64,24
 	.type	.ffi_call_LINUX64,@function
 	.text
 .ffi_call_LINUX64:
+#  endif
+# endif
 .LFB1:
 	mflr	%r0
 	std	%r28, -32(%r1)
 	std	%r29, -24(%r1)
 	std	%r30, -16(%r1)
 	std	%r31, -8(%r1)
 	std	%r0, 16(%r1)
 
 	mr	%r28, %r1	/* our AP.  */
 .LCFI0:
 	stdux	%r1, %r1, %r4
 	mr	%r31, %r5	/* flags, */
 	mr	%r30, %r6	/* rvalue, */
 	mr	%r29, %r7	/* function address.  */
+/* Save toc pointer, not for the ffi_prep_args64 call, but for the later
+   bctrl function call.  */
+# if _CALL_ELF == 2
+	std	%r2, 24(%r1)
+# else
 	std	%r2, 40(%r1)
+# endif
 
 	/* Call ffi_prep_args64.  */
 	mr	%r4, %r1
+# if defined _CALL_LINUX || _CALL_ELF == 2
+	bl	ffi_prep_args64
+# else
 	bl	.ffi_prep_args64
+# endif
 
-	ld	%r0, 0(%r29)
+# if _CALL_ELF == 2
+	mr	%r12, %r29
+# else
+	ld	%r12, 0(%r29)
 	ld	%r2, 8(%r29)
 	ld	%r11, 16(%r29)
-
+# endif
 	/* Now do the call.  */
 	/* Set up cr1 with bits 4-7 of the flags.  */
 	mtcrf	0x40, %r31
 
 	/* Get the address to call into CTR.  */
-	mtctr	%r0
+	mtctr	%r12
 	/* Load all those argument registers.  */
 	ld	%r3, -32-(8*8)(%r28)
 	ld	%r4, -32-(7*8)(%r28)
 	ld	%r5, -32-(6*8)(%r28)
 	ld	%r6, -32-(5*8)(%r28)
 	bf-	5, 1f
 	ld	%r7, -32-(4*8)(%r28)
 	ld	%r8, -32-(3*8)(%r28)
@@ -99,50 +129,93 @@ 1:
 	lfd	%f13, -32-(9*8)(%r28)
 2:
 
 	/* Make the call.  */
 	bctrl
 
 	/* This must follow the call immediately, the unwinder
 	   uses this to find out if r2 has been saved or not.  */
+# if _CALL_ELF == 2
+	ld	%r2, 24(%r1)
+# else
 	ld	%r2, 40(%r1)
+# endif
 
 	/* Now, deal with the return value.  */
 	mtcrf	0x01, %r31
-	bt-	30, .Ldone_return_value
-	bt-	29, .Lfp_return_value
+	bt	31, .Lstruct_return_value
+	bt	30, .Ldone_return_value
+	bt	29, .Lfp_return_value
 	std	%r3, 0(%r30)
 	/* Fall through...  */
 
 .Ldone_return_value:
 	/* Restore the registers we used and return.  */
 	mr	%r1, %r28
 	ld	%r0, 16(%r28)
-	ld	%r28, -32(%r1)
+	ld	%r28, -32(%r28)
 	mtlr	%r0
 	ld	%r29, -24(%r1)
 	ld	%r30, -16(%r1)
 	ld	%r31, -8(%r1)
 	blr
 
 .Lfp_return_value:
 	bf	28, .Lfloat_return_value
 	stfd	%f1, 0(%r30)
 	mtcrf	0x02, %r31 /* cr6  */
 	bf	27, .Ldone_return_value
 	stfd	%f2, 8(%r30)
 	b	.Ldone_return_value
 .Lfloat_return_value:
 	stfs	%f1, 0(%r30)
 	b	.Ldone_return_value
+
+.Lstruct_return_value:
+	bf	29, .Lsmall_struct
+	bf	28, .Lfloat_homog_return_value
+	stfd	%f1, 0(%r30)
+	stfd	%f2, 8(%r30)
+	stfd	%f3, 16(%r30)
+	stfd	%f4, 24(%r30)
+	stfd	%f5, 32(%r30)
+	stfd	%f6, 40(%r30)
+	stfd	%f7, 48(%r30)
+	stfd	%f8, 56(%r30)
+	b	.Ldone_return_value
+
+.Lfloat_homog_return_value:
+	stfs	%f1, 0(%r30)
+	stfs	%f2, 4(%r30)
+	stfs	%f3, 8(%r30)
+	stfs	%f4, 12(%r30)
+	stfs	%f5, 16(%r30)
+	stfs	%f6, 20(%r30)
+	stfs	%f7, 24(%r30)
+	stfs	%f8, 28(%r30)
+	b	.Ldone_return_value
+
+.Lsmall_struct:
+	std	%r3, 0(%r30)
+	std	%r4, 8(%r30)
+	b	.Ldone_return_value
+
 .LFE1:
 	.long	0
 	.byte	0,12,0,1,128,4,0,0
+# if _CALL_ELF == 2
+	.size	ffi_call_LINUX64,.-ffi_call_LINUX64
+# else
+#  ifdef _CALL_LINUX
+	.size	ffi_call_LINUX64,.-.L.ffi_call_LINUX64
+#  else
 	.size	.ffi_call_LINUX64,.-.ffi_call_LINUX64
+#  endif
+# endif
 
 	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
 .Lframe1:
 	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
 .LSCIE1:
 	.4byte	0x0	 # CIE Identifier Tag
 	.byte	0x1	 # CIE Version
 	.ascii "zR\0"	 # CIE Augmentation
@@ -175,13 +248,13 @@ 2:
 	.byte	0x9e	 # DW_CFA_offset, column 0x1e
 	.uleb128 0x2
 	.byte	0x9d	 # DW_CFA_offset, column 0x1d
 	.uleb128 0x3
 	.byte	0x9c	 # DW_CFA_offset, column 0x1c
 	.uleb128 0x4
 	.align 3
 .LEFDE1:
+
+# if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
+	.section	.note.GNU-stack,"",@progbits
+# endif
 #endif
-
-#if defined __ELF__ && defined __linux__
-	.section	.note.GNU-stack,"",@progbits
-#endif
--- a/js/src/ctypes/libffi/src/powerpc/linux64_closure.S
+++ b/js/src/ctypes/libffi/src/powerpc/linux64_closure.S
@@ -27,179 +27,330 @@
 #define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
 
 	.file	"linux64_closure.S"
 
 #ifdef __powerpc64__
 	FFI_HIDDEN (ffi_closure_LINUX64)
-	FFI_HIDDEN (.ffi_closure_LINUX64)
-	.globl  ffi_closure_LINUX64, .ffi_closure_LINUX64
+	.globl  ffi_closure_LINUX64
+# if _CALL_ELF == 2
+	.text
+ffi_closure_LINUX64:
+	addis	%r2, %r12, .TOC.-ffi_closure_LINUX64@ha
+	addi	%r2, %r2, .TOC.-ffi_closure_LINUX64@l
+	.localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
+# else
 	.section        ".opd","aw"
 	.align  3
 ffi_closure_LINUX64:
+#  ifdef _CALL_LINUX
+	.quad   .L.ffi_closure_LINUX64,.TOC.@tocbase,0
+	.type   ffi_closure_LINUX64,@function
+	.text
+.L.ffi_closure_LINUX64:
+#  else
+	FFI_HIDDEN (.ffi_closure_LINUX64)
+	.globl  .ffi_closure_LINUX64
 	.quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
 	.size   ffi_closure_LINUX64,24
 	.type   .ffi_closure_LINUX64,@function
 	.text
 .ffi_closure_LINUX64:
+#  endif
+# endif
+
+# if _CALL_ELF == 2
+#  32 byte special reg save area + 64 byte parm save area
+#  + 64 byte retval area + 13*8 fpr save area + round to 16
+#  define STACKFRAME 272
+#  define PARMSAVE 32
+#  define RETVAL PARMSAVE+64
+# else
+#  48 bytes special reg save area + 64 bytes parm save area
+#  + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
+#  define STACKFRAME 240
+#  define PARMSAVE 48
+#  define RETVAL PARMSAVE+64
+# endif
+
 .LFB1:
-	# save general regs into parm save area
-	std	%r3, 48(%r1)
-	std	%r4, 56(%r1)
-	std	%r5, 64(%r1)
-	std	%r6, 72(%r1)
+# if _CALL_ELF == 2
+	ld	%r12, FFI_TRAMPOLINE_SIZE(%r11)		# closure->cif
 	mflr	%r0
+	lwz	%r12, 28(%r12)				# cif->flags
+	mtcrf	0x40, %r12
+	addi	%r12, %r1, PARMSAVE
+	bt	7, .Lparmsave
+	# Our caller has not allocated a parameter save area.
+	# We need to allocate one here and use it to pass gprs to
+	# ffi_closure_helper_LINUX64.
+	addi	%r12, %r1, -STACKFRAME+PARMSAVE
+.Lparmsave:
+	std	%r0, 16(%r1)
+	# Save general regs into parm save area
+	std	%r3, 0(%r12)
+	std	%r4, 8(%r12)
+	std	%r5, 16(%r12)
+	std	%r6, 24(%r12)
+	std	%r7, 32(%r12)
+	std	%r8, 40(%r12)
+	std	%r9, 48(%r12)
+	std	%r10, 56(%r12)
 
-	std	%r7, 80(%r1)
-	std	%r8, 88(%r1)
-	std	%r9, 96(%r1)
-	std	%r10, 104(%r1)
+	# load up the pointer to the parm save area
+	mr	%r5, %r12
+# else
+	mflr	%r0
+	# Save general regs into parm save area
+	# This is the parameter save area set up by our caller.
+	std	%r3, PARMSAVE+0(%r1)
+	std	%r4, PARMSAVE+8(%r1)
+	std	%r5, PARMSAVE+16(%r1)
+	std	%r6, PARMSAVE+24(%r1)
+	std	%r7, PARMSAVE+32(%r1)
+	std	%r8, PARMSAVE+40(%r1)
+	std	%r9, PARMSAVE+48(%r1)
+	std	%r10, PARMSAVE+56(%r1)
+
 	std	%r0, 16(%r1)
 
-	# mandatory 48 bytes special reg save area + 64 bytes parm save area
-	# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
-	stdu	%r1, -240(%r1)
-.LCFI0:
+	# load up the pointer to the parm save area
+	addi	%r5, %r1, PARMSAVE
+# endif
 
 	# next save fpr 1 to fpr 13
-	stfd  %f1, 128+(0*8)(%r1)
-	stfd  %f2, 128+(1*8)(%r1)
-	stfd  %f3, 128+(2*8)(%r1)
-	stfd  %f4, 128+(3*8)(%r1)
-	stfd  %f5, 128+(4*8)(%r1)
-	stfd  %f6, 128+(5*8)(%r1)
-	stfd  %f7, 128+(6*8)(%r1)
-	stfd  %f8, 128+(7*8)(%r1)
-	stfd  %f9, 128+(8*8)(%r1)
-	stfd  %f10, 128+(9*8)(%r1)
-	stfd  %f11, 128+(10*8)(%r1)
-	stfd  %f12, 128+(11*8)(%r1)
-	stfd  %f13, 128+(12*8)(%r1)
+	stfd	%f1, -104+(0*8)(%r1)
+	stfd	%f2, -104+(1*8)(%r1)
+	stfd	%f3, -104+(2*8)(%r1)
+	stfd	%f4, -104+(3*8)(%r1)
+	stfd	%f5, -104+(4*8)(%r1)
+	stfd	%f6, -104+(5*8)(%r1)
+	stfd	%f7, -104+(6*8)(%r1)
+	stfd	%f8, -104+(7*8)(%r1)
+	stfd	%f9, -104+(8*8)(%r1)
+	stfd	%f10, -104+(9*8)(%r1)
+	stfd	%f11, -104+(10*8)(%r1)
+	stfd	%f12, -104+(11*8)(%r1)
+	stfd	%f13, -104+(12*8)(%r1)
 
-	# set up registers for the routine that actually does the work
-	# get the context pointer from the trampoline
-	mr %r3, %r11
+	# load up the pointer to the saved fpr registers */
+	addi	%r6, %r1, -104
 
-	# now load up the pointer to the result storage
-	addi %r4, %r1, 112
+	# load up the pointer to the result storage
+	addi	%r4, %r1, -STACKFRAME+RETVAL
 
-	# now load up the pointer to the parameter save area
-	# in the previous frame
-	addi %r5, %r1, 240 + 48
+	stdu	%r1, -STACKFRAME(%r1)
+.LCFI0:
 
-	# now load up the pointer to the saved fpr registers */
-	addi %r6, %r1, 128
+	# get the context pointer from the trampoline
+	mr	%r3, %r11
 
 	# make the call
+# if defined _CALL_LINUX || _CALL_ELF == 2
+	bl ffi_closure_helper_LINUX64
+# else
 	bl .ffi_closure_helper_LINUX64
+# endif
 .Lret:
 
 	# now r3 contains the return type
 	# so use it to look up in a table
 	# so we know how to deal with each type
 
 	# look up the proper starting point in table
 	# by using return type as offset
+	ld %r0, STACKFRAME+16(%r1)
+	cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
+	bge .Lsmall
 	mflr %r4		# move address of .Lret to r4
 	sldi %r3, %r3, 4	# now multiply return type by 16
 	addi %r4, %r4, .Lret_type0 - .Lret
-	ld %r0, 240+16(%r1)
 	add %r3, %r3, %r4	# add contents of table to table address
 	mtctr %r3
 	bctr			# jump to it
 
 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
 # first.
 	.align 4
 
 .Lret_type0:
 # case FFI_TYPE_VOID
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 	nop
 # case FFI_TYPE_INT
-	lwa %r3, 112+4(%r1)
+# ifdef __LITTLE_ENDIAN__
+	lwa %r3, RETVAL+0(%r1)
+# else
+	lwa %r3, RETVAL+4(%r1)
+# endif
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_FLOAT
-	lfs %f1, 112+0(%r1)
+	lfs %f1, RETVAL+0(%r1)
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_DOUBLE
-	lfd %f1, 112+0(%r1)
+	lfd %f1, RETVAL+0(%r1)
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_LONGDOUBLE
-	lfd %f1, 112+0(%r1)
+	lfd %f1, RETVAL+0(%r1)
 	mtlr %r0
-	lfd %f2, 112+8(%r1)
+	lfd %f2, RETVAL+8(%r1)
 	b .Lfinish
 # case FFI_TYPE_UINT8
-	lbz %r3, 112+7(%r1)
+# ifdef __LITTLE_ENDIAN__
+	lbz %r3, RETVAL+0(%r1)
+# else
+	lbz %r3, RETVAL+7(%r1)
+# endif
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_SINT8
-	lbz %r3, 112+7(%r1)
+# ifdef __LITTLE_ENDIAN__
+	lbz %r3, RETVAL+0(%r1)
+# else
+	lbz %r3, RETVAL+7(%r1)
+# endif
 	extsb %r3,%r3
 	mtlr %r0
 	b .Lfinish
 # case FFI_TYPE_UINT16
-	lhz %r3, 112+6(%r1)
+# ifdef __LITTLE_ENDIAN__
+	lhz %r3, RETVAL+0(%r1)
+# else
+	lhz %r3, RETVAL+6(%r1)
+# endif
 	mtlr %r0
 .Lfinish:
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_SINT16
-	lha %r3, 112+6(%r1)
+# ifdef __LITTLE_ENDIAN__
+	lha %r3, RETVAL+0(%r1)
+# else
+	lha %r3, RETVAL+6(%r1)
+# endif
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_UINT32
-	lwz %r3, 112+4(%r1)
+# ifdef __LITTLE_ENDIAN__
+	lwz %r3, RETVAL+0(%r1)
+# else
+	lwz %r3, RETVAL+4(%r1)
+# endif
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_SINT32
-	lwa %r3, 112+4(%r1)
+# ifdef __LITTLE_ENDIAN__
+	lwa %r3, RETVAL+0(%r1)
+# else
+	lwa %r3, RETVAL+4(%r1)
+# endif
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_UINT64
-	ld %r3, 112+0(%r1)
+	ld %r3, RETVAL+0(%r1)
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_SINT64
-	ld %r3, 112+0(%r1)
+	ld %r3, RETVAL+0(%r1)
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 # case FFI_TYPE_STRUCT
 	mtlr %r0
-	addi %r1, %r1, 240
+	addi %r1, %r1, STACKFRAME
 	blr
 	nop
 # case FFI_TYPE_POINTER
-	ld %r3, 112+0(%r1)
+	ld %r3, RETVAL+0(%r1)
+	mtlr %r0
+	addi %r1, %r1, STACKFRAME
+	blr
+# case FFI_V2_TYPE_FLOAT_HOMOG
+	lfs %f1, RETVAL+0(%r1)
+	lfs %f2, RETVAL+4(%r1)
+	lfs %f3, RETVAL+8(%r1)
+	b .Lmorefloat
+# case FFI_V2_TYPE_DOUBLE_HOMOG
+	lfd %f1, RETVAL+0(%r1)
+	lfd %f2, RETVAL+8(%r1)
+	lfd %f3, RETVAL+16(%r1)
+	lfd %f4, RETVAL+24(%r1)
+	mtlr %r0
+	lfd %f5, RETVAL+32(%r1)
+	lfd %f6, RETVAL+40(%r1)
+	lfd %f7, RETVAL+48(%r1)
+	lfd %f8, RETVAL+56(%r1)
+	addi %r1, %r1, STACKFRAME
+	blr
+.Lmorefloat:
+	lfs %f4, RETVAL+12(%r1)
 	mtlr %r0
-	addi %r1, %r1, 240
+	lfs %f5, RETVAL+16(%r1)
+	lfs %f6, RETVAL+20(%r1)
+	lfs %f7, RETVAL+24(%r1)
+	lfs %f8, RETVAL+28(%r1)
+	addi %r1, %r1, STACKFRAME
+	blr
+.Lsmall:
+# ifdef __LITTLE_ENDIAN__
+	ld %r3,RETVAL+0(%r1)
+	mtlr %r0
+	ld %r4,RETVAL+8(%r1)
+	addi %r1, %r1, STACKFRAME
 	blr
-# esac
+# else
+	# A struct smaller than a dword is returned in the low bits of r3
+	# ie. right justified.  Larger structs are passed left justified
+	# in r3 and r4.  The return value area on the stack will have
+	# the structs as they are usually stored in memory.
+	cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
+	neg %r5, %r3
+	ld %r3,RETVAL+0(%r1)
+	blt .Lsmalldown
+	mtlr %r0
+	ld %r4,RETVAL+8(%r1)
+	addi %r1, %r1, STACKFRAME
+	blr
+.Lsmalldown:
+	addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
+	mtlr %r0
+	sldi %r5, %r5, 3
+	addi %r1, %r1, STACKFRAME
+	srd %r3, %r3, %r5
+	blr
+# endif
+
 .LFE1:
 	.long	0
 	.byte	0,12,0,1,128,0,0,0
+# if _CALL_ELF == 2
+	.size	ffi_closure_LINUX64,.-ffi_closure_LINUX64
+# else
+#  ifdef _CALL_LINUX
+	.size	ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
+#  else
 	.size	.ffi_closure_LINUX64,.-.ffi_closure_LINUX64
+#  endif
+# endif
 
 	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
 .Lframe1:
 	.4byte	.LECIE1-.LSCIE1	 # Length of Common Information Entry
 .LSCIE1:
 	.4byte	0x0	 # CIE Identifier Tag
 	.byte	0x1	 # CIE Version
 	.ascii "zR\0"	 # CIE Augmentation
@@ -218,19 +369,19 @@ ffi_closure_LINUX64:
 .LASFDE1:
 	.4byte	.LASFDE1-.Lframe1	 # FDE CIE offset
 	.8byte	.LFB1-.	 # FDE initial location
 	.8byte	.LFE1-.LFB1	 # FDE address range
 	.uleb128 0x0	 # Augmentation size
 	.byte	0x2	 # DW_CFA_advance_loc1
 	.byte	.LCFI0-.LFB1
 	.byte	0xe	 # DW_CFA_def_cfa_offset
-	.uleb128 240
+	.uleb128 STACKFRAME
 	.byte	0x11	 # DW_CFA_offset_extended_sf
 	.uleb128 0x41
 	.sleb128 -2
 	.align 3
 .LEFDE1:
+
+# if defined __ELF__ && defined __linux__
+	.section	.note.GNU-stack,"",@progbits
+# endif
 #endif
-
-#if defined __ELF__ && defined __linux__
-	.section	.note.GNU-stack,"",@progbits
-#endif
--- a/js/src/ctypes/libffi/src/powerpc/ppc_closure.S
+++ b/js/src/ctypes/libffi/src/powerpc/ppc_closure.S
@@ -117,53 +117,88 @@ ENTRY(ffi_closure_SYSV)
 # case FFI_TYPE_INT
 	lwz %r3,112+0(%r1)
 	mtlr %r0
 .Lfinish:
 	addi %r1,%r1,144
 	blr
 
 # case FFI_TYPE_FLOAT
+#ifndef __NO_FPRS__
 	lfs %f1,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+#else
+	nop
+	nop
+	nop
+#endif
 	blr
 
 # case FFI_TYPE_DOUBLE
+#ifndef __NO_FPRS__
 	lfd %f1,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
+#else
+	nop
+	nop
+	nop
+#endif
 	blr
 
 # case FFI_TYPE_LONGDOUBLE
+#ifndef __NO_FPRS__
 	lfd %f1,112+0(%r1)
 	lfd %f2,112+8(%r1)
 	mtlr %r0
 	b .Lfinish
+#else
+	nop
+	nop
+	nop
+	blr
+#endif
 
 # case FFI_TYPE_UINT8
+#ifdef __LITTLE_ENDIAN__
+	lbz %r3,112+0(%r1)
+#else
 	lbz %r3,112+3(%r1)
+#endif
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
 # case FFI_TYPE_SINT8
+#ifdef __LITTLE_ENDIAN__
+	lbz %r3,112+0(%r1)
+#else
 	lbz %r3,112+3(%r1)
+#endif
 	extsb %r3,%r3
 	mtlr %r0
 	b .Lfinish
 
 # case FFI_TYPE_UINT16
+#ifdef __LITTLE_ENDIAN__
+	lhz %r3,112+0(%r1)
+#else
 	lhz %r3,112+2(%r1)
+#endif
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
 # case FFI_TYPE_SINT16
+#ifdef __LITTLE_ENDIAN__
+	lha %r3,112+0(%r1)
+#else
 	lha %r3,112+2(%r1)
+#endif
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
 # case FFI_TYPE_UINT32
 	lwz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
@@ -198,76 +233,99 @@ ENTRY(ffi_closure_SYSV)
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
 # case FFI_TYPE_UINT128
 	lwz %r3,112+0(%r1)
 	lwz %r4,112+4(%r1)
 	lwz %r5,112+8(%r1)
-	bl .Luint128
+	b .Luint128
 
 # The return types below are only used when the ABI type is FFI_SYSV.
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
 	lbz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
 	lhz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
 	lwz %r3,112+0(%r1)
+#ifdef __LITTLE_ENDIAN__
+	mtlr %r0
+	addi %r1,%r1,144
+	blr
+#else
 	srwi %r3,%r3,8
 	mtlr %r0
 	b .Lfinish
+#endif
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
 	lwz %r3,112+0(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
 	lwz %r3,112+0(%r1)
 	lwz %r4,112+4(%r1)
+#ifdef __LITTLE_ENDIAN__
+	mtlr %r0
+	b .Lfinish
+#else
 	li %r5,24
 	b .Lstruct567
+#endif
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
 	lwz %r3,112+0(%r1)
 	lwz %r4,112+4(%r1)
+#ifdef __LITTLE_ENDIAN__
+	mtlr %r0
+	b .Lfinish
+#else
 	li %r5,16
 	b .Lstruct567
+#endif
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
 	lwz %r3,112+0(%r1)
 	lwz %r4,112+4(%r1)
+#ifdef __LITTLE_ENDIAN__
+	mtlr %r0
+	b .Lfinish
+#else
 	li %r5,8
 	b .Lstruct567
+#endif
 
 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
 	lwz %r3,112+0(%r1)
 	lwz %r4,112+4(%r1)
 	mtlr %r0
 	b .Lfinish
 
+#ifndef __LITTLE_ENDIAN__
 .Lstruct567:
 	subfic %r6,%r5,32
 	srw %r4,%r4,%r5
 	slw %r6,%r3,%r6
 	srw %r3,%r3,%r5
 	or %r4,%r6,%r4
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
+#endif
 
 .Luint128:
 	lwz %r6,112+12(%r1)
 	mtlr %r0
 	addi %r1,%r1,144
 	blr
 
 END(ffi_closure_SYSV)
--- a/js/src/ctypes/libffi/src/powerpc/sysv.S
+++ b/js/src/ctypes/libffi/src/powerpc/sysv.S
@@ -78,37 +78,41 @@ ENTRY(ffi_call_SYSV)
 	nop
 	lwz	%r7,-16-(4*4)(%r28)
 	lwz	%r8,-16-(3*4)(%r28)
 	lwz	%r9,-16-(2*4)(%r28)
 	lwz	%r10,-16-(1*4)(%r28)
 	nop
 1:
 
+#ifndef __NO_FPRS__
 	/* Load all the FP registers.  */
 	bf-	6,2f
 	lfd	%f1,-16-(8*4)-(8*8)(%r28)
 	lfd	%f2,-16-(8*4)-(7*8)(%r28)
 	lfd	%f3,-16-(8*4)-(6*8)(%r28)
 	lfd	%f4,-16-(8*4)-(5*8)(%r28)
 	nop
 	lfd	%f5,-16-(8*4)-(4*8)(%r28)
 	lfd	%f6,-16-(8*4)-(3*8)(%r28)
 	lfd	%f7,-16-(8*4)-(2*8)(%r28)
 	lfd	%f8,-16-(8*4)-(1*8)(%r28)
+#endif
 2:
 
 	/* Make the call.  */
 	bctrl
 
 	/* Now, deal with the return value.  */
 	mtcrf	0x01,%r31 /* cr7  */
 	bt-	31,L(small_struct_return_value)
 	bt-	30,L(done_return_value)
+#ifndef __NO_FPRS__
 	bt-	29,L(fp_return_value)
+#endif
 	stw	%r3,0(%r30)
 	bf+	28,L(done_return_value)
 	stw	%r4,4(%r30)
 	mtcrf	0x02,%r31 /* cr6  */
 	bf	27,L(done_return_value)
 	stw     %r5,8(%r30)
 	stw	%r6,12(%r30)
 	/* Fall through...  */
@@ -119,41 +123,38 @@ L(done_return_value):
 	lwz	%r31, -4(%r28)
 	mtlr	%r9
 	lwz	%r30, -8(%r28)
 	lwz	%r29,-12(%r28)
 	lwz	%r28,-16(%r28)
 	lwz	%r1,0(%r1)
 	blr
 
+#ifndef __NO_FPRS__
 L(fp_return_value):
 	bf	28,L(float_return_value)
 	stfd	%f1,0(%r30)
 	mtcrf   0x02,%r31 /* cr6  */
 	bf	27,L(done_return_value)
 	stfd	%f2,8(%r30)
 	b	L(done_return_value)
 L(float_return_value):
 	stfs	%f1,0(%r30)
 	b	L(done_return_value)
+#endif
 
 L(small_struct_return_value):
-	extrwi	%r6,%r31,2,19         /* number of bytes padding = shift/8 */
-	mtcrf	0x02,%r31	      /* copy flags to cr[24:27] (cr6) */
-	extrwi	%r5,%r31,5,19         /* r5 <- number of bits of padding */
-	subfic  %r6,%r6,4             /* r6 <- number of useful bytes in r3 */
-	bf-	25,L(done_return_value) /* struct in r3 ? if not, done. */
-/* smst_one_register: */
-	slw	%r3,%r3,%r5           /* Left-justify value in r3 */
-	mtxer	%r6                   /* move byte count to XER ... */
-	stswx	%r3,0,%r30            /* ... and store that many bytes */
-	bf+	26,L(done_return_value)  /* struct in r3:r4 ? */
-	add	%r6,%r6,%r30          /* adjust pointer */
-	stswi	%r4,%r6,4             /* store last four bytes */
-	b	L(done_return_value)
+	/*
+	 * The C code always allocates a properly-aligned 8-byte bounce
+	 * buffer to make this assembly code very simple.  Just write out
+	 * r3 and r4 to the buffer to allow the C code to handle the rest.
+	 */
+	stw %r3, 0(%r30)
+	stw %r4, 4(%r30)
+	b L(done_return_value)
 
 .LFE1:
 END(ffi_call_SYSV)
 
       .section	".eh_frame",EH_FRAME_FLAGS,@progbits
 .Lframe1:
       .4byte    .LECIE1-.LSCIE1  /*  Length of Common Information Entry */
 .LSCIE1:
--- a/js/src/jit-test/tests/basic/cross-context-stack-1.js
+++ b/js/src/jit-test/tests/basic/cross-context-stack-1.js
@@ -1,17 +1,21 @@
-// Error().stack (ScriptFrameIter) should not include frames from other contexts.
-function g() {
-    evaluate("function h() {\nstack = Error().stack;\n };\n h();", {newContext: true});
+// Error().stack (ScriptFrameIter) is no longer context-bound.
+function beta() {
+    evaluate("function gamma() {\nstack = Error().stack;\n };\n gamma();", {newContext: true});
 }
-function f() {
-    g();
+function alpha() {
+    beta();
 }
-f();
-assertEq(stack,
-    "h@@evaluate:2:1\n" +
-    "@@evaluate:4:2\n");
+alpha();
+assertEq(/alpha/.test(stack), true);
+assertEq(/beta/.test(stack), true);
+assertEq(/gamma/.test(stack), true);
+assertEq(/delta/.test(stack), false);
 
-function k() {
+function delta() {
     evaluate("stack = Error().stack", {newContext: true});
 }
-k();
-assertEq(stack, "@@evaluate:1:1\n");
+delta();
+assertEq(/alpha/.test(stack), false);
+assertEq(/beta/.test(stack), false);
+assertEq(/gamma/.test(stack), false);
+assertEq(/delta/.test(stack), true);
--- a/js/src/jit-test/tests/basic/save-frame-chain.js
+++ b/js/src/jit-test/tests/basic/save-frame-chain.js
@@ -1,16 +1,15 @@
-// Error().stack (ScriptFrameIter) should not see through JS_SaveFrameChain.
-function h() {
+// Error().stack (ScriptFrameIter) should see through JS_SaveFrameChain.
+function gamma() {
     stack = Error().stack;
 }
-function g() {
-    evaluate("h()", {saveFrameChain: true});
+function beta() {
+    evaluate("gamma()", {saveFrameChain: true});
 }
-function f() {
-    g();
+function alpha() {
+    beta();
 }
-f();
-var lines = stack.split("\n");
-assertEq(lines.length, 3);
-assertEq(lines[0].startsWith("h@"), true);
-assertEq(lines[1].startsWith("@@evaluate"), true);
-assertEq(lines[2], "");
+alpha();
+
+assertEq(/alpha/.test(stack), true);
+assertEq(/beta/.test(stack), true);
+assertEq(/gamma/.test(stack), true);
--- a/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js
+++ b/js/src/jit-test/tests/basic/typed-array-index-out-of-range.js
@@ -9,21 +9,28 @@ function f() {
 	if (i >= 0 && i < 10)
 	    assertEq(x[i], i + 1);
 	else
 	    assertEq(x[i], undefined);
     }
 }
 f();
 
-// Integers which don't fit in a double value's mantissa aren't really integers.
+// Really big integers not representable with a double or uint64 are still integers.
 
 var bigint = "" + Math.pow(2, 53);
 x[bigint] = "twelve";
-assertEq(x[bigint], "twelve");
+assertEq(x[bigint], undefined);
+
+x["9999999999999999999999"] = "twelve";
+assertEq(x["9999999999999999999999"], undefined);
+
+// Except when their toString() makes them not look like integers!
+x[9999999999999999999999] = "twelve";
+assertEq(x[9999999999999999999999], "twelve");
 
 // Infinity and -Infinity maybe are supposed to be integers, but they aren't currently.
 
 x["Infinity"] = "twelve";
 assertEq(x["Infinity"], "twelve");
 
 x["-Infinity"] = "twelve";
 assertEq(x["-Infinity"], "twelve");
--- a/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js
+++ b/js/src/jit-test/tests/basic/typed-array-sealed-frozen.js
@@ -61,19 +61,19 @@ for (constructor of constructors) {
   // New indexed properties should not show up on typed arrays.
   a[20] = "twelve";
   assertEq(a[20], undefined);
 
   // Watch for especially large indexed properties.
   a[-10 >>> 0] = "twelve";
   assertEq(a[-10 >>> 0], undefined);
 
-  // Watch for overly large indexed properties.
+  // Watch for really large indexed properties too.
   a[Math.pow(2, 53)] = "twelve";
-  assertEq(a[Math.pow(2, 53)], "twelve");
+  assertEq(a[Math.pow(2, 53)], undefined);
 
   // Don't define old properties.
   Object.defineProperty(a, 5, {value: 3});
   assertEq(a[5], 0);
 
   // Don't define new properties.
   Object.defineProperty(a, 20, {value: 3});
   assertEq(a[20], undefined);
--- a/js/src/jscpucfg.h
+++ b/js/src/jscpucfg.h
@@ -22,17 +22,17 @@
 
 # ifdef __WATCOMC__
 #  define HAVE_VA_LIST_AS_ARRAY 1
 # endif
 
 # define IS_LITTLE_ENDIAN 1
 # undef  IS_BIG_ENDIAN
 
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) || defined(__powerpc__) || defined(__ppc__)
 # if __LITTLE_ENDIAN__
 #  define IS_LITTLE_ENDIAN 1
 #  undef  IS_BIG_ENDIAN
 # elif __BIG_ENDIAN__
 #  undef  IS_LITTLE_ENDIAN
 #  define IS_BIG_ENDIAN 1
 # endif
 
@@ -84,18 +84,17 @@
 #  if defined(_STACK_GROWS_UPWARD)
 #   define JS_STACK_GROWTH_DIRECTION (1)
 #  elif defined(_STACK_GROWS_DOWNWARD)
 #   define JS_STACK_GROWTH_DIRECTION (-1)
 #  endif
 # endif
 
 #elif defined(__sparc) || defined(__sparc__) || \
-      defined(_POWER) || defined(__powerpc__) || \
-      defined(__ppc__) || defined(__hppa) || \
+      defined(_POWER) || defined(__hppa) || \
       defined(_MIPSEB) || defined(_BIG_ENDIAN)
 /* IA64 running HP-UX will have _BIG_ENDIAN defined.
  * IA64 running Linux will have endian.h and be handled above.
  */
 # undef IS_LITTLE_ENDIAN
 # define IS_BIG_ENDIAN 1
 
 #else /* !defined(__sparc) && !defined(__sparc__) && ... */
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -207,20 +207,18 @@ struct SuppressErrorsGuard
 JSString *
 js::ComputeStackString(JSContext *cx)
 {
     StringBuffer sb(cx);
 
     {
         RootedAtom atom(cx);
         SuppressErrorsGuard seg(cx);
-        // We should get rid of the CURRENT_CONTEXT and STOP_AT_SAVED here.
-        // See bug 960820.
-        for (NonBuiltinScriptFrameIter i(cx, ScriptFrameIter::CURRENT_CONTEXT,
-                                         ScriptFrameIter::STOP_AT_SAVED,
+        for (NonBuiltinScriptFrameIter i(cx, ScriptFrameIter::ALL_CONTEXTS,
+                                         ScriptFrameIter::GO_THROUGH_SAVED,
                                          cx->compartment()->principals);
             !i.done(); ++i)
         {
             /* First append the function name, if any. */
             atom = nullptr;
             if (i.isNonEvalFunctionFrame() && i.callee()->displayAtom())
                 atom = i.callee()->displayAtom();
             if (atom && !sb.append(atom))
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3755,17 +3755,17 @@ DefinePropertyOrElement(typename Executi
                 return false;
             if (definesPast)
                 return true;
         }
     }
 
     // Don't define new indexed properties on typed arrays.
     if (obj->is<TypedArrayObject>()) {
-        double index;
+        uint64_t index;
         if (IsTypedArrayIndex(id, &index))
             return true;
     }
 
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     RootedShape shape(cx, JSObject::putProperty<mode>(cx, obj, id, getter, setter,
                                                       SHAPE_INVALID_SLOT, attrs, flags));
@@ -3997,19 +3997,19 @@ LookupOwnPropertyWithFlagsInline(Exclusi
         *donep = true;
         return true;
     }
 
     // Check for a typed array element. Integer lookups always finish here
     // so that integer properties on the prototype are ignored even for out
     // of bounds accesses.
     if (obj->template is<TypedArrayObject>()) {
-        double index;
+        uint64_t index;
         if (IsTypedArrayIndex(id, &index)) {
-            if (index >= 0 && index < obj->template as<TypedArrayObject>().length()) {
+            if (index < obj->template as<TypedArrayObject>().length()) {
                 objp.set(obj);
                 MarkDenseOrTypedArrayElementFound<allowGC>(propp);
             }
             *donep = true;
             return true;
         }
     }
 
@@ -4590,19 +4590,19 @@ LookupPropertyPureInline(JSObject *obj, 
 
         if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) {
             *objp = current;
             MarkDenseOrTypedArrayElementFound<NoGC>(propp);
             return true;
         }
 
         if (current->is<TypedArrayObject>()) {
-            double index;
+            uint64_t index;
             if (IsTypedArrayIndex(id, &index)) {
-                if (index >= 0 && index < obj->as<TypedArrayObject>().length()) {
+                if (index < obj->as<TypedArrayObject>().length()) {
                     *objp = current;
                     MarkDenseOrTypedArrayElementFound<NoGC>(propp);
                 } else {
                     *objp = nullptr;
                     *propp = nullptr;
                 }
                 return true;
             }
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -2495,64 +2495,60 @@ js::AsTypedArrayBuffer(HandleValue v)
 {
     JS_ASSERT(IsTypedArrayBuffer(v));
     if (v.toObject().is<ArrayBufferObject>())
         return v.toObject().as<ArrayBufferObject>();
     return v.toObject().as<SharedArrayBufferObject>();
 }
 
 bool
-js::StringIsTypedArrayIndex(JSLinearString *str, double *indexp)
+js::StringIsTypedArrayIndex(JSLinearString *str, uint64_t *indexp)
 {
-    // Largest double (2^53 - 1) which can be exactly represented in the
-    // mantissa of a double.
-    static const double MAX_INTEGER = 9007199254740991;
-
     const jschar *s = str->chars();
     const jschar *end = s + str->length();
 
     if (s == end)
         return false;
 
     bool negative = false;
     if (*s == '-') {
         negative = true;
         if (++s == end)
             return false;
     }
 
     if (!JS7_ISDEC(*s))
         return false;
 
-    double index = 0;
+    uint64_t index = 0;
     uint32_t digit = JS7_UNDEC(*s++);
 
     /* Don't allow leading zeros. */
     if (digit == 0 && s != end)
         return false;
 
     index = digit;
 
     for (; s < end; s++) {
         if (!JS7_ISDEC(*s))
             return false;
 
         digit = JS7_UNDEC(*s);
 
-        /* Watch for mantissa overflows. */
-        if ((MAX_INTEGER - digit) / 10 < index)
-            return false;
-
-        index = 10 * index + digit;
+        /* Watch for overflows. */
+        if ((UINT64_MAX - digit) / 10 < index)
+            index = UINT64_MAX;
+        else
+            index = 10 * index + digit;
     }
 
     if (negative)
-        index = -index;
-
-    *indexp = index;
+        *indexp = UINT64_MAX;
+    else
+        *indexp = index;
     return true;
 }
 
 /* JS Friend API */
 
 JS_FRIEND_API(bool)
 JS_IsTypedArrayObject(JSObject *obj)
 {
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -135,33 +135,42 @@ bool
 IsTypedArrayConstructor(HandleValue v, uint32_t type);
 
 bool
 IsTypedArrayBuffer(HandleValue v);
 
 ArrayBufferObject &
 AsTypedArrayBuffer(HandleValue v);
 
+// Return value is whether the string is some integer. If the string is an
+// integer which is not representable as a uint64_t, the return value is true
+// and the resulting index is UINT64_MAX.
 bool
-StringIsTypedArrayIndex(JSLinearString *str, double *indexp);
+StringIsTypedArrayIndex(JSLinearString *str, uint64_t *indexp);
 
 inline bool
-IsTypedArrayIndex(jsid id, double *indexp)
+IsTypedArrayIndex(jsid id, uint64_t *indexp)
 {
     if (JSID_IS_INT(id)) {
         int32_t i = JSID_TO_INT(id);
         JS_ASSERT(i >= 0);
         *indexp = (double)i;
         return true;
     }
 
     if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
         return false;
 
-    return StringIsTypedArrayIndex(JSID_TO_ATOM(id), indexp);
+    JSAtom *atom = JSID_TO_ATOM(id);
+
+    jschar c = atom->chars()[0];
+    if (!JS7_ISDEC(c) && c != '-')
+        return false;
+
+    return StringIsTypedArrayIndex(atom, indexp);
 }
 
 static inline unsigned
 TypedArrayShift(ArrayBufferView::ViewType viewType)
 {
     switch (viewType) {
       case ArrayBufferView::TYPE_INT8:
       case ArrayBufferView::TYPE_UINT8:
--- a/js/xpconnect/tests/mochitest/mochitest.ini
+++ b/js/xpconnect/tests/mochitest/mochitest.ini
@@ -82,15 +82,16 @@ support-files =
 [test_bug865260.html]
 [test_bug870423.html]
 [test_bug871887.html]
 [test_bug912322.html]
 [test_bug916945.html]
 [test_bug92773.html]
 [test_bug940783.html]
 [test_bug965082.html]
+[test_bug960820.html]
 [test_crosscompartment_weakmap.html]
 [test_frameWrapping.html]
 # The JS test component we use below is only available in debug builds.
 [test_getWebIDLCaller.html]
 skip-if = debug == false
 [test_nac.xhtml]
 [test_sameOriginPolicy.html]
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/mochitest/test_bug960820.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=960820
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 960820</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for exception stacks crossing **/
+
+  // Synchronous event dispatch creates a new script entry point. At the time
+  // of this writing, an event listener defined in a Sandbox will cause the
+  // SafeJSContext to be pushed to the cx stack, which differs from the JSContext
+  // associated with this DOM window. So we test both kinds of boundaries.
+  var sb = new SpecialPowers.Cu.Sandbox(SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal());
+  sb.win = window;
+  SpecialPowers.Cu.evalInSandbox("win.document.addEventListener('click', " +
+                                 "function clickHandler() { win.wrappedJSObject.clickCallback(); });", sb);
+  function clickCallback() {
+    var stack = (new Error()).stack;
+    ok(true, "Invoked clickCallback. Stack: " + stack);
+    ok(/clickCallback/.test(stack), "clickCallback should be in the stack");
+    ok(!/clickHandler/.test(stack), "clickHandler should not be in the stack");
+    ok(/dispatchClick/.test(stack), "dispatchClick should be in the stack");
+  }
+  function dispatchClick() {
+    document.dispatchEvent(new MouseEvent('click'));
+  }
+  dispatchClick();
+
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=960820">Mozilla Bug 960820</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/847242.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.f { unicode-bidi: bidi-override; width: 1px; white-space: pre-line; }
+.f:first-letter { font-size: 200% }
+</style>
+</head>
+<body>
+<div class="f">&#x2029;&#x062a;&#x8401;
+x</div>
+</body>
+</html>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -410,16 +410,17 @@ skip-if(1) load 802902.html # bug 901752
 load 806056-1.html
 load 806056-2.html
 load 813372-1.html
 asserts-if(gtk2Widget,0-1) load 822865.html # bug 540078
 load 826163.html
 load 833604-1.html
 load 835056.html
 load 836990-1.html
+load 847242.html
 load 852293.html
 load 860579-1.html
 pref(layers.force-active,true) load 859526-1.html
 pref(layers.force-active,true) load 859630-1.html
 load 866588.html
 load 897852.html
 asserts(4-6) load 898913.html # bug 847368
 load 931464.html
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -30,16 +30,30 @@ static const char16_t kSpace            
 static const char16_t kZWSP             = 0x200B;
 static const char16_t kLineSeparator    = 0x2028;
 static const char16_t kObjectSubstitute = 0xFFFC;
 static const char16_t kLRE              = 0x202A;
 static const char16_t kRLE              = 0x202B;
 static const char16_t kLRO              = 0x202D;
 static const char16_t kRLO              = 0x202E;
 static const char16_t kPDF              = 0x202C;
+static const char16_t kSeparators[] = {
+  // All characters with Bidi type Segment Separator or Block Separator
+  char16_t('\t'),
+  char16_t('\r'),
+  char16_t('\n'),
+  char16_t(0xb),
+  char16_t(0x1c),
+  char16_t(0x1d),
+  char16_t(0x1e),
+  char16_t(0x1f),
+  char16_t(0x85),
+  char16_t(0x2029),
+  char16_t(0)
+};
 
 #define NS_BIDI_CONTROL_FRAME ((nsIFrame*)0xfffb1d1)
 
 struct BidiParagraphData {
   nsString            mBuffer;
   nsAutoTArray<char16_t, 16> mEmbeddingStack;
   nsTArray<nsIFrame*> mLogicalFrames;
   nsTArray<nsLineBox*> mLinePerFrame;
@@ -626,17 +640,17 @@ nsresult
 nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame,
                                   BidiParagraphData* aBpd)
 {
   nsPresContext *presContext = aBlockFrame->PresContext();
 
   if (aBpd->BufferLength() < 1) {
     return NS_OK;
   }
-  aBpd->mBuffer.ReplaceChar("\t\r\n", kSpace);
+  aBpd->mBuffer.ReplaceChar(kSeparators, kSpace);
 
   int32_t runCount;
 
   nsresult rv = aBpd->SetPara();
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint8_t embeddingLevel = aBpd->GetParaLevel();
 
--- a/layout/generic/test/mochitest.ini
+++ b/layout/generic/test/mochitest.ini
@@ -81,16 +81,17 @@ support-files = bug633762_iframe.html
 [test_bug784410.html]
 [test_bug785324.html]
 [test_bug791616.html]
 [test_bug831780.html]
 [test_bug841361.html]
 [test_bug904810.html]
 [test_bug938772.html]
 [test_contained_plugin_transplant.html]
+skip-if = os=='win'
 [test_image_selection.html]
 [test_image_selection_2.html]
 [test_invalidate_during_plugin_paint.html]
 skip-if = toolkit == 'android'
 [test_movement_by_characters.html]
 [test_movement_by_words.html]
 # Disable the caret movement by word test on Linux because the shortcut keys
 # are defined in system level.  So, it depends on the environment.
--- a/layout/media/symbols.def.in
+++ b/layout/media/symbols.def.in
@@ -312,16 +312,253 @@ MOZ_XML_SetNamespaceDeclHandler
 MOZ_XML_SetNotationDeclHandler
 MOZ_XML_SetParamEntityParsing
 MOZ_XML_SetProcessingInstructionHandler
 MOZ_XML_SetReturnNSTriplet
 MOZ_XML_SetUnparsedEntityDeclHandler
 MOZ_XML_SetUserData
 MOZ_XML_SetXmlDeclHandler
 MOZ_XML_StopParser
+#ifdef MOZ_TREE_CAIRO
+_moz_cairo_append_path
+_moz_cairo_arc
+_moz_cairo_arc_negative
+_moz_cairo_clip
+_moz_cairo_clip_extents
+_moz_cairo_clip_preserve
+_moz_cairo_close_path
+_moz_cairo_copy_clip_rectangle_list
+_moz_cairo_copy_path
+_moz_cairo_copy_path_flat
+_moz_cairo_create
+_moz_cairo_curve_to
+_moz_cairo_debug_reset_static_data
+_moz_cairo_destroy
+_moz_cairo_device_to_user
+_moz_cairo_device_to_user_distance
+_moz_cairo_fill
+_moz_cairo_fill_extents
+_moz_cairo_fill_preserve
+_moz_cairo_font_face_destroy
+_moz_cairo_font_options_create
+_moz_cairo_font_options_destroy
+_moz_cairo_font_options_get_hint_metrics
+_moz_cairo_font_options_set_antialias
+_moz_cairo_format_stride_for_width
+_moz_cairo_get_antialias
+_moz_cairo_get_current_point
+_moz_cairo_get_dash
+_moz_cairo_get_dash_count
+_moz_cairo_get_fill_rule
+_moz_cairo_get_font_matrix
+_moz_cairo_get_group_target
+_moz_cairo_get_line_cap
+_moz_cairo_get_line_join
+_moz_cairo_get_line_width
+_moz_cairo_get_matrix
+_moz_cairo_get_miter_limit
+_moz_cairo_get_operator
+_moz_cairo_get_scaled_font
+_moz_cairo_get_source
+_moz_cairo_get_target
+_moz_cairo_glyph_extents
+_moz_cairo_glyph_path
+_moz_cairo_identity_matrix
+_moz_cairo_image_surface_create
+_moz_cairo_image_surface_create_for_data
+_moz_cairo_image_surface_get_data
+_moz_cairo_image_surface_get_format
+_moz_cairo_image_surface_get_height
+_moz_cairo_image_surface_get_stride
+_moz_cairo_image_surface_get_width
+_moz_cairo_in_fill
+_moz_cairo_in_stroke
+_moz_cairo_line_to
+_moz_cairo_mask
+_moz_cairo_mask_surface
+_moz_cairo_matrix_init
+_moz_cairo_matrix_init_identity
+_moz_cairo_matrix_init_scale
+_moz_cairo_matrix_init_translate
+_moz_cairo_matrix_invert
+_moz_cairo_matrix_multiply
+_moz_cairo_matrix_rotate
+_moz_cairo_matrix_scale
+_moz_cairo_matrix_transform_distance
+_moz_cairo_matrix_transform_point
+_moz_cairo_matrix_translate
+_moz_cairo_move_to
+_moz_cairo_new_path
+_moz_cairo_new_sub_path
+_moz_cairo_paint
+_moz_cairo_paint_with_alpha
+_moz_cairo_path_destroy
+_moz_cairo_path_extents
+_moz_cairo_pattern_add_color_stop_rgba
+_moz_cairo_pattern_create_for_surface
+_moz_cairo_pattern_create_linear
+_moz_cairo_pattern_create_radial
+_moz_cairo_pattern_create_rgba
+_moz_cairo_pattern_destroy
+_moz_cairo_pattern_get_color_stop_count
+_moz_cairo_pattern_get_color_stop_rgba
+_moz_cairo_pattern_get_extend
+_moz_cairo_pattern_get_filter
+_moz_cairo_pattern_get_linear_points
+_moz_cairo_pattern_get_matrix
+_moz_cairo_pattern_get_radial_circles
+_moz_cairo_pattern_get_rgba
+_moz_cairo_pattern_get_surface
+_moz_cairo_pattern_get_type
+_moz_cairo_pattern_reference
+_moz_cairo_pattern_set_extend
+_moz_cairo_pattern_set_filter
+_moz_cairo_pattern_set_matrix
+_moz_cairo_pattern_status
+_moz_cairo_pdf_surface_create_for_stream
+_moz_cairo_pop_group
+_moz_cairo_pop_group_to_source
+_moz_cairo_push_group
+_moz_cairo_push_group_with_content
+_moz_cairo_rectangle
+_moz_cairo_rectangle_list_destroy
+_moz_cairo_reference
+_moz_cairo_reset_clip
+_moz_cairo_restore
+_moz_cairo_rotate
+_moz_cairo_save
+_moz_cairo_scale
+_moz_cairo_scaled_font_create
+_moz_cairo_scaled_font_destroy
+_moz_cairo_scaled_font_get_font_matrix
+_moz_cairo_scaled_font_get_font_options
+_moz_cairo_scaled_font_get_type
+_moz_cairo_scaled_font_reference
+_moz_cairo_scaled_font_status
+_moz_cairo_set_antialias
+_moz_cairo_set_dash
+_moz_cairo_set_fill_rule
+_moz_cairo_set_font_face
+_moz_cairo_set_font_size
+_moz_cairo_set_line_cap
+_moz_cairo_set_line_join
+_moz_cairo_set_line_width
+_moz_cairo_set_matrix
+_moz_cairo_set_miter_limit
+_moz_cairo_set_operator
+_moz_cairo_set_scaled_font
+_moz_cairo_set_source
+_moz_cairo_set_source_rgba
+_moz_cairo_set_source_surface
+_moz_cairo_show_glyphs
+_moz_cairo_status
+_moz_cairo_stroke
+_moz_cairo_stroke_extents
+_moz_cairo_stroke_preserve
+_moz_cairo_surface_create_similar
+_moz_cairo_surface_destroy
+_moz_cairo_surface_finish
+_moz_cairo_surface_flush
+_moz_cairo_surface_get_content
+_moz_cairo_surface_get_device_offset
+_moz_cairo_surface_get_reference_count
+_moz_cairo_surface_get_subpixel_antialiasing
+_moz_cairo_surface_get_type
+_moz_cairo_surface_get_user_data
+_moz_cairo_surface_mark_dirty
+_moz_cairo_surface_mark_dirty_rectangle
+_moz_cairo_surface_reference
+_moz_cairo_surface_set_device_offset
+_moz_cairo_surface_set_fallback_resolution
+_moz_cairo_surface_set_subpixel_antialiasing
+_moz_cairo_surface_set_user_data
+_moz_cairo_surface_show_page
+_moz_cairo_surface_status
+_moz_cairo_tee_surface_add
+_moz_cairo_tee_surface_create
+_moz_cairo_tee_surface_index
+_moz_cairo_transform
+_moz_cairo_translate
+_moz_cairo_user_to_device
+_moz_cairo_user_to_device_distance
+_moz_cairo_win32_font_face_create_for_logfontw_hfont
+#ifdef NS_PRINTING
+_moz_cairo_win32_printing_surface_create
+#endif
+_moz_cairo_win32_scaled_font_select_font
+_moz_cairo_win32_surface_create
+_moz_cairo_win32_surface_create_with_d3dsurface9
+_moz_cairo_win32_surface_create_with_ddb
+_moz_cairo_win32_surface_create_with_dib
+_moz_cairo_win32_surface_get_dc
+_moz_cairo_win32_surface_get_image
+#ifdef MOZ_TREE_PIXMAN
+_moz_pixman_image_composite32
+_moz_pixman_image_create_bits
+_moz_pixman_image_set_transform
+_moz_pixman_image_unref
+_moz_pixman_transform_from_pixman_f_transform
+_moz_pixman_transform_invert
+_moz_pixman_region32_reset
+_moz_pixman_region32_init
+_moz_pixman_region32_init_rect
+_moz_pixman_region32_init_rects
+_moz_pixman_region32_init_with_extents
+_moz_pixman_region32_fini
+_moz_pixman_region32_translate
+_moz_pixman_region32_copy
+_moz_pixman_region32_intersect
+_moz_pixman_region32_intersect_rect
+_moz_pixman_region32_union
+_moz_pixman_region32_union_rect
+_moz_pixman_region32_subtract
+_moz_pixman_region32_inverse
+_moz_pixman_region32_contains_point
+_moz_pixman_region32_contains_rectangle
+_moz_pixman_region32_not_empty
+_moz_pixman_region32_extents
+_moz_pixman_region32_n_rects
+_moz_pixman_region32_rectangles
+_moz_pixman_region32_equal
+_moz_pixman_region32_selfcheck
+_moz_pixman_region32_reset
+_moz_pixman_region32_clear
+#endif
+cairo_d2d_create_device
+cairo_d2d_create_device_from_d3d10device
+cairo_d2d_device_get_device
+cairo_d2d_get_dc
+cairo_d2d_get_image_surface_cache_usage
+cairo_d2d_get_surface_vram_usage
+cairo_d2d_present_backbuffer
+cairo_d2d_release_dc
+cairo_d2d_scroll
+cairo_d2d_surface_create
+cairo_d2d_surface_create_for_handle
+cairo_d2d_surface_create_for_hwnd
+cairo_d2d_surface_create_for_texture
+cairo_d2d_surface_get_height
+cairo_d2d_surface_get_texture
+cairo_d2d_surface_get_width
+cairo_dwrite_font_face_create_for_dwrite_fontface
+cairo_dwrite_get_cleartype_rendering_mode
+cairo_dwrite_scaled_font_allow_manual_show_glyphs
+cairo_dwrite_scaled_font_get_force_GDI_classic
+cairo_dwrite_scaled_font_set_force_GDI_classic
+cairo_dwrite_set_cleartype_params
+cairo_null_surface_create
+cairo_release_device
+cairo_surface_attach_snapshot
+cairo_win32_get_dc_with_clip
+cairo_win32_get_system_text_quality
+cairo_win32_surface_create_with_alpha
+cairo_win32_surface_get_height
+cairo_win32_surface_get_width
+cairo_win32_surface_set_can_convert_to_dib
+#endif
 hb_blob_create
 hb_blob_destroy
 hb_blob_get_data
 hb_blob_get_empty
 hb_blob_get_length
 hb_blob_reference
 hb_buffer_add_utf16
 hb_buffer_create
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bidi/847242-1-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="utf-8">
+   <style>
+    div {
+     font-family: monospace;
+     font-size: 24px;
+     }
+   </style>
+ </head>
+ <body>
+   <div>PASS&#x2029;</div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bidi/847242-1.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="utf-8">
+   <style>
+    div {
+     unicode-bidi: bidi-override;
+     direction: rtl;
+     text-align: left;
+     font-family: monospace;
+     font-size: 24px;
+     }
+   </style>
+ </head>
+ <body>
+   <div>&#x2029;SSAP</div>
+ </body>
+</html>
--- a/layout/reftests/bidi/reftest.list
+++ b/layout/reftests/bidi/reftest.list
@@ -133,11 +133,12 @@ skip-if(B2G) == 726420-1.html 726420-1-r
 == 729047-1.html 729047-1-ref.html
 == 730562-1.html 730562-1-ref.html
 == 746987-1.html 746987-1-ref.html
 == 746987-2.html 746987-2-ref.html
 == 746987-3.html 746987-3-ref.html
 == 746987-4.html 746987-4-ref.html
 == 779003-1.html 779003-1-ref.html
 == 779003-1-dynamic.html 779003-1-ref.html
+== 847242-1.html 847242-1-ref.html
 == 869833-1.xul 869833-1-ref.xul
 == 922530-1.html 922530-1-ref.html
 == 922550-1.html 922550-1-ref.html
--- a/layout/reftests/svg/filters/reftest.list
+++ b/layout/reftests/svg/filters/reftest.list
@@ -97,14 +97,14 @@ skip-if(B2G) fuzzy-if(cocoaWidget,4,184)
 == feMorphology-radius-zero-02.svg pass.svg
 
 == feTile-large-01.svg pass.svg
 == feTile-large-02.svg feTile-large-02-ref.svg
 == feTile-outside-01.svg feTile-outside-01-ref.svg
 
 fuzzy(1,119) == feDiffuseLighting-1.svg feDiffuseLighting-1-ref.svg
 
-skip-if(d2d) == feSpecularLighting-1.svg feSpecularLighting-1-ref.svg
+fuzzy(2,2659) skip-if(d2d) == feSpecularLighting-1.svg feSpecularLighting-1-ref.svg
 
 pref(layout.css.filters.enabled,true) == multiple-svg-filters.svg multiple-svg-filters-ref.svg
 pref(layout.css.filters.enabled,true) == multiple-svg-filters-long-chain.svg multiple-svg-filters-ref.svg
 pref(layout.css.filters.enabled,true) == multiple-svg-filters-second-uses-SourceGraphic.svg multiple-svg-filters-ref.svg
 pref(layout.css.filters.enabled,true) == multiple-svg-filters-with-multiple-primitives.svg multiple-svg-filters-ref.svg
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/963086-1.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+   viewBox="0 0 64 64">
+  <defs>
+    <filter id="dropShadow">
+      <feGaussianBlur stdDeviation="2" />
+      <feOffset
+         result="offsetBlur"
+         dy="1073741824"/>
+      <feMerge>
+        <feMergeNode
+           in="offsetBlur" />
+        <feMergeNode
+           in="SourceGraphic" />
+      </feMerge>
+    </filter>
+  </defs>
+  <rect height="64" width="64" style="filter:url(#dropShadow)" />
+</svg>
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -173,10 +173,11 @@ load 890782-1.svg
 load 890783-1.svg
 load 893510-1.svg
 load 895311-1.svg
 load 897342-1.svg
 load 898909-1.svg
 load 898951-1.svg
 load 919371-1.xhtml
 load 952270-1.svg
+load 963086-1.svg
 load 975773-1.svg
 load 974746-1.svg
--- a/media/webrtc/moz.build
+++ b/media/webrtc/moz.build
@@ -64,16 +64,17 @@ if CONFIG['MOZ_WEBRTC_SIGNALING']:
         'signaling/src/media/CSFVideoControlWrapper.cpp',
         'signaling/src/media/VcmSIPCCBinding.cpp',
         'signaling/src/mediapipeline/MediaPipeline.cpp',
         'signaling/src/mediapipeline/SrtpFlow.cpp',
         'signaling/src/peerconnection/MediaStreamList.cpp',
         'signaling/src/peerconnection/PeerConnectionCtx.cpp',
         'signaling/src/peerconnection/PeerConnectionImpl.cpp',
         'signaling/src/peerconnection/PeerConnectionMedia.cpp',
+        'signaling/src/peerconnection/WebrtcGlobalInformation.cpp',
         'signaling/src/sipcc/core/ccapp/call_logger.c',
         'signaling/src/sipcc/core/ccapp/capability_set.c',
         'signaling/src/sipcc/core/ccapp/cc_call_feature.c',
         'signaling/src/sipcc/core/ccapp/cc_config.c',
         'signaling/src/sipcc/core/ccapp/cc_device_feature.c',
         'signaling/src/sipcc/core/ccapp/cc_device_manager.c',
         'signaling/src/sipcc/core/ccapp/cc_info.c',
         'signaling/src/sipcc/core/ccapp/cc_service.c',
--- a/media/webrtc/signaling/signaling.gyp
+++ b/media/webrtc/signaling/signaling.gyp
@@ -188,16 +188,20 @@
       #
       # Conditionals
       #
       'conditions': [
         ['build_for_test==0', {
           'defines' : [
             'MOZILLA_INTERNAL_API'
           ],
+          'sources': [
+            './src/peerconnection/WebrtcGlobalInformation.cpp',
+            './src/peerconnection/WebrtcGlobalInformation.h',
+          ],
         }],
         ['build_for_test!=0', {
           'include_dirs': [
             './test'
           ],
           'defines' : [
             'NO_CHROMIUM_LOGGING',
             'USE_FAKE_MEDIA_STREAMS',
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h
@@ -20,16 +20,20 @@
 #include "cpr_stdlib.h"
 
 #include "StaticPtr.h"
 #include "PeerConnectionImpl.h"
 
 namespace mozilla {
 class PeerConnectionCtxShutdown;
 
+namespace dom {
+class WebrtcGlobalInformation;
+}
+
 // Unit-test helper, because cc_media_constraints_t is hard to forward-declare
 
 class MediaConstraintsExternal {
 public:
   MediaConstraintsExternal();
   MediaConstraintsExternal(const dom::MediaConstraintsInternal &aOther);
   cc_media_constraints_t* build() const;
 protected:
@@ -71,16 +75,17 @@ class PeerConnectionCtx : public CSF::CC
   // Create a SIPCC Call
   CSF::CC_CallPtr createCall();
 
   mozilla::dom::PCImplSipccState sipcc_state() { return mSipccState; }
 
   // Make these classes friend so that they can access mPeerconnections.
   friend class PeerConnectionImpl;
   friend class PeerConnectionWrapper;
+  friend class mozilla::dom::WebrtcGlobalInformation;
 
  private:
   // We could make these available only via accessors but it's too much trouble.
   std::map<const std::string, PeerConnectionImpl *> mPeerConnections;
 
   PeerConnectionCtx() :  mSipccState(mozilla::dom::PCImplSipccState::Idle),
                          mCCM(nullptr), mDevice(nullptr) {}
   // This is a singleton, so don't copy construct it, etc.
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -142,16 +142,26 @@ PRLogModuleInfo *signalingLogInfo() {
     logModuleInfo = PR_NewLogModule("signaling");
   }
   return logModuleInfo;
 }
 
 
 namespace sipcc {
 
+#ifdef MOZILLA_INTERNAL_API
+RTCStatsQuery::RTCStatsQuery(bool internal) : internalStats(internal) {
+}
+
+RTCStatsQuery::~RTCStatsQuery() {
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+#endif
+
 // Getting exceptions back down from PCObserver is generally not harmful.
 namespace {
 class JSErrorResult : public ErrorResult
 {
 public:
   ~JSErrorResult()
   {
 #ifdef MOZILLA_INTERNAL_API
@@ -1277,105 +1287,53 @@ public:
     mIceCandidateStats.Construct();
     mCodecStats.Construct();
   }
 };
 
 // Specialized helper - push map[key] if specified or all map values onto array
 
 static void
-PushBackSelect(std::vector<RefPtr<MediaPipeline>>& aDst,
+PushBackSelect(nsTArray<RefPtr<MediaPipeline>>& aDst,
                const std::map<TrackID, RefPtr<mozilla::MediaPipeline>> & aSrc,
                TrackID aKey = 0) {
   auto begin = aKey ? aSrc.find(aKey) : aSrc.begin(), it = begin;
   for (auto end = (aKey && begin != aSrc.end())? ++begin : aSrc.end();
        it != end; ++it) {
-    aDst.push_back(it->second);
+    aDst.AppendElement(it->second);
   }
 }
 #endif
 
 NS_IMETHODIMP
-PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector, bool internalStats) {
+PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector) {
   PC_AUTO_ENTER_API_CALL(true);
 
 #ifdef MOZILLA_INTERNAL_API
   if (!mMedia) {
     // Since we zero this out before the d'tor, we should check.
     return NS_ERROR_UNEXPECTED;
   }
 
-  // Gather up pipelines from mMedia and dispatch them to STS for inspection
-
-  std::vector<RefPtr<MediaPipeline>> pipelines;
-  TrackID trackId = aSelector ? aSelector->GetTrackID() : 0;
-
-  for (int i = 0, len = mMedia->LocalStreamsLength(); i < len; i++) {
-    PushBackSelect(pipelines, mMedia->GetLocalStream(i)->GetPipelines(), trackId);
-  }
-  for (int i = 0, len = mMedia->RemoteStreamsLength(); i < len; i++) {
-    PushBackSelect(pipelines, mMedia->GetRemoteStream(i)->GetPipelines(), trackId);
-  }
+  nsAutoPtr<RTCStatsQuery> query(new RTCStatsQuery(false));
 
-  // From the list of MediaPipelines, determine the set of NrIceMediaStreams
-  // we are interested in.
-  std::vector<RefPtr<NrIceMediaStream> > streams;
-  RefPtr<NrIceCtx> iceCtx(mMedia->ice_ctx());
-  for (auto p = pipelines.begin(); p != pipelines.end(); ++p) {
-    size_t level = p->get()->level();
-    // TODO(bcampen@mozilla.com): I may need to revisit this for bundle.
-    // (Bug 786234)
-    RefPtr<NrIceMediaStream> temp(mMedia->ice_media_stream(level-1));
-    if (temp.get()) {
-      streams.push_back(temp);
-    } else {
-       CSFLogError(logTag, "Failed to get NrIceMediaStream for level %u "
-                           "in %s:  %s",
-                           uint32_t(level), __FUNCTION__, mHandle.c_str());
-       MOZ_CRASH();
-    }
-  }
+  nsresult rv = BuildStatsQuery_m(aSelector, query.get());
 
-  DOMHighResTimeStamp now;
-  nsresult rv = GetTimeSinceEpoch(&now);
   NS_ENSURE_SUCCESS(rv, rv);
 
   RUN_ON_THREAD(mSTSThread,
-                WrapRunnableNM(&PeerConnectionImpl::GetStats_s,
+                WrapRunnableNM(&PeerConnectionImpl::GetStatsForPCObserver_s,
                                mHandle,
-                               mName,
-                               mThread,
-                               internalStats,
-                               pipelines,
-                               iceCtx,
-                               streams,
-                               now),
+                               query),
                 NS_DISPATCH_NORMAL);
 #endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PeerConnectionImpl::GetLogging(const nsAString& aPattern) {
-  PC_AUTO_ENTER_API_CALL_NO_CHECK();
-
-#ifdef MOZILLA_INTERNAL_API
-  std::string pattern(NS_ConvertUTF16toUTF8(aPattern).get());
-  RUN_ON_THREAD(mSTSThread,
-                WrapRunnableNM(&PeerConnectionImpl::GetLogging_s,
-                               mHandle,
-                               mThread,
-                               pattern),
-                NS_DISPATCH_NORMAL);
-
-#endif
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, unsigned short aLevel) {
   PC_AUTO_ENTER_API_CALL(true);
 
   Timecard *tc = mTimeCard;
   mTimeCard = nullptr;
   STAMP_TIMECARD(tc, "Add Ice Candidate");
 
   mInternal->mCall->addICECandidate(aCandidate, aMid, aLevel, tc);
@@ -1786,16 +1744,22 @@ PeerConnectionImpl::SetSignalingState_m(
   if (!pco) {
     return;
   }
   JSErrorResult rv;
   pco->OnStateChange(PCObserverStateType::SignalingState, rv);
   MOZ_ASSERT(!rv.Failed());
 }
 
+bool
+PeerConnectionImpl::IsClosed() const
+{
+  return !mMedia;
+}
+
 PeerConnectionWrapper::PeerConnectionWrapper(const std::string& handle)
     : impl_(nullptr) {
   if (PeerConnectionCtx::GetInstance()->mPeerConnections.find(handle) ==
     PeerConnectionCtx::GetInstance()->mPeerConnections.end()) {
     return;
   }
 
   PeerConnectionImpl *impl = PeerConnectionCtx::GetInstance()->mPeerConnections[handle];
@@ -1961,151 +1925,87 @@ PeerConnectionImpl::IceGatheringStateCha
                              PCObserverStateType::IceGatheringState,
                              rv, static_cast<JSCompartment*>(nullptr)),
                 NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
 #ifdef MOZILLA_INTERNAL_API
 nsresult
-PeerConnectionImpl::GetStatsImpl_s(
-    bool internalStats,
-    const std::vector<RefPtr<MediaPipeline>>& pipelines,
-    const RefPtr<NrIceCtx>& iceCtx,
-    const std::vector<RefPtr<NrIceMediaStream>>& streams,
-    DOMHighResTimeStamp now,
-    RTCStatsReportInternal* report) {
+PeerConnectionImpl::BuildStatsQuery_m(
+    mozilla::dom::MediaStreamTrack *aSelector,
+    RTCStatsQuery *query) {
+
+  if (IsClosed()) {
+    return NS_OK;
+  }
+
+  if (!mMedia->ice_ctx() || !mThread) {
+    CSFLogError(logTag, "Could not build stats query, critical components of "
+                        "PeerConnectionImpl not set.");
+    return NS_ERROR_UNEXPECTED;
+  }
 
-  ASSERT_ON_THREAD(iceCtx->thread());
+  nsresult rv = GetTimeSinceEpoch(&(query->now));
 
-  // Gather stats from pipelines provided (can't touch mMedia + stream on STS)
+  if (NS_FAILED(rv)) {
+    CSFLogError(logTag, "Could not build stats query, could not get timestamp");
+    return rv;
+  }
 
-  for (auto it = pipelines.begin(); it != pipelines.end(); ++it) {
-    const MediaPipeline& mp = **it;
-    nsString idstr = (mp.Conduit()->type() == MediaSessionConduit::AUDIO) ?
-        NS_LITERAL_STRING("audio_") : NS_LITERAL_STRING("video_");
-    idstr.AppendInt(mp.trackid());
+  // We do not use the pcHandle here, since that's risky to expose to content.
+  query->report = RTCStatsReportInternalConstruct(
+      NS_ConvertASCIItoUTF16(mName.c_str()),
+      query->now);
+
+  // Gather up pipelines from mMedia so they may be inspected on STS
+  TrackID trackId = aSelector ? aSelector->GetTrackID() : 0;
 
-    switch (mp.direction()) {
-      case MediaPipeline::TRANSMIT: {
-        nsString localId = NS_LITERAL_STRING("outbound_rtp_") + idstr;
-        nsString remoteId;
-        nsString ssrc;
-        unsigned int ssrcval;
-        if (mp.Conduit()->GetLocalSSRC(&ssrcval)) {
-          ssrc.AppendInt(ssrcval);
-        }
-        {
-          // First, fill in remote stat with rtcp receiver data, if present.
-          // ReceiverReports have less information than SenderReports,
-          // so fill in what we can.
-          DOMHighResTimeStamp timestamp;
-          uint32_t jitterMs;
-          uint32_t packetsReceived;
-          uint64_t bytesReceived;
-          uint32_t packetsLost;
-          if (mp.Conduit()->GetRTCPReceiverReport(&timestamp, &jitterMs,
-                                                  &packetsReceived,
-                                                  &bytesReceived,
-                                                  &packetsLost)) {
-            remoteId = NS_LITERAL_STRING("outbound_rtcp_") + idstr;
-            RTCInboundRTPStreamStats s;
-            s.mTimestamp.Construct(timestamp);
-            s.mId.Construct(remoteId);
-            s.mType.Construct(RTCStatsType::Inboundrtp);
-            if (ssrc.Length()) {
-              s.mSsrc.Construct(ssrc);
-            }
-            s.mJitter.Construct(double(jitterMs)/1000);
-            s.mRemoteId.Construct(localId);
-            s.mIsRemote = true;
-            s.mPacketsReceived.Construct(packetsReceived);
-            s.mBytesReceived.Construct(bytesReceived);
-            s.mPacketsLost.Construct(packetsLost);
-            report->mInboundRTPStreamStats.Value().AppendElement(s);
-          }
-        }
-        // Then, fill in local side (with cross-link to remote only if present)
-        {
-          RTCOutboundRTPStreamStats s;
-          s.mTimestamp.Construct(now);
-          s.mId.Construct(localId);
-          s.mType.Construct(RTCStatsType::Outboundrtp);
-          if (ssrc.Length()) {
-            s.mSsrc.Construct(ssrc);
-          }
-          s.mRemoteId.Construct(remoteId);
-          s.mIsRemote = false;
-          s.mPacketsSent.Construct(mp.rtp_packets_sent());
-          s.mBytesSent.Construct(mp.rtp_bytes_sent());
-          report->mOutboundRTPStreamStats.Value().AppendElement(s);
-        }
-        break;
-      }
-      case MediaPipeline::RECEIVE: {
-        nsString localId = NS_LITERAL_STRING("inbound_rtp_") + idstr;
-        nsString remoteId;
-        nsString ssrc;
-        unsigned int ssrcval;
-        if (mp.Conduit()->GetRemoteSSRC(&ssrcval)) {
-          ssrc.AppendInt(ssrcval);
-        }
-        {
-          // First, fill in remote stat with rtcp sender data, if present.
-          DOMHighResTimeStamp timestamp;
-          uint32_t packetsSent;
-          uint64_t bytesSent;
-          if (mp.Conduit()->GetRTCPSenderReport(&timestamp,
-                                                &packetsSent, &bytesSent)) {
-            remoteId = NS_LITERAL_STRING("inbound_rtcp_") + idstr;
-            RTCOutboundRTPStreamStats s;
-            s.mTimestamp.Construct(timestamp);
-            s.mId.Construct(remoteId);
-            s.mType.Construct(RTCStatsType::Outboundrtp);
-            if (ssrc.Length()) {
-              s.mSsrc.Construct(ssrc);
-            }
-            s.mRemoteId.Construct(localId);
-            s.mIsRemote = true;
-            s.mPacketsSent.Construct(packetsSent);
-            s.mBytesSent.Construct(bytesSent);
-            report->mOutboundRTPStreamStats.Value().AppendElement(s);
-          }
-        }
-        // Then, fill in local side (with cross-link to remote only if present)
-        RTCInboundRTPStreamStats s;
-        s.mTimestamp.Construct(now);
-        s.mId.Construct(localId);
-        s.mType.Construct(RTCStatsType::Inboundrtp);
-        if (ssrc.Length()) {
-          s.mSsrc.Construct(ssrc);
-        }
-        unsigned int jitterMs, packetsLost;
-        if (mp.Conduit()->GetRTPStats(&jitterMs, &packetsLost)) {
-          s.mJitter.Construct(double(jitterMs)/1000);
-          s.mPacketsLost.Construct(packetsLost);
-        }
-        if (remoteId.Length()) {
-          s.mRemoteId.Construct(remoteId);
-        }
-        s.mIsRemote = false;
-        s.mPacketsReceived.Construct(mp.rtp_packets_received());
-        s.mBytesReceived.Construct(mp.rtp_bytes_received());
-        report->mInboundRTPStreamStats.Value().AppendElement(s);
-        break;
-      }
+  for (int i = 0, len = mMedia->LocalStreamsLength(); i < len; i++) {
+    PushBackSelect(query->pipelines,
+                   mMedia->GetLocalStream(i)->GetPipelines(),
+                   trackId);
+  }
+
+  for (int i = 0, len = mMedia->RemoteStreamsLength(); i < len; i++) {
+    PushBackSelect(query->pipelines,
+                   mMedia->GetRemoteStream(i)->GetPipelines(),
+                   trackId);
+  }
+
+  query->iceCtx = mMedia->ice_ctx();
+
+  // From the list of MediaPipelines, determine the set of NrIceMediaStreams
+  // we are interested in.
+  std::set<size_t> streamsGrabbed;
+  for (size_t p = 0; p < query->pipelines.Length(); ++p) {
+
+    size_t level = query->pipelines[p]->level();
+
+    // Don't grab the same stream twice, since that causes duplication
+    // of the ICE stats.
+    if (streamsGrabbed.count(level)) {
+      continue;
+    }
+
+    streamsGrabbed.insert(level);
+    // TODO(bcampen@mozilla.com): I may need to revisit this for bundle.
+    // (Bug 786234)
+    RefPtr<NrIceMediaStream> temp(mMedia->ice_media_stream(level-1));
+    if (temp.get()) {
+      query->streams.AppendElement(temp);
+    } else {
+       CSFLogError(logTag, "Failed to get NrIceMediaStream for level %u "
+                           "in %s:  %s",
+                           uint32_t(level), __FUNCTION__, mHandle.c_str());
+       MOZ_CRASH();
     }
   }
 
-  // Gather stats from ICE
-  for (auto s = streams.begin(); s != streams.end(); ++s) {
-    FillStatsReport_s(**s, internalStats, now, report);
-  }
-
-  return NS_OK;
+  return rv;
 }
 
 static void ToRTCIceCandidateStats(
     const std::vector<NrIceCandidate>& candidates,
     RTCStatsType candidateType,
     const nsString& componentId,
     DOMHighResTimeStamp now,
     RTCStatsReportInternal* report) {
@@ -2122,17 +2022,17 @@ static void ToRTCIceCandidateStats(
         RTCStatsIceCandidateType(c->type));
     cand.mIpAddress.Construct(
         NS_ConvertASCIItoUTF16(c->cand_addr.host.c_str()));
     cand.mPortNumber.Construct(c->cand_addr.port);
     report->mIceCandidateStats.Value().AppendElement(cand);
   }
 }
 
-void PeerConnectionImpl::FillStatsReport_s(
+static void RecordIceStats_s(
     NrIceMediaStream& mediaStream,
     bool internalStats,
     DOMHighResTimeStamp now,
     RTCStatsReportInternal* report) {
 
   NS_ConvertASCIItoUTF16 componentId(mediaStream.name().c_str());
   if (internalStats) {
     std::vector<NrIceCandidatePair> candPairs;
@@ -2178,121 +2078,202 @@ void PeerConnectionImpl::FillStatsReport
     ToRTCIceCandidateStats(candidates,
                            RTCStatsType::Remotecandidate,
                            componentId,
                            now,
                            report);
   }
 }
 
-void PeerConnectionImpl::GetStats_s(
-    const std::string& pcHandle, // The Runnable holds the memory
-    const std::string& pcName, // The Runnable holds the memory
-    nsCOMPtr<nsIThread> callbackThread,
-    bool internalStats,
-    const std::vector<RefPtr<MediaPipeline>>& pipelines,
-    const RefPtr<NrIceCtx>& iceCtx,
-    const std::vector<RefPtr<NrIceMediaStream>>& streams,
-    DOMHighResTimeStamp now) {
+nsresult
+PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) {
+
+  ASSERT_ON_THREAD(query->iceCtx->thread());
 
-  ASSERT_ON_THREAD(iceCtx->thread());
+  // NrIceCtx must be destroyed on STS, so it is not safe to dispatch it back
+  // to main.
+  RefPtr<NrIceCtx> iceCtxTmp(query->iceCtx);
+  query->iceCtx = nullptr;
+
+  // Gather stats from pipelines provided (can't touch mMedia + stream on STS)
+
+  for (size_t p = 0; p < query->pipelines.Length(); ++p) {
+    const MediaPipeline& mp = *query->pipelines[p];
+    nsString idstr = (mp.Conduit()->type() == MediaSessionConduit::AUDIO) ?
+        NS_LITERAL_STRING("audio_") : NS_LITERAL_STRING("video_");
+    idstr.AppendInt(mp.trackid());
 
-  // We do not use the pcHandle here, since that's risky to expose to content.
-  nsAutoPtr<RTCStatsReportInternal> report(
-      new RTCStatsReportInternalConstruct(
-          NS_ConvertASCIItoUTF16(pcName.c_str()),
-          now));
+    switch (mp.direction()) {
+      case MediaPipeline::TRANSMIT: {
+        nsString localId = NS_LITERAL_STRING("outbound_rtp_") + idstr;
+        nsString remoteId;
+        nsString ssrc;
+        unsigned int ssrcval;
+        if (mp.Conduit()->GetLocalSSRC(&ssrcval)) {
+          ssrc.AppendInt(ssrcval);
+        }
+        {
+          // First, fill in remote stat with rtcp receiver data, if present.
+          // ReceiverReports have less information than SenderReports,
+          // so fill in what we can.
+          DOMHighResTimeStamp timestamp;
+          uint32_t jitterMs;
+          uint32_t packetsReceived;
+          uint64_t bytesReceived;
+          uint32_t packetsLost;
+          if (mp.Conduit()->GetRTCPReceiverReport(&timestamp, &jitterMs,
+                                                  &packetsReceived,
+                                                  &bytesReceived,
+                                                  &packetsLost)) {
+            remoteId = NS_LITERAL_STRING("outbound_rtcp_") + idstr;
+            RTCInboundRTPStreamStats s;
+            s.mTimestamp.Construct(timestamp);
+            s.mId.Construct(remoteId);
+            s.mType.Construct(RTCStatsType::Inboundrtp);
+            if (ssrc.Length()) {
+              s.mSsrc.Construct(ssrc);
+            }
+            s.mJitter.Construct(double(jitterMs)/1000);
+            s.mRemoteId.Construct(localId);
+            s.mIsRemote = true;
+            s.mPacketsReceived.Construct(packetsReceived);
+            s.mBytesReceived.Construct(bytesReceived);
+            s.mPacketsLost.Construct(packetsLost);
+            query->report.mInboundRTPStreamStats.Value().AppendElement(s);
+          }
+        }
+        // Then, fill in local side (with cross-link to remote only if present)
+        {
+          RTCOutboundRTPStreamStats s;
+          s.mTimestamp.Construct(query->now);
+          s.mId.Construct(localId);
+          s.mType.Construct(RTCStatsType::Outboundrtp);
+          if (ssrc.Length()) {
+            s.mSsrc.Construct(ssrc);
+          }
+          s.mRemoteId.Construct(remoteId);
+          s.mIsRemote = false;
+          s.mPacketsSent.Construct(mp.rtp_packets_sent());
+          s.mBytesSent.Construct(mp.rtp_bytes_sent());
+          query->report.mOutboundRTPStreamStats.Value().AppendElement(s);
+        }
+        break;
+      }
+      case MediaPipeline::RECEIVE: {
+        nsString localId = NS_LITERAL_STRING("inbound_rtp_") + idstr;
+        nsString remoteId;
+        nsString ssrc;
+        unsigned int ssrcval;
+        if (mp.Conduit()->GetRemoteSSRC(&ssrcval)) {
+          ssrc.AppendInt(ssrcval);
+        }
+        {
+          // First, fill in remote stat with rtcp sender data, if present.
+          DOMHighResTimeStamp timestamp;
+          uint32_t packetsSent;
+          uint64_t bytesSent;
+          if (mp.Conduit()->GetRTCPSenderReport(&timestamp,
+                                                &packetsSent, &bytesSent)) {
+            remoteId = NS_LITERAL_STRING("inbound_rtcp_") + idstr;
+            RTCOutboundRTPStreamStats s;
+            s.mTimestamp.Construct(timestamp);
+            s.mId.Construct(remoteId);
+            s.mType.Construct(RTCStatsType::Outboundrtp);
+            if (ssrc.Length()) {
+              s.mSsrc.Construct(ssrc);
+            }
+            s.mRemoteId.Construct(localId);
+            s.mIsRemote = true;
+            s.mPacketsSent.Construct(packetsSent);
+            s.mBytesSent.Construct(bytesSent);
+            query->report.mOutboundRTPStreamStats.Value().AppendElement(s);
+          }
+        }
+        // Then, fill in local side (with cross-link to remote only if present)
+        RTCInboundRTPStreamStats s;
+        s.mTimestamp.Construct(query->now);
+        s.mId.Construct(localId);
+        s.mType.Construct(RTCStatsType::Inboundrtp);
+        if (ssrc.Length()) {
+          s.mSsrc.Construct(ssrc);
+        }
+        unsigned int jitterMs, packetsLost;
+        if (mp.Conduit()->GetRTPStats(&jitterMs, &packetsLost)) {
+          s.mJitter.Construct(double(jitterMs)/1000);
+          s.mPacketsLost.Construct(packetsLost);
+        }
+        if (remoteId.Length()) {
+          s.mRemoteId.Construct(remoteId);
+        }
+        s.mIsRemote = false;
+        s.mPacketsReceived.Construct(mp.rtp_packets_received());
+        s.mBytesReceived.Construct(mp.rtp_bytes_received());
+        query->report.mInboundRTPStreamStats.Value().AppendElement(s);
+        break;
+      }
+    }
+  }
 
-  nsresult rv = GetStatsImpl_s(internalStats,
-                               pipelines,
-                               iceCtx,
-                               streams,
-                               now,
-                               report);
+  // Gather stats from ICE
+  for (size_t s = 0; s != query->streams.Length(); ++s) {
+    RecordIceStats_s(*query->streams[s],
+                     query->internalStats,
+                     query->now,
+                     &(query->report));
+  }
 
-  RUN_ON_THREAD(callbackThread,
-                WrapRunnableNM(&PeerConnectionImpl::OnStatsReport_m,
-                               pcHandle,
-                               rv,
-                               pipelines, // return for release on main thread
-                               report),
-                NS_DISPATCH_NORMAL);
+  return NS_OK;
 }
 
-void PeerConnectionImpl::OnStatsReport_m(
+void PeerConnectionImpl::GetStatsForPCObserver_s(
+    const std::string& pcHandle, // The Runnable holds the memory
+    nsAutoPtr<RTCStatsQuery> query) {
+
+  MOZ_ASSERT(query);
+  MOZ_ASSERT(query->iceCtx);
+  ASSERT_ON_THREAD(query->iceCtx->thread());
+
+  nsresult rv = PeerConnectionImpl::ExecuteStatsQuery_s(query.get());
+
+  NS_DispatchToMainThread(
+      WrapRunnableNM(
+          &PeerConnectionImpl::DeliverStatsReportToPCObserver_m,
+          pcHandle,
+          rv,
+          query),
+      NS_DISPATCH_NORMAL);
+}
+
+void PeerConnectionImpl::DeliverStatsReportToPCObserver_m(
     const std::string& pcHandle,
     nsresult result,
-    const std::vector<RefPtr<MediaPipeline>>& pipelines, //returned for release
-    nsAutoPtr<RTCStatsReportInternal> report) {
+    nsAutoPtr<RTCStatsQuery> query) {
 
   // Is the PeerConnectionImpl still around?
   PeerConnectionWrapper pcw(pcHandle);
   if (pcw.impl()) {
     nsRefPtr<PeerConnectionObserver> pco =
         do_QueryObjectReferent(pcw.impl()->mPCObserver);
     if (pco) {
       JSErrorResult rv;
       if (NS_SUCCEEDED(result)) {
-        pco->OnGetStatsSuccess(*report, rv);
+        pco->OnGetStatsSuccess(query->report, rv);
       } else {
         pco->OnGetStatsError(kInternalError,
             ObString("Failed to fetch statistics"),
             rv);
       }
 
       if (rv.Failed()) {
         CSFLogError(logTag, "Error firing stats observer callback");
       }
     }
   }
 }
 
-void PeerConnectionImpl::GetLogging_s(const std::string& pcHandle,
-                                      nsCOMPtr<nsIThread> callbackThread,
-                                      const std::string& pattern) {
-  RLogRingBuffer* logs = RLogRingBuffer::GetInstance();
-  nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
-  logs->Filter(pattern, 0, result);
-  RUN_ON_THREAD(callbackThread,
-                WrapRunnableNM(&PeerConnectionImpl::OnGetLogging_m,
-                               pcHandle,
-                               pattern,
-                               result),
-                NS_DISPATCH_NORMAL);
-}
-
-void PeerConnectionImpl::OnGetLogging_m(
-    const std::string& pcHandle,
-    const std::string& pattern,
-    nsAutoPtr<std::deque<std::string>> logging) {
-
-  // Is the PeerConnectionImpl still around?
-  PeerConnectionWrapper pcw(pcHandle);
-  if (pcw.impl()) {
-    nsRefPtr<PeerConnectionObserver> pco =
-        do_QueryObjectReferent(pcw.impl()->mPCObserver);
-    if (pco) {
-      JSErrorResult rv;
-      if (!logging->empty()) {
-        Sequence<nsString> nsLogs;
-        for (auto l = logging->begin(); l != logging->end(); ++l) {
-          nsLogs.AppendElement(ObString(l->c_str()));
-        }
-        pco->OnGetLoggingSuccess(nsLogs, rv);
-      } else {
-        pco->OnGetLoggingError(kInternalError,
-            ObString(("No logging matching pattern " + pattern).c_str()), rv);
-      }
-
-      if (rv.Failed()) {
-        CSFLogError(logTag, "Error firing stats observer callback");
-      }
-    }
-  }
-}
 #endif
 
 void
 PeerConnectionImpl::IceStreamReady(NrIceMediaStream *aStream)
 {
   PC_AUTO_ENTER_API_CALL_NO_CHECK();
   MOZ_ASSERT(aStream);
 
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -9,16 +9,17 @@
 #include <string>
 #include <vector>
 #include <map>
 #include <cmath>
 
 #include "prlock.h"
 #include "mozilla/RefPtr.h"
 #include "nsWeakPtr.h"
+#include "nsAutoPtr.h"
 #include "nsIWeakReferenceUtils.h" // for the definition of nsWeakPtr
 #include "IPeerConnection.h"
 #include "sigslot.h"
 #include "nricectx.h"
 #include "nricemediastream.h"
 #include "nsComponentManagerUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsIThread.h"
@@ -28,16 +29,17 @@
 #include "StreamBuffer.h"
 
 #ifdef MOZILLA_INTERNAL_API
 #include "mozilla/TimeStamp.h"
 #include "mozilla/net/DataChannel.h"
 #include "VideoUtils.h"
 #include "VideoSegment.h"
 #include "nsNSSShutDown.h"
+#include "mozilla/dom/RTCStatsReportBinding.h"
 #endif
 
 namespace test {
 #ifdef USE_FAKE_PCOBSERVER
 class AFakePCObserver;
 #endif
 }
 
@@ -149,16 +151,37 @@ public:
   void addTurnServer(const NrIceTurnServer& server) { mTurnServers.push_back (server); }
   const std::vector<NrIceStunServer>& getStunServers() const { return mStunServers; }
   const std::vector<NrIceTurnServer>& getTurnServers() const { return mTurnServers; }
 private:
   std::vector<NrIceStunServer> mStunServers;
   std::vector<NrIceTurnServer> mTurnServers;
 };
 
+#ifdef MOZILLA_INTERNAL_API
+// Not an inner class so we can forward declare.
+class RTCStatsQuery {
+  public:
+    explicit RTCStatsQuery(bool internalStats);
+    ~RTCStatsQuery();
+
+    mozilla::dom::RTCStatsReportInternal report;
+    std::string error;
+
+  private:
+    friend class PeerConnectionImpl;
+    std::string pcName;
+    bool internalStats;
+    nsTArray<mozilla::RefPtr<mozilla::MediaPipeline>> pipelines;
+    mozilla::RefPtr<NrIceCtx> iceCtx;
+    nsTArray<mozilla::RefPtr<NrIceMediaStream>> streams;
+    DOMHighResTimeStamp now;
+};
+#endif // MOZILLA_INTERNAL_API
+
 // Enter an API call and check that the state is OK,
 // the PC isn't closed, etc.
 #define PC_AUTO_ENTER_API_CALL(assert_ice_ready) \
     do { \
       /* do/while prevents res from conflicting with locals */    \
       nsresult res = CheckApiState(assert_ice_ready);             \
       if (NS_FAILED(res)) return res; \
     } while(0)
@@ -308,26 +331,19 @@ public:
   NS_IMETHODIMP SetRemoteDescription (int32_t aAction, const char* aSDP);
 
   void SetRemoteDescription (int32_t aAction, const nsAString& aSDP, ErrorResult &rv)
   {
     rv = SetRemoteDescription(aAction, NS_ConvertUTF16toUTF8(aSDP).get());
   }
 
   NS_IMETHODIMP_TO_ERRORRESULT(GetStats, ErrorResult &rv,
-                               mozilla::dom::MediaStreamTrack *aSelector,
-                               bool internalStats)
+                               mozilla::dom::MediaStreamTrack *aSelector)
   {
-    rv = GetStats(aSelector, internalStats);
-  }
-
-  NS_IMETHODIMP_TO_ERRORRESULT(GetLogging, ErrorResult &rv,
-                               const nsAString& pattern)
-  {
-    rv = GetLogging(pattern);
+    rv = GetStats(aSelector);
   }
 
   NS_IMETHODIMP AddIceCandidate(const char* aCandidate, const char* aMid,
                                 unsigned short aLevel);
 
   void AddIceCandidate(const nsAString& aCandidate, const nsAString& aMid,
                        unsigned short aLevel, ErrorResult &rv)
   {
@@ -485,19 +501,27 @@ public:
   void ClearSdpParseErrorMessages();
 
   // Called to retreive the list of parsing errors.
   const std::vector<std::string> &GetSdpParseErrors();
 
   // Sets the RTC Signaling State
   void SetSignalingState_m(mozilla::dom::PCImplSignalingState aSignalingState);
 
+  bool IsClosed() const;
+
 #ifdef MOZILLA_INTERNAL_API
   // initialize telemetry for when calls start
   void startCallTelem();
+
+  nsresult BuildStatsQuery_m(
+      mozilla::dom::MediaStreamTrack *aSelector,
+      RTCStatsQuery *query);
+
+  static nsresult ExecuteStatsQuery_s(RTCStatsQuery *query);
 #endif
 
 private:
   PeerConnectionImpl(const PeerConnectionImpl&rhs);
   PeerConnectionImpl& operator=(PeerConnectionImpl);
   NS_IMETHODIMP Initialize(PeerConnectionObserver& aObserver,
                            nsGlobalWindow* aWindow,
                            const IceConfiguration* aConfiguration,
@@ -539,61 +563,25 @@ private:
   nsresult IceGatheringStateChange_m(
       mozilla::dom::PCImplIceGatheringState aState);
 
   NS_IMETHOD FingerprintSplitHelper(
       std::string& fingerprint, size_t& spaceIdx) const;
 
 
 #ifdef MOZILLA_INTERNAL_API
-  // TODO(bcampen@mozilla.com): Once the dust settles on this stuff, it
-  // probably makes sense to make these static in PeerConnectionImpl.cpp
-  // (ie; stop exporting them)
-
-  // Fills in an RTCStatsReportInternal. Must be run on STS.
-  static void GetStats_s(
+  static void GetStatsForPCObserver_s(
       const std::string& pcHandle,
-      const std::string& pcName,
-      nsCOMPtr<nsIThread> callbackThread,
-      bool internalStats,
-      const std::vector<mozilla::RefPtr<mozilla::MediaPipeline>> &pipelines,
-      const mozilla::RefPtr<NrIceCtx> &iceCtx,
-      const std::vector<mozilla::RefPtr<NrIceMediaStream>> &streams,
-      DOMHighResTimeStamp now);
-
-  static nsresult GetStatsImpl_s(
-      bool internalStats,
-      const std::vector<mozilla::RefPtr<mozilla::MediaPipeline>> &pipelines,
-      const mozilla::RefPtr<NrIceCtx> &iceCtx,
-      const std::vector<mozilla::RefPtr<NrIceMediaStream>> &streams,
-      DOMHighResTimeStamp now,
-      mozilla::dom::RTCStatsReportInternal *report);
-
-  static void FillStatsReport_s(
-      NrIceMediaStream& stream,
-      bool internalStats,
-      DOMHighResTimeStamp now,
-      mozilla::dom::RTCStatsReportInternal* stats);
+      nsAutoPtr<RTCStatsQuery> query);
 
   // Sends an RTCStatsReport to JS. Must run on main thread.
-  static void OnStatsReport_m(
+  static void DeliverStatsReportToPCObserver_m(
       const std::string& pcHandle,
       nsresult result,
-      const std::vector<mozilla::RefPtr<mozilla::MediaPipeline>> &pipelines,
-      nsAutoPtr<mozilla::dom::RTCStatsReportInternal> report);
-
-  // Fetches logs matching pattern from RLogRingBuffer. Must be run on STS.
-  static void GetLogging_s(const std::string& pcHandle,
-                           nsCOMPtr<nsIThread> callbackThread,
-                           const std::string& pattern);
-
-  // Sends logging to JS. Must run on main thread.
-  static void OnGetLogging_m(const std::string& pcHandle,
-                             const std::string& pattern,
-                             nsAutoPtr<std::deque<std::string>> logging);
+      nsAutoPtr<RTCStatsQuery> query);
 #endif
 
   // Timecard used to measure processing time. This should be the first class
   // attribute so that we accurately measure the time required to instantiate
   // any other attributes of this class.
   Timecard *mTimeCard;
 
   // The call
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp
@@ -0,0 +1,216 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebrtcGlobalInformation.h"
+
+#include <deque>
+#include <string>
+
+#include "CSFLog.h"
+
+#include "mozilla/dom/WebrtcGlobalInformationBinding.h"
+
+#include "nsAutoPtr.h"
+#include "nsNetCID.h" // NS_SOCKETTRANSPORTSERVICE_CONTRACTID
+#include "nsServiceManagerUtils.h" // do_GetService
+#include "mozilla/ErrorResult.h"
+#include "mozilla/Vector.h"
+#include "nsProxyRelease.h"
+
+#include "rlogringbuffer.h"
+#include "runnable_utils.h"
+#include "PeerConnectionCtx.h"
+#include "PeerConnectionImpl.h"
+
+using sipcc::PeerConnectionImpl;
+using sipcc::PeerConnectionCtx;
+using sipcc::RTCStatsQuery;
+
+static const char* logTag = "WebrtcGlobalInformation";
+
+namespace mozilla {
+namespace dom {
+
+typedef Vector<nsAutoPtr<RTCStatsQuery>> RTCStatsQueries;
+
+static void OnStatsReport_m(
+  nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> aStatsCallback,
+  nsAutoPtr<RTCStatsQueries> aQueryList)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aQueryList);
+
+  WebrtcGlobalStatisticsReport report;
+  report.mReports.Construct();
+  for (auto q = aQueryList->begin(); q != aQueryList->end(); ++q) {
+    MOZ_ASSERT(*q);
+    report.mReports.Value().AppendElement((*q)->report);
+  }
+
+  ErrorResult rv;
+  aStatsCallback.get()->Call(report, rv);
+
+  if (rv.Failed()) {
+    CSFLogError(logTag, "Error firing stats observer callback");
+  }
+}
+
+static void GetAllStats_s(
+  nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> aStatsCallback,
+  nsAutoPtr<RTCStatsQueries> aQueryList)
+{
+  MOZ_ASSERT(aQueryList);
+
+  for (auto q = aQueryList->begin(); q != aQueryList->end(); ++q) {
+    MOZ_ASSERT(*q);
+    PeerConnectionImpl::ExecuteStatsQuery_s(*q);
+  }
+
+  NS_DispatchToMainThread(WrapRunnableNM(&OnStatsReport_m,
+                                         aStatsCallback,
+                                         aQueryList),
+                          NS_DISPATCH_NORMAL);
+}
+
+static void OnGetLogging_m(
+  nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback> aLoggingCallback,
+  const std::string& aPattern,
+  nsAutoPtr<std::deque<std::string>> aLogList)
+{
+  ErrorResult rv;
+  if (!aLogList->empty()) {
+    Sequence<nsString> nsLogs;
+    for (auto l = aLogList->begin(); l != aLogList->end(); ++l) {
+      nsLogs.AppendElement(NS_ConvertUTF8toUTF16(l->c_str()));
+    }
+    aLoggingCallback.get()->Call(nsLogs, rv);
+  }
+
+  if (rv.Failed()) {
+    CSFLogError(logTag, "Error firing logging observer callback");
+  }
+}
+
+static void GetLogging_s(
+  nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback> aLoggingCallback,
+  const std::string& aPattern)
+{
+  RLogRingBuffer* logs = RLogRingBuffer::GetInstance();
+  nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
+  // Might not exist yet.
+  if (logs) {
+    logs->Filter(aPattern, 0, result);
+  }
+  NS_DispatchToMainThread(WrapRunnableNM(&OnGetLogging_m,
+                                         aLoggingCallback,
+                                         aPattern,
+                                         result),
+                          NS_DISPATCH_NORMAL);
+}
+
+
+void
+WebrtcGlobalInformation::GetAllStats(
+  const GlobalObject& aGlobal,
+  WebrtcGlobalStatisticsCallback& aStatsCallback,
+  ErrorResult& aRv)
+{
+  if (!NS_IsMainThread()) {
+    aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
+    return;
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsIEventTarget> stsThread =
+    do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
+
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
+
+  if (!stsThread) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
+
+  nsAutoPtr<RTCStatsQueries> queries(new RTCStatsQueries);
+
+  // If there is no PeerConnectionCtx, go through the same motions, since
+  // the API consumer doesn't care why there are no PeerConnectionImpl.
+  if (PeerConnectionCtx::isActive()) {
+    PeerConnectionCtx *ctx = PeerConnectionCtx::GetInstance();
+    MOZ_ASSERT(ctx);
+    for (auto p = ctx->mPeerConnections.begin();
+         p != ctx->mPeerConnections.end();
+         ++p) {
+      MOZ_ASSERT(p->second);
+
+      if (!p->second->IsClosed()) {
+        queries->append(nsAutoPtr<RTCStatsQuery>(new RTCStatsQuery(true)));
+        p->second->BuildStatsQuery_m(nullptr, // all tracks
+                                     queries->back());
+      }
+    }
+  }
+
+  // CallbackObject does not support threadsafe refcounting, and must be
+  // destroyed on main.
+  nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> callbackHandle(
+    new nsMainThreadPtrHolder<WebrtcGlobalStatisticsCallback>(&aStatsCallback));
+
+  rv = RUN_ON_THREAD(stsThread,
+                     WrapRunnableNM(&GetAllStats_s, callbackHandle, queries),
+                     NS_DISPATCH_NORMAL);
+
+  aRv = rv;
+}
+
+void
+WebrtcGlobalInformation::GetLogging(
+  const GlobalObject& aGlobal,
+  const nsAString& aPattern,
+  WebrtcGlobalLoggingCallback& aLoggingCallback,
+  ErrorResult& aRv)
+{
+  if (!NS_IsMainThread()) {
+    aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
+    return;
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsIEventTarget> stsThread =
+    do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
+
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
+
+  if (!stsThread) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
+
+  std::string pattern(NS_ConvertUTF16toUTF8(aPattern).get());
+
+  // CallbackObject does not support threadsafe refcounting, and must be
+  // destroyed on main.
+  nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback> callbackHandle(
+    new nsMainThreadPtrHolder<WebrtcGlobalLoggingCallback>(&aLoggingCallback));
+
+  rv = RUN_ON_THREAD(stsThread,
+                     WrapRunnableNM(&GetLogging_s, callbackHandle, pattern),
+                     NS_DISPATCH_NORMAL);
+
+  if (NS_FAILED(rv)) {
+    aLoggingCallback.Release();
+  }
+
+  aRv = rv;
+}
+
+} // namespace dom
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.h
@@ -0,0 +1,41 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _WEBRTC_GLOBAL_INFORMATION_H_
+#define _WEBRTC_GLOBAL_INFORMATION_H_
+
+#include "nsString.h"
+
+namespace mozilla {
+class ErrorResult;
+
+namespace dom {
+class GlobalObject;
+class WebrtcGlobalStatisticsCallback;
+class WebrtcGlobalLoggingCallback;
+
+class WebrtcGlobalInformation
+{
+public:
+  static void GetAllStats(const GlobalObject& aGlobal,
+                          WebrtcGlobalStatisticsCallback& aStatsCallback,
+                          ErrorResult& aRv);
+
+  static void GetLogging(const GlobalObject& aGlobal,
+                         const nsAString& aPattern,
+                         WebrtcGlobalLoggingCallback& aLoggingCallback,
+                         ErrorResult& aRv);
+
+private:
+  WebrtcGlobalInformation() MOZ_DELETE;
+  WebrtcGlobalInformation(const WebrtcGlobalInformation& aOrig) MOZ_DELETE;
+  WebrtcGlobalInformation& operator=(
+    const WebrtcGlobalInformation& aRhs) MOZ_DELETE;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif  // _WEBRTC_GLOBAL_INFORMATION_H_
+
--- a/media/webrtc/trunk/webrtc/typedefs.h
+++ b/media/webrtc/trunk/webrtc/typedefs.h
@@ -47,23 +47,33 @@
 //#define WEBRTC_ARCH_ARM_FAMILY
 //#define WEBRTC_ARCH_ARMEL
 #define WEBRTC_ARCH_32_BITS
 #define WEBRTC_ARCH_LITTLE_ENDIAN
 #define WEBRTC_LITTLE_ENDIAN
 #elif defined(__powerpc64__)
 #define WEBRTC_ARCH_PPC64 1
 #define WEBRTC_ARCH_64_BITS 1
+#ifdef __LITTLE_ENDIAN__
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#define WEBRTC_LITTLE_ENDIAN
+#else
 #define WEBRTC_ARCH_BIG_ENDIAN
 #define WEBRTC_BIG_ENDIAN
+#endif
 #elif defined(__ppc__) || defined(__powerpc__)
 #define WEBRTC_ARCH_PPC 1
 #define WEBRTC_ARCH_32_BITS 1
+#ifdef __LITTLE_ENDIAN__
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#define WEBRTC_LITTLE_ENDIAN
+#else
 #define WEBRTC_ARCH_BIG_ENDIAN
 #define WEBRTC_BIG_ENDIAN
+#endif
 #elif defined(__sparc64__)
 #define WEBRTC_ARCH_SPARC 1
 #define WEBRTC_ARCH_64_BITS 1
 #define WEBRTC_ARCH_BIG_ENDIAN
 #define WEBRTC_BIG_ENDIAN
 #elif defined(__sparc__)
 #define WEBRTC_ARCH_SPARC 1
 #define WEBRTC_ARCH_32_BITS 1
--- a/mfbt/Endian.h
+++ b/mfbt/Endian.h
@@ -86,17 +86,17 @@
 #    error "CPU type is unknown"
 #  endif
 #elif defined(_WIN32)
 #  if defined(_M_IX86)
 #    define MOZ_LITTLE_ENDIAN 1
 #  else
 #    error "CPU type is unknown"
 #  endif
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) || defined(__powerpc__) || defined(__ppc__)
 #  if __LITTLE_ENDIAN__
 #    define MOZ_LITTLE_ENDIAN 1
 #  elif __BIG_ENDIAN__
 #    define MOZ_BIG_ENDIAN 1
 #  endif
 #elif defined(__GNUC__) && \
       defined(__BYTE_ORDER__) && \
       defined(__ORDER_LITTLE_ENDIAN__) && \
@@ -114,18 +114,17 @@
 #  endif
 /*
  * We can't include useful headers like <endian.h> or <sys/isa_defs.h>
  * here because they're not present on all platforms.  Instead we have
  * this big conditional that ideally will catch all the interesting
  * cases.
  */
 #elif defined(__sparc) || defined(__sparc__) || \
-      defined(_POWER) || defined(__powerpc__) || \
-      defined(__ppc__) || defined(__hppa) || \
+      defined(_POWER) || defined(__hppa) || \
       defined(_MIPSEB) || defined(__ARMEB__) || \
       defined(__s390__) || defined(__AARCH64EB__) || \
       (defined(__sh__) && defined(__LITTLE_ENDIAN__)) || \
       (defined(__ia64) && defined(__BIG_ENDIAN__))
 #  define MOZ_BIG_ENDIAN 1
 #elif defined(__i386) || defined(__i386__) || \
       defined(__x86_64) || defined(__x86_64__) || \
       defined(_MIPSEL) || defined(__ARMEL__) || \
--- a/mobile/android/chrome/content/aboutApps.js
+++ b/mobile/android/chrome/content/aboutApps.js
@@ -7,17 +7,19 @@
  * ***** END LICENSE BLOCK ***** */
 
 let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm")
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 
+#ifdef MOZ_ANDROID_SYNTHAPKS
 XPCOMUtils.defineLazyModuleGetter(this, "WebappManager", "resource://gre/modules/WebappManager.jsm");
+#endif
 
 const DEFAULT_ICON = "chrome://browser/skin/images/default-app-icon.png";
 
 let gStrings = Services.strings.createBundle("chrome://browser/locale/aboutApps.properties");
 
 XPCOMUtils.defineLazyGetter(window, "gChromeWin", function()
   window.QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIWebNavigation)
@@ -38,19 +40,21 @@ function openLink(aEvent) {
   try {
     let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
     let url = formatter.formatURLPref(aEvent.currentTarget.getAttribute("pref"));
     let BrowserApp = gChromeWin.BrowserApp;
     BrowserApp.addTab(url, { selected: true, parentId: BrowserApp.selectedTab.id });
   } catch (ex) {}
 }
 
+#ifdef MOZ_ANDROID_SYNTHAPKS
 function checkForUpdates(aEvent) {
   WebappManager.checkForUpdates(true);
 }
+#endif
 
 #ifndef MOZ_ANDROID_SYNTHAPKS
 var ContextMenus = {
   target: null,
 
   init: function() {
     document.addEventListener("contextmenu", this, false);
     document.getElementById("addToHomescreenLabel").addEventListener("click", this.addToHomescreen, false);
@@ -88,17 +92,19 @@ var ContextMenus = {
 #endif
 
 function onLoad(aEvent) {
   let elmts = document.querySelectorAll("[pref]");
   for (let i = 0; i < elmts.length; i++) {
     elmts[i].addEventListener("click",  openLink,  false);
   }
 
+#ifdef MOZ_ANDROID_SYNTHAPKS
   document.getElementById("update-item").addEventListener("click", checkForUpdates, false);
+#endif
 
   navigator.mozApps.mgmt.oninstall = onInstall;
   navigator.mozApps.mgmt.onuninstall = onUninstall;
   updateList();
 
 #ifndef MOZ_ANDROID_SYNTHAPKS
   ContextMenus.init();
 #endif
--- a/mobile/android/chrome/content/aboutApps.xhtml
+++ b/mobile/android/chrome/content/aboutApps.xhtml
@@ -50,17 +50,18 @@
     </div>
 
     <div class="list-item" role="button" pref="app.marketplaceURL">
       <img class="icon" src="chrome://browser/skin/images/marketplace-logo.png" />
       <div class="inner">
         <div id="browse-title" class="title">&aboutApps.browseMarketplace;</div>
       </div>
     </div>
-
+#ifdef MOZ_ANDROID_SYNTHAPKS
     <div class="list-item" id="update-item" role="button">
       <img class="icon" src="chrome://browser/skin/images/update.png" />
       <div class="inner">
         <div id="browse-title" class="title">&aboutApps.checkForUpdates;</div>
       </div>
     </div>
+#endif
   </body>
 </html>
--- a/mobile/android/modules/WebappManager.jsm
+++ b/mobile/android/modules/WebappManager.jsm
@@ -23,23 +23,25 @@ Cu.import("resource://gre/modules/Task.j
 Cu.import("resource://gre/modules/PluralForm.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "Strings", function() {
   return Services.strings.createBundle("chrome://browser/locale/webapp.properties");
 });
 
-function log(message) {
+function debug(aMessage) {
   // We use *dump* instead of Services.console.logStringMessage so the messages
   // have the INFO level of severity instead of the ERROR level.  And we don't
   // append a newline character to the end of the message because *dump* spills
   // into the Android native logging system, which strips newlines from messages
   // and breaks messages into lines automatically at display time (i.e. logcat).
-  dump(message);
+#ifdef MOZ_DEBUG
+  dump(aMessage);
+#endif
 }
 
 function sendMessageToJava(aMessage) {
   return Services.androidBridge.handleGeckoMessage(JSON.stringify(aMessage));
 }
 
 this.WebappManager = {
   __proto__: DOMRequestIpcHelper.prototype,
@@ -75,62 +77,62 @@ this.WebappManager = {
   _installApk: function(aMessage, aMessageManager) { return Task.spawn((function*() {
     let filePath;
 
     try {
       filePath = yield this._downloadApk(aMessage.app.manifestURL);
     } catch(ex) {
       aMessage.error = ex;
       aMessageManager.sendAsyncMessage("Webapps:Install:Return:KO", aMessage);
-      log("error downloading APK: " + ex);
+      debug("error downloading APK: " + ex);
       return;
     }
 
     sendMessageToJava({
       type: "Webapps:InstallApk",
       filePath: filePath,
       data: JSON.stringify(aMessage),
     });
   }).bind(this)); },
 
   _downloadApk: function(aManifestUrl) {
-    log("_downloadApk for " + aManifestUrl);
+    debug("_downloadApk for " + aManifestUrl);
     let deferred = Promise.defer();
 
     // Get the endpoint URL and convert it to an nsIURI/nsIURL object.
     const GENERATOR_URL_PREF = "browser.webapps.apkFactoryUrl";
     const GENERATOR_URL_BASE = Services.prefs.getCharPref(GENERATOR_URL_PREF);
     let generatorUrl = NetUtil.newURI(GENERATOR_URL_BASE).QueryInterface(Ci.nsIURL);
 
     // Populate the query part of the URL with the manifest URL parameter.
     let params = {
       manifestUrl: aManifestUrl,
     };
     generatorUrl.query =
       [p + "=" + encodeURIComponent(params[p]) for (p in params)].join("&");
-    log("downloading APK from " + generatorUrl.spec);
+    debug("downloading APK from " + generatorUrl.spec);
 
     let file = Cc["@mozilla.org/download-manager;1"].
                getService(Ci.nsIDownloadManager).
                defaultDownloadsDirectory.
                clone();
     file.append(aManifestUrl.replace(/[^a-zA-Z0-9]/gi, "") + ".apk");
     file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-    log("downloading APK to " + file.path);
+    debug("downloading APK to " + file.path);
 
     let worker = new ChromeWorker("resource://gre/modules/WebappManagerWorker.js");
     worker.onmessage = function(event) {
       let { type, message } = event.data;
 
       worker.terminate();
 
       if (type == "success") {
         deferred.resolve(file.path);
       } else { // type == "failure"
-        log("error downloading APK: " + message);
+        debug("error downloading APK: " + message);
         deferred.reject(message);
       }
     }
 
     // Trigger the download.
     worker.postMessage({ url: generatorUrl.spec, path: file.path });
 
     return deferred.promise;
@@ -142,17 +144,17 @@ this.WebappManager = {
 
     // We don't yet support pre-installing an appcache because it isn't clear
     // how to do it without degrading the user experience (since users expect
     // apps to be available after the system tells them they've been installed,
     // which has already happened) and because nsCacheService shuts down
     // when we trigger the native install dialog and doesn't re-init itself
     // afterward (TODO: file bug about this behavior).
     if ("appcache_path" in aData.app.manifest) {
-      log("deleting appcache_path from manifest: " + aData.app.manifest.appcache_path);
+      debug("deleting appcache_path from manifest: " + aData.app.manifest.appcache_path);
       delete aData.app.manifest.appcache_path;
     }
 
     DOMApplicationRegistry.registryReady.then(() => {
       DOMApplicationRegistry.confirmInstall(aData, file, (function(aManifest) {
         let localeManifest = new ManifestHelper(aManifest, aData.app.origin);
 
         // aData.app.origin may now point to the app: url that hosts this app.
@@ -163,27 +165,27 @@ this.WebappManager = {
         });
 
         this.writeDefaultPrefs(file, localeManifest);
       }).bind(this));
     });
   },
 
   launch: function({ manifestURL, origin }) {
-    log("launchWebapp: " + manifestURL);
+    debug("launchWebapp: " + manifestURL);
 
     sendMessageToJava({
       type: "Webapps:Open",
       manifestURL: manifestURL,
       origin: origin
     });
   },
 
   uninstall: function(aData) {
-    log("uninstall: " + aData.manifestURL);
+    debug("uninstall: " + aData.manifestURL);
 
     if (this._testing) {
       // We don't have to do anything, as the registry does all the work.
       return;
     }
 
     // TODO: uninstall the APK.
   },
@@ -194,17 +196,17 @@ this.WebappManager = {
       // If the app is already installed, update the existing installation.
       this._autoUpdate(aData, oldApp);
       return;
     }
 
     let mm = {
       sendAsyncMessage: function (aMessageName, aData) {
         // TODO hook this back to Java to report errors.
-        log("sendAsyncMessage " + aMessageName + ": " + JSON.stringify(aData));
+        debug("sendAsyncMessage " + aMessageName + ": " + JSON.stringify(aData));
       }
     };
 
     let origin = Services.io.newURI(aData.manifestURL, null, null).prePath;
 
     let message = aData.request || {
       app: {
         origin: origin,
@@ -239,36 +241,36 @@ this.WebappManager = {
           message.isPackage = true;
           DOMApplicationRegistry.doInstallPackage(message, mm);
           break;
       }
     });
   },
 
   _autoUpdate: function(aData, aOldApp) { return Task.spawn((function*() {
-    log("_autoUpdate app of type " + aData.type);
+    debug("_autoUpdate app of type " + aData.type);
 
     if (aData.type == "hosted") {
       let oldManifest = yield DOMApplicationRegistry.getManifestFor(aData.manifestURL);
       DOMApplicationRegistry.updateHostedApp(aData, aOldApp.id, aOldApp, oldManifest, aData.manifest);
     } else {
       DOMApplicationRegistry.updatePackagedApp(aData, aOldApp.id, aOldApp, aData.manifest);
     }
   }).bind(this)); },
 
   _checkingForUpdates: false,
 
   checkForUpdates: function(userInitiated) { return Task.spawn((function*() {
-    log("checkForUpdates");
+    debug("checkForUpdates");
 
     // Don't start checking for updates if we're already doing so.
     // TODO: Consider cancelling the old one and starting a new one anyway
     // if the user requested this one.
     if (this._checkingForUpdates) {
-      log("already checking for updates");
+      debug("already checking for updates");
       return;
     }
     this._checkingForUpdates = true;
 
     try {
       let installedApps = yield this._getInstalledApps();
       if (installedApps.length === 0) {
         return;
@@ -461,17 +463,17 @@ this.WebappManager = {
         });
       }
     } else {
       // The user cancelled the notification, so remove the downloaded APKs.
       for (let apk of downloadedApks) {
         try {
           yield OS.file.remove(apk.filePath);
         } catch(ex) {
-          log("error removing " + apk.filePath + " for cancelled update: " + ex);
+          debug("error removing " + apk.filePath + " for cancelled update: " + ex);
         }
       }
     }
 
   }).bind(this)); },
 
   _notify: function(aOptions) {
     dump("_notify: " + aOptions.title);
@@ -507,24 +509,24 @@ this.WebappManager = {
     };
   },
 
   autoUninstall: function(aData) {
     DOMApplicationRegistry.registryReady.then(() => {
       for (let id in DOMApplicationRegistry.webapps) {
         let app = DOMApplicationRegistry.webapps[id];
         if (aData.apkPackageNames.indexOf(app.apkPackageName) > -1) {
-          log("attempting to uninstall " + app.name);
+          debug("attempting to uninstall " + app.name);
           DOMApplicationRegistry.uninstall(
             app.manifestURL,
             function() {
-              log("success uninstalling " + app.name);
+              debug("success uninstalling " + app.name);
             },
             function(error) {
-              log("error uninstalling " + app.name + ": " + error);
+              debug("error uninstalling " + app.name + ": " + error);
             }
           );
         }
       }
     });
   },
 
   writeDefaultPrefs: function(aProfile, aManifest) {
@@ -543,16 +545,16 @@ this.WebappManager = {
       defaultPrefsFile.append(this.DEFAULT_PREFS_FILENAME);
       this._writeData(defaultPrefsFile, prefs);
   },
 
   _writeData: function(aFile, aPrefs) {
     if (aPrefs.length > 0) {
       let array = new TextEncoder().encode(JSON.stringify(aPrefs));
       OS.File.writeAtomic(aFile.path, array, { tmpPath: aFile.path + ".tmp" }).then(null, function onError(reason) {
-        log("Error writing default prefs: " + reason);
+        debug("Error writing default prefs: " + reason);
       });
     }
   },
 
   DEFAULT_PREFS_FILENAME: "default-prefs.js",
 
 };
--- a/mobile/android/modules/moz.build
+++ b/mobile/android/modules/moz.build
@@ -18,12 +18,14 @@ EXTRA_JS_MODULES += [
     'Prompt.jsm',
     'Sanitizer.jsm',
     'SharedPreferences.jsm',
     'SimpleServiceDiscovery.jsm',
     'SSLExceptions.jsm',
 ]
 
 if CONFIG['MOZ_ANDROID_SYNTHAPKS']:
+    EXTRA_PP_JS_MODULES += [
+        'WebappManager.jsm',
+    ]
     EXTRA_JS_MODULES += [
-        'WebappManager.jsm',
         'WebappManagerWorker.js',
     ]
--- a/netwerk/cache2/CacheEntry.cpp
+++ b/netwerk/cache2/CacheEntry.cpp
@@ -1036,26 +1036,25 @@ NS_IMETHODIMP CacheEntry::GetSecurityInf
     if (mSecurityInfoLoaded) {
       NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
       return NS_OK;
     }
   }
 
   NS_ENSURE_SUCCESS(mFileStatus, NS_ERROR_NOT_AVAILABLE);
 
-  char const* info;
+  nsXPIDLCString info;
   nsCOMPtr<nsISupports> secInfo;
   nsresult rv;
 
-  rv = mFile->GetElement("security-info", &info);
+  rv = mFile->GetElement("security-info", getter_Copies(info));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (info) {
-    rv = NS_DeserializeObject(nsDependentCString(info),
-                              getter_AddRefs(secInfo));
+    rv = NS_DeserializeObject(info, getter_AddRefs(secInfo));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   {
     mozilla::MutexAutoLock lock(mLock);
 
     mSecurityInfo.swap(secInfo);
     mSecurityInfoLoaded = true;
@@ -1132,25 +1131,17 @@ NS_IMETHODIMP CacheEntry::AsyncDoom(nsIC
 
   return NS_OK;
 }
 
 NS_IMETHODIMP CacheEntry::GetMetaDataElement(const char * aKey, char * *aRetval)
 {
   NS_ENSURE_SUCCESS(mFileStatus, NS_ERROR_NOT_AVAILABLE);
 
-  const char *value;
-  nsresult rv = mFile->GetElement(aKey, &value);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!value)
-    return NS_ERROR_NOT_AVAILABLE;
-
-  *aRetval = NS_strdup(value);
-  return NS_OK;
+  return mFile->GetElement(aKey, aRetval);
 }
 
 NS_IMETHODIMP CacheEntry::SetMetaDataElement(const char * aKey, const char * aValue)
 {
   NS_ENSURE_SUCCESS(mFileStatus, NS_ERROR_NOT_AVAILABLE);
 
   return mFile->SetElement(aKey, aValue);
 }
--- a/netwerk/cache2/CacheFile.cpp
+++ b/netwerk/cache2/CacheFile.cpp
@@ -740,23 +740,28 @@ CacheFile::ThrowMemoryCachedData()
     return NS_ERROR_ABORT;
   }
 
   mCachedChunks.Clear();
   return NS_OK;
 }
 
 nsresult
-CacheFile::GetElement(const char *aKey, const char **_retval)
+CacheFile::GetElement(const char *aKey, char **_retval)
 {
   CacheFileAutoLock lock(this);
   MOZ_ASSERT(mMetadata);
   NS_ENSURE_TRUE(mMetadata, NS_ERROR_UNEXPECTED);
 
-  *_retval = mMetadata->GetElement(aKey);
+  const char *value;
+  value = mMetadata->GetElement(aKey);
+  if (!value)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  *_retval = NS_strdup(value);
   return NS_OK;
 }
 
 nsresult
 CacheFile::SetElement(const char *aKey, const char *aValue)
 {
   CacheFileAutoLock lock(this);
   MOZ_ASSERT(mMetadata);
--- a/netwerk/cache2/CacheFile.h
+++ b/netwerk/cache2/CacheFile.h
@@ -78,17 +78,17 @@ public:
   NS_IMETHOD OpenInputStream(nsIInputStream **_retval);
   NS_IMETHOD OpenOutputStream(CacheOutputCloseListener *aCloseListener, nsIOutputStream **_retval);
   NS_IMETHOD SetMemoryOnly();
   NS_IMETHOD Doom(CacheFileListener *aCallback);
 
   nsresult   ThrowMemoryCachedData();
 
   // metadata forwarders
-  nsresult GetElement(const char *aKey, const char **_retval);
+  nsresult GetElement(const char *aKey, char **_retval);
   nsresult SetElement(const char *aKey, const char *aValue);
   nsresult ElementsSize(uint32_t *_retval);
   nsresult SetExpirationTime(uint32_t aExpirationTime);
   nsresult GetExpirationTime(uint32_t *_retval);
   nsresult SetLastModified(uint32_t aLastModified);
   nsresult GetLastModified(uint32_t *_retval);
   nsresult SetFrecency(uint32_t aFrecency);
   nsresult GetFrecency(uint32_t *_retval);
--- a/netwerk/protocol/http/HttpChannelParentListener.cpp
+++ b/netwerk/protocol/http/HttpChannelParentListener.cpp
@@ -190,17 +190,21 @@ HttpChannelParentListener::OnRedirectRes
   }
 
   nsCOMPtr<nsIParentRedirectingChannel> activeRedirectingChannel =
       do_QueryInterface(mActiveChannel);
   MOZ_ASSERT(activeRedirectingChannel,
     "Channel finished a redirect response, but doesn't implement "
     "nsIParentRedirectingChannel to complete it.");
 
-  activeRedirectingChannel->CompleteRedirect(succeeded);
+  if (activeRedirectingChannel) {
+    activeRedirectingChannel->CompleteRedirect(succeeded);
+  } else {
+    succeeded = false;
+  }
 
   if (succeeded) {
     // Switch to redirect channel and delete the old one.
     mActiveChannel->Delete();
     mActiveChannel = redirectChannel;
   } else if (redirectChannel) {
     // Delete the redirect target channel: continue using old channel
     redirectChannel->Delete();
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -142,17 +142,26 @@ WillRedirect(const nsHttpResponseHead * 
            response->PeekHeader(nsHttp::Location);
 }
 
 } // unnamed namespace
 
 class AutoRedirectVetoNotifier
 {
 public:
-    AutoRedirectVetoNotifier(nsHttpChannel* channel) : mChannel(channel) {}
+    AutoRedirectVetoNotifier(nsHttpChannel* channel) : mChannel(channel)
+    {
+      if (mChannel->mHasAutoRedirectVetoNotifier) {
+        MOZ_CRASH("Nested AutoRedirectVetoNotifier on the stack");
+        mChannel = nullptr;
+        return;
+      }
+
+      mChannel->mHasAutoRedirectVetoNotifier = true;
+    }
     ~AutoRedirectVetoNotifier() {ReportRedirectResult(false);}
     void RedirectSucceeded() {ReportRedirectResult(true);}
 
 private:
     nsHttpChannel* mChannel;
     void ReportRedirectResult(bool succeeded);
 };
 
@@ -164,23 +173,25 @@ AutoRedirectVetoNotifier::ReportRedirect
 
     mChannel->mRedirectChannel = nullptr;
 
     nsCOMPtr<nsIRedirectResultListener> vetoHook;
     NS_QueryNotificationCallbacks(mChannel,
                                   NS_GET_IID(nsIRedirectResultListener),
                                   getter_AddRefs(vetoHook));
 
-#ifdef MOZ_VISUAL_EVENT_TRACER
     nsHttpChannel* channel = mChannel;
-#endif
     mChannel = nullptr;
+
     if (vetoHook)
         vetoHook->OnRedirectResult(succeeded);
 
+    // Drop after the notification
+    channel->mHasAutoRedirectVetoNotifier = false;
+
     MOZ_EVENT_TRACER_DONE(channel, "net::http::redirect-callbacks");
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel <public>
 //-----------------------------------------------------------------------------
 
 nsHttpChannel::nsHttpChannel()
@@ -202,16 +213,17 @@ nsHttpChannel::nsHttpChannel()
     , mWaitingForRedirectCallback(false)
     , mRequestTimeInitialized(false)
     , mCacheEntryIsReadOnly(false)
     , mCacheEntryIsWriteOnly(false)
     , mCacheEntriesToWaitFor(0)
     , mHasQueryString(0)
     , mConcurentCacheAccess(0)
     , mIsPartialRequest(0)
+    , mHasAutoRedirectVetoNotifier(0)
     , mDidReval(false)
 {
     LOG(("Creating nsHttpChannel [this=%p]\n", this));
     mChannelCreationTime = PR_Now();
     mChannelCreationTimestamp = TimeStamp::Now();
 }
 
 nsHttpChannel::~nsHttpChannel()
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -390,16 +390,18 @@ private:
     uint32_t                          mHasQueryString : 1;
     // whether cache entry data write was in progress during cache entry check
     // when true, after we finish read from cache we must check all data
     // had been loaded from cache. If not, then an error has to be propagated
     // to the consumer.
     uint32_t                          mConcurentCacheAccess : 1;
     // whether the request is setup be byte-range
     uint32_t                          mIsPartialRequest : 1;
+    // true iff there is AutoRedirectVetoNotifier on the stack
+    uint32_t                          mHasAutoRedirectVetoNotifier : 1;
 
     nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
 
     PRTime                            mChannelCreationTime;
     TimeStamp                         mChannelCreationTimestamp;
     TimeStamp                         mAsyncOpenTime;
     TimeStamp                         mCacheReadStart;
     TimeStamp                         mCacheReadEnd;
rename from testing/mochitest/tests/SpecialPowersLoadChromeScript.js
rename to testing/mochitest/tests/Harness_sanity/SpecialPowersLoadChromeScript.js
rename from testing/mochitest/tests/file_SpecialPowersFrame1.html
rename to testing/mochitest/tests/Harness_sanity/file_SpecialPowersFrame1.html
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/tests/Harness_sanity/mochitest.ini
@@ -0,0 +1,18 @@
+[test_sanity.html]
+[test_sanityException.html]
+[test_sanityException2.html]
+[test_sanityWindowSnapshot.html]
+[test_SpecialPowersExtension.html]
+[test_SpecialPowersExtension2.html]
+support-files = file_SpecialPowersFrame1.html
+[test_SpecialPowersPushPermissions.html]
+[test_SpecialPowersPushPrefEnv.html]
+[test_SimpleTestGetTestFileURL.html]
+[test_SpecialPowersLoadChromeScript.html]
+support-files = SpecialPowersLoadChromeScript.js
+[test_bug816847.html]
+[test_sanity_cleanup.html]
+[test_sanity_cleanup2.html]
+[test_sanityEventUtils.html]
+[test_sanitySimpletest.html]
+
rename from testing/mochitest/tests/test_SimpleTestGetTestFileURL.html
rename to testing/mochitest/tests/Harness_sanity/test_SimpleTestGetTestFileURL.html
rename from testing/mochitest/tests/test_SpecialPowersExtension.html
rename to testing/mochitest/tests/Harness_sanity/test_SpecialPowersExtension.html
rename from testing/mochitest/tests/test_SpecialPowersExtension2.html
rename to testing/mochitest/tests/Harness_sanity/test_SpecialPowersExtension2.html
rename from testing/mochitest/tests/test_SpecialPowersLoadChromeScript.html
rename to testing/mochitest/tests/Harness_sanity/test_SpecialPowersLoadChromeScript.html
rename from testing/mochitest/tests/test_SpecialPowersPushPermissions.html
rename to testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushPermissions.html
rename from testing/mochitest/tests/test_SpecialPowersPushPrefEnv.html
rename to testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushPrefEnv.html
rename from testing/mochitest/tests/test_bug362788.xhtml
rename to testing/mochitest/tests/Harness_sanity/test_bug362788.xhtml
rename from testing/mochitest/tests/test_bug816847.html
rename to testing/mochitest/tests/Harness_sanity/test_bug816847.html
rename from testing/mochitest/tests/test_sanity.html
rename to testing/mochitest/tests/Harness_sanity/test_sanity.html
rename from testing/mochitest/tests/test_sanityEventUtils.html
rename to testing/mochitest/tests/Harness_sanity/test_sanityEventUtils.html
rename from testing/mochitest/tests/test_sanityException.html
rename to testing/mochitest/tests/Harness_sanity/test_sanityException.html
rename from testing/mochitest/tests/test_sanityException2.html
rename to testing/mochitest/tests/Harness_sanity/test_sanityException2.html
rename from testing/mochitest/tests/test_sanitySimpletest.html
rename to testing/mochitest/tests/Harness_sanity/test_sanitySimpletest.html
rename from testing/mochitest/tests/test_sanityWindowSnapshot.html
rename to testing/mochitest/tests/Harness_sanity/test_sanityWindowSnapshot.html
rename from testing/mochitest/tests/test_sanity_cleanup.html
rename to testing/mochitest/tests/Harness_sanity/test_sanity_cleanup.html
rename from testing/mochitest/tests/test_sanity_cleanup2.html
rename to testing/mochitest/tests/Harness_sanity/test_sanity_cleanup2.html
deleted file mode 100644
--- a/testing/mochitest/tests/Makefile.in
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-TEST_FILES = \
-  test_sanity.html \
-  test_sanityException.html \
-  test_sanityException2.html \
-  test_sanityWindowSnapshot.html \
-  test_SpecialPowersExtension.html \
-  test_SpecialPowersExtension2.html \
-  test_SpecialPowersPushPermissions.html \
-  test_SpecialPowersPushPrefEnv.html \
-  file_SpecialPowersFrame1.html \
-  test_SimpleTestGetTestFileURL.html \
-  test_SpecialPowersLoadChromeScript.html \
-  SpecialPowersLoadChromeScript.js \
-  test_bug816847.html \
-  test_sanity_cleanup.html \
-  test_sanity_cleanup2.html \
-  test_sanityEventUtils.html \
-  test_sanitySimpletest.html \
-  $(NULL)
-# Copy the sanity tests into a subdirectory, so the top level is all dirs
-# in the test screen.
-TEST_DEST = $(DEPTH)/_tests/$(relativesrcdir)/Harness_sanity
-INSTALL_TARGETS += TEST
--- a/testing/mochitest/tests/moz.build
+++ b/testing/mochitest/tests/moz.build
@@ -4,8 +4,11 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 PARALLEL_DIRS += [
     'MochiKit-1.4.2',
     'SimpleTest',
     'browser',
 ]
+
+MOCHITEST_MANIFESTS += ['Harness_sanity/mochitest.ini']
+
--- a/testing/mozbase/manifestdestiny/manifestparser/manifestparser.py
+++ b/testing/mozbase/manifestdestiny/manifestparser/manifestparser.py
@@ -385,17 +385,20 @@ def read_ini(fp, variables=None, default
                 else:
                     filename = 'unknown'
                 raise Exception("Error parsing manifest file '%s', line %s" %
                                 (filename, linenum))
 
     # interpret the variables
     def interpret_variables(global_dict, local_dict):
         variables = global_dict.copy()
+        if 'skip-if' in local_dict and 'skip-if' in variables:
+            local_dict['skip-if'] = "(%s) || (%s)" % (variables['skip-if'].split('#')[0], local_dict['skip-if'].split('#')[0])
         variables.update(local_dict)
+            
         return variables
 
     sections = [(i, interpret_variables(variables, j)) for i, j in sections]
     return sections
 
 
 ### objects for parsing manifests
 
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/manifestdestiny/tests/default-skipif.ini
@@ -0,0 +1,22 @@
+[DEFAULT]
+skip-if = os == 'win' && debug # a pesky comment
+
+
+[test1]
+skip-if = debug
+
+[test2]
+skip-if = os == 'linux'
+
+[test3]
+skip-if = os == 'win'
+
+[test4]
+skip-if = os == 'win' && debug
+
+[test5]
+foo = bar
+
+[test6]
+skip-if = debug # a second pesky comment
+
new file mode 100755
--- /dev/null
+++ b/testing/mozbase/manifestdestiny/tests/test_default_skipif.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import unittest
+from manifestparser import ManifestParser
+
+here = os.path.dirname(os.path.abspath(__file__))
+
+class TestDefaultSkipif(unittest.TestCase):
+    """test applying a skip-if condition in [DEFAULT] and || with the value for the test"""
+
+
+    def test_defaults(self):
+
+        default = os.path.join(here, 'default-skipif.ini')
+        parser = ManifestParser(manifests=(default,))
+        for test in parser.tests:
+            if test['name'] == 'test1':
+                self.assertEqual(test['skip-if'], "(os == 'win' && debug ) || (debug)")
+            elif test['name'] == 'test2':
+                self.assertEqual(test['skip-if'], "(os == 'win' && debug ) || (os == 'linux')")
+            elif test['name'] == 'test3':
+                self.assertEqual(test['skip-if'], "(os == 'win' && debug ) || (os == 'win')")
+            elif test['name'] == 'test4':
+                self.assertEqual(test['skip-if'], "(os == 'win' && debug ) || (os == 'win' && debug)")
+            elif test['name'] == 'test5':
+                self.assertEqual(test['skip-if'], "os == 'win' && debug # a pesky comment")
+            elif test['name'] == 'test6':
+                self.assertEqual(test['skip-if'], "(os == 'win' && debug ) || (debug )")
+
+if __name__ == '__main__':
+    unittest.main()
--- a/toolkit/content/aboutWebrtc.xhtml
+++ b/toolkit/content/aboutWebrtc.xhtml
@@ -10,72 +10,46 @@
 
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>Webrtc Internals</title>
   </head>
   <script>
 
 
-function getCandPairLogs(id) {
-  try {
-    var wg = new WebrtcGlobalInformation();
-    wg.getCandPairLogs(id, displayLogs, console.log);
-  } catch (e) {
-    console.log("Exception while creating WebrtcGlobalInformation" + e.toString());
-  }
-}
-
-function getAllLogs() {
-  try {
-    var wg = new WebrtcGlobalInformation();
-    wg.getLogs('', displayLogs, console.log);
-  } catch(e) {
-    console.log("Exception while creating WebrtcGlobalInformation" + e.toString());
-  }
-}
-
 function displayLogs(logs) {
   var logsDiv = document.getElementById('logs');
   while (logsDiv.lastChild) {
     logsDiv.removeChild(logsDiv.lastChild);
   }
   logsDiv.appendChild(document.createElement('h3'))
          .appendChild(document.createTextNode('Logging:'));
   logs.forEach(function(logLine){
     logsDiv.appendChild(document.createElement('div'))
            .appendChild(document.createTextNode(logLine));
   });
 }
 
-function buildCandPairTableRow(candPair, stats) {
+function buildCandPairTableRow(candPair, localCand, remoteCand) {
   var row = document.createElement('tr');
   row.onclick = function() {
-    getCandPairLogs(candPair.id);
+    WebrtcGlobalInformation.getLogging("CAND-PAIR(" + row.id, displayLogs);
   }
 
-  if (stats.has(candPair.localCandidateId)) {
-    // TODO: Might have collisions; we either need to be able to supply
-    // desired type to get(), or do the ugly business of putting the type
-    // in the id as well as the type field.
-    var localCand = stats.get(candPair.localCandidateId);
+  if (localCand) {
     row.appendChild(document.createElement('td'))
        .appendChild(document.createTextNode(localCand.ipAddress + ':' +
                                             localCand.portNumber + '/' +
                                             localCand.candidateType));
   } else {
     row.appendChild(document.createElement('td'))
        .appendChild(document.createTextNode(candPair.localCandidateId));
   }
 
-  if (stats.has(candPair.remoteCandidateId)) {
-    // TODO: Might have collisions; we either need to be able to supply
-    // desired type to get(), or do the ugly business of putting the type
-    // in the id as well as the type field.
-    var remoteCand = stats.get(candPair.remoteCandidateId);
+  if (remoteCand) {
     row.appendChild(document.createElement('td'))
        .appendChild(document.createTextNode(remoteCand.ipAddress + ':' +
                                             remoteCand.portNumber + '/' +
                                             remoteCand.candidateType));
   } else {
     row.appendChild(document.createElement('td'))
        .appendChild(document.createTextNode(candPair.remoteCandidateId));
   }
@@ -87,17 +61,17 @@ function buildCandPairTableRow(candPair,
 
   row.appendChild(document.createElement('td'))
      .appendChild(document.createTextNode(candPair.nominated ? '*' : ''));
   row.appendChild(document.createElement('td'))
      .appendChild(document.createTextNode(candPair.selected ? '*' : ''));
   return row;
 }
 
-function buildCandTableRow(cand, stats) {
+function buildCandTableRow(cand) {
   var row = document.createElement('tr');
 
   row.appendChild(document.createElement('td'))
      .appendChild(document.createTextNode(cand.ipAddress + ':' +
                                           cand.portNumber));
 
   row.appendChild(document.createElement('td'))
      .appendChild(document.createTextNode(cand.candidateType));
@@ -163,102 +137,171 @@ function dumpStat(stat, label) {
     if (stat.bytesSent !== undefined) {
       statsString += " (" + round00(stat.bytesSent/1024) + " Kb)";
     }
   }
   div.appendChild(document.createTextNode(statsString));
   return div;
 }
 
-function buildPcDiv(stats, pcDivId) {
+function buildPcDiv(stats, pcDivHeading) {
   var newPcDiv = document.createElement('div');
 
   var heading = document.createElement('h3');
-  heading.appendChild(document.createTextNode(pcDivId));
+  heading.appendChild(document.createTextNode(pcDivHeading));
   newPcDiv.appendChild(heading);
 
-  var subDivs = {};
+  // First, ICE stats
+  var iceHeading = document.createElement('h4');
+  iceHeading.appendChild(document.createTextNode("ICE statistics"));
+  newPcDiv.appendChild(iceHeading);
+
+  var iceTablesByComponent = {};
 
-  stats.forEach(function(stat) {
-    if (!stat.componentId) {
-      if (!stat.isRemote) {
-        newPcDiv.appendChild(document.createElement('h4'))
-                .appendChild(document.createTextNode(stat.id));
-        if (stat.remoteId) {
-          newPcDiv.appendChild(dumpStat(stat, "Local: "));
-          newPcDiv.appendChild(dumpStat(stats.get(stat.remoteId), "Remote: "));
-        } else {
-          newPcDiv.appendChild(dumpStat(stat, ""));
-        }
-      }
-      return;
-    }
-
-    if (!subDivs[stat.componentId]) {
-      subDivs[stat.componentId] = {
-        candPairTable: buildEmptyCandPairTable(),
-        localCandTable: buildEmptyCandTable(true),
-        remoteCandTable: buildEmptyCandTable(false)
+  function getIceTables(componentId) {
+    if (!iceTablesByComponent[componentId]) {
+      iceTablesByComponent[componentId] = {
+        candidatePairTable: buildEmptyCandPairTable(),
+        localCandidateTable: buildEmptyCandTable(true),
+        remoteCandidateTable: buildEmptyCandTable(false)
       };
     }
+    return iceTablesByComponent[componentId];
+  }
 
-    var subDiv = subDivs[stat.componentId];
+  // Candidates
+  var candidateMap = {}; // Used later to speed up recording of candidate pairs
+
+  if (stats.iceCandidateStats) {
+    stats.iceCandidateStats.forEach(function(cand) {
+        var tables = getIceTables(cand.componentId);
+
+        candidateMap[cand.id] = cand;
 
-    if (stat.type == 'candidatepair') {
-      subDiv.candPairTable.appendChild(buildCandPairTableRow(stat, stats));
-    } else if (stat.type == 'localcandidate') {
-      subDiv.localCandTable.appendChild(buildCandTableRow(stat, stats));
-    } else if (stat.type == 'remotecandidate') {
-      subDiv.remoteCandTable.appendChild(buildCandTableRow(stat, stats));
-    }
-  });
+        if (cand.type == "localcandidate") {
+          tables.localCandidateTable.appendChild(buildCandTableRow(cand));
+        } else {
+          tables.remoteCandidateTable.appendChild(buildCandTableRow(cand));
+        }
+    });
+  }
 
-  for (var cid in subDivs) {
-    if (subDivs.hasOwnProperty(cid)) {
-      var subDiv = subDivs[cid];
+  // Candidate pairs
+  if (stats.iceCandidatePairStats) {
+    stats.iceCandidatePairStats.forEach(function(candPair) {
+      var candPairTable =
+        getIceTables(candPair.componentId).candidatePairTable;
+      candPairTable.appendChild(
+          buildCandPairTableRow(candPair,
+                                candidateMap[candPair.localCandidateId],
+                                candidateMap[candPair.remoteCandidateId]));
+    });
+  }
+
+  // Now that tables are completely built, put them on the page.
+  for (var cid in iceTablesByComponent) {
+    if (iceTablesByComponent.hasOwnProperty(cid)) {
+      var tables = iceTablesByComponent[cid];
       newPcDiv.appendChild(document.createElement('h4'))
               .appendChild(document.createTextNode(cid));
-      newPcDiv.appendChild(subDiv.candPairTable);
-      newPcDiv.appendChild(subDiv.localCandTable);
-      newPcDiv.appendChild(subDiv.remoteCandTable);
+      newPcDiv.appendChild(tables.candidatePairTable);
+      newPcDiv.appendChild(tables.localCandidateTable);
+      newPcDiv.appendChild(tables.remoteCandidateTable);
+    }
+  }
+
+  // end of ICE stats
+
+  // Now, RTP stats
+  var rtpHeading = document.createElement('h4');
+  rtpHeading.appendChild(document.createTextNode("RTP statistics"));
+  newPcDiv.appendChild(rtpHeading);
+
+  // Build map from id -> remote RTP stats (ie; stats obtained from RTCP
+  // from the other end). This allows us to pair up local/remote stats for
+  // the same stream more easily.
+  var remoteRtpStatsMap = {};
+
+  var addRemoteStatToMap = function (rtpStat) {
+    if (rtpStat.isRemote) {
+      remoteRtpStatsMap[rtpStat.id] = rtpStat;
     }
   }
 
+  if (stats.inboundRTPStreamStats) {
+    stats.inboundRTPStreamStats.forEach(addRemoteStatToMap);
+  }
+
+  if (stats.outboundRTPStreamStats) {
+    stats.outboundRTPStreamStats.forEach(addRemoteStatToMap);
+  }
+
+  var addRtpStatPairToDocument = function (rtpStat) {
+    if (!rtpStat.isRemote) {
+      newPcDiv.appendChild(document.createElement('h5'))
+              .appendChild(document.createTextNode(rtpStat.id));
+      newPcDiv.appendChild(dumpStat(rtpStat, "Local: "));
+
+      // Might not be receiving RTCP, so we have no idea what the
+      // statistics look like from the perspective of the other end.
+      if (rtpStat.remoteId) {
+        var remoteRtpStat = remoteRtpStatsMap[rtpStat.remoteId];
+        newPcDiv.appendChild(dumpStat(remoteRtpStat, "Remote: "));
+      }
+    }
+  }
+
+  if (stats.outboundRTPStreamStats) {
+    stats.outboundRTPStreamStats.forEach(addRtpStatPairToDocument);
+  }
+
+  if (stats.inboundRTPStreamStats) {
+    stats.inboundRTPStreamStats.forEach(addRtpStatPairToDocument);
+  }
+
   return newPcDiv;
 }
 
-function displayStats(obj) {
+function displayStats(globalReport) {
   console.log("Got stats callback.");
-  var pcid = obj.mozPcid;
-  var pcDivId = 'PeerConnection:' + pcid;
+  globalReport.reports.forEach(function (report) {
+    var pcDivHeading = 'PeerConnection:' + report.pcid;
 
-  var pcDiv = document.getElementById(pcDivId);
-  var newPcDiv = buildPcDiv(obj, pcDivId);
-  newPcDiv.id = pcDivId;
+    var pcDiv = document.getElementById(pcDivHeading);
+    var newPcDiv = buildPcDiv(report, pcDivHeading);
+    newPcDiv.id = pcDivHeading;
 
-  if (!pcDiv) {
-    document.getElementById('stats').appendChild(newPcDiv);
-  } else {
-    document.getElementById('stats').replaceChild(newPcDiv, pcDiv);
-  }
-}
+    if (!pcDiv) {
+      document.getElementById('stats').appendChild(newPcDiv);
+    } else {
+      document.getElementById('stats').replaceChild(newPcDiv, pcDiv);
+    }
+  });
+
+  globalReport.errors.forEach(function (error) {
+    var pcDivHeading = 'PeerConnection:' + error.pcid;
 
-function refreshStats() {
-  try {
-    var wg = new WebrtcGlobalInformation();
-    wg.getAllStats(displayStats, console.log);
-  } catch(e) {
-    console.log("Exception while creating WebrtcGlobalInformation:" + e.toString());
-  }
+    var pcDiv = document.getElementById(pcDivHeading);
+    var newPcDiv = buildPcDiv(error, pcDivHeading);
+    newPcDiv.id = pcDivHeading;
+
+    if (pcDiv) {
+      document.getElementById('stats').replaceChild(newPcDiv, pcDiv);
+    } else {
+      document.getElementById('stats').appendChild(newPcDiv);
+    }
+  });
 }
 
   </script>
 
-  <body id="body" onload="refreshStats()">
+  <body id="body" onload="WebrtcGlobalInformation.getAllStats(displayStats)">
     <div id="stats">
     </div>
-    <button onclick="getAllLogs()">Show/refresh logging</button>
+    <button onclick="WebrtcGlobalInformation.getLogging('', displayLogs)">
+      Show/refresh logging
+    </button>
     <div id="logs">
     </div>
   </body>
 </html>
 <!-- vim: softtabstop=2:shiftwidth=2:expandtab
 -->
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -1249,22 +1249,21 @@ nsExternalAppHandler::nsExternalAppHandl
     char16_t(0x202a), // Left-to-Right Embedding
     char16_t(0x202b), // Right-to-Left Embedding
     char16_t(0x202c), // Pop Directional Formatting
     char16_t(0x202d), // Left-to-Right Override
     char16_t(0x202e), // Right-to-Left Override
     char16_t(0x2066), // Left-to-Right Isolate
     char16_t(0x2067), // Right-to-Left Isolate
     char16_t(0x2068), // First Strong Isolate
-    char16_t(0x2069)  // Pop Directional Isolate
+    char16_t(0x2069), // Pop Directional Isolate
+    char16_t(0)
   };
-  for (uint32_t i = 0; i < ArrayLength(unsafeBidiCharacters); ++i) {
-    mSuggestedFileName.ReplaceChar(unsafeBidiCharacters[i], '_');
-    mTempFileExtension.ReplaceChar(unsafeBidiCharacters[i], '_');
-  }
+  mSuggestedFileName.ReplaceChar(unsafeBidiCharacters, '_');
+  mTempFileExtension.ReplaceChar(unsafeBidiCharacters, '_');
 
   // Make sure extension is correct.
   EnsureSuggestedFileName();
 
   mBufferSize = Preferences::GetUint("network.buffer.cache.size", 4096);
 }
 
 nsExternalAppHandler::~nsExternalAppHandler()
--- a/widget/tests/chrome.ini
+++ b/widget/tests/chrome.ini
@@ -21,16 +21,17 @@ support-files = window_wheeltransaction.
 support-files = window_imestate_iframes.html
 [test_plugin_scroll_consistency.html]
 [test_composition_text_querycontent.xul]
 support-files = window_composition_text_querycontent.xul
 [test_input_events_on_deactive_window.xul]
 [test_position_on_resize.xul]
 [test_sizemode_events.xul]
 [test_bug760802.xul]
+[test_clipboard.xul]
 
 # Cocoa
 [test_native_menus.xul]
 skip-if = toolkit != "cocoa"
 support-files = native_menus_window.xul
 [test_native_mouse_mac.xul]
 skip-if = toolkit != "cocoa"
 support-files = native_mouse_mac_window.xul
new file mode 100644
--- /dev/null
+++ b/widget/tests/test_clipboard.xul
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=948065
+-->
+<window title="Mozilla Bug 948065"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        onload="initAndRunTests()">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <p id="display"></p>
+    <div id="content" style="display: none"></div>
+    <pre id="test"></pre>
+  </body>
+
+  <!-- test code goes here -->
+  <script class="testbody" type="application/javascript">
+  <![CDATA[
+
+  /** Test for Bug 948065 **/
+
+  const Cc = Components.classes;
+  const Ci = Components.interfaces;
+
+  const kIsMac = navigator.platform.indexOf("Mac") == 0;
+
+  function getLoadContext() {
+    return window.QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsILoadContext);
+  }
+
+  // Get clipboard data to paste.
+  function paste(clipboard) {
+    let trans = Cc['@mozilla.org/widget/transferable;1']
+                .createInstance(Ci.nsITransferable);
+    trans.init(getLoadContext());
+    trans.addDataFlavor("text/unicode");
+    clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
+    let str = {};
+    let length = {};
+    try {
+      trans.getTransferData('text/unicode', str, length);
+    } catch (e) {
+      str = '';
+    }
+    if (str) {
+      str = str.value.QueryInterface(Ci.nsISupportsString);
+      if (str) {
+        str = str.data.substring(0, length.value / 2);
+      }
+    }
+    return str;
+  }
+
+  function initAndRunTests() {
+    let clipboard = Cc['@mozilla.org/widget/clipboard;1']
+                    .getService(Ci.nsIClipboard);
+
+    // Test copy.
+    const data = "random number: " + Math.random();
+    let helper = Cc['@mozilla.org/widget/clipboardhelper;1']
+                 .getService(Ci.nsIClipboardHelper);
+    helper.copyString(data, document);
+    is(paste(clipboard), data, 'Data was successfully copied.');
+
+    // Test emptyClipboard, disabled for OSX because bug 666254
+    if (!kIsMac) {
+      clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard);
+      is(paste(clipboard), '', 'Data was successfully cleared.');
+    }
+  }
+
+  ]]>
+  </script>
+</window>
--- a/xpcom/reflect/xptcall/src/md/unix/moz.build
+++ b/xpcom/reflect/xptcall/src/md/unix/moz.build
@@ -209,22 +209,22 @@ if CONFIG['OS_TEST'] == 'powerpc':
     if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
         SOURCES += [
             'xptcinvoke_asm_ppc_linux.S',
             'xptcinvoke_ppc_linux.cpp',
             'xptcstubs_asm_ppc_linux.S',
             'xptcstubs_ppc_linux.cpp',
         ]
 
-if CONFIG['OS_TEST'] == 'powerpc64':
+if CONFIG['OS_TEST'] in ('powerpc64', 'powerpc64le'):
     if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
           SOURCES += [
-              'xptcinvoke_asm_ppc64_linux.s',
+              'xptcinvoke_asm_ppc64_linux.S',
               'xptcinvoke_ppc64_linux.cpp',
-              'xptcstubs_asm_ppc64_linux.s',
+              'xptcstubs_asm_ppc64_linux.S',
               'xptcstubs_ppc64_linux.cpp',
           ]
 
 if CONFIG['OS_TEST'] in ('macppc', 'bebox', 'ofppc', 'prep', 'amigappc'):
     if CONFIG['OS_ARCH'] == 'NetBSD':
         SOURCES += [
             'xptcinvoke_asm_ppc_netbsd.s',
             'xptcinvoke_ppc_netbsd.cpp',
rename from xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.s
rename to xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.S
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.S
@@ -12,90 +12,121 @@
 .set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
 .set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
 .set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
 .set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
 .set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
 .set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
 .set f30,30; .set f31,31
 
+# The ABI defines a fixed stack frame area of 4 doublewords (ELFv2)
+# or 6 doublewords (ELFv1); the last of these doublewords is used
+# as TOC pointer save area.  The fixed area is followed by a parameter
+# save area of 8 doublewords (used for vararg routines), followed
+# by space for parameters passed on the stack.
+#
+# We set STACK_TOC to the offset of the TOC pointer save area, and
+# STACK_PARAMS to the offset of the first on-stack parameter.
+
+#if _CALL_ELF == 2
+#define STACK_TOC      24
+#define STACK_PARAMS   96
+#else
+#define STACK_TOC      40
+#define STACK_PARAMS   112
+#endif
 
 #
 # NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 #                    uint32_t paramCount, nsXPTCVariant* params)
 #
 
+#if _CALL_ELF == 2
+        .section ".text"
+        .type   NS_InvokeByIndex,@function
+        .globl  NS_InvokeByIndex
+        .align 2
+NS_InvokeByIndex:
+0:      addis 2,12,(.TOC.-0b)@ha
+        addi 2,2,(.TOC.-0b)@l
+        .localentry NS_InvokeByIndex,.-NS_InvokeByIndex
+#else
         .section ".toc","aw"
         .section ".text"
         .align 2
         .globl  NS_InvokeByIndex
         .section ".opd","aw"
         .align 3
 NS_InvokeByIndex:
         .quad   .NS_InvokeByIndex,.TOC.@tocbase
         .previous
         .type   NS_InvokeByIndex,@function
 .NS_InvokeByIndex:
+#endif
         mflr    0
         std     0,16(r1)
 
         std     r29,-24(r1)
         std     r30,-16(r1)
         std     r31,-8(r1)
 
         mr      r29,r3                  # Save 'that' in r29
         mr      r30,r4                  # Save 'methodIndex' in r30
         mr      r31,r1                  # Save old frame
 
         # Allocate stack frame with space for params. Since at least the
         # first 7 parameters (not including 'that') will be in registers,
         # we don't actually need stack space for those. We must ensure
         # that the stack remains 16-byte aligned.
         #
-        #  | ..128-byte stack frame.. |     | 7 GP | 13 FP | 3 NV |
-        #  |               |(params)........| regs | regs  | regs |
-        # (r1)...........(+112)....(+128)
-        #                               (-23*8).(-16*8).(-3*8)..(r31)
+        #  | (fixed area + |                | 7 GP | 13 FP | 3 NV |
+        #  |  param. save) |(params)........| regs | regs  | regs |
+        # (r1)......(+STACK_PARAMS)...  (-23*8).(-16*8).(-3*8)..(r31)
 
         # +stack frame, -unused stack params, +regs storage, +1 for alignment
-        addi    r7,r5,((112/8)-7+7+13+3+1)
+        addi    r7,r5,((STACK_PARAMS/8)-7+7+13+3+1)
         rldicr  r7,r7,3,59              # multiply by 8 and mask with ~15
         neg     r7,r7
         stdux   r1,r1,r7
 
 
         # Call invoke_copy_to_stack(uint64_t* gpregs, double* fpregs,
         #                           uint32_t paramCount, nsXPTCVariant* s, 
         #                           uint64_t* d))
 
         # r5, r6 are passed through intact (paramCount, params)
-        # r7 (d) has to be r1+112 -- where parameters are passed on the stack.
+        # r7 (d) has to be r1+STACK_PARAMS
+        #        -- where parameters are passed on the stack.
         # r3, r4 are above that, easier to address from r31 than from r1
 
         subi    r3,r31,(23*8)           # r3 --> GPRS
         subi    r4,r31,(16*8)           # r4 --> FPRS
-        addi    r7,r1,112               # r7 --> params
+        addi    r7,r1,STACK_PARAMS      # r7 --> params
         bl      invoke_copy_to_stack
         nop
 
         # Set up to invoke function
 
         ld      r9,0(r29)               # vtable (r29 is 'that')
         mr      r3,r29                  # self is first arg, obviously
 
         sldi    r30,r30,3               # Find function descriptor 
         add     r9,r9,r30
-        ld      r9,0(r9)
+        ld      r12,0(r9)
+
+        std     r2,STACK_TOC(r1)        # Save r2 (TOC pointer)
 
-        ld      r0,0(r9)                # Actual address from fd.
-        std     r2,40(r1)               # Save r2 (TOC pointer)
-
+#if _CALL_ELF == 2
+        mtctr   r12
+#else
+        ld      r0,0(r12)               # Actual address from fd.
         mtctr   0
-        ld      r11,16(r9)              # Environment pointer from fd.
-        ld      r2,8(r9)                # TOC pointer from fd.
+        ld      r11,16(r12)             # Environment pointer from fd.
+        ld      r2,8(r12)               # TOC pointer from fd.
+#endif
 
         # Load FP and GP registers as required
         ld      r4, -(23*8)(r31) 
         ld      r5, -(22*8)(r31) 
         ld      r6, -(21*8)(r31) 
         ld      r7, -(20*8)(r31) 
         ld      r8, -(19*8)(r31) 
         ld      r9, -(18*8)(r31) 
@@ -112,21 +143,25 @@ NS_InvokeByIndex:
         lfd     f9, -(8*8)(r31)
         lfd     f10, -(7*8)(r31)
         lfd     f11, -(6*8)(r31)
         lfd     f12, -(5*8)(r31)
         lfd     f13, -(4*8)(r31)
 
         bctrl                           # Do it
 
-        ld      r2,40(r1)               # Load our own TOC pointer
+        ld      r2,STACK_TOC(r1)        # Load our own TOC pointer
         ld      r1,0(r1)                # Revert stack frame
         ld      0,16(r1)                # Reload lr
         ld      29,-24(r1)              # Restore NVGPRS
         ld      30,-16(r1)
         ld      31,-8(r1)
         mtlr    0
         blr
 
+#if _CALL_ELF == 2
+        .size   NS_InvokeByIndex,.-NS_InvokeByIndex
+#else
         .size   NS_InvokeByIndex,.-.NS_InvokeByIndex
+#endif
 
         # Magic indicating no need for an executable stack
         .section .note.GNU-stack, "", @progbits ; .previous
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc64_linux.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc64_linux.cpp
@@ -69,17 +69,19 @@ invoke_copy_to_stack(uint64_t* gpregs,
             else
                 *(double *)d = s->val.d;
         }
         else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
             if (i < FPR_COUNT) {
                 fpregs[i]   = s->val.f; // if passed in registers, floats are promoted to doubles
             } else {
                 float *p = (float *)d;
+#ifndef __LITTLE_ENDIAN__
                 p++;
+#endif
                 *p = s->val.f;
             }
         }
         else {
             if (i < GPR_COUNT)
                 gpregs[i] = tempu64;
             else
                 *d = tempu64;
rename from xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc64_linux.s
rename to xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc64_linux.S
--- a/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc64_linux.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc64_linux.S
@@ -12,16 +12,37 @@
 .set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
 .set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
 .set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
 .set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
 .set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
 .set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
 .set f30,30; .set f31,31