--- 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">
ت萁
+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
</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>
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(×tamp, &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(×tamp,
- &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(×tamp, &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(×tamp,
+ &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/tools/update-packaging/make_incremental_update.sh
+++ b/tools/update-packaging/make_incremental_update.sh
@@ -230,27 +230,16 @@ for ((i=0; $i<$num_newfiles; i=$i+1)); d
dir=$(dirname "$workdir/$f")
mkdir -p "$dir"
$BZIP2 -cz9 "$newdir/$f" > "$workdir/$f"
copy_perm "$newdir/$f" "$workdir/$f"
if check_for_add_if_not_update "$f"; then
- # Raise an exception if a new channel-prefs.js or update-settings.ini file
- # is found to prevent it from being to a new location like happened in
- # bug 756325.
- if [ `basename $f` = "channel-prefs.js" ]; then
- notice "new channel-prefs.js file found: $f"
- exit 1
- fi
- if [ `basename $f` = "update-settings.ini" ]; then
- notice "new update-settings.ini file found: $f"
- exit 1
- fi
make_add_if_not_instruction "$f" "$updatemanifestv3"
else
make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3"
fi
archivefiles="$archivefiles \"$f\""
done
--- a/tools/update-packaging/make_incremental_updates.py
+++ b/tools/update-packaging/make_incremental_updates.py
@@ -361,25 +361,16 @@ def create_partial_patch(from_dir_path,
# Not the same - calculate a patch
create_partial_patch_for_file(from_marfile_entry, to_marfile_entry, shas, patch_info)
# files in to_dir not in from_dir need to added
add_filenames = list(to_file_set - from_file_set)
add_filenames.sort(reverse=True)
for filename in add_filenames:
if os.path.basename(filename) in add_if_not_list:
- # Raise an exception if a new channel-prefs.js or
- # update-settings.ini file is found to prevent it from being
- # to a new location like happened in bug 756325.
- if os.path.basename(filename) == 'channel-prefs.js':
- raise Exception, "new channel-prefs.js file found: "+filename
-
- if os.path.basename(filename) == 'update-settings.ini':
- raise Exception, "new update-settings.ini file found: "+filename
-
create_add_if_not_patch_for_file(to_dir_hash[filename], patch_info)
else:
create_add_patch_for_file(to_dir_hash[filename], patch_info)
# files in from_dir not in to_dir need to be removed
remove_filenames = list(from_file_set - to_file_set)
remove_filenames.sort(reverse=True)
for filename in remove_filenames:
--- 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