Page MenuHomeWildfire Games

D3094.diff
No OneTemporary

Size
1 MB
Referenced Files
None
Subscribers
None

D3094.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: ps/trunk/build/premake/extern_libs5.lua
===================================================================
--- ps/trunk/build/premake/extern_libs5.lua
+++ ps/trunk/build/premake/extern_libs5.lua
@@ -533,9 +533,9 @@
},
spidermonkey = {
compile_settings = function()
- if _OPTIONS["with-system-mozjs45"] then
+ if _OPTIONS["with-system-mozjs52"] then
if not _OPTIONS["android"] then
- pkgconfig.add_includes("mozjs-45")
+ pkgconfig.add_includes("mozjs-52")
end
else
if os.istarget("windows") then
@@ -553,21 +553,21 @@
end
end,
link_settings = function()
- if _OPTIONS["with-system-mozjs45"] then
+ if _OPTIONS["with-system-mozjs52"] then
if _OPTIONS["android"] then
- links { "mozjs-45" }
+ links { "mozjs-52" }
else
- pkgconfig.add_links("mozjs-45")
+ pkgconfig.add_links("mozjs-52")
end
else
filter { "Debug", "action:vs2015" }
- links { "mozjs45-ps-debug-vc140" }
+ links { "mozjs52-ps-debug-vc140" }
filter { "Release", "action:vs2015" }
- links { "mozjs45-ps-release-vc140" }
+ links { "mozjs52-ps-release-vc140" }
filter { "Debug", "action:not vs*" }
- links { "mozjs45-ps-debug" }
+ links { "mozjs52-ps-debug" }
filter { "Release", "action:not vs*" }
- links { "mozjs45-ps-release" }
+ links { "mozjs52-ps-release" }
filter { }
add_source_lib_paths("spidermonkey")
end
Index: ps/trunk/build/premake/premake5.lua
===================================================================
--- ps/trunk/build/premake/premake5.lua
+++ ps/trunk/build/premake/premake5.lua
@@ -6,7 +6,7 @@
newoption { trigger = "jenkins-tests", description = "Configure CxxTest to use the XmlPrinter runner which produces Jenkins-compatible output" }
newoption { trigger = "minimal-flags", description = "Only set compiler/linker flags that are really needed. Has no effect on Windows builds" }
newoption { trigger = "outpath", description = "Location for generated project files" }
-newoption { trigger = "with-system-mozjs45", description = "Search standard paths for libmozjs45, instead of using bundled copy" }
+newoption { trigger = "with-system-mozjs52", description = "Search standard paths for libmozjs52, instead of using bundled copy" }
newoption { trigger = "with-system-nvtt", description = "Search standard paths for nvidia-texture-tools library, instead of using bundled copy" }
newoption { trigger = "without-audio", description = "Disable use of OpenAL/Ogg/Vorbis APIs" }
newoption { trigger = "without-lobby", description = "Disable the use of gloox and the multiplayer lobby" }
Index: ps/trunk/libraries/osx/build-osx-libs.sh
===================================================================
--- ps/trunk/libraries/osx/build-osx-libs.sh
+++ ps/trunk/libraries/osx/build-osx-libs.sh
@@ -48,12 +48,11 @@
SODIUM_VERSION="libsodium-1.0.18"
# --------------------------------------------------------------
# Bundled with the game:
-# * SpiderMonkey 45
+# * SpiderMonkey
# * NVTT
# * FCollada
# --------------------------------------------------------------
# We use suffixes here in order to force rebuilding when patching these libs
-SPIDERMONKEY_VERSION="mozjs-45.0.2+wildfiregames.2"
NVTT_VERSION="nvtt-2.1.1+wildfiregames.1"
FCOLLADA_VERSION="fcollada-3.05+wildfiregames.1"
# --------------------------------------------------------------
@@ -911,88 +910,16 @@
# be customized, so we build and install them from bundled sources
# --------------------------------------------------------------------
# SpiderMonkey - bundled, no download
-echo -e "Building SpiderMonkey..."
-
-LIB_VERSION="${SPIDERMONKEY_VERSION}"
-LIB_DIRECTORY="mozjs-45.0.2"
-LIB_ARCHIVE="$LIB_DIRECTORY.tar.bz2"
-
pushd ../source/spidermonkey/ > /dev/null
-if [[ "$force_rebuild" = "true" ]] || [[ ! -e .already-built ]] || [[ "$(<.already-built)" != "$LIB_VERSION" ]]
+if [[ "$force_rebuild" = "true" ]]
then
- INSTALL_DIR="$(pwd)"
- INCLUDE_DIR_DEBUG=$INSTALL_DIR/include-unix-debug
- INCLUDE_DIR_RELEASE=$INSTALL_DIR/include-unix-release
-
rm -f .already-built
- rm -f lib/*.a
- rm -rf $LIB_DIRECTORY $INCLUDE_DIR_DEBUG $INCLUDE_DIR_RELEASE
- tar -xf $LIB_ARCHIVE
-
- # Apply patches
- pushd $LIB_DIRECTORY
- . ../patch.sh
- popd
-
- pushd $LIB_DIRECTORY/js/src
-
- CONF_OPTS="--target=$ARCH-apple-darwin
- --prefix=${INSTALL_DIR}
- --enable-posix-nspr-emulation
- --with-system-zlib=${ZLIB_DIR}
- --disable-tests
- --disable-shared-js
- --disable-jemalloc
- --without-intl-api"
- # Change the default location where the tracelogger should store its output, which is /tmp/ on OSX.
- TLCXXFLAGS='-DTRACE_LOG_DIR="\"../../source/tools/tracelogger/\""'
- if [[ $MIN_OSX_VERSION && ${MIN_OSX_VERSION-_} ]]; then
- CONF_OPTS="$CONF_OPTS --enable-macos-target=$MIN_OSX_VERSION"
- fi
- if [[ $SYSROOT && ${SYSROOT-_} ]]; then
- CONF_OPTS="$CONF_OPTS --with-macosx-sdk=$SYSROOT"
- fi
+fi
- # We want separate debug/release versions of the library, so change their install name in the Makefile
- perl -i.bak -pe 's/(^STATIC_LIBRARY_NAME\s+=).*/$1'\''mozjs45-ps-debug'\''/' moz.build
- mkdir -p build-debug
- pushd build-debug
- (CC="clang" CXX="clang++" CXXFLAGS="${TLCXXFLAGS}" AR=ar CROSS_COMPILE=1 \
- ../configure $CONF_OPTS \
- --enable-debug \
- --disable-optimize \
- --enable-js-diagnostics \
- --enable-gczeal \
- && make ${JOBS}) || die "SpiderMonkey build failed"
- # js-config.h is different for debug and release builds, so we need different include directories for both
- mkdir -p $INCLUDE_DIR_DEBUG
- cp -R -L dist/include/* $INCLUDE_DIR_DEBUG/
- cp dist/sdk/lib/*.a $INSTALL_DIR/lib
- cp js/src/*.a $INSTALL_DIR/lib
- popd
- mv moz.build.bak moz.build
+# Use the regular build script for SM.
+JOBS="$JOBS" ZLIB_DIR="$ZLIB_DIR" ./build.sh
- perl -i.bak -pe 's/(^STATIC_LIBRARY_NAME\s+=).*/$1'\''mozjs45-ps-release'\''/' moz.build
- mkdir -p build-release
- pushd build-release
- (CC="clang" CXX="clang++" CXXFLAGS="${TLCXXFLAGS}" AR=ar CROSS_COMPILE=1 \
- ../configure $CONF_OPTS \
- --enable-optimize \
- && make ${JOBS}) || die "SpiderMonkey build failed"
- # js-config.h is different for debug and release builds, so we need different include directories for both
- mkdir -p $INCLUDE_DIR_RELEASE
- cp -R -L dist/include/* $INCLUDE_DIR_RELEASE/
- cp dist/sdk/lib/*.a $INSTALL_DIR/lib
- cp js/src/*.a $INSTALL_DIR/lib
- popd
- mv moz.build.bak moz.build
-
- popd
- echo "$LIB_VERSION" > .already-built
-else
- already_built
-fi
popd > /dev/null
# --------------------------------------------------------------
Index: ps/trunk/libraries/source/spidermonkey/DisableGCC9WerrorFormat.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/DisableGCC9WerrorFormat.diff
+++ ps/trunk/libraries/source/spidermonkey/DisableGCC9WerrorFormat.diff
@@ -0,0 +1,26 @@
+diff --git a/js/src/moz.build b/js/src/moz.build
+--- a/js/src/moz.build 2020-07-16 11:42:39.578932510 +0200
++++ b/js/src/moz.build 2020-07-16 11:45:18.937079912 +0200
+@@ -785,7 +785,7 @@
+ DEFINES['FFI_BUILDING'] = True
+
+ if CONFIG['GNU_CXX']:
+- CXXFLAGS += ['-Wno-shadow', '-Werror=format']
++ CXXFLAGS += ['-Wno-shadow']
+
+ # Suppress warnings in third-party code.
+ if CONFIG['CLANG_CXX']:
+diff --git a/js/src/shell/moz.build b/js/src/shell/moz.build
+--- a/js/src/shell/moz.build 2020-07-16 11:46:16.786621311 +0200
++++ b/js/src/shell/moz.build 2020-07-16 11:46:35.616493037 +0200
+@@ -51,7 +51,7 @@
+ ]
+
+ if CONFIG['GNU_CXX']:
+- CXXFLAGS += ['-Wno-shadow', '-Werror=format']
++ CXXFLAGS += ['-Wno-shadow']
+
+ # This is intended as a temporary workaround to enable VS2015.
+ if CONFIG['_MSC_VER']:
+
+
Index: ps/trunk/libraries/source/spidermonkey/ExportJSPropertyDescriptor.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/ExportJSPropertyDescriptor.diff
+++ ps/trunk/libraries/source/spidermonkey/ExportJSPropertyDescriptor.diff
@@ -1,26 +0,0 @@
-diff --git a/js/src/jsapi.h b/js/src/jsapi.h
-index 29406243..2370457f 100644
---- a/js/src/jsapi.h
-+++ b/js/src/jsapi.h
-@@ -2399,7 +2399,7 @@ JS_FreezeObject(JSContext* cx, JS::Handle<JSObject*> obj);
-
- /*** Property descriptors ************************************************************************/
-
--struct JSPropertyDescriptor : public JS::Traceable {
-+struct JS_PUBLIC_API(JSPropertyDescriptor) : public JS::Traceable {
- JSObject* obj;
- unsigned attrs;
- JSGetterOp getter;
-diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h
-index ba592525..3c185527 100644
---- a/js/src/jspubtd.h
-+++ b/js/src/jspubtd.h
-@@ -97,7 +97,7 @@ struct JSFunctionSpec;
- struct JSLocaleCallbacks;
- struct JSObjectMap;
- struct JSPrincipals;
--struct JSPropertyDescriptor;
-+struct JS_PUBLIC_API(JSPropertyDescriptor);
- struct JSPropertyName;
- struct JSPropertySpec;
- struct JSRuntime;
Index: ps/trunk/libraries/source/spidermonkey/FixLinking.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/FixLinking.diff
+++ ps/trunk/libraries/source/spidermonkey/FixLinking.diff
@@ -1,49 +0,0 @@
-From dcf520da15d940c900d7e8ffd5a9b05427c54dc8 Mon Sep 17 00:00:00 2001
-From: Philip Chimento <philip.chimento@gmail.com>
-Date: Wed, 5 Jul 2017 22:47:44 -0700
-Subject: [PATCH 4/9] headers: Fix symbols visibility
-
-Some symbols that need to be public are not marked as such.
----
- js/public/Utility.h | 2 +-
- js/src/jsalloc.h | 4 +++-
- 2 files changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/js/public/Utility.h b/js/public/Utility.h
-index 75214c32..f50fd8dd 100644
---- a/js/public/Utility.h
-+++ b/js/public/Utility.h
-@@ -77,7 +77,7 @@ enum ThreadType {
- # if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
- extern bool InitThreadType(void);
- extern void SetThreadType(ThreadType);
--extern uint32_t GetThreadType(void);
-+extern JS_FRIEND_API(uint32_t) GetThreadType(void);
- # else
- inline bool InitThreadType(void) { return true; }
- inline void SetThreadType(ThreadType t) {};
-diff --git a/js/src/jsalloc.h b/js/src/jsalloc.h
-index b9ae5190..234ea9dc 100644
---- a/js/src/jsalloc.h
-+++ b/js/src/jsalloc.h
-@@ -17,6 +17,8 @@
- #include "js/TypeDecls.h"
- #include "js/Utility.h"
-
-+extern JS_PUBLIC_API(void) JS_ReportOutOfMemory(JSContext* cx);
-+
- namespace js {
-
- enum class AllocFunction {
-@@ -130,7 +132,7 @@ class TempAllocPolicy
-
- bool checkSimulatedOOM() const {
- if (js::oom::ShouldFailWithOOM()) {
-- js::ReportOutOfMemory(reinterpret_cast<ExclusiveContext*>(cx_));
-+ JS_ReportOutOfMemory(reinterpret_cast<JSContext*>(cx_));
- return false;
- }
-
---
-2.11.0 (Apple Git-81)
-
Index: ps/trunk/libraries/source/spidermonkey/FixMSVCBuild.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/FixMSVCBuild.diff
+++ ps/trunk/libraries/source/spidermonkey/FixMSVCBuild.diff
@@ -0,0 +1,447 @@
+
+# HG changeset patch
+# User Vladimir Vukicevic <vladimir@pobox.com>
+# Date 1479240485 21600
+# Node ID 9822e0525b82bcca19078eab6532c8972977a156
+# Parent 07fa89dfac8390c8529181cbf818b6e5c1a75bf1
+Bug 1300925 - Change Intl.cpp stubs to an anonymous namespace. r=Waldo
+
+MozReview-Commit-ID: 9Ed1gglWsby
+
+diff --git a/js/src/builtin/Intl.cpp b/js/src/builtin/Intl.cpp
+--- a/js/src/builtin/Intl.cpp
++++ b/js/src/builtin/Intl.cpp
+@@ -69,26 +69,28 @@ using mozilla::PodCopy;
+ * against ICU. However, we still want to compile this code in order to prevent
+ * bit rot. The following stub implementations for ICU functions make this
+ * possible. The functions using them should never be called, so they assert
+ * and return error codes. Signatures adapted from ICU header files locid.h,
+ * numsys.h, ucal.h, ucol.h, udat.h, udatpg.h, uenum.h, unum.h; see the ICU
+ * directory for license.
+ */
+
++namespace {
++
+ typedef bool UBool;
+ typedef char16_t UChar;
+ typedef double UDate;
+
+ enum UErrorCode {
+ U_ZERO_ERROR,
+ U_BUFFER_OVERFLOW_ERROR,
+ };
+
+-static inline UBool
++inline UBool
+ U_FAILURE(UErrorCode code)
+ {
+ MOZ_CRASH("U_FAILURE: Intl API disabled");
+ }
+
+ inline const UChar*
+ Char16ToUChar(const char16_t* chars)
+ {
+@@ -96,37 +98,37 @@ Char16ToUChar(const char16_t* chars)
+ }
+
+ inline UChar*
+ Char16ToUChar(char16_t* chars)
+ {
+ MOZ_CRASH("Char16ToUChar: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ u_strlen(const UChar* s)
+ {
+ MOZ_CRASH("u_strlen: Intl API disabled");
+ }
+
+ struct UEnumeration;
+
+-static int32_t
++int32_t
+ uenum_count(UEnumeration* en, UErrorCode* status)
+ {
+ MOZ_CRASH("uenum_count: Intl API disabled");
+ }
+
+-static const char*
++const char*
+ uenum_next(UEnumeration* en, int32_t* resultLength, UErrorCode* status)
+ {
+ MOZ_CRASH("uenum_next: Intl API disabled");
+ }
+
+-static void
++void
+ uenum_close(UEnumeration* en)
+ {
+ MOZ_CRASH("uenum_close: Intl API disabled");
+ }
+
+ struct UCollator;
+
+ enum UColAttribute {
+@@ -151,54 +153,54 @@ enum UColAttributeValue {
+ };
+
+ enum UCollationResult {
+ UCOL_EQUAL = 0,
+ UCOL_GREATER = 1,
+ UCOL_LESS = -1
+ };
+
+-static int32_t
++int32_t
+ ucol_countAvailable()
+ {
+ MOZ_CRASH("ucol_countAvailable: Intl API disabled");
+ }
+
+-static const char*
++const char*
+ ucol_getAvailable(int32_t localeIndex)
+ {
+ MOZ_CRASH("ucol_getAvailable: Intl API disabled");
+ }
+
+-static UCollator*
++UCollator*
+ ucol_open(const char* loc, UErrorCode* status)
+ {
+ MOZ_CRASH("ucol_open: Intl API disabled");
+ }
+
+-static void
++void
+ ucol_setAttribute(UCollator* coll, UColAttribute attr, UColAttributeValue value, UErrorCode* status)
+ {
+ MOZ_CRASH("ucol_setAttribute: Intl API disabled");
+ }
+
+-static UCollationResult
++UCollationResult
+ ucol_strcoll(const UCollator* coll, const UChar* source, int32_t sourceLength,
+ const UChar* target, int32_t targetLength)
+ {
+ MOZ_CRASH("ucol_strcoll: Intl API disabled");
+ }
+
+-static void
++void
+ ucol_close(UCollator* coll)
+ {
+ MOZ_CRASH("ucol_close: Intl API disabled");
+ }
+
+-static UEnumeration*
++UEnumeration*
+ ucol_getKeywordValuesForLocale(const char* key, const char* locale, UBool commonlyUsed,
+ UErrorCode* status)
+ {
+ MOZ_CRASH("ucol_getKeywordValuesForLocale: Intl API disabled");
+ }
+
+ struct UParseError;
+ struct UFieldPosition;
+@@ -227,76 +229,76 @@ enum UNumberFormatAttribute {
+ UNUM_MIN_SIGNIFICANT_DIGITS,
+ UNUM_MAX_SIGNIFICANT_DIGITS,
+ };
+
+ enum UNumberFormatTextAttribute {
+ UNUM_CURRENCY_CODE,
+ };
+
+-static int32_t
++int32_t
+ unum_countAvailable()
+ {
+ MOZ_CRASH("unum_countAvailable: Intl API disabled");
+ }
+
+-static const char*
++const char*
+ unum_getAvailable(int32_t localeIndex)
+ {
+ MOZ_CRASH("unum_getAvailable: Intl API disabled");
+ }
+
+-static UNumberFormat*
++UNumberFormat*
+ unum_open(UNumberFormatStyle style, const UChar* pattern, int32_t patternLength,
+ const char* locale, UParseError* parseErr, UErrorCode* status)
+ {
+ MOZ_CRASH("unum_open: Intl API disabled");
+ }
+
+-static void
++void
+ unum_setAttribute(UNumberFormat* fmt, UNumberFormatAttribute attr, int32_t newValue)
+ {
+ MOZ_CRASH("unum_setAttribute: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ unum_formatDouble(const UNumberFormat* fmt, double number, UChar* result,
+ int32_t resultLength, UFieldPosition* pos, UErrorCode* status)
+ {
+ MOZ_CRASH("unum_formatDouble: Intl API disabled");
+ }
+
+-static void
++void
+ unum_close(UNumberFormat* fmt)
+ {
+ MOZ_CRASH("unum_close: Intl API disabled");
+ }
+
+-static void
++void
+ unum_setTextAttribute(UNumberFormat* fmt, UNumberFormatTextAttribute tag, const UChar* newValue,
+ int32_t newValueLength, UErrorCode* status)
+ {
+ MOZ_CRASH("unum_setTextAttribute: Intl API disabled");
+ }
+
+ typedef void* UNumberingSystem;
+
+-static UNumberingSystem*
++UNumberingSystem*
+ unumsys_open(const char* locale, UErrorCode* status)
+ {
+ MOZ_CRASH("unumsys_open: Intl API disabled");
+ }
+
+-static const char*
++const char*
+ unumsys_getName(const UNumberingSystem* unumsys)
+ {
+ MOZ_CRASH("unumsys_getName: Intl API disabled");
+ }
+
+-static void
++void
+ unumsys_close(UNumberingSystem* unumsys)
+ {
+ MOZ_CRASH("unumsys_close: Intl API disabled");
+ }
+
+ typedef void* UCalendar;
+
+ enum UCalendarType {
+@@ -350,97 +352,97 @@ enum UCalendarDateFields {
+ UCAL_EXTENDED_YEAR,
+ UCAL_JULIAN_DAY,
+ UCAL_MILLISECONDS_IN_DAY,
+ UCAL_IS_LEAP_MONTH,
+ UCAL_FIELD_COUNT,
+ UCAL_DAY_OF_MONTH = UCAL_DATE
+ };
+
+-static UCalendar*
++UCalendar*
+ ucal_open(const UChar* zoneID, int32_t len, const char* locale,
+ UCalendarType type, UErrorCode* status)
+ {
+ MOZ_CRASH("ucal_open: Intl API disabled");
+ }
+
+-static const char*
++const char*
+ ucal_getType(const UCalendar* cal, UErrorCode* status)
+ {
+ MOZ_CRASH("ucal_getType: Intl API disabled");
+ }
+
+-static UEnumeration*
++UEnumeration*
+ ucal_getKeywordValuesForLocale(const char* key, const char* locale,
+ UBool commonlyUsed, UErrorCode* status)
+ {
+ MOZ_CRASH("ucal_getKeywordValuesForLocale: Intl API disabled");
+ }
+
+-static void
++void
+ ucal_close(UCalendar* cal)
+ {
+ MOZ_CRASH("ucal_close: Intl API disabled");
+ }
+
+-static UCalendarWeekdayType
++UCalendarWeekdayType
+ ucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status)
+ {
+ MOZ_CRASH("ucal_getDayOfWeekType: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ ucal_getAttribute(const UCalendar* cal,
+ UCalendarAttribute attr)
+ {
+ MOZ_CRASH("ucal_getAttribute: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ ucal_get(const UCalendar *cal, UCalendarDateFields field, UErrorCode *status)
+ {
+ MOZ_CRASH("ucal_get: Intl API disabled");
+ }
+
+-static UEnumeration*
++UEnumeration*
+ ucal_openTimeZones(UErrorCode* status)
+ {
+ MOZ_CRASH("ucal_openTimeZones: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ ucal_getCanonicalTimeZoneID(const UChar* id, int32_t len, UChar* result, int32_t resultCapacity,
+ UBool* isSystemID, UErrorCode* status)
+ {
+ MOZ_CRASH("ucal_getCanonicalTimeZoneID: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* status)
+ {
+ MOZ_CRASH("ucal_getDefaultTimeZone: Intl API disabled");
+ }
+
+ typedef void* UDateTimePatternGenerator;
+
+-static UDateTimePatternGenerator*
++UDateTimePatternGenerator*
+ udatpg_open(const char* locale, UErrorCode* pErrorCode)
+ {
+ MOZ_CRASH("udatpg_open: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ udatpg_getBestPattern(UDateTimePatternGenerator* dtpg, const UChar* skeleton,
+ int32_t length, UChar* bestPattern, int32_t capacity,
+ UErrorCode* pErrorCode)
+ {
+ MOZ_CRASH("udatpg_getBestPattern: Intl API disabled");
+ }
+
+-static void
++void
+ udatpg_close(UDateTimePatternGenerator* dtpg)
+ {
+ MOZ_CRASH("udatpg_close: Intl API disabled");
+ }
+
+ typedef void* UCalendar;
+ typedef void* UDateFormat;
+
+@@ -486,87 +488,89 @@ enum UDateFormatField {
+ UDAT_FIELD_COUNT = 38
+ };
+
+ enum UDateFormatStyle {
+ UDAT_PATTERN = -2,
+ UDAT_IGNORE = UDAT_PATTERN
+ };
+
+-static int32_t
++int32_t
+ udat_countAvailable()
+ {
+ MOZ_CRASH("udat_countAvailable: Intl API disabled");
+ }
+
+-static const char*
++const char*
+ udat_getAvailable(int32_t localeIndex)
+ {
+ MOZ_CRASH("udat_getAvailable: Intl API disabled");
+ }
+
+-static UDateFormat*
++UDateFormat*
+ udat_open(UDateFormatStyle timeStyle, UDateFormatStyle dateStyle, const char* locale,
+ const UChar* tzID, int32_t tzIDLength, const UChar* pattern,
+ int32_t patternLength, UErrorCode* status)
+ {
+ MOZ_CRASH("udat_open: Intl API disabled");
+ }
+
+-static const UCalendar*
++const UCalendar*
+ udat_getCalendar(const UDateFormat* fmt)
+ {
+ MOZ_CRASH("udat_getCalendar: Intl API disabled");
+ }
+
+-static void
++void
+ ucal_setGregorianChange(UCalendar* cal, UDate date, UErrorCode* pErrorCode)
+ {
+ MOZ_CRASH("ucal_setGregorianChange: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ udat_format(const UDateFormat* format, UDate dateToFormat, UChar* result,
+ int32_t resultLength, UFieldPosition* position, UErrorCode* status)
+ {
+ MOZ_CRASH("udat_format: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ udat_formatForFields(const UDateFormat* format, UDate dateToFormat,
+ UChar* result, int32_t resultLength, UFieldPositionIterator* fpositer,
+ UErrorCode* status)
+ {
+ MOZ_CRASH("udat_formatForFields: Intl API disabled");
+ }
+
+-static UFieldPositionIterator*
++UFieldPositionIterator*
+ ufieldpositer_open(UErrorCode* status)
+ {
+ MOZ_CRASH("ufieldpositer_open: Intl API disabled");
+ }
+
+-static void
++void
+ ufieldpositer_close(UFieldPositionIterator* fpositer)
+ {
+ MOZ_CRASH("ufieldpositer_close: Intl API disabled");
+ }
+
+-static int32_t
++int32_t
+ ufieldpositer_next(UFieldPositionIterator* fpositer, int32_t* beginIndex, int32_t* endIndex)
+ {
+ MOZ_CRASH("ufieldpositer_next: Intl API disabled");
+ }
+
+-static void
++void
+ udat_close(UDateFormat* format)
+ {
+ MOZ_CRASH("udat_close: Intl API disabled");
+ }
+
++} // anonymous namespace
++
+ #endif
+
+
+ /******************** Common to Intl constructors ********************/
+
+ static bool
+ IntlInitialize(JSContext* cx, HandleObject obj, Handle<PropertyName*> initializer,
+ HandleValue locales, HandleValue options)
+
Index: ps/trunk/libraries/source/spidermonkey/FixMozglue.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/FixMozglue.diff
+++ ps/trunk/libraries/source/spidermonkey/FixMozglue.diff
@@ -0,0 +1,70 @@
+From 4de4b45ff25690aabd5797928b66005555379ffa Mon Sep 17 00:00:00 2001
+From: Till Schneidereit <till@tillschneidereit.net>
+Date: Thu, 1 Oct 2015 12:59:09 +0200
+Subject: [PATCH 5/9] Disable MOZ_GLUE_IN_PROGRAM in stand-alone builds on all
+ platforms
+
+Otherwise, build fails not being able to find HashBytes.
+
+Patch ported forward to mozjs52 by Philip Chimento
+<philip.chimento@gmail.com>.
+
+https://bugzilla.mozilla.org/show_bug.cgi?id=1176787
+---
+ js/src/old-configure.in | 23 ++++++++++++++---------
+ mozglue/build/moz.build | 2 +-
+ 2 files changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/js/src/old-configure.in b/js/src/old-configure.in
+index c40eb962..336e1aa7 100644
+--- a/js/src/old-configure.in
++++ b/js/src/old-configure.in
+@@ -1620,16 +1620,21 @@ dnl ========================================================
+ dnl = Enable jemalloc
+ dnl ========================================================
+
+-case "${OS_TARGET}" in
+-Android|WINNT|Darwin)
++dnl In stand-alone builds we always only want to link executables against mozglue.
++if test "$JS_STANDALONE"; then
+ MOZ_GLUE_IN_PROGRAM=
+- ;;
+-*)
+- dnl On !Android !Windows !OSX, we only want to link executables against mozglue
+- MOZ_GLUE_IN_PROGRAM=1
+- AC_DEFINE(MOZ_GLUE_IN_PROGRAM)
+- ;;
+-esac
++else
++ case "${OS_TARGET}" in
++ Android|WINNT|Darwin)
++ MOZ_GLUE_IN_PROGRAM=
++ ;;
++ *)
++ dnl On !Android !Windows !OSX, we only want to link executables against mozglue
++ MOZ_GLUE_IN_PROGRAM=1
++ AC_DEFINE(MOZ_GLUE_IN_PROGRAM)
++ ;;
++ esac
++fi
+
+ if test "$MOZ_MEMORY"; then
+ if test "x$MOZ_DEBUG" = "x1"; then
+diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build
+index d289747785a1..fd1e78a543ed 100644
+--- a/mozglue/build/moz.build
++++ b/mozglue/build/moz.build
+@@ -4,9 +4,12 @@
+ # 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/.
+
++if CONFIG['JS_STANDALONE']:
++ Library('mozglue')
++ FINAL_LIBRARY = 'js'
+ # Build mozglue as a shared lib on Windows, OSX and Android.
+ # If this is ever changed, update MOZ_SHARED_MOZGLUE in browser/installer/Makefile.in
+-if CONFIG['OS_TARGET'] in ('WINNT', 'Darwin', 'Android'):
++elif CONFIG['OS_TARGET'] in ('WINNT', 'Darwin', 'Android'):
+ SharedLibrary('mozglue')
+ else:
+ Library('mozglue')
Index: ps/trunk/libraries/source/spidermonkey/FixMozglueStatic.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/FixMozglueStatic.diff
+++ ps/trunk/libraries/source/spidermonkey/FixMozglueStatic.diff
@@ -1,20 +0,0 @@
-diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build
-index 58e2db6..1cfb504 100644
---- a/mozglue/build/moz.build
-+++ b/mozglue/build/moz.build
-@@ -4,12 +4,9 @@
- # 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/.
-
--# Build mozglue as a shared lib on Windows, OSX and Android.
--# If this is ever changed, update MOZ_SHARED_MOZGLUE in browser/installer/Makefile.in
--if CONFIG['OS_TARGET'] in ('WINNT', 'Darwin', 'Android'):
-- SharedLibrary('mozglue')
--else:
-- Library('mozglue')
-+# Build mozglue as a static lib into js for 0 A.D.
-+Library('mozglue')
-+FINAL_LIBRARY = 'js'
-
- if not CONFIG['MOZ_CRT']:
- SDK_LIBRARY = True
Index: ps/trunk/libraries/source/spidermonkey/FixNonx86.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/FixNonx86.diff
+++ ps/trunk/libraries/source/spidermonkey/FixNonx86.diff
@@ -1,229 +0,0 @@
-diff --git a/js/src/gc/Memory.cpp b/js/src/gc/Memory.cpp
---- a/js/src/gc/Memory.cpp
-+++ b/js/src/gc/Memory.cpp
-@@ -430,17 +430,17 @@ InitMemorySubsystem()
- if (pageSize == 0)
- pageSize = allocGranularity = size_t(sysconf(_SC_PAGESIZE));
- }
-
- static inline void*
- MapMemoryAt(void* desired, size_t length, int prot = PROT_READ | PROT_WRITE,
- int flags = MAP_PRIVATE | MAP_ANON, int fd = -1, off_t offset = 0)
- {
--#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__))
-+#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__)) || defined(__aarch64__)
- MOZ_ASSERT(0xffff800000000000ULL & (uintptr_t(desired) + length - 1) == 0);
- #endif
- void* region = mmap(desired, length, prot, flags, fd, offset);
- if (region == MAP_FAILED)
- return nullptr;
- /*
- * mmap treats the given address as a hint unless the MAP_FIXED flag is
- * used (which isn't usually what you want, as this overrides existing
-@@ -480,16 +480,51 @@ MapMemory(size_t length, int prot = PROT
- * as out of memory.
- */
- if ((uintptr_t(region) + (length - 1)) & 0xffff800000000000) {
- if (munmap(region, length))
- MOZ_ASSERT(errno == ENOMEM);
- return nullptr;
- }
- return region;
-+#elif defined(__aarch64__)
-+ /*
-+ * There might be similar virtual address issue on arm64 which depends on
-+ * hardware and kernel configurations. But the work around is slightly
-+ * different due to the different mmap behavior.
-+ *
-+ * TODO: Merge with the above code block if this implementation works for
-+ * ia64 and sparc64.
-+ */
-+ const uintptr_t start = UINT64_C(0x0000070000000000);
-+ const uintptr_t end = UINT64_C(0x0000800000000000);
-+ const uintptr_t step = js::gc::ChunkSize;
-+ /*
-+ * Optimization options if there are too many retries in practice:
-+ * 1. Examine /proc/self/maps to find an available address. This file is
-+ * not always available, however. In addition, even if we examine
-+ * /proc/self/maps, we may still need to retry several times due to
-+ * racing with other threads.
-+ * 2. Use a global/static variable with lock to track the addresses we have
-+ * allocated or tried.
-+ */
-+ uintptr_t hint;
-+ void* region = MAP_FAILED;
-+ for (hint = start; region == MAP_FAILED && hint + length <= end; hint += step) {
-+ region = mmap((void*)hint, length, prot, flags, fd, offset);
-+ if (region != MAP_FAILED) {
-+ if ((uintptr_t(region) + (length - 1)) & 0xffff800000000000) {
-+ if (munmap(region, length)) {
-+ MOZ_ASSERT(errno == ENOMEM);
-+ }
-+ region = MAP_FAILED;
-+ }
-+ }
-+ }
-+ return region == MAP_FAILED ? nullptr : region;
- #else
- void* region = MozTaggedAnonymousMmap(nullptr, length, prot, flags, fd, offset, "js-gc-heap");
- if (region == MAP_FAILED)
- return nullptr;
- return region;
- #endif
- }
-
-diff --git a/js/src/jit/none/MacroAssembler-none.h b/js/src/jit/none/MacroAssembler-none.h
---- a/js/src/jit/none/MacroAssembler-none.h
-+++ b/js/src/jit/none/MacroAssembler-none.h
-@@ -254,16 +254,18 @@ class MacroAssemblerNone : public Assemb
- template <typename T, typename S> void branchSub32(Condition, T, S, Label*) { MOZ_CRASH(); }
- template <typename T, typename S> void branchPtr(Condition, T, S, Label*) { MOZ_CRASH(); }
- template <typename T, typename S> void branchTestPtr(Condition, T, S, Label*) { MOZ_CRASH(); }
- template <typename T, typename S> void branchDouble(DoubleCondition, T, S, Label*) { MOZ_CRASH(); }
- template <typename T, typename S> void branchFloat(DoubleCondition, T, S, Label*) { MOZ_CRASH(); }
- template <typename T, typename S> void branchPrivatePtr(Condition, T, S, Label*) { MOZ_CRASH(); }
- template <typename T, typename S> void decBranchPtr(Condition, T, S, Label*) { MOZ_CRASH(); }
- template <typename T, typename S> void branchTest64(Condition, T, T, S, Label*) { MOZ_CRASH(); }
-+ template <typename T, typename S> void branch64(Condition, T, S, Label*) { MOZ_CRASH(); }
-+ template <typename T, typename S> void branch64(Condition, T, T, S, Label*) { MOZ_CRASH(); }
- template <typename T, typename S> void mov(T, S) { MOZ_CRASH(); }
- template <typename T, typename S> void movq(T, S) { MOZ_CRASH(); }
- template <typename T, typename S> void movePtr(T, S) { MOZ_CRASH(); }
- template <typename T, typename S> void move32(T, S) { MOZ_CRASH(); }
- template <typename T, typename S> void moveFloat32(T, S) { MOZ_CRASH(); }
- template <typename T, typename S> void moveDouble(T, S) { MOZ_CRASH(); }
- template <typename T, typename S> void move64(T, S) { MOZ_CRASH(); }
- template <typename T> CodeOffset movWithPatch(T, Register) { MOZ_CRASH(); }
-
-diff --git a/js/src/jsapi-tests/testGCAllocator.cpp b/js/src/jsapi-tests/testGCAllocator.cpp
---- a/js/src/jsapi-tests/testGCAllocator.cpp
-+++ b/js/src/jsapi-tests/testGCAllocator.cpp
-@@ -307,48 +307,72 @@ void* mapMemoryAt(void* desired, size_t
- void* mapMemory(size_t length) { return nullptr; }
- void unmapPages(void* p, size_t size) { }
-
- #elif defined(XP_UNIX)
-
- void*
- mapMemoryAt(void* desired, size_t length)
- {
--#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__))
-+#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__)) || defined(__aarch64__)
- MOZ_RELEASE_ASSERT(0xffff800000000000ULL & (uintptr_t(desired) + length - 1) == 0);
- #endif
- void* region = mmap(desired, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
- if (region == MAP_FAILED)
- return nullptr;
- if (region != desired) {
- if (munmap(region, length))
- MOZ_RELEASE_ASSERT(errno == ENOMEM);
- return nullptr;
- }
- return region;
- }
-
- void*
- mapMemory(size_t length)
- {
-- void* hint = nullptr;
-+ int prot = PROT_READ | PROT_WRITE;
-+ int flags = MAP_PRIVATE | MAP_ANON;
-+ int fd = -1;
-+ off_t offset = 0;
-+ // The test code must be aligned with the implementation in gc/Memory.cpp.
- #if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__))
-- hint = (void*)0x0000070000000000ULL;
--#endif
-- void* region = mmap(hint, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
-+ void* region = mmap((void*)0x0000070000000000, length, prot, flags, fd, offset);
- if (region == MAP_FAILED)
- return nullptr;
--#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__))
-- if ((uintptr_t(region) + (length - 1)) & 0xffff800000000000ULL) {
-+ if ((uintptr_t(region) + (length - 1)) & 0xffff800000000000) {
- if (munmap(region, length))
- MOZ_RELEASE_ASSERT(errno == ENOMEM);
- return nullptr;
- }
-+ return region;
-+#elif defined(__aarch64__)
-+ const uintptr_t start = UINT64_C(0x0000070000000000);
-+ const uintptr_t end = UINT64_C(0x0000800000000000);
-+ const uintptr_t step = js::gc::ChunkSize;
-+ uintptr_t hint;
-+ void* region = MAP_FAILED;
-+ for (hint = start; region == MAP_FAILED && hint + length <= end; hint += step) {
-+ region = mmap((void*)hint, length, prot, flags, fd, offset);
-+ if (region != MAP_FAILED) {
-+ if ((uintptr_t(region) + (length - 1)) & 0xffff800000000000) {
-+ if (munmap(region, length)) {
-+ MOZ_RELEASE_ASSERT(errno == ENOMEM);
-+ }
-+ region = MAP_FAILED;
-+ }
-+ }
-+ }
-+ return region == MAP_FAILED ? nullptr : region;
-+#else
-+ void* region = mmap(nullptr, length, prot, flags, fd, offset);
-+ if (region == MAP_FAILED)
-+ return nullptr;
-+ return region;
- #endif
-- return region;
- }
-
- void
- unmapPages(void* p, size_t size)
- {
- if (munmap(p, size))
- MOZ_RELEASE_ASSERT(errno == ENOMEM);
- }
-
-diff --git a/js/src/jit/AtomicOperations.h b/js/src/jit/AtomicOperations.h
-index 8606a18..60af775 100644
---- a/js/src/jit/AtomicOperations.h
-+++ b/js/src/jit/AtomicOperations.h
-@@ -302,7 +302,9 @@ AtomicOperations::isLockfree(int32_t size)
- # include "jit/mips-shared/AtomicOperations-mips-shared.h"
- #elif defined(__ppc64__) || defined(__PPC64_) \
- || defined(__ppc64le__) || defined(__PPC64LE__) \
-- || defined(__ppc__) || defined(__PPC__)
-+ || defined(__ppc__) || defined(__PPC__) \
-+ || defined(__aarch64__) || defined(__arm__) \
-+ || defined(__s390x__) || defined(__mips__)
- # include "jit/none/AtomicOperations-ppc.h"
- #elif defined(JS_CODEGEN_NONE)
- # include "jit/none/AtomicOperations-none.h"
-
-diff --git a/js/src/tests/js1_5/Array/regress-157652.js b/js/src/tests/js1_5/Array/regress-157652.js
-index 0bdba8f..9d77802 100644
---- a/js/src/tests/js1_5/Array/regress-157652.js
-+++ b/js/src/tests/js1_5/Array/regress-157652.js
-@@ -1,4 +1,4 @@
--// |reftest| skip-if(xulRuntime.XPCOMABI.match(/x86_64/)||Android) -- No test results
-+// |reftest| skip-if(xulRuntime.XPCOMABI.match(/x86_64|aarch64|ppc64|ppc64le|s390x/)||Android) -- No test results
- /* -*- 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
-diff --git a/js/src/tests/js1_5/Array/regress-330812.js b/js/src/tests/js1_5/Array/regress-330812.js
-index 3a39297..c48f4c8 100644
---- a/js/src/tests/js1_5/Array/regress-330812.js
-+++ b/js/src/tests/js1_5/Array/regress-330812.js
-@@ -1,4 +1,4 @@
--// |reftest| skip-if(xulRuntime.XPCOMABI.match(/x86_64/)||Android) -- No test results
-+// |reftest| skip-if(xulRuntime.XPCOMABI.match(/x86_64|aarch64|ppc64|ppc64le|s390x/)||Android) -- No test results
- /* -*- 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
-diff --git a/js/src/tests/js1_5/Regress/regress-422348.js b/js/src/tests/js1_5/Regress/regress-422348.js
-index f2443c2..7ae83f4 100644
---- a/js/src/tests/js1_5/Regress/regress-422348.js
-+++ b/js/src/tests/js1_5/Regress/regress-422348.js
-@@ -1,4 +1,4 @@
--// |reftest| skip-if(xulRuntime.XPCOMABI.match(/x86_64/)) -- On 64-bit, takes forever rather than throwing
-+// |reftest| skip-if(xulRuntime.XPCOMABI.match(/x86_64|aarch64|ppc64|ppc64le|s390x/)) -- On 64-bit, takes forever rather than throwing
- /* -*- 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
-
Index: ps/trunk/libraries/source/spidermonkey/FixTracelogger.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/FixTracelogger.diff
+++ ps/trunk/libraries/source/spidermonkey/FixTracelogger.diff
@@ -1,223 +0,0 @@
-diff --git a/js/src/jit-test/tests/tracelogger/bug1266649.js b/js/src/jit-test/tests/tracelogger/bug1266649.js
-new file mode 100644
-index 0000000..2878e0c
---- /dev/null
-+++ b/js/src/jit-test/tests/tracelogger/bug1266649.js
-@@ -0,0 +1,8 @@
-+
-+var du = new Debugger();
-+if (typeof du.setupTraceLogger === "function") {
-+ du.setupTraceLogger({
-+ Scripts: true
-+ })
-+ oomTest(() => function(){});
-+}
-diff --git a/js/src/vm/TraceLogging.cpp b/js/src/vm/TraceLogging.cpp
-index ce7acc6..8f8aca4 100644
---- a/js/src/vm/TraceLogging.cpp
-+++ b/js/src/vm/TraceLogging.cpp
-@@ -393,14 +393,14 @@ TraceLoggerThread::getOrCreateEventPayload(const char* text)
- return nullptr;
- }
-
-- if (!pointerMap.add(p, text, payload))
-- return nullptr;
--
- if (graph.get())
- graph->addTextId(textId, str);
-
- nextTextId++;
-
-+ if (!pointerMap.add(p, text, payload))
-+ return nullptr;
-+
- return payload;
- }
-
-@@ -420,10 +420,13 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f
- if (!traceLoggerState->isTextIdEnabled(type))
- return getOrCreateEventPayload(type);
-
-- PointerHashMap::AddPtr p = pointerMap.lookupForAdd(ptr);
-- if (p) {
-- MOZ_ASSERT(p->value()->textId() < nextTextId); // Sanity check.
-- return p->value();
-+ PointerHashMap::AddPtr p;
-+ if (ptr) {
-+ p = pointerMap.lookupForAdd(ptr);
-+ if (p) {
-+ MOZ_ASSERT(p->value()->textId() < nextTextId); // Sanity check.
-+ return p->value();
-+ }
- }
-
- // Compute the length of the string to create.
-@@ -455,14 +458,16 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f
- return nullptr;
- }
-
-- if (!pointerMap.add(p, ptr, payload))
-- return nullptr;
--
- if (graph.get())
- graph->addTextId(textId, str);
-
- nextTextId++;
-
-+ if (ptr) {
-+ if (!pointerMap.add(p, ptr, payload))
-+ return nullptr;
-+ }
-+
- return payload;
- }
-
-@@ -477,7 +482,7 @@ TraceLoggerEventPayload*
- TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type,
- const JS::ReadOnlyCompileOptions& script)
- {
-- return getOrCreateEventPayload(type, script.filename(), script.lineno, script.column, &script);
-+ return getOrCreateEventPayload(type, script.filename(), script.lineno, script.column, nullptr);
- }
-
- void
-@@ -550,19 +555,42 @@ TraceLoggerThread::log(uint32_t id)
- return;
-
- MOZ_ASSERT(traceLoggerState);
-- if (!events.ensureSpaceBeforeAdd()) {
-+ if (!events.hasSpaceForAdd(3)) {
- uint64_t start = rdtsc() - traceLoggerState->startupTime;
-
-- if (graph.get())
-- graph->log(events);
-+ if (!events.ensureSpaceBeforeAdd(3)) {
-+ if (graph.get())
-+ graph->log(events);
-
-- iteration_++;
-- events.clear();
-+ iteration_++;
-+ events.clear();
-+
-+ // Remove the item in the pointerMap for which the payloads
-+ // have no uses anymore
-+ for (PointerHashMap::Enum e(pointerMap); !e.empty(); e.popFront()) {
-+ if (e.front().value()->uses() != 0)
-+ continue;
-+
-+ TextIdHashMap::Ptr p = textIdPayloads.lookup(e.front().value()->textId());
-+ MOZ_ASSERT(p);
-+ textIdPayloads.remove(p);
-+
-+ e.removeFront();
-+ }
-+
-+ // Free all payloads that have no uses anymore.
-+ for (TextIdHashMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) {
-+ if (e.front().value()->uses() == 0) {
-+ js_delete(e.front().value());
-+ e.removeFront();
-+ }
-+ }
-+ }
-
- // Log the time it took to flush the events as being from the
- // Tracelogger.
- if (graph.get()) {
-- MOZ_ASSERT(events.capacity() > 2);
-+ MOZ_ASSERT(events.capacity() - events.size() > 2);
- EventEntry& entryStart = events.pushUninitialized();
- entryStart.time = start;
- entryStart.textId = TraceLogger_Internal;
-@@ -572,26 +600,6 @@ TraceLoggerThread::log(uint32_t id)
- entryStop.textId = TraceLogger_Stop;
- }
-
-- // Remove the item in the pointerMap for which the payloads
-- // have no uses anymore
-- for (PointerHashMap::Enum e(pointerMap); !e.empty(); e.popFront()) {
-- if (e.front().value()->uses() != 0)
-- continue;
--
-- TextIdHashMap::Ptr p = textIdPayloads.lookup(e.front().value()->textId());
-- MOZ_ASSERT(p);
-- textIdPayloads.remove(p);
--
-- e.removeFront();
-- }
--
-- // Free all payloads that have no uses anymore.
-- for (TextIdHashMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) {
-- if (e.front().value()->uses() == 0) {
-- js_delete(e.front().value());
-- e.removeFront();
-- }
-- }
- }
-
- uint64_t time = rdtsc() - traceLoggerState->startupTime;
-diff --git a/js/src/vm/TraceLogging.h b/js/src/vm/TraceLogging.h
-index 270478c..313950e 100644
---- a/js/src/vm/TraceLogging.h
-+++ b/js/src/vm/TraceLogging.h
-@@ -242,7 +242,7 @@ class TraceLoggerThread
-
- // If we are in a consecutive iteration we are only sure we didn't lose any events,
- // when the lastSize equals the maximum size 'events' can get.
-- if (lastIteration == iteration_ - 1 && lastSize == CONTINUOUSSPACE_LIMIT)
-+ if (lastIteration == iteration_ - 1 && lastSize == events.max_items())
- return false;
-
- return true;
-diff --git a/js/src/vm/TraceLoggingTypes.h b/js/src/vm/TraceLoggingTypes.h
-index bb8ccc7..1d98bf6 100644
---- a/js/src/vm/TraceLoggingTypes.h
-+++ b/js/src/vm/TraceLoggingTypes.h
-@@ -130,15 +130,15 @@ TLTextIdIsTreeEvent(uint32_t id)
- id >= TraceLogger_Last;
- }
-
--// The maximum amount of ram memory a continuous space structure can take (in bytes).
--static const uint32_t CONTINUOUSSPACE_LIMIT = 200 * 1024 * 1024;
--
- template <class T>
- class ContinuousSpace {
- T* data_;
- uint32_t size_;
- uint32_t capacity_;
-
-+ // The maximum amount of ram memory a continuous space structure can take (in bytes).
-+ static const uint32_t LIMIT = 200 * 1024 * 1024;
-+
- public:
- ContinuousSpace ()
- : data_(nullptr)
-@@ -160,6 +160,10 @@ class ContinuousSpace {
- data_ = nullptr;
- }
-
-+ uint32_t max_items() {
-+ return LIMIT / sizeof(T);
-+ }
-+
- T* data() {
- return data_;
- }
-@@ -197,11 +201,14 @@ class ContinuousSpace {
- return true;
-
- uint32_t nCapacity = capacity_ * 2;
-- if (size_ + count > nCapacity || nCapacity * sizeof(T) > CONTINUOUSSPACE_LIMIT) {
-+ if (size_ + count > nCapacity)
- nCapacity = size_ + count;
-
-+ if (nCapacity > max_items()) {
-+ nCapacity = max_items();
-+
- // Limit the size of a continuous buffer.
-- if (nCapacity * sizeof(T) > CONTINUOUSSPACE_LIMIT)
-+ if (size_ + count > nCapacity)
- return false;
- }
-
Index: ps/trunk/libraries/source/spidermonkey/FixZLibMozBuild.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/FixZLibMozBuild.diff
+++ ps/trunk/libraries/source/spidermonkey/FixZLibMozBuild.diff
@@ -1,11 +0,0 @@
---- a/config/external/zlib/moz.build
-+++ b/config/external/zlib/moz.build
-@@ -15,7 +15,7 @@
- # USE_LIBS += [
- # 'mozglue'
- # ]
- pass
- DIRS += [
-- '../../../modules/zlib',
-+ '../../../modules/src',
- ]
Index: ps/trunk/libraries/source/spidermonkey/README.txt
===================================================================
--- ps/trunk/libraries/source/spidermonkey/README.txt
+++ ps/trunk/libraries/source/spidermonkey/README.txt
@@ -1,15 +1,15 @@
Important notice:
-----------------
This version of SpiderMonkey comes from
-https://ftp.mozilla.org/pub/spidermonkey/releases/45.0.2/mozjs-45.0.2.tar.bz2
+https://ftp.mozilla.org/pub/spidermonkey/prereleases/52/pre1/mozjs-52.9.1pre1.tar.bz2
-The game must be compiled with precisely this version since SpiderMonkey
-does not guarantee API stability and may have behavioural changes that
+The game must be compiled with precisely this version since SpiderMonkey
+does not guarantee API stability and may have behavioural changes that
cause subtle bugs or network out-of-sync errors.
A standard system-provided version of the library may only be used if it's
-exactly the same version or if it's another minor release that does not
+exactly the same version or if it's another minor release that does not
change the behaviour of the scripts executed by SpiderMonkey. Also it's
-crucial that "--enable-gcgenerational" was used for building the system
+crucial that "--enable-gcgenerational" was used for building the system
provided libraries and that exact stack rooting was not disabled.
Using different settings for compiling SpiderMonkey and 0 A.D.
causes incompatibilities on the ABI (binary) level and can lead to
@@ -33,23 +33,25 @@
Setting up the build environment:
1. Get https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Windows_Prerequisites#MozillaBuild
+2. Download both an older version (2.x) which uses the old Mozilla build system, for NSPR; and the latest version to build
+ SpiderMonkey. Install them to different locations.
Building NSPR:
-1. Get nspr. We are using nspr-4.12 which was the newest version when SM45.0.2 was out.
+1. Get nspr. We are using nspr-4.26 which was the newest version when this was written.
Newer versions should probably work too.
Download link: https://ftp.mozilla.org/pub/mozilla.org/nspr/releases/
-2. Run mozillabuild (start-shell-msvc2015.bat) as administrator
+2. Run MozillaBuild 2.x (start-shell-msvc2015.bat)
3. Extract nspr to libraries/source/spidermonkey
- tar -xzvf nspr-4.12.tar.gz
- cd nspr-4.12
+ tar -xzvf nspr-4.26.tar.gz
+ cd nspr-4.26
cd nspr
-4. Patch nspr with https://bugzilla.mozilla.org/show_bug.cgi?id=1238154#c7
+4. Patch nspr with https://bugzilla.mozilla.org/show_bug.cgi?id=1238154#c15
5. Call configure. I've used this command:
./configure --disable-debug --enable-optimize --enable-win32-target=WIN95
6. Call make
Building SpiderMonkey:
1. Adjust the absolute paths to nspr in the build.sh file to match your environment.
-2. Run mozillabuild (start-shell-msvc2015.bat) as administrator and run ./build.sh.
+2. Run MozillaBuild 3.x (start-shell.bat) and run ./build.sh.
Index: ps/trunk/libraries/source/spidermonkey/RemoveNSPRDependency.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/RemoveNSPRDependency.diff
+++ ps/trunk/libraries/source/spidermonkey/RemoveNSPRDependency.diff
@@ -1,51 +0,0 @@
-
-# HG changeset patch
-# User Philip Chimento <philip.chimento@gmail.com>
-# Date 1501017350 25200
-# Node ID 5d95b2833b30582ab3df4e28373d749ddbf7c04e
-# Parent c24e6fc9f689aeb32de0bf7916b1d0098d4a2bb9
-Bug 1379539 - Remove unnecessary NSPR dependency. r=glandium, a=jcristau
-
-diff --git a/build/autoconf/nspr-build.m4 b/build/autoconf/nspr-build.m4
-index 970e1e7..66d96b1 100644
---- a/build/autoconf/nspr-build.m4
-+++ b/build/autoconf/nspr-build.m4
-@@ -167,11 +167,8 @@ fi
-
- AC_SUBST_LIST(NSPR_CFLAGS)
-
--NSPR_PKGCONF_CHECK="nspr"
-+PKGCONF_REQUIRES_PRIVATE="Requires.private: nspr"
- if test -n "$MOZ_NATIVE_NSPR"; then
-- # piggy back on $MOZ_NATIVE_NSPR to set a variable for the nspr check for js.pc
-- NSPR_PKGCONF_CHECK="nspr >= $NSPR_MINVER"
--
- _SAVE_CFLAGS=$CFLAGS
- CFLAGS="$CFLAGS $NSPR_CFLAGS"
- AC_TRY_COMPILE([#include "prlog.h"],
-@@ -181,8 +178,12 @@ if test -n "$MOZ_NATIVE_NSPR"; then
- ,
- AC_MSG_ERROR([system NSPR does not support PR_STATIC_ASSERT]))
- CFLAGS=$_SAVE_CFLAGS
-+ # piggy back on $MOZ_NATIVE_NSPR to set a variable for the nspr check for js.pc
-+ PKGCONF_REQUIRES_PRIVATE="Requires.private: nspr >= $NSPR_MINVER"
-+elif test -n "$JS_POSIX_NSPR"; then
-+ PKGCONF_REQUIRES_PRIVATE=
- fi
--AC_SUBST(NSPR_PKGCONF_CHECK)
-+AC_SUBST([PKGCONF_REQUIRES_PRIVATE])
-
- fi # _IS_OUTER_CONFIGURE
-
-diff --git a/js/src/js.pc.in b/js/src/js.pc.in
-index 1efea33..2eae393 100644
---- a/js/src/js.pc.in
-+++ b/js/src/js.pc.in
-@@ -6,6 +6,6 @@ includedir=@includedir@
- Name: SpiderMonkey @MOZILLA_VERSION@
- Description: The Mozilla library for JavaScript
- Version: @MOZILLA_VERSION@
--Requires.private: @NSPR_PKGCONF_CHECK@
-+@PKGCONF_REQUIRES_PRIVATE@
- Libs: -L${libdir} -l@JS_LIBRARY_NAME@
- Cflags: -include ${includedir}/@JS_LIBRARY_NAME@/js/RequiredDefines.h -I${includedir}/@JS_LIBRARY_NAME@
Index: ps/trunk/libraries/source/spidermonkey/RenameLibs.diff
===================================================================
--- ps/trunk/libraries/source/spidermonkey/RenameLibs.diff
+++ ps/trunk/libraries/source/spidermonkey/RenameLibs.diff
@@ -0,0 +1,20 @@
+diff --git a/js/src/old-configure b/js/src/old-configure
+index 7d621b52ce..85e2934fa9 100644
+--- a/js/src/old-configure
++++ b/js/src/old-configure
+@@ -10469,12 +10469,12 @@ done
+
+
+
+-if test -n "$JS_STANDALONE"; then
+ MOZ_APP_NAME="mozjs"
+ MOZ_APP_VERSION="$MOZILLA_SYMBOLVERSION"
+-JS_LIBRARY_NAME="mozjs-$MOZILLA_SYMBOLVERSION"
++if test -n "$MOZ_DEBUG"; then
++JS_LIBRARY_NAME="mozjs$MOZILLA_SYMBOLVERSION-ps-debug"
+ else
+-JS_LIBRARY_NAME="mozjs"
++JS_LIBRARY_NAME="mozjs$MOZILLA_SYMBOLVERSION-ps-release"
+ fi
+ JS_CONFIG_LIBS="$NSPR_LIBS $LIBS"
+ if test -n "$GNU_CC"; then
Index: ps/trunk/libraries/source/spidermonkey/build.sh
===================================================================
--- ps/trunk/libraries/source/spidermonkey/build.sh
+++ ps/trunk/libraries/source/spidermonkey/build.sh
@@ -1,14 +1,18 @@
#!/bin/sh
-
+# This script is called by update-workspaces.sh / build-osx-libraries.sh
set -e
+# This should match the version in config/milestone.txt
+FOLDER="mozjs-52.9.1pre1"
+# If same-version changes are needed, increment this.
+LIB_VERSION="52.9.1pre1+0"
+LIB_NAME="mozjs52-ps"
+
# Since this script is called by update-workspaces.sh, we want to quickly
# avoid doing any work if SpiderMonkey is already built and up-to-date.
# Running SM's Makefile is a bit slow and noisy, so instead we'll make a
-# special file and only rebuild if it's older than SVN.
-# README.txt should be updated whenever we update SM, so use that as
-# a time comparison.
-if [ -e .already-built -a .already-built -nt README.txt ]
+# special file and only rebuild if the build.sh version differs.
+if [ -e .already-built ] && [ "$(cat .already-built)" = "${LIB_VERSION}" ]
then
echo "SpiderMonkey is already up to date"
exit
@@ -27,37 +31,34 @@
MAKE_OPTS="${JOBS}"
-# jemalloc is outdated on SM45, do not use it
-CONF_OPTS="--disable-tests --disable-jemalloc --enable-shared-js --without-intl-api"
-
-# Bug 1269319
-# When compiled with GCC 6 (or later), SpiderMonkey 45 (and versions up to 49) is
-# subject to segfaults. Disabling a few optimizations fixes that.
-# See also #4053
-if [ "${OS}" != "Windows_NT" ]
-then
- if [ "`${CXX:=g++} -dumpversion | cut -f1 -d.`" -ge "6" ]
- then
- CXXFLAGS="${CXXFLAGS} -fno-schedule-insns2 -fno-delete-null-pointer-checks"
- fi
-fi
-
-# Change the default location where the tracelogger should store its output.
-# The default location is . on Windows and /tmp/ on *nix.
-TLCXXFLAGS='-DTRACE_LOG_DIR="\"../../source/tools/tracelogger/\""'
+# Standalone SpiderMonkey can not use jemalloc (see https://bugzilla.mozilla.org/show_bug.cgi?id=1465038)
+CONF_OPTS="--disable-tests
+ --disable-jemalloc
+ --disable-js-shell
+ --without-intl-api
+ --enable-shared-js" # We're linking statically but JS has quirks with static-only compilation.
# NSPR is needed on Windows for POSIX emulation.
-# If you want to build on Windows, check README.txt and edit the absolute paths
+# If you want to build on Windows, check README.txt and edit the absolute paths
# to match your environment.
if [ "${OS}" = "Windows_NT" ]
then
- NSPR_INCLUDES="-ID:/nspr-4.12/nspr/dist/include/nspr"
- NSPR_LIBS=" \
- D:/nspr-4.12/nspr/dist/lib/nspr4 \
- D:/nspr-4.12/nspr/dist/lib/plds4 \
- D:/nspr-4.12/nspr/dist/lib/plc4"
+ CONF_OPTS="${CONF_OPTS} --with-nspr-prefix="D:/nspr-4.21/nspr/""
else
- CONF_OPTS="${CONF_OPTS} --enable-posix-nspr-emulation"
+ CONF_OPTS="${CONF_OPTS} --enable-posix-nspr-emulation"
+fi
+
+if [ "`uname -s`" = "Darwin" ]
+then
+ # Link to custom-built zlib
+ CONF_OPTS="${CONF_OPTS} --with-system-zlib=${ZLIB_DIR}"
+ # Specify target versions and SDK
+ if [ "${MIN_OSX_VERSION}" ] && [ "${MIN_OSX_VERSION-_}" ]; then
+ CONF_OPTS="${CONF_OPTS} --enable-macos-target=$MIN_OSX_VERSION"
+ fi
+ if [ "${SYSROOT}" ] && [ "${SYSROOT-_}" ]; then
+ CONF_OPTS="${CONF_OPTS} --with-macosx-sdk=${SYSROOT}"
+ fi
fi
# If Valgrind looks like it's installed, then set up SM to support it
@@ -74,98 +75,64 @@
${CTARGET:+--target=${CTARGET}}"
echo "SpiderMonkey build options: ${CONF_OPTS}"
-echo ${CONF_OPTS}
-
-FOLDER=mozjs-45.0.2
-
-# Delete the existing directory to avoid conflicts and extract the tarball
-rm -rf $FOLDER
-tar xjf mozjs-45.0.2.tar.bz2
-
-# Clean up header files that may be left over by earlier versions of SpiderMonkey
-rm -rf include-unix-*
-
-cd $FOLDER
-# Apply patches
-. ../patch.sh
-
-cd js/src
+# It can occasionally be useful to not rebuild everything, but don't do this by default.
+REBUILD=true
+if $REBUILD = true;
+then
+ # Delete the existing directory to avoid conflicts and extract the tarball
+ rm -rf "$FOLDER"
+ if [ ! -e "${FOLDER}.tar.bz2" ];
+ then
+ # The tarball is committed to svn, but it's useful to let jenkins download it (when testing upgrade scripts).
+ download="$(command -v wget || echo "curl -L -o "${FOLDER}.tar.bz2"")"
+ $download "https://github.com/wraitii/spidermonkey-tarballs/releases/download/v52.9.1/${FOLDER}.tar.bz2"
+ fi
+ tar xjf "${FOLDER}.tar.bz2"
-# Clean up data generated by previous builds that could cause problems
-rm -rf build-debug
-rm -rf build-release
+ # Clean up header files that may be left over by earlier versions of SpiderMonkey
+ rm -rf include-unix-debug
+ rm -rf include-unix-release
+
+ # Apply patches
+ cd "$FOLDER"
+ . ../patch.sh
+ # Prevent complaining that configure is outdated.
+ touch ./js/src/configure
+else
+ cd "$FOLDER"
+fi
-# We want separate debug/release versions of the library, so we have to change
-# the LIBRARY_NAME for each build.
-# (We use perl instead of sed so that it works with MozillaBuild on Windows,
-# which has an ancient sed.)
-perl -i.bak -pe 's/(SHARED_LIBRARY_NAME\s+=).*/$1 '\''mozjs45-ps-debug'\''/' moz.build
mkdir -p build-debug
cd build-debug
-if [ "${OS}" = "Windows_NT" ]
-then
- CXXFLAGS="${CXXFLAGS} ${TLCXXFLAGS}" ../configure ${CONF_OPTS} \
- --with-nspr-cflags="${NSPR_INCLUDES}" --with-nspr-libs="${NSPR_LIBS}" \
- --enable-debug \
- --disable-optimize \
- --enable-js-diagnostics \
- --enable-gczeal
-else
- CXXFLAGS="${CXXFLAGS} ${TLCXXFLAGS}" ../configure ${CONF_OPTS} \
- --enable-debug \
- --disable-optimize \
- --enable-js-diagnostics \
- --enable-gczeal
-fi
+# SM build scripts check for autoconf, but it isn't actually needed, so just pass something.
+CXXFLAGS="${CXXFLAGS}" ../js/src/configure AUTOCONF="false" ${CONF_OPTS} \
+ --enable-debug \
+ --disable-optimize \
+ --enable-gczeal
${MAKE} ${MAKE_OPTS}
cd ..
-perl -i.bak -pe 's/(SHARED_LIBRARY_NAME\s+=).*/$1 '\''mozjs45-ps-release'\''/' moz.build
mkdir -p build-release
cd build-release
-if [ "${OS}" = "Windows_NT" ]
-then
- CXXFLAGS="${CXXFLAGS} ${TLCXXFLAGS}" ../configure ${CONF_OPTS} \
- --with-nspr-cflags="${NSPR_INCLUDES}" --with-nspr-libs="${NSPR_LIBS}" \
- --enable-optimize \
- #--enable-gczeal \
- #--enable-debug-symbols
-else
- CXXFLAGS="${CXXFLAGS} ${TLCXXFLAGS}" ../configure ${CONF_OPTS} \
- --enable-optimize \
- #--enable-gczeal \
- #--enable-debug-symbols
-fi
+CXXFLAGS="${CXXFLAGS}" ../js/src/configure AUTOCONF="false" ${CONF_OPTS} \
+ --enable-optimize
${MAKE} ${MAKE_OPTS}
cd ..
-cd ../../..
+cd ..
if [ "${OS}" = "Windows_NT" ]
then
INCLUDE_DIR_DEBUG=include-win32-debug
INCLUDE_DIR_RELEASE=include-win32-release
- DLL_SRC_SUFFIX=.dll
- DLL_DST_SUFFIX=.dll
LIB_PREFIX=
- LIB_SRC_SUFFIX=.lib
- LIB_DST_SUFFIX=.lib
+ LIB_SUFFIX=.lib
else
INCLUDE_DIR_DEBUG=include-unix-debug
INCLUDE_DIR_RELEASE=include-unix-release
- DLL_SRC_SUFFIX=.so
- DLL_DST_SUFFIX=.so
LIB_PREFIX=lib
- LIB_SRC_SUFFIX=.so
- LIB_DST_SUFFIX=.so
- if [ "`uname -s`" = "OpenBSD" ]
- then
- DLL_SRC_SUFFIX=.so.1.0
- DLL_DST_SUFFIX=.so.1.0
- LIB_SRC_SUFFIX=.so.1.0
- LIB_DST_SUFFIX=:so.1.0
- fi
+ LIB_SUFFIX=.a
fi
if [ "${OS}" = "Windows_NT" ]
@@ -173,10 +140,10 @@
# Bug #776126
# SpiderMonkey uses a tweaked zlib when building, and it wrongly copies its own files to include dirs
# afterwards, so we have to remove them to not have them conflicting with the regular zlib
- pushd ${FOLDER}/js/src/build-release/dist/include
+ pushd "${FOLDER}/build-release/dist/include"
rm mozzconf.h zconf.h zlib.h
popd
- pushd ${FOLDER}/js/src/build-debug/dist/include
+ pushd "${FOLDER}/build-debug/dist/include"
rm mozzconf.h zconf.h zlib.h
popd
fi
@@ -184,23 +151,26 @@
# Copy files into the necessary locations for building and running the game
# js-config.h is different for debug and release builds, so we need different include directories for both
-mkdir -p ${INCLUDE_DIR_DEBUG}
-mkdir -p ${INCLUDE_DIR_RELEASE}
-cp -R -L ${FOLDER}/js/src/build-release/dist/include/* ${INCLUDE_DIR_RELEASE}/
-cp -R -L ${FOLDER}/js/src/build-debug/dist/include/* ${INCLUDE_DIR_DEBUG}/
+mkdir -p "${INCLUDE_DIR_DEBUG}"
+mkdir -p "${INCLUDE_DIR_RELEASE}"
+cp -R -L "${FOLDER}"/build-release/dist/include/* "${INCLUDE_DIR_RELEASE}/"
+cp -R -L "${FOLDER}"/build-debug/dist/include/* "${INCLUDE_DIR_DEBUG}/"
mkdir -p lib/
-cp -L ${FOLDER}/js/src/build-debug/dist/sdk/lib/${LIB_PREFIX}mozjs45-ps-debug${LIB_SRC_SUFFIX} lib/${LIB_PREFIX}mozjs45-ps-debug${LIB_DST_SUFFIX}
-cp -L ${FOLDER}/js/src/build-release/dist/sdk/lib/${LIB_PREFIX}mozjs45-ps-release${LIB_SRC_SUFFIX} lib/${LIB_PREFIX}mozjs45-ps-release${LIB_DST_SUFFIX}
-cp -L ${FOLDER}/js/src/build-debug/dist/bin/${LIB_PREFIX}mozjs45-ps-debug${DLL_SRC_SUFFIX} ../../../binaries/system/${LIB_PREFIX}mozjs45-ps-debug${DLL_DST_SUFFIX}
-cp -L ${FOLDER}/js/src/build-release/dist/bin/${LIB_PREFIX}mozjs45-ps-release${DLL_SRC_SUFFIX} ../../../binaries/system/${LIB_PREFIX}mozjs45-ps-release${DLL_DST_SUFFIX}
+cp -L "${FOLDER}/build-debug/js/src/${LIB_PREFIX}js_static${LIB_SUFFIX}" "lib/${LIB_PREFIX}${LIB_NAME}-debug${LIB_SUFFIX}"
+cp -L "${FOLDER}/build-release/js/src/${LIB_PREFIX}js_static${LIB_SUFFIX}" "lib/${LIB_PREFIX}${LIB_NAME}-release${LIB_SUFFIX}"
-# On Windows, also copy debugging symbols files
+# On Windows, also copy nspr .DLL and .pdb debug symbols.
if [ "${OS}" = "Windows_NT" ]
then
- cp -L ${FOLDER}/js/src/build-debug/js/src/${LIB_PREFIX}mozjs45-ps-debug-vc140.pdb ../../../binaries/system/${LIB_PREFIX}mozjs45-ps-debug-vc140.pdb
- cp -L ${FOLDER}/js/src/build-release/js/src/${LIB_PREFIX}mozjs45-ps-release-vc140.pdb ../../../binaries/system/${LIB_PREFIX}mozjs45-ps-release-vc140.pdb
+ cp -L "${FOLDER}/build-debug/js/src/${LIB_PREFIX}nspr4.dll" "../../../binaries/system/${LIB_PREFIX}nspr4.dll"
+ cp -L "${FOLDER}/build-debug/js/src/${LIB_PREFIX}plc4.dll" "../../../binaries/system/${LIB_PREFIX}plc4.dll"
+ cp -L "${FOLDER}/build-debug/js/src/${LIB_PREFIX}plds4.dll" "../../../binaries/system/${LIB_PREFIX}plds4.dll"
+ cp -L "${FOLDER}/build-debug/js/src/${LIB_PREFIX}mozjs-52-debug.dll" "lib/${LIB_PREFIX}${LIB_NAME}-debug.dll"
+ cp -L "${FOLDER}/build-debug/js/src/${LIB_PREFIX}mozjs-52-debug.pdb" "lib/${LIB_PREFIX}${LIB_NAME}-debug.pdb"
+ cp -L "${FOLDER}/build-release/js/src/${LIB_PREFIX}mozjs-52-release.dll" "lib/${LIB_PREFIX}${LIB_NAME}-release.dll"
+ cp -L "${FOLDER}/build-release/js/src/${LIB_PREFIX}mozjs-52-release.pdb" "lib/${LIB_PREFIX}${LIB_NAME}-release.pdb"
fi
# Flag that it's already been built successfully so we can skip it next time
-touch .already-built
+echo "${LIB_VERSION}" > .already-built
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/fdlibm.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/fdlibm.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/fdlibm.h
@@ -0,0 +1,65 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $FreeBSD$
+ */
+
+#ifndef mozilla_imported_fdlibm_h
+#define mozilla_imported_fdlibm_h
+
+namespace fdlibm {
+
+double acos(double);
+double asin(double);
+double atan(double);
+double atan2(double, double);
+
+double cosh(double);
+double sinh(double);
+double tanh(double);
+
+double exp(double);
+double log(double);
+double log10(double);
+
+double pow(double, double);
+double sqrt(double);
+double fabs(double);
+
+double floor(double);
+double trunc(double);
+double ceil(double);
+
+double acosh(double);
+double asinh(double);
+double atanh(double);
+double cbrt(double);
+double expm1(double);
+double hypot(double, double);
+double log1p(double);
+double log2(double);
+double rint(double);
+double copysign(double, double);
+double nearbyint(double);
+double scalbn(double, int);
+
+float ceilf(float);
+float floorf(float);
+
+float nearbyintf(float);
+float rintf(float);
+float truncf(float);
+
+} /* namespace fdlibm */
+
+#endif /* mozilla_imported_fdlibm_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js-config.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js-config.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js-config.h
@@ -15,6 +15,20 @@
/* Define to 1 if SpiderMonkey is in debug mode. */
#define JS_DEBUG 1
+/*
+ * NB: We have a special case for rust-bindgen, which wants to be able to
+ * generate both debug and release bindings on a single objdir.
+ */
+#ifdef JS_DEBUG
+#if !defined(DEBUG) && !defined(RUST_BINDGEN)
+# error "SpiderMonkey was configured with --enable-debug, so DEBUG must be defined when including this header"
+# endif
+#else
+# if defined(DEBUG) && !defined(RUST_BINDGEN)
+# error "SpiderMonkey was configured with --disable-debug, so DEBUG must be not defined when including this header"
+# endif
+#endif
+
/* Define to 1 if SpiderMonkey should not use struct types in debug builds. */
/* #undef JS_NO_JSVAL_JSID_STRUCT_TYPES */
@@ -34,18 +48,6 @@
/* Define to 1 to perform extra assertions and heap poisoning. */
/* #undef JS_CRASH_DIAGNOSTICS */
-/* Define to 1 if the <endian.h> header is present and
- useable. See jscpucfg.h. */
-/* #undef JS_HAVE_ENDIAN_H */
-
-/* Define to 1 if the <machine/endian.h> header is present and
- useable. See jscpucfg.h. */
-/* #undef JS_HAVE_MACHINE_ENDIAN_H */
-
-/* Define to 1 if the <sys/isa_defs.h> header is present and
- useable. See jscpucfg.h. */
-/* #undef JS_HAVE_SYS_ISA_DEFS_H */
-
/* Define to 1 if SpiderMonkey is in NUNBOX32 mode. */
#define JS_NUNBOX32 1
@@ -53,7 +55,7 @@
/* #undef JS_PUNBOX64 */
/* MOZILLA JSAPI version number components */
-#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 0
+#define MOZJS_MAJOR_VERSION 52
+#define MOZJS_MINOR_VERSION 9
#endif /* js_config_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js.msg
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js.msg
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js.msg
@@ -34,14 +34,14 @@
*
* can be used:
*
- * JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
+ * JS_ReportErrorNumberASCII(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
*
* to report:
*
* "Rhino is not a member of the Monkey family"
*/
-MSG_DEF(JSMSG_NOT_AN_ERROR, 0, JSEXN_NONE, "<Error #0 is reserved>")
+MSG_DEF(JSMSG_NOT_AN_ERROR, 0, JSEXN_ERR, "<Error #0 is reserved>")
MSG_DEF(JSMSG_NOT_DEFINED, 1, JSEXN_REFERENCEERR, "{0} is not defined")
MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, JSEXN_TYPEERR, "{0} requires more than {1} argument{2}")
MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}")
@@ -63,7 +63,7 @@
MSG_DEF(JSMSG_BAD_WEAKMAP_KEY, 0, JSEXN_TYPEERR, "cannot use the given object as a weak map key")
MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 1, JSEXN_TYPEERR, "invalid {0} usage")
MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 0, JSEXN_RANGEERR, "invalid array length")
-MSG_DEF(JSMSG_REDECLARED_VAR, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}")
+MSG_DEF(JSMSG_REDECLARED_VAR, 2, JSEXN_SYNTAXERR, "redeclaration of {0} {1}")
MSG_DEF(JSMSG_UNDECLARED_VAR, 1, JSEXN_REFERENCEERR, "assignment to undeclared variable {0}")
MSG_DEF(JSMSG_GETTER_ONLY, 0, JSEXN_TYPEERR, "setting a property that has only a getter")
MSG_DEF(JSMSG_OVERWRITING_ACCESSOR, 1, JSEXN_TYPEERR, "can't overwrite accessor property {0}")
@@ -71,14 +71,12 @@
MSG_DEF(JSMSG_INVALID_MAP_ITERABLE, 1, JSEXN_TYPEERR, "iterable for {0} should have array-like objects")
MSG_DEF(JSMSG_NESTING_GENERATOR, 0, JSEXN_TYPEERR, "already executing generator")
MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
-MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED, 0, JSEXN_NONE, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead")
-MSG_DEF(JSMSG_TYPE_ERR_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
+MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED, 0, JSEXN_WARN, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead")
+MSG_DEF(JSMSG_ARRAYBUFFER_SLICE_DEPRECATED, 0, JSEXN_WARN, "ArrayBuffer.slice is deprecated; use ArrayBuffer.prototype.slice instead")
MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 1, JSEXN_TYPEERR, "bad surrogate character {0}")
MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large")
MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}")
-MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 1, JSEXN_TYPEERR, "wrong constructor called for {0}")
MSG_DEF(JSMSG_BUILTIN_CTOR_NO_NEW, 1, JSEXN_TYPEERR, "calling a builtin {0} constructor without new is forbidden")
-MSG_DEF(JSMSG_PROTO_SETTING_SLOW, 0, JSEXN_NONE, "mutating the [[Prototype]] of an object will cause your code to run very slowly; instead create the object with the correct initial [[Prototype]] value using Object.create")
MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 1, JSEXN_TYPEERR, "yield from closing generator {0}")
MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value")
MSG_DEF(JSMSG_UNEXPECTED_TYPE, 2, JSEXN_TYPEERR, "{0} is {1}")
@@ -89,14 +87,15 @@
MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 1, JSEXN_TYPEERR, "{0}: Object is not extensible")
MSG_DEF(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE, 2, JSEXN_TYPEERR, "can't define property {1}: {0} is not extensible")
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property {0}")
-MSG_DEF(JSMSG_CANT_APPEND_TO_ARRAY, 0, JSEXN_TYPEERR, "can't add elements past the end of an array if its length property is unwritable")
MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't redefine array length")
MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length")
MSG_DEF(JSMSG_BAD_GET_SET_FIELD, 1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function")
MSG_DEF(JSMSG_THROW_TYPE_ERROR, 0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them")
MSG_DEF(JSMSG_NOT_EXPECTED_TYPE, 3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}")
MSG_DEF(JSMSG_NOT_ITERABLE, 1, JSEXN_TYPEERR, "{0} is not iterable")
-MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 2, JSEXN_NONE, "{0} is being assigned a {1}, but already has one")
+MSG_DEF(JSMSG_NOT_ITERATOR, 1, JSEXN_TYPEERR, "{0} is not iterator")
+MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 2, JSEXN_WARN, "{0} is being assigned a {1}, but already has one")
+MSG_DEF(JSMSG_GET_ITER_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "[Symbol.iterator]() returned a non-object value")
MSG_DEF(JSMSG_NEXT_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "iterator.next() returned a non-object value")
MSG_DEF(JSMSG_CANT_SET_PROTO, 0, JSEXN_TYPEERR, "can't set prototype of this object")
MSG_DEF(JSMSG_CANT_SET_PROTO_OF, 1, JSEXN_TYPEERR, "can't set prototype of {0}")
@@ -106,11 +105,12 @@
MSG_DEF(JSMSG_PROTO_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0}.prototype is not an object or null")
MSG_DEF(JSMSG_CANT_CALL_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class constructors must be invoked with |new|")
MSG_DEF(JSMSG_UNINITIALIZED_THIS, 1, JSEXN_REFERENCEERR, "|this| used uninitialized in {0} class constructor")
+MSG_DEF(JSMSG_UNINITIALIZED_THIS_ARROW, 0, JSEXN_REFERENCEERR, "|this| used uninitialized in arrow function in class constructor")
MSG_DEF(JSMSG_BAD_DERIVED_RETURN, 1, JSEXN_TYPEERR, "derived class constructor returned invalid value {0}")
// JSON
MSG_DEF(JSMSG_JSON_BAD_PARSE, 3, JSEXN_SYNTAXERR, "JSON.parse: {0} at line {1} column {2} of the JSON data")
-MSG_DEF(JSMSG_JSON_CYCLIC_VALUE, 1, JSEXN_TYPEERR, "cyclic {0} value")
+MSG_DEF(JSMSG_JSON_CYCLIC_VALUE, 0, JSEXN_TYPEERR, "cyclic object value")
// Runtime errors
MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}")
@@ -121,6 +121,7 @@
MSG_DEF(JSMSG_TOO_MANY_FUN_SPREADARGS, 0, JSEXN_RANGEERR, "too many function arguments")
MSG_DEF(JSMSG_UNINITIALIZED_LEXICAL, 1, JSEXN_REFERENCEERR, "can't access lexical declaration `{0}' before initialization")
MSG_DEF(JSMSG_BAD_CONST_ASSIGN, 1, JSEXN_TYPEERR, "invalid assignment to const `{0}'")
+MSG_DEF(JSMSG_CANT_DECLARE_GLOBAL_BINDING, 2, JSEXN_TYPEERR, "cannot declare global binding `{0}': {1}")
// Date
MSG_DEF(JSMSG_INVALID_DATE, 0, JSEXN_RANGEERR, "invalid date")
@@ -132,7 +133,6 @@
MSG_DEF(JSMSG_NEGATIVE_REPETITION_COUNT, 0, JSEXN_RANGEERR, "repeat count must be non-negative")
MSG_DEF(JSMSG_NOT_A_CODEPOINT, 1, JSEXN_RANGEERR, "{0} is not a valid code point")
MSG_DEF(JSMSG_RESULTING_STRING_TOO_LARGE, 0, JSEXN_RANGEERR, "repeat count must be less than infinity and not overflow maximum string size")
-MSG_DEF(JSMSG_DEPRECATED_STRING_CONTAINS, 0, JSEXN_NONE, "String.prototype.contains() is deprecated and will be removed in a future release; use String.prototype.includes() instead")
// Number
MSG_DEF(JSMSG_BAD_RADIX, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36")
@@ -146,7 +146,7 @@
MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION, 1, JSEXN_TYPEERR, "{0} is not a scripted function")
MSG_DEF(JSMSG_NO_REST_NAME, 0, JSEXN_SYNTAXERR, "no parameter name after ...")
MSG_DEF(JSMSG_PARAMETER_AFTER_REST, 0, JSEXN_SYNTAXERR, "parameter after rest parameter")
-MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
+MSG_DEF(JSMSG_TOO_MANY_ARGUMENTS, 0, JSEXN_RANGEERR, "too many arguments provided for a function call")
// CSP
MSG_DEF(JSMSG_CSP_BLOCKED_EVAL, 0, JSEXN_ERR, "call to eval() blocked by CSP")
@@ -158,10 +158,7 @@
MSG_DEF(JSMSG_UNWRAP_DENIED, 0, JSEXN_ERR, "permission denied to unwrap object")
// JSAPI-only (Not thrown as JS exceptions)
-MSG_DEF(JSMSG_BAD_CHAR, 1, JSEXN_INTERNALERR, "invalid format character {0}")
MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE, 0, JSEXN_TYPEERR, "bad cloned function scope chain")
-MSG_DEF(JSMSG_BAD_NEW_RESULT, 1, JSEXN_TYPEERR, "invalid new expression result {0}")
-MSG_DEF(JSMSG_BAD_TYPE, 1, JSEXN_TYPEERR, "unknown type {0}")
MSG_DEF(JSMSG_CANT_CLONE_OBJECT, 0, JSEXN_TYPEERR, "can't clone object")
MSG_DEF(JSMSG_CANT_OPEN, 2, JSEXN_ERR, "can't open {0}: {1}")
MSG_DEF(JSMSG_USER_DEFINED_ERROR, 0, JSEXN_ERR, "JS_ReportError was called")
@@ -169,11 +166,10 @@
// Internal errors
MSG_DEF(JSMSG_ALLOC_OVERFLOW, 0, JSEXN_INTERNALERR, "allocation size overflow")
MSG_DEF(JSMSG_BAD_BYTECODE, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
-MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 0, JSEXN_INTERNALERR, "buffer too small")
+MSG_DEF(JSMSG_BUILD_ID_NOT_AVAILABLE, 0, JSEXN_INTERNALERR, "build ID is not available")
MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
-MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties")
-MSG_DEF(JSMSG_INACTIVE, 0, JSEXN_INTERNALERR, "nothing active on context")
+MSG_DEF(JSMSG_ERR_DURING_THROW, 0, JSEXN_INTERNALERR, "an internal error occurred while throwing an exception")
MSG_DEF(JSMSG_NEED_DIET, 1, JSEXN_INTERNALERR, "{0} too large")
MSG_DEF(JSMSG_OUT_OF_MEMORY, 0, JSEXN_INTERNALERR, "out of memory")
MSG_DEF(JSMSG_OVER_RECURSED, 0, JSEXN_INTERNALERR, "too much recursion")
@@ -185,9 +181,11 @@
// Frontend
MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}")
MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
-MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initialiser too large")
+MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initializer too large")
MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'as' after import *")
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
+MSG_DEF(JSMSG_ASYNC_GENERATOR, 0, JSEXN_SYNTAXERR, "generator function or method can't be async")
+MSG_DEF(JSMSG_AWAIT_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "await can't be used in default expression")
MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
@@ -199,18 +197,19 @@
MSG_DEF(JSMSG_BAD_DESTRUCT_DECL, 0, JSEXN_SYNTAXERR, "missing = in destructuring declaration")
MSG_DEF(JSMSG_BAD_DUP_ARGS, 0, JSEXN_SYNTAXERR, "duplicate argument names not allowed in this context")
MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 0, JSEXN_SYNTAXERR, "invalid for each loop")
-MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side")
-MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
-MSG_DEF(JSMSG_BAD_YIELD_SYNTAX, 0, JSEXN_SYNTAXERR, "yield expression must be parenthesized")
-MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 0, JSEXN_SYNTAXERR, "generator expression must be parenthesized")
+MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for-in/of left-hand side")
+MSG_DEF(JSMSG_LEXICAL_DECL_DEFINES_LET,0, JSEXN_SYNTAXERR, "a lexical declaration can't define a 'let' binding")
+MSG_DEF(JSMSG_LET_STARTING_FOROF_LHS, 0, JSEXN_SYNTAXERR, "an expression X in 'for (X of Y)' must not start with 'let'")
+MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
MSG_DEF(JSMSG_BAD_GENEXP_BODY, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression")
MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_REFERENCEERR, "invalid increment/decrement operand")
MSG_DEF(JSMSG_BAD_METHOD_DEF, 0, JSEXN_SYNTAXERR, "bad method definition")
MSG_DEF(JSMSG_BAD_OCTAL, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant")
MSG_DEF(JSMSG_BAD_OPERAND, 1, JSEXN_SYNTAXERR, "invalid {0} operand")
+MSG_DEF(JSMSG_BAD_POW_LEFTSIDE, 0, JSEXN_SYNTAXERR, "unparenthesized unary expression can't appear on the left-hand side of '**'")
MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id")
MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 1, JSEXN_SYNTAXERR, "{0} not in function")
-MSG_DEF(JSMSG_BAD_STRICT_ASSIGN, 1, JSEXN_SYNTAXERR, "can't assign to {0} in strict mode")
+MSG_DEF(JSMSG_BAD_STRICT_ASSIGN, 1, JSEXN_SYNTAXERR, "'{0}' can't be defined or assigned to in strict mode code")
MSG_DEF(JSMSG_BAD_SWITCH, 0, JSEXN_SYNTAXERR, "invalid switch statement")
MSG_DEF(JSMSG_BAD_SUPER, 0, JSEXN_SYNTAXERR, "invalid use of keyword 'super'")
MSG_DEF(JSMSG_BAD_SUPERPROP, 1, JSEXN_SYNTAXERR, "use of super {0} accesses only valid within methods or eval code within methods")
@@ -230,13 +229,11 @@
MSG_DEF(JSMSG_CURLY_AFTER_BODY, 0, JSEXN_SYNTAXERR, "missing } after function body")
MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 0, JSEXN_SYNTAXERR, "missing } after catch block")
MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 0, JSEXN_SYNTAXERR, "missing } after finally block")
-MSG_DEF(JSMSG_CURLY_AFTER_LET, 0, JSEXN_SYNTAXERR, "missing } after let block")
MSG_DEF(JSMSG_CURLY_AFTER_LIST, 0, JSEXN_SYNTAXERR, "missing } after property list")
MSG_DEF(JSMSG_CURLY_AFTER_TRY, 0, JSEXN_SYNTAXERR, "missing } after try block")
MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 0, JSEXN_SYNTAXERR, "missing { before function body")
MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 0, JSEXN_SYNTAXERR, "missing { before catch block")
MSG_DEF(JSMSG_CURLY_BEFORE_CLASS, 0, JSEXN_SYNTAXERR, "missing { before class body")
-MSG_DEF(JSMSG_CURLY_BEFORE_LET, 0, JSEXN_SYNTAXERR, "missing { before let block")
MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 0, JSEXN_SYNTAXERR, "missing { before finally block")
MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 0, JSEXN_SYNTAXERR, "missing { before switch body")
MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 0, JSEXN_SYNTAXERR, "missing { before try block")
@@ -244,32 +241,37 @@
MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword")
MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword")
MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 0, JSEXN_SYNTAXERR, "applying the 'delete' operator to an unqualified name is deprecated")
-MSG_DEF(JSMSG_DEPRECATED_EXPR_CLOSURE, 0, JSEXN_NONE, "expression closures are deprecated")
-MSG_DEF(JSMSG_DEPRECATED_FLAGS_ARG, 0, JSEXN_NONE, "flags argument of String.prototype.{search,match,replace} is deprecated")
-MSG_DEF(JSMSG_DEPRECATED_FOR_EACH, 0, JSEXN_NONE, "JavaScript 1.6's for-each-in loops are deprecated; consider using ES6 for-of instead")
-MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "octal literals and octal escape sequences are deprecated")
-MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_NONE, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead")
+MSG_DEF(JSMSG_DEPRECATED_EXPR_CLOSURE, 0, JSEXN_WARN, "expression closures are deprecated")
+MSG_DEF(JSMSG_DEPRECATED_FOR_EACH, 0, JSEXN_WARN, "JavaScript 1.6's for-each-in loops are deprecated; consider using ES6 for-of instead")
+MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal literals and octal escape sequences are deprecated; for octal literals use the \"0o\" prefix instead")
+MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_WARN, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead")
+MSG_DEF(JSMSG_DEPRECATED_BLOCK_SCOPE_FUN_REDECL, 1, JSEXN_WARN, "redeclaration of block-scoped function `{0}' is deprecated")
MSG_DEF(JSMSG_DUPLICATE_EXPORT_NAME, 1, JSEXN_SYNTAXERR, "duplicate export name '{0}'")
MSG_DEF(JSMSG_DUPLICATE_FORMAL, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}")
MSG_DEF(JSMSG_DUPLICATE_LABEL, 0, JSEXN_SYNTAXERR, "duplicate label")
MSG_DEF(JSMSG_DUPLICATE_PROPERTY, 1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal")
+MSG_DEF(JSMSG_DUPLICATE_PROTO_PROPERTY, 0, JSEXN_SYNTAXERR, "property name __proto__ appears more than once in object literal")
MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 0, JSEXN_SYNTAXERR, "mistyped ; after conditional?")
MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?")
MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL,0, JSEXN_SYNTAXERR, "export declarations may only appear at top level of a module")
MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 0, JSEXN_SYNTAXERR, "finally without try")
+MSG_DEF(JSMSG_FORBIDDEN_AS_STATEMENT, 1, JSEXN_SYNTAXERR, "{0} can't appear in single-statement context")
MSG_DEF(JSMSG_FROM_AFTER_IMPORT_CLAUSE, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import clause")
MSG_DEF(JSMSG_FROM_AFTER_EXPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after export *")
MSG_DEF(JSMSG_GARBAGE_AFTER_INPUT, 2, JSEXN_SYNTAXERR, "unexpected garbage after {0}, starting with {1}")
MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal")
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 0, JSEXN_SYNTAXERR, "illegal character")
MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level of a module")
-MSG_DEF(JSMSG_INVALID_FOR_INOF_DECL_WITH_INIT,1,JSEXN_SYNTAXERR,"for-{0} loop head declarations may not have initializers")
-MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for")
+MSG_DEF(JSMSG_INVALID_FOR_IN_DECL_WITH_INIT,0,JSEXN_SYNTAXERR,"for-in loop head declarations may not have initializers")
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 0, JSEXN_SYNTAXERR, "label not found")
-MSG_DEF(JSMSG_LET_CLASS_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a class")
MSG_DEF(JSMSG_LET_COMP_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a comprehension variable")
MSG_DEF(JSMSG_LEXICAL_DECL_NOT_IN_BLOCK, 1, JSEXN_SYNTAXERR, "{0} declaration not directly within block")
+MSG_DEF(JSMSG_LEXICAL_DECL_LABEL, 1, JSEXN_SYNTAXERR, "{0} declarations cannot be labelled")
+MSG_DEF(JSMSG_GENERATOR_LABEL, 0, JSEXN_SYNTAXERR, "generator functions cannot be labelled")
+MSG_DEF(JSMSG_FUNCTION_LABEL, 0, JSEXN_SYNTAXERR, "functions cannot be labelled")
+MSG_DEF(JSMSG_SLOPPY_FUNCTION_LABEL, 0, JSEXN_SYNTAXERR, "functions can only be labelled inside blocks")
MSG_DEF(JSMSG_LINE_BREAK_AFTER_THROW, 0, JSEXN_SYNTAXERR, "no line break is allowed between 'throw' and its expression")
+MSG_DEF(JSMSG_LINE_BREAK_BEFORE_ARROW, 0, JSEXN_SYNTAXERR, "no line break is allowed before '=>'")
MSG_DEF(JSMSG_MALFORMED_ESCAPE, 1, JSEXN_SYNTAXERR, "malformed {0} character escape sequence")
MSG_DEF(JSMSG_MISSING_BINARY_DIGITS, 0, JSEXN_SYNTAXERR, "missing binary digits after '0b'")
MSG_DEF(JSMSG_MISSING_EXPONENT, 0, JSEXN_SYNTAXERR, "missing exponent")
@@ -279,11 +281,8 @@
MSG_DEF(JSMSG_MISSING_OCTAL_DIGITS, 0, JSEXN_SYNTAXERR, "missing octal digits after '0o'")
MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword")
MSG_DEF(JSMSG_NAME_AFTER_DOT, 0, JSEXN_SYNTAXERR, "missing name after . operator")
-MSG_DEF(JSMSG_NAME_AFTER_IMPORT_STAR_AS, 0, JSEXN_SYNTAXERR, "missing name after import * as")
MSG_DEF(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT, 0, JSEXN_SYNTAXERR, "expected named imports or namespace import after comma")
-MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
MSG_DEF(JSMSG_NO_BINDING_NAME, 0, JSEXN_SYNTAXERR, "missing binding name")
-MSG_DEF(JSMSG_NO_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class default constructors not yet implemented")
MSG_DEF(JSMSG_NO_EXPORT_NAME, 0, JSEXN_SYNTAXERR, "missing export name")
MSG_DEF(JSMSG_NO_IMPORT_NAME, 0, JSEXN_SYNTAXERR, "missing import name")
MSG_DEF(JSMSG_NO_VARIABLE_NAME, 0, JSEXN_SYNTAXERR, "missing variable name")
@@ -295,32 +294,30 @@
MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control")
MSG_DEF(JSMSG_PAREN_AFTER_FOR_OF_ITERABLE, 0, JSEXN_SYNTAXERR, "missing ) after for-of iterable")
-MSG_DEF(JSMSG_PAREN_AFTER_LET, 0, JSEXN_SYNTAXERR, "missing ) after let head")
MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 0, JSEXN_SYNTAXERR, "missing ) after switch expression")
MSG_DEF(JSMSG_PAREN_AFTER_WITH, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object")
MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 0, JSEXN_SYNTAXERR, "missing ( before catch")
MSG_DEF(JSMSG_PAREN_BEFORE_COND, 0, JSEXN_SYNTAXERR, "missing ( before condition")
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
-MSG_DEF(JSMSG_PAREN_BEFORE_LET, 0, JSEXN_SYNTAXERR, "missing ( before let head")
MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 0, JSEXN_SYNTAXERR, "missing ( before switch expression")
MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object")
MSG_DEF(JSMSG_PAREN_IN_PAREN, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical")
MSG_DEF(JSMSG_RC_AFTER_EXPORT_SPEC_LIST, 0, JSEXN_SYNTAXERR, "missing '}' after export specifier list")
MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list")
-MSG_DEF(JSMSG_REDECLARED_CATCH_IDENTIFIER, 1, JSEXN_TYPEERR, "redeclaration of identifier '{0}' in catch")
-MSG_DEF(JSMSG_REDECLARED_PARAM, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}")
+MSG_DEF(JSMSG_REDECLARED_CATCH_IDENTIFIER, 1, JSEXN_SYNTAXERR, "redeclaration of identifier '{0}' in catch")
MSG_DEF(JSMSG_RESERVED_ID, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
+MSG_DEF(JSMSG_REST_WITH_COMMA, 0, JSEXN_SYNTAXERR, "rest element may not have a trailing comma")
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LEXICAL, 1, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level {0} declarations")
+MSG_DEF(JSMSG_SELFHOSTED_METHOD_CALL, 0, JSEXN_SYNTAXERR, "self-hosted code may not contain direct method calls. Use callFunction() or callContentFunction()")
MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups")
-MSG_DEF(JSMSG_SELFHOSTED_METHOD_CALL, 0, JSEXN_SYNTAXERR, "self-hosted code may not contain direct method calls")
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 0, JSEXN_SYNTAXERR, "missing ; before statement")
MSG_DEF(JSMSG_SOURCE_TOO_LONG, 0, JSEXN_RANGEERR, "source is too long")
-MSG_DEF(JSMSG_STMT_AFTER_RETURN, 0, JSEXN_NONE, "unreachable code after return statement")
+MSG_DEF(JSMSG_STMT_AFTER_RETURN, 0, JSEXN_WARN, "unreachable code after return statement")
MSG_DEF(JSMSG_STRICT_CODE_WITH, 0, JSEXN_SYNTAXERR, "strict mode code may not contain 'with' statements")
-MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function")
+MSG_DEF(JSMSG_STRICT_NON_SIMPLE_PARAMS, 1, JSEXN_SYNTAXERR, "\"use strict\" not allowed in function with {0} parameter")
MSG_DEF(JSMSG_TEMPLSTR_UNTERM_EXPR, 0, JSEXN_SYNTAXERR, "missing } in template string")
MSG_DEF(JSMSG_SIMD_NOT_A_VECTOR, 2, JSEXN_TYPEERR, "expecting a SIMD {0} object as argument {1}")
MSG_DEF(JSMSG_TOO_MANY_CASES, 0, JSEXN_INTERNALERR, "too many switch cases")
@@ -343,19 +340,53 @@
MSG_DEF(JSMSG_WHILE_AFTER_DO, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
MSG_DEF(JSMSG_YIELD_IN_ARROW, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield")
MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "yield in default expression")
+MSG_DEF(JSMSG_YIELD_IN_METHOD, 0, JSEXN_SYNTAXERR, "non-generator method definitions may not contain yield")
MSG_DEF(JSMSG_BAD_COLUMN_NUMBER, 0, JSEXN_RANGEERR, "column number out of range")
MSG_DEF(JSMSG_COMPUTED_NAME_IN_PATTERN,0, JSEXN_SYNTAXERR, "computed property names aren't supported in this destructuring declaration")
MSG_DEF(JSMSG_DEFAULT_IN_PATTERN, 0, JSEXN_SYNTAXERR, "destructuring defaults aren't supported in this destructuring declaration")
-MSG_DEF(JSMSG_BAD_NEWTARGET, 0, JSEXN_SYNTAXERR, "new.target only allowed in non-exotic functions")
+MSG_DEF(JSMSG_BAD_NEWTARGET, 0, JSEXN_SYNTAXERR, "new.target only allowed within functions")
MSG_DEF(JSMSG_ESCAPED_KEYWORD, 0, JSEXN_SYNTAXERR, "keywords must be written literally, without embedded escapes")
// asm.js
MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}")
MSG_DEF(JSMSG_USE_ASM_LINK_FAIL, 1, JSEXN_TYPEERR, "asm.js link error: {0}")
-MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 1, JSEXN_NONE, "Successfully compiled asm.js code ({0})")
+MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 1, JSEXN_WARN, "Successfully compiled asm.js code ({0})")
+
+// wasm
+MSG_DEF(JSMSG_WASM_COMPILE_ERROR, 1, JSEXN_WASMCOMPILEERROR, "{0}")
+MSG_DEF(JSMSG_WASM_IND_CALL_TO_NULL, 0, JSEXN_WASMRUNTIMEERROR, "indirect call to null")
+MSG_DEF(JSMSG_WASM_IND_CALL_BAD_SIG, 0, JSEXN_WASMRUNTIMEERROR, "indirect call signature mismatch")
+MSG_DEF(JSMSG_WASM_UNREACHABLE, 0, JSEXN_WASMRUNTIMEERROR, "unreachable executed")
+MSG_DEF(JSMSG_WASM_INTEGER_OVERFLOW, 0, JSEXN_WASMRUNTIMEERROR, "integer overflow")
+MSG_DEF(JSMSG_WASM_INVALID_CONVERSION, 0, JSEXN_WASMRUNTIMEERROR, "invalid conversion to integer")
+MSG_DEF(JSMSG_WASM_INT_DIVIDE_BY_ZERO, 0, JSEXN_WASMRUNTIMEERROR, "integer divide by zero")
+MSG_DEF(JSMSG_WASM_OUT_OF_BOUNDS, 0, JSEXN_WASMRUNTIMEERROR, "index out of bounds")
+MSG_DEF(JSMSG_WASM_UNALIGNED_ACCESS, 0, JSEXN_WASMRUNTIMEERROR, "unaligned memory access")
+MSG_DEF(JSMSG_WASM_BAD_UINT32, 2, JSEXN_RANGEERR, "bad {0} {1}")
+MSG_DEF(JSMSG_WASM_BAD_GROW, 1, JSEXN_RANGEERR, "failed to grow {0}")
+MSG_DEF(JSMSG_WASM_BAD_FIT, 2, JSEXN_RANGEERR, "{0} segment does not fit in {1}")
+MSG_DEF(JSMSG_WASM_BAD_BUF_ARG, 0, JSEXN_TYPEERR, "first argument must be an ArrayBuffer or typed array object")
+MSG_DEF(JSMSG_WASM_BAD_MOD_ARG, 0, JSEXN_TYPEERR, "first argument must be a WebAssembly.Module")
+MSG_DEF(JSMSG_WASM_BAD_BUF_MOD_ARG, 0, JSEXN_TYPEERR, "first argument must be a WebAssembly.Module, ArrayBuffer or typed array object")
+MSG_DEF(JSMSG_WASM_BAD_DESC_ARG, 1, JSEXN_TYPEERR, "first argument must be a {0} descriptor")
+MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE, 1, JSEXN_TYPEERR, "imported {0} with incompatible size")
+MSG_DEF(JSMSG_WASM_BAD_IMP_MAX, 1, JSEXN_TYPEERR, "imported {0} with incompatible maximum size")
+MSG_DEF(JSMSG_WASM_BAD_ELEMENT, 0, JSEXN_TYPEERR, "\"element\" property of table descriptor must be \"anyfunc\"")
+MSG_DEF(JSMSG_WASM_BAD_IMPORT_ARG, 0, JSEXN_TYPEERR, "second argument must be an object")
+MSG_DEF(JSMSG_WASM_BAD_IMPORT_FIELD, 2, JSEXN_TYPEERR, "import object field '{0}' is not {1}")
+MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG, 0, JSEXN_TYPEERR, "imported function signature mismatch")
+MSG_DEF(JSMSG_WASM_BAD_TABLE_VALUE, 0, JSEXN_TYPEERR, "can only assign WebAssembly exported functions to Table")
+MSG_DEF(JSMSG_WASM_BAD_I64, 0, JSEXN_TYPEERR, "cannot pass i64 to or from JS")
+MSG_DEF(JSMSG_WASM_NO_TRANSFER, 0, JSEXN_TYPEERR, "cannot transfer WebAssembly/asm.js ArrayBuffer")
+MSG_DEF(JSMSG_WASM_TEXT_FAIL, 1, JSEXN_SYNTAXERR, "wasm text error: {0}")
// Proxy
MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
+MSG_DEF(JSMSG_BAD_GETPROTOTYPEOF_TRAP_RETURN,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler returned a non-object, non-null value")
+MSG_DEF(JSMSG_INCONSISTENT_GETPROTOTYPEOF_TRAP,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler didn't return the target object's prototype")
+MSG_DEF(JSMSG_PROXY_SETPROTOTYPEOF_RETURNED_FALSE, 0, JSEXN_TYPEERR, "proxy setPrototypeOf handler returned false")
+MSG_DEF(JSMSG_PROXY_ISEXTENSIBLE_RETURNED_FALSE,0,JSEXN_TYPEERR,"proxy isExtensible handler must return the same extensibility as target")
+MSG_DEF(JSMSG_INCONSISTENT_SETPROTOTYPEOF_TRAP,0,JSEXN_TYPEERR,"proxy setPrototypeOf handler returned true, even though the target's prototype is immutable because the target is non-extensible")
MSG_DEF(JSMSG_CANT_CHANGE_EXTENSIBILITY, 0, JSEXN_TYPEERR, "can't change object's extensibility")
MSG_DEF(JSMSG_CANT_DEFINE_INVALID, 0, JSEXN_TYPEERR, "proxy can't define an incompatible property descriptor")
MSG_DEF(JSMSG_CANT_DEFINE_NEW, 0, JSEXN_TYPEERR, "proxy can't define a new property on a non-extensible object")
@@ -374,7 +405,6 @@
MSG_DEF(JSMSG_CANT_SET_NW_NC, 0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property")
MSG_DEF(JSMSG_CANT_SET_WO_SETTER, 0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter")
MSG_DEF(JSMSG_CANT_SKIP_NC, 0, JSEXN_TYPEERR, "proxy can't skip a non-configurable property")
-MSG_DEF(JSMSG_INVALID_TRAP_RESULT, 2, JSEXN_TYPEERR, "trap {1} for {0} returned an invalid result")
MSG_DEF(JSMSG_ONWKEYS_STR_SYM, 0, JSEXN_TYPEERR, "proxy [[OwnPropertyKeys]] must return an array with only string and symbol elements")
MSG_DEF(JSMSG_MUST_REPORT_SAME_VALUE, 0, JSEXN_TYPEERR, "proxy must report the same value for a non-writable, non-configurable property")
MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 0, JSEXN_TYPEERR, "proxy must report undefined for a non-configurable accessor property without a getter")
@@ -385,6 +415,7 @@
MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined")
MSG_DEF(JSMSG_PROXY_REVOKED, 0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy")
MSG_DEF(JSMSG_PROXY_ARG_REVOKED, 1, JSEXN_TYPEERR, "argument {0} cannot be a revoked proxy")
+MSG_DEF(JSMSG_BAD_TRAP, 1, JSEXN_TYPEERR, "proxy handler's {0} trap wasn't undefined, null, or callable")
// Structured cloning
MSG_DEF(JSMSG_SC_BAD_CLONE_VERSION, 0, JSEXN_ERR, "unsupported structured clone version")
@@ -392,14 +423,18 @@
MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE, 0, JSEXN_TYPEERR, "duplicate transferable for structured clone")
MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE, 0, JSEXN_TYPEERR, "invalid transferable array for structured clone")
MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 0, JSEXN_TYPEERR, "unsupported type for structured data")
-MSG_DEF(JSMSG_SC_SHMEM_MUST_TRANSFER, 0, JSEXN_TYPEERR, "SharedArrayBuffer must be explicitly transfered during structured cloning")
+MSG_DEF(JSMSG_SC_NOT_CLONABLE, 1, JSEXN_TYPEERR, "{0} cannot be cloned in this context")
+MSG_DEF(JSMSG_SC_SAB_TRANSFER, 0, JSEXN_WARN, "SharedArrayBuffer must not be in the transfer list")
+MSG_DEF(JSMSG_SC_SAB_DISABLED, 0, JSEXN_TYPEERR, "SharedArrayBuffer not cloned - shared memory disabled in receiver")
// Debugger
MSG_DEF(JSMSG_ASSIGN_FUNCTION_OR_NULL, 1, JSEXN_TYPEERR, "value assigned to {0} must be a function or null")
+MSG_DEF(JSMSG_DEBUG_BAD_AWAIT, 0, JSEXN_TYPEERR, "await expression received invalid value")
MSG_DEF(JSMSG_DEBUG_BAD_LINE, 0, JSEXN_TYPEERR, "invalid line number")
MSG_DEF(JSMSG_DEBUG_BAD_OFFSET, 0, JSEXN_TYPEERR, "invalid script offset")
MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 2, JSEXN_TYPEERR, "{0} does not refer to {1}")
MSG_DEF(JSMSG_DEBUG_BAD_RESUMPTION, 0, JSEXN_TYPEERR, "debugger resumption value must be undefined, {throw: val}, {return: val}, or null")
+MSG_DEF(JSMSG_DEBUG_BAD_YIELD, 0, JSEXN_TYPEERR, "generator yielded invalid value")
MSG_DEF(JSMSG_DEBUG_CANT_DEBUG_GLOBAL, 0, JSEXN_TYPEERR, "passing non-debuggable global to addDebuggee")
MSG_DEF(JSMSG_DEBUG_CCW_REQUIRED, 1, JSEXN_TYPEERR, "{0}: argument must be an object from a different compartment")
MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object")
@@ -408,22 +443,25 @@
MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING, 0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee")
MSG_DEF(JSMSG_DEBUG_NOT_IDLE, 0, JSEXN_ERR, "can't start debugging: a debuggee script is on the stack")
MSG_DEF(JSMSG_DEBUG_NOT_LIVE, 1, JSEXN_ERR, "{0} is not live")
-MSG_DEF(JSMSG_DEBUG_NO_SCOPE_OBJECT, 0, JSEXN_TYPEERR, "declarative Environments don't have binding objects")
-MSG_DEF(JSMSG_DEBUG_OBJECT_PROTO, 0, JSEXN_TYPEERR, "Debugger.Object.prototype is not a valid Debugger.Object")
-MSG_DEF(JSMSG_DEBUG_OBJECT_WRONG_OWNER,0, JSEXN_TYPEERR, "Debugger.Object belongs to a different Debugger")
-MSG_DEF(JSMSG_DEBUG_OPTIMIZED_OUT, 0, JSEXN_ERR, "variable has been optimized out")
+MSG_DEF(JSMSG_DEBUG_NO_ENV_OBJECT, 0, JSEXN_TYPEERR, "declarative Environments don't have binding objects")
+MSG_DEF(JSMSG_DEBUG_PROTO, 2, JSEXN_TYPEERR, "{0}.prototype is not a valid {1} instance")
+MSG_DEF(JSMSG_DEBUG_WRONG_OWNER, 1, JSEXN_TYPEERR, "{0} belongs to a different Debugger")
+MSG_DEF(JSMSG_DEBUG_OPTIMIZED_OUT, 1, JSEXN_ERR, "variable `{0}' has been optimized out")
MSG_DEF(JSMSG_DEBUG_RESUMPTION_VALUE_DISALLOWED, 0, JSEXN_TYPEERR, "resumption values are disallowed in this hook")
MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND,0, JSEXN_TYPEERR, "variable not found in environment")
MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY, 3, JSEXN_TYPEERR, "{0} is {1}{2}a global object, but a direct reference is required")
+MSG_DEF(JSMSG_DEBUGGEE_WOULD_RUN, 2, JSEXN_DEBUGGEEWOULDRUN, "debuggee `{0}:{1}' would run")
MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 0, JSEXN_TYPEERR, "value is not a function or undefined")
MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true")
-MSG_DEF(JSMSG_NOT_TRACKING_TENURINGS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingTenurePromotions to true")
MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so")
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line' and either 'displayURL', 'url', or 'source'")
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'displayURL', 'url', or 'source' property")
MSG_DEF(JSMSG_DEBUG_CANT_SET_OPT_ENV, 1, JSEXN_REFERENCEERR, "can't set `{0}' in an optimized-out environment")
MSG_DEF(JSMSG_DEBUG_INVISIBLE_COMPARTMENT, 0, JSEXN_TYPEERR, "object in compartment marked as invisible to Debugger")
MSG_DEF(JSMSG_DEBUG_CENSUS_BREAKDOWN, 1, JSEXN_TYPEERR, "unrecognized 'by' value in takeCensus breakdown: {0}")
+MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_RESOLVED, 0, JSEXN_TYPEERR, "Promise hasn't been resolved")
+MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_FULFILLED, 0, JSEXN_TYPEERR, "Promise hasn't been fulfilled")
+MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_REJECTED, 0, JSEXN_TYPEERR, "Promise hasn't been rejected")
// Tracelogger
MSG_DEF(JSMSG_TRACELOGGER_ENABLE_FAIL, 1, JSEXN_ERR, "enabling tracelogger failed: {0}")
@@ -443,14 +481,23 @@
MSG_DEF(JSMSG_UNDEFINED_CURRENCY, 0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style")
// RegExp
+MSG_DEF(JSMSG_BACK_REF_OUT_OF_RANGE, 0, JSEXN_SYNTAXERR, "back reference out of range in regular expression")
MSG_DEF(JSMSG_BAD_CLASS_RANGE, 0, JSEXN_SYNTAXERR, "invalid range in character class")
MSG_DEF(JSMSG_ESCAPE_AT_END_OF_REGEXP, 0, JSEXN_SYNTAXERR, "\\ at end of pattern")
+MSG_DEF(JSMSG_EXEC_NOT_OBJORNULL, 0, JSEXN_TYPEERR, "RegExp exec method should return object or null")
+MSG_DEF(JSMSG_INVALID_DECIMAL_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid decimal escape in regular expression")
MSG_DEF(JSMSG_INVALID_GROUP, 0, JSEXN_SYNTAXERR, "invalid regexp group")
+MSG_DEF(JSMSG_INVALID_IDENTITY_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid identity escape in regular expression")
+MSG_DEF(JSMSG_INVALID_UNICODE_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid unicode escape in regular expression")
MSG_DEF(JSMSG_MISSING_PAREN, 0, JSEXN_SYNTAXERR, "unterminated parenthetical")
MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another")
MSG_DEF(JSMSG_NOTHING_TO_REPEAT, 0, JSEXN_SYNTAXERR, "nothing to repeat")
MSG_DEF(JSMSG_NUMBERS_OUT_OF_ORDER, 0, JSEXN_SYNTAXERR, "numbers out of order in {} quantifier.")
+MSG_DEF(JSMSG_RANGE_WITH_CLASS_ESCAPE, 0, JSEXN_SYNTAXERR, "character class escape cannot be used in class range in regular expression")
+MSG_DEF(JSMSG_RAW_BRACE_IN_REGEP, 0, JSEXN_SYNTAXERR, "raw brace is not allowed in regular expression with unicode flag")
+MSG_DEF(JSMSG_RAW_BRACKET_IN_REGEP, 0, JSEXN_SYNTAXERR, "raw bracket is not allowed in regular expression with unicode flag")
MSG_DEF(JSMSG_TOO_MANY_PARENS, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression")
+MSG_DEF(JSMSG_UNICODE_OVERFLOW, 0, JSEXN_SYNTAXERR, "unicode codepoint should not be greater than 0x10FFFF in regular expression")
MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
MSG_DEF(JSMSG_UNTERM_CLASS, 0, JSEXN_SYNTAXERR, "unterminated character class")
@@ -466,30 +513,34 @@
MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS, 0, JSEXN_RANGEERR, "invalid field descriptor")
MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 0, JSEXN_ERR, "Type is too large to allocate")
MSG_DEF(JSMSG_SIMD_FAILED_CONVERSION, 0, JSEXN_RANGEERR, "SIMD conversion loses precision")
+MSG_DEF(JSMSG_SIMD_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert SIMD value to number")
+
+// Array
+MSG_DEF(JSMSG_TOO_LONG_ARRAY, 0, JSEXN_TYPEERR, "Too long array")
// Typed array
MSG_DEF(JSMSG_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
+MSG_DEF(JSMSG_NON_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected ArrayBuffer, but species constructor returned non-ArrayBuffer")
+MSG_DEF(JSMSG_SAME_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different ArrayBuffer, but species constructor returned same ArrayBuffer")
+MSG_DEF(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected ArrayBuffer with at least {0} bytes, but species constructor returns ArrayBuffer with {1} bytes")
MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
-MSG_DEF(JSMSG_TYPED_ARRAY_BAD_OBJECT, 0, JSEXN_TYPEERR, "invalid object argument")
-MSG_DEF(JSMSG_TYPED_ARRAY_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
MSG_DEF(JSMSG_TYPED_ARRAY_NEGATIVE_ARG,1, JSEXN_RANGEERR, "argument {0} must be >= 0")
MSG_DEF(JSMSG_TYPED_ARRAY_DETACHED, 0, JSEXN_TYPEERR, "attempting to access detached ArrayBuffer")
+MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS, 0, JSEXN_RANGEERR, "attempting to construct out-of-bounds TypedArray on ArrayBuffer")
+MSG_DEF(JSMSG_TYPED_ARRAY_CALL_OR_CONSTRUCT, 1, JSEXN_TYPEERR, "cannot directly {0} builtin %TypedArray%")
+MSG_DEF(JSMSG_NON_TYPED_ARRAY_RETURNED, 0, JSEXN_TYPEERR, "constructor didn't return TypedArray object")
+MSG_DEF(JSMSG_SHORT_TYPED_ARRAY_RETURNED, 2, JSEXN_TYPEERR, "expected TypedArray of at least length {0}, but constructor returned TypedArray of length {1}")
// Shared array buffer
-MSG_DEF(JSMSG_SHARED_ARRAY_BAD_OBJECT, 0, JSEXN_TYPEERR, "invalid object argument")
MSG_DEF(JSMSG_SHARED_ARRAY_BAD_LENGTH, 0, JSEXN_RANGEERR, "length argument out of range")
-
-// Shared typed array
-MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_OBJECT, 0, JSEXN_TYPEERR, "invalid object argument")
-MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_RANGEERR, "bad combination of offset, length, and element size")
-MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_ARG_RANGE, 1, JSEXN_RANGEERR, "argument {0} out of range")
-MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_LENGTH, 0, JSEXN_TYPEERR, "length argument must not be an object")
+MSG_DEF(JSMSG_NON_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected SharedArrayBuffer, but species constructor returned non-SharedArrayBuffer")
+MSG_DEF(JSMSG_SAME_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different SharedArrayBuffer, but species constructor returned same SharedArrayBuffer")
+MSG_DEF(JSMSG_SHORT_SHARED_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected SharedArrayBuffer with at least {0} bytes, but species constructor returns SharedArrayBuffer with {1} bytes")
// Reflect
MSG_DEF(JSMSG_BAD_PARSE_NODE, 0, JSEXN_INTERNALERR, "bad parse node")
// Symbol
-MSG_DEF(JSMSG_BAD_SYMBOL, 1, JSEXN_TYPEERR, "{0} is not a well-known @@-symbol")
MSG_DEF(JSMSG_SYMBOL_TO_STRING, 0, JSEXN_TYPEERR, "can't convert symbol to string")
MSG_DEF(JSMSG_SYMBOL_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert symbol to number")
@@ -497,7 +548,6 @@
MSG_DEF(JSMSG_ATOMICS_BAD_ARRAY, 0, JSEXN_TYPEERR, "invalid array type for the operation")
MSG_DEF(JSMSG_ATOMICS_TOO_LONG, 0, JSEXN_RANGEERR, "timeout value too large")
MSG_DEF(JSMSG_ATOMICS_WAIT_NOT_ALLOWED, 0, JSEXN_ERR, "waiting is not allowed on this thread")
-MSG_DEF(JSMSG_ATOMICS_BAD_INDEX, 0, JSEXN_RANGEERR, "out-of-range index for atomic access")
// XPConnect wrappers and DOM bindings
MSG_DEF(JSMSG_CANT_SET_INTERPOSED, 1, JSEXN_TYPEERR, "unable to set interposed data property '{0}'")
@@ -520,3 +570,12 @@
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 1, JSEXN_SYNTAXERR, "ambiguous import '{0}'")
MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT, 0, JSEXN_SYNTAXERR, "export not found for namespace")
MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
+MSG_DEF(JSMSG_MODULE_INSTANTIATE_FAILED, 0, JSEXN_INTERNALERR, "attempt to re-instantiate module after failure")
+MSG_DEF(JSMSG_BAD_MODULE_STATE, 0, JSEXN_INTERNALERR, "module record in unexpected state")
+
+// Promise
+MSG_DEF(JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF, 0, JSEXN_TYPEERR, "A promise cannot be resolved with itself.")
+MSG_DEF(JSMSG_PROMISE_CAPABILITY_HAS_SOMETHING_ALREADY, 0, JSEXN_TYPEERR, "GetCapabilitiesExecutor function already invoked with non-undefined values.")
+MSG_DEF(JSMSG_PROMISE_RESOLVE_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the resolve function.")
+MSG_DEF(JSMSG_PROMISE_REJECT_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the reject function.")
+MSG_DEF(JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON,0, JSEXN_INTERNALERR, "Promise rejection value is a non-unwrappable cross-compartment wrapper.")
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/CallArgs.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/CallArgs.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/CallArgs.h
@@ -6,16 +6,51 @@
/*
* Helper classes encapsulating access to the callee, |this| value, arguments,
- * and argument count for a function call.
+ * and argument count for a call/construct operation.
*
- * The intent of JS::CallArgs and JS::CallReceiver is that they be used to
- * encapsulate access to the un-abstracted |unsigned argc, Value* vp| arguments
- * to a function. It's possible (albeit deprecated) to manually index into
- * |vp| to access the callee, |this|, and arguments of a function, and to set
- * its return value. It's also possible to use the supported API of JS_CALLEE,
- * JS_THIS, JS_ARGV, JS_RVAL and JS_SET_RVAL to the same ends. But neither API
- * has the error-handling or moving-GC correctness of CallArgs or CallReceiver.
- * New code should use CallArgs and CallReceiver instead whenever possible.
+ * JS::CallArgs encapsulates access to a JSNative's un-abstracted
+ * |unsigned argc, Value* vp| arguments. The principal way to create a
+ * JS::CallArgs is using JS::CallArgsFromVp:
+ *
+ * // If provided no arguments or a non-numeric first argument, return zero.
+ * // Otherwise return |this| exactly as given, without boxing.
+ * static bool
+ * Func(JSContext* cx, unsigned argc, JS::Value* vp)
+ * {
+ * JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ *
+ * // Guard against no arguments or a non-numeric arg0.
+ * if (args.length() == 0 || !args[0].isNumber()) {
+ * args.rval().setInt32(0);
+ * return true;
+ * }
+ *
+ * // Access to the callee must occur before accessing/setting
+ * // the return value.
+ * JSObject& callee = args.callee();
+ * args.rval().setObject(callee);
+ *
+ * // callee() and calleev() will now assert.
+ *
+ * // It's always fine to access thisv().
+ * HandleValue thisv = args.thisv();
+ * args.rval().set(thisv);
+ *
+ * // As the return value was last set to |this|, returns |this|.
+ * return true;
+ * }
+ *
+ * CallArgs is exposed publicly and used internally. Not all parts of its
+ * public interface are meant to be used by embedders! See inline comments to
+ * for details.
+ *
+ * It's possible (albeit deprecated) to manually index into |vp| to access the
+ * callee, |this|, and arguments of a function, and to set its return value.
+ * It's also possible to use the supported API of JS_CALLEE, JS_THIS, JS_ARGV,
+ * JS_RVAL, and JS_SET_RVAL to the same ends.
+ *
+ * But neither API has the error-handling or moving-GC correctness of CallArgs.
+ * New code should use CallArgs instead whenever possible.
*
* The eventual plan is to change JSNative to take |const CallArgs&| directly,
* for automatic assertion of correct use and to make calling functions more
@@ -42,118 +77,99 @@
typedef bool
(* JSNative)(JSContext* cx, unsigned argc, JS::Value* vp);
-/*
- * Compute |this| for the |vp| inside a JSNative, either boxing primitives or
- * replacing with the global object as necessary.
- *
- * This method will go away at some point: instead use |args.thisv()|. If the
- * value is an object, no further work is required. If that value is |null| or
- * |undefined|, use |JS_GetGlobalForObject| to compute the global object. If
- * the value is some other primitive, use |JS_ValueToObject| to box it.
- */
-extern JS_PUBLIC_API(JS::Value)
-JS_ComputeThis(JSContext* cx, JS::Value* vp);
-
namespace JS {
extern JS_PUBLIC_DATA(const HandleValue) UndefinedHandleValue;
+namespace detail {
+
/*
- * JS::CallReceiver encapsulates access to the callee, |this|, and eventual
- * return value for a function call. The principal way to create a
- * CallReceiver is using JS::CallReceiverFromVp:
- *
- * static bool
- * FunctionReturningThis(JSContext* cx, unsigned argc, JS::Value* vp)
- * {
- * JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
- *
- * // Access to the callee must occur before accessing/setting
- * // the return value.
- * JSObject& callee = rec.callee();
- * rec.rval().set(JS::ObjectValue(callee));
- *
- * // callee() and calleev() will now assert.
- *
- * // It's always fine to access thisv().
- * HandleValue thisv = rec.thisv();
- * rec.rval().set(thisv);
- *
- * // As the return value was last set to |this|, returns |this|.
- * return true;
- * }
- *
- * A note on JS_ComputeThis and JS_THIS_OBJECT: these methods currently aren't
- * part of the CallReceiver interface. We will likely add them at some point.
- * Until then, you should probably continue using |vp| directly for these two
- * cases.
- *
- * CallReceiver is exposed publicly and used internally. Not all parts of its
- * public interface are meant to be used by embedders! See inline comments to
- * for details.
+ * Compute |this| for the |vp| inside a JSNative, either boxing primitives or
+ * replacing with the global object as necessary.
*/
-
-namespace detail {
+extern JS_PUBLIC_API(Value)
+ComputeThis(JSContext* cx, JS::Value* vp);
#ifdef JS_DEBUG
extern JS_PUBLIC_API(void)
-CheckIsValidConstructible(Value v);
+CheckIsValidConstructible(const Value& v);
#endif
-enum UsedRval { IncludeUsedRval, NoUsedRval };
-
-template<UsedRval WantUsedRval>
-class MOZ_STACK_CLASS UsedRvalBase;
-
-template<>
-class MOZ_STACK_CLASS UsedRvalBase<IncludeUsedRval>
+class MOZ_STACK_CLASS IncludeUsedRval
{
protected:
+#ifdef JS_DEBUG
mutable bool usedRval_;
void setUsedRval() const { usedRval_ = true; }
void clearUsedRval() const { usedRval_ = false; }
+ void assertUnusedRval() const { MOZ_ASSERT(!usedRval_); }
+#else
+ void setUsedRval() const {}
+ void clearUsedRval() const {}
+ void assertUnusedRval() const {}
+#endif
};
-template<>
-class MOZ_STACK_CLASS UsedRvalBase<NoUsedRval>
+class MOZ_STACK_CLASS NoUsedRval
{
protected:
void setUsedRval() const {}
void clearUsedRval() const {}
+ void assertUnusedRval() const {}
};
-template<UsedRval WantUsedRval>
-class MOZ_STACK_CLASS CallReceiverBase : public UsedRvalBase<
-#ifdef JS_DEBUG
- WantUsedRval
-#else
- NoUsedRval
-#endif
- >
+template<class WantUsedRval>
+class MOZ_STACK_CLASS CallArgsBase : public WantUsedRval
{
+ static_assert(mozilla::IsSame<WantUsedRval, IncludeUsedRval>::value ||
+ mozilla::IsSame<WantUsedRval, NoUsedRval>::value,
+ "WantUsedRval can only be IncludeUsedRval or NoUsedRval");
+
protected:
Value* argv_;
+ unsigned argc_;
+ bool constructing_;
public:
- /*
- * Returns the function being called, as an object. Must not be called
- * after rval() has been used!
- */
- JSObject& callee() const {
- MOZ_ASSERT(!this->usedRval_);
- return argv_[-2].toObject();
- }
+ // CALLEE ACCESS
/*
* Returns the function being called, as a value. Must not be called after
* rval() has been used!
*/
HandleValue calleev() const {
- MOZ_ASSERT(!this->usedRval_);
+ this->assertUnusedRval();
return HandleValue::fromMarkedLocation(&argv_[-2]);
}
/*
+ * Returns the function being called, as an object. Must not be called
+ * after rval() has been used!
+ */
+ JSObject& callee() const {
+ return calleev().toObject();
+ }
+
+ // CALLING/CONSTRUCTING-DIFFERENTIATIONS
+
+ bool isConstructing() const {
+ if (!argv_[-1].isMagic())
+ return false;
+
+#ifdef JS_DEBUG
+ if (!this->usedRval_)
+ CheckIsValidConstructible(calleev());
+#endif
+
+ return true;
+ }
+
+ MutableHandleValue newTarget() const {
+ MOZ_ASSERT(constructing_);
+ return MutableHandleValue::fromMarkedLocation(&this->argv_[argc_]);
+ }
+
+ /*
* Returns the |this| value passed to the function. This method must not
* be called when the function is being called as a constructor via |new|.
* The value may or may not be an object: it is the individual function's
@@ -170,17 +186,40 @@
if (thisv().isObject())
return thisv();
- return JS_ComputeThis(cx, base());
+ return ComputeThis(cx, base());
}
- bool isConstructing() const {
-#ifdef JS_DEBUG
- if (this->usedRval_)
- CheckIsValidConstructible(calleev());
-#endif
- return argv_[-1].isMagic();
+ // ARGUMENTS
+
+ /* Returns the number of arguments. */
+ unsigned length() const { return argc_; }
+
+ /* Returns the i-th zero-indexed argument. */
+ MutableHandleValue operator[](unsigned i) const {
+ MOZ_ASSERT(i < argc_);
+ return MutableHandleValue::fromMarkedLocation(&this->argv_[i]);
+ }
+
+ /*
+ * Returns the i-th zero-indexed argument, or |undefined| if there's no
+ * such argument.
+ */
+ HandleValue get(unsigned i) const {
+ return i < length()
+ ? HandleValue::fromMarkedLocation(&this->argv_[i])
+ : UndefinedHandleValue;
+ }
+
+ /*
+ * Returns true if the i-th zero-indexed argument is present and is not
+ * |undefined|.
+ */
+ bool hasDefined(unsigned i) const {
+ return i < argc_ && !this->argv_[i].isUndefined();
}
+ // RETURN VALUE
+
/*
* Returns the currently-set return value. The initial contents of this
* value are unspecified. Once this method has been called, callee() and
@@ -198,135 +237,41 @@
}
public:
- // These methods are only intended for internal use. Embedders shouldn't
- // use them!
-
- Value* base() const { return argv_ - 2; }
-
- Value* spAfterCall() const {
- this->setUsedRval();
- return argv_ - 1;
- }
-
- public:
// These methods are publicly exposed, but they are *not* to be used when
// implementing a JSNative method and encapsulating access to |vp| within
// it. You probably don't want to use these!
- void setCallee(Value aCalleev) const {
+ void setCallee(const Value& aCalleev) const {
this->clearUsedRval();
argv_[-2] = aCalleev;
}
- void setThis(Value aThisv) const {
+ void setThis(const Value& aThisv) const {
argv_[-1] = aThisv;
}
MutableHandleValue mutableThisv() const {
return MutableHandleValue::fromMarkedLocation(&argv_[-1]);
}
-};
-
-} // namespace detail
-
-class MOZ_STACK_CLASS CallReceiver : public detail::CallReceiverBase<detail::IncludeUsedRval>
-{
- private:
- friend CallReceiver CallReceiverFromVp(Value* vp);
- friend CallReceiver CallReceiverFromArgv(Value* argv);
-};
-
-MOZ_ALWAYS_INLINE CallReceiver
-CallReceiverFromArgv(Value* argv)
-{
- CallReceiver receiver;
- receiver.clearUsedRval();
- receiver.argv_ = argv;
- return receiver;
-}
-
-MOZ_ALWAYS_INLINE CallReceiver
-CallReceiverFromVp(Value* vp)
-{
- return CallReceiverFromArgv(vp + 2);
-}
-
-/*
- * JS::CallArgs encapsulates everything JS::CallReceiver does, plus access to
- * the function call's arguments. The principal way to create a CallArgs is
- * like so, using JS::CallArgsFromVp:
- *
- * static bool
- * FunctionReturningArgcTimesArg0(JSContext* cx, unsigned argc, JS::Value* vp)
- * {
- * JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
- *
- * // Guard against no arguments or a non-numeric arg0.
- * if (args.length() == 0 || !args[0].isNumber()) {
- * args.rval().setInt32(0);
- * return true;
- * }
- *
- * args.rval().set(JS::NumberValue(args.length() * args[0].toNumber()));
- * return true;
- * }
- *
- * CallArgs is exposed publicly and used internally. Not all parts of its
- * public interface are meant to be used by embedders! See inline comments to
- * for details.
- */
-namespace detail {
-
-template<UsedRval WantUsedRval>
-class MOZ_STACK_CLASS CallArgsBase :
- public mozilla::Conditional<WantUsedRval == detail::IncludeUsedRval,
- CallReceiver,
- CallReceiverBase<NoUsedRval> >::Type
-{
- protected:
- unsigned argc_;
- bool constructing_;
public:
- /* Returns the number of arguments. */
- unsigned length() const { return argc_; }
+ // These methods are publicly exposed, but we're unsure of the interfaces
+ // (because they're hackish and drop assertions). Avoid using these if you
+ // can.
- /* Returns the i-th zero-indexed argument. */
- MutableHandleValue operator[](unsigned i) const {
- MOZ_ASSERT(i < argc_);
- return MutableHandleValue::fromMarkedLocation(&this->argv_[i]);
- }
+ Value* array() const { return argv_; }
+ Value* end() const { return argv_ + argc_ + constructing_; }
- /*
- * Returns the i-th zero-indexed argument, or |undefined| if there's no
- * such argument.
- */
- HandleValue get(unsigned i) const {
- return i < length()
- ? HandleValue::fromMarkedLocation(&this->argv_[i])
- : UndefinedHandleValue;
- }
+ public:
+ // These methods are only intended for internal use. Embedders shouldn't
+ // use them!
- /*
- * Returns true if the i-th zero-indexed argument is present and is not
- * |undefined|.
- */
- bool hasDefined(unsigned i) const {
- return i < argc_ && !this->argv_[i].isUndefined();
- }
+ Value* base() const { return argv_ - 2; }
- MutableHandleValue newTarget() const {
- MOZ_ASSERT(constructing_);
- return MutableHandleValue::fromMarkedLocation(&this->argv_[argc_]);
+ Value* spAfterCall() const {
+ this->setUsedRval();
+ return argv_ - 1;
}
-
- public:
- // These methods are publicly exposed, but we're less sure of the interface
- // here than we'd like (because they're hackish and drop assertions). Try
- // to avoid using these if you can.
-
- Value* array() const { return this->argv_; }
- Value* end() const { return this->argv_ + argc_ + constructing_; }
};
} // namespace detail
@@ -343,6 +288,10 @@
args.argv_ = argv;
args.argc_ = argc;
args.constructing_ = constructing;
+#ifdef DEBUG
+ for (unsigned i = 0; i < argc; ++i)
+ MOZ_ASSERT_IF(argv[i].isMarkable(), !GCThingIsMarkedGray(GCCellPtr(argv[i])));
+#endif
return args;
}
@@ -351,7 +300,7 @@
* Returns true if there are at least |required| arguments passed in. If
* false, it reports an error message on the context.
*/
- bool requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const;
+ JS_PUBLIC_API(bool) requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const;
};
@@ -379,19 +328,30 @@
* take a const JS::CallArgs&.
*/
-#define JS_THIS_OBJECT(cx,vp) (JS_THIS(cx,vp).toObjectOrNull())
-
/*
+ * Return |this| if |this| is an object. Otherwise, return the global object
+ * if |this| is null or undefined, and finally return a boxed version of any
+ * other primitive.
+ *
* Note: if this method returns null, an error has occurred and must be
* propagated or caught.
*/
MOZ_ALWAYS_INLINE JS::Value
JS_THIS(JSContext* cx, JS::Value* vp)
{
- return vp[1].isPrimitive() ? JS_ComputeThis(cx, vp) : vp[1];
+ return vp[1].isPrimitive() ? JS::detail::ComputeThis(cx, vp) : vp[1];
}
/*
+ * A note on JS_THIS_OBJECT: no equivalent method is part of the CallArgs
+ * interface, and we're unlikely to add one (functions shouldn't be implicitly
+ * exposing the global object to arbitrary callers). Continue using |vp|
+ * directly for this case, but be aware this API will eventually be replaced
+ * with a function that operates directly upon |args.thisv()|.
+ */
+#define JS_THIS_OBJECT(cx,vp) (JS_THIS(cx,vp).toObjectOrNull())
+
+/*
* |this| is passed to functions in ES5 without change. Functions themselves
* do any post-processing they desire to box |this|, compute the global object,
* &c. This macro retrieves a function's unboxed |this| value.
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/CharacterEncoding.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/CharacterEncoding.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/CharacterEncoding.h
@@ -31,6 +31,8 @@
typedef mozilla::Range<Latin1Char> Base;
public:
+ using CharT = Latin1Char;
+
Latin1Chars() : Base() {}
Latin1Chars(char* aBytes, size_t aLength) : Base(reinterpret_cast<Latin1Char*>(aBytes), aLength) {}
Latin1Chars(const Latin1Char* aBytes, size_t aLength)
@@ -49,6 +51,8 @@
typedef mozilla::RangedPtr<Latin1Char> Base;
public:
+ using CharT = Latin1Char;
+
Latin1CharsZ() : Base(nullptr, 0) {}
Latin1CharsZ(char* aBytes, size_t aLength)
@@ -73,6 +77,8 @@
typedef mozilla::Range<unsigned char> Base;
public:
+ using CharT = unsigned char;
+
UTF8Chars() : Base() {}
UTF8Chars(char* aBytes, size_t aLength)
: Base(reinterpret_cast<unsigned char*>(aBytes), aLength)
@@ -90,6 +96,8 @@
typedef mozilla::RangedPtr<unsigned char> Base;
public:
+ using CharT = unsigned char;
+
UTF8CharsZ() : Base(nullptr, 0) {}
UTF8CharsZ(char* aBytes, size_t aLength)
@@ -110,6 +118,43 @@
};
/*
+ * A wrapper for a "const char*" that is encoded using UTF-8.
+ * This class does not manage ownership of the data; that is left
+ * to others. This differs from UTF8CharsZ in that the chars are
+ * const and it allows assignment.
+ */
+class JS_PUBLIC_API(ConstUTF8CharsZ)
+{
+ const char* data_;
+
+ public:
+ using CharT = unsigned char;
+
+ ConstUTF8CharsZ() : data_(nullptr)
+ {}
+
+ ConstUTF8CharsZ(const char* aBytes, size_t aLength)
+ : data_(aBytes)
+ {
+ MOZ_ASSERT(aBytes[aLength] == '\0');
+#ifdef DEBUG
+ validate(aLength);
+#endif
+ }
+
+ const void* get() const { return data_; }
+
+ const char* c_str() const { return data_; }
+
+ explicit operator bool() const { return data_ != nullptr; }
+
+ private:
+#ifdef DEBUG
+ void validate(size_t aLength);
+#endif
+};
+
+/*
* SpiderMonkey uses a 2-byte character representation: it is a
* 2-byte-at-a-time view of a UTF-16 byte stream. This is similar to UCS-2,
* but unlike UCS-2, we do not strip UTF-16 extension bytes. This allows a
@@ -122,6 +167,8 @@
typedef mozilla::Range<char16_t> Base;
public:
+ using CharT = char16_t;
+
TwoByteChars() : Base() {}
TwoByteChars(char16_t* aChars, size_t aLength) : Base(aChars, aLength) {}
TwoByteChars(const char16_t* aChars, size_t aLength) : Base(const_cast<char16_t*>(aChars), aLength) {}
@@ -135,6 +182,8 @@
typedef mozilla::RangedPtr<char16_t> Base;
public:
+ using CharT = char16_t;
+
TwoByteCharsZ() : Base(nullptr, 0) {}
TwoByteCharsZ(char16_t* chars, size_t length)
@@ -156,6 +205,8 @@
typedef mozilla::Range<const char16_t> Base;
public:
+ using CharT = char16_t;
+
ConstTwoByteChars() : Base() {}
ConstTwoByteChars(const char16_t* aChars, size_t aLength) : Base(aChars, aLength) {}
};
@@ -174,11 +225,18 @@
LossyTwoByteCharsToNewLatin1CharsZ(js::ExclusiveContext* cx,
const mozilla::Range<const char16_t> tbchars);
+inline Latin1CharsZ
+LossyTwoByteCharsToNewLatin1CharsZ(js::ExclusiveContext* cx, const char16_t* begin, size_t length)
+{
+ const mozilla::Range<const char16_t> tbchars(begin, length);
+ return JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars);
+}
+
template <typename CharT>
extern UTF8CharsZ
-CharsToNewUTF8CharsZ(js::ExclusiveContext* maybeCx, const mozilla::Range<const CharT> chars);
+CharsToNewUTF8CharsZ(js::ExclusiveContext* maybeCx, const mozilla::Range<CharT> chars);
-uint32_t
+JS_PUBLIC_API(uint32_t)
Utf8ToOneUcs4Char(const uint8_t* utf8Buffer, int utf8Length);
/*
@@ -187,17 +245,26 @@
* - On success, returns a malloc'd TwoByteCharsZ, and updates |outlen| to hold
* its length; the length value excludes the trailing null.
*/
-extern TwoByteCharsZ
+extern JS_PUBLIC_API(TwoByteCharsZ)
UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
/*
+ * Like UTF8CharsToNewTwoByteCharsZ, but for ConstUTF8CharsZ.
+ */
+extern JS_PUBLIC_API(TwoByteCharsZ)
+UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, size_t* outlen);
+
+/*
* The same as UTF8CharsToNewTwoByteCharsZ(), except that any malformed UTF-8 characters
* will be replaced by \uFFFD. No exception will be thrown for malformed UTF-8
* input.
*/
-extern TwoByteCharsZ
+extern JS_PUBLIC_API(TwoByteCharsZ)
LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
+extern JS_PUBLIC_API(TwoByteCharsZ)
+LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, size_t* outlen);
+
/*
* Returns the length of the char buffer required to encode |s| as UTF8.
* Does not include the null-terminator.
@@ -206,11 +273,62 @@
GetDeflatedUTF8StringLength(JSFlatString* s);
/*
- * Encode |src| as UTF8. The caller must ensure |dst| has enough space.
- * Does not write the null terminator.
+ * Encode |src| as UTF8. The caller must either ensure |dst| has enough space
+ * to encode the entire string or pass the length of the buffer as |dstlenp|,
+ * in which case the function will encode characters from the string until
+ * the buffer is exhausted. Does not write the null terminator.
+ *
+ * If |dstlenp| is provided, it will be updated to hold the number of bytes
+ * written to the buffer. If |numcharsp| is provided, it will be updated to hold
+ * the number of Unicode characters written to the buffer (which can be less
+ * than the length of the string, if the buffer is exhausted before the string
+ * is fully encoded).
*/
JS_PUBLIC_API(void)
-DeflateStringToUTF8Buffer(JSFlatString* src, mozilla::RangedPtr<char> dst);
+DeflateStringToUTF8Buffer(JSFlatString* src, mozilla::RangedPtr<char> dst,
+ size_t* dstlenp = nullptr, size_t* numcharsp = nullptr);
+
+/*
+ * The smallest character encoding capable of fully representing a particular
+ * string.
+ */
+enum class SmallestEncoding {
+ ASCII,
+ Latin1,
+ UTF16
+};
+
+/*
+ * Returns the smallest encoding possible for the given string: if all
+ * codepoints are <128 then ASCII, otherwise if all codepoints are <256
+ * Latin-1, else UTF16.
+ */
+JS_PUBLIC_API(SmallestEncoding)
+FindSmallestEncoding(UTF8Chars utf8);
+
+/*
+ * Return a null-terminated Latin-1 string copied from the input string,
+ * storing its length (excluding null terminator) in |*outlen|. Fail and
+ * report an error if the string contains non-Latin-1 codepoints. Returns
+ * Latin1CharsZ() on failure.
+ */
+extern JS_PUBLIC_API(Latin1CharsZ)
+UTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
+
+/*
+ * Return a null-terminated Latin-1 string copied from the input string,
+ * storing its length (excluding null terminator) in |*outlen|. Non-Latin-1
+ * codepoints are replaced by '?'. Returns Latin1CharsZ() on failure.
+ */
+extern JS_PUBLIC_API(Latin1CharsZ)
+LossyUTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
+
+/*
+ * Returns true if all characters in the given null-terminated string are
+ * ASCII, i.e. < 0x80, false otherwise.
+ */
+extern JS_PUBLIC_API(bool)
+StringIsASCII(const char* s);
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Class.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Class.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Class.h
@@ -9,8 +9,6 @@
#ifndef js_Class_h
#define js_Class_h
-#include "mozilla/DebugOnly.h"
-
#include "jstypes.h"
#include "js/CallArgs.h"
@@ -42,9 +40,7 @@
namespace JS {
-template <typename T>
-class AutoVectorRooter;
-typedef AutoVectorRooter<jsid> AutoIdVector;
+class AutoIdVector;
/**
* The answer to a successful query as to whether an object is an Array per
@@ -337,8 +333,8 @@
* (e.g., the DOM attributes for a given node reflected as obj) on demand.
*
* JS looks for a property in an object, and if not found, tries to resolve
- * the given id. *resolvedp should be set to true iff the property was
- * was defined on |obj|.
+ * the given id. *resolvedp should be set to true iff the property was defined
+ * on |obj|.
*/
typedef bool
(* JSResolveOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
@@ -368,7 +364,7 @@
/** Finalizes external strings created by JS_NewExternalString. */
struct JSStringFinalizer {
- void (*finalize)(const JSStringFinalizer* fin, char16_t* chars);
+ void (*finalize)(JS::Zone* zone, const JSStringFinalizer* fin, char16_t* chars);
};
/**
@@ -383,8 +379,8 @@
/**
* Function type for trace operation of the class called to enumerate all
* traceable things reachable from obj's private data structure. For each such
- * thing, a trace implementation must call one of the JS_Call*Tracer variants
- * on the thing.
+ * thing, a trace implementation must call JS::TraceEdge on the thing's
+ * location.
*
* JSTraceOp implementation can assume that no other threads mutates object
* state. It must not change state of the object or corresponding native
@@ -412,7 +408,7 @@
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* DefinePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::Handle<JSPropertyDescriptor> desc,
+ JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
typedef bool
(* HasPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
@@ -424,7 +420,7 @@
JS::HandleValue receiver, JS::ObjectOpResult& result);
typedef bool
(* GetOwnPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
typedef bool
(* DeletePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::ObjectOpResult& result);
@@ -453,15 +449,25 @@
JS::Value* vp_;
uint32_t index_;
- mozilla::DebugOnly<uint32_t> length_;
+#ifdef DEBUG
+ uint32_t length_;
+#endif
GetBehavior getBehavior_;
public:
ElementAdder(JSContext* cx, JSObject* obj, uint32_t length, GetBehavior behavior)
- : resObj_(cx, obj), vp_(nullptr), index_(0), length_(length), getBehavior_(behavior)
+ : resObj_(cx, obj), vp_(nullptr), index_(0),
+#ifdef DEBUG
+ length_(length),
+#endif
+ getBehavior_(behavior)
{}
ElementAdder(JSContext* cx, JS::Value* vp, uint32_t length, GetBehavior behavior)
- : resObj_(cx), vp_(vp), index_(0), length_(length), getBehavior_(behavior)
+ : resObj_(cx), vp_(vp), index_(0),
+#ifdef DEBUG
+ length_(length),
+#endif
+ getBehavior_(behavior)
{}
GetBehavior getBehavior() const { return getBehavior_; }
@@ -477,23 +483,55 @@
typedef void
(* FinalizeOp)(FreeOp* fop, JSObject* obj);
-#define JS_CLASS_MEMBERS(FinalizeOpType) \
- const char* name; \
- uint32_t flags; \
- \
- /* Function pointer members (may be null). */ \
- JSAddPropertyOp addProperty; \
- JSDeletePropertyOp delProperty; \
- JSGetterOp getProperty; \
- JSSetterOp setProperty; \
- JSEnumerateOp enumerate; \
- JSResolveOp resolve; \
- JSMayResolveOp mayResolve; \
- FinalizeOpType finalize; \
- JSNative call; \
- JSHasInstanceOp hasInstance; \
- JSNative construct; \
- JSTraceOp trace
+// The special treatment of |finalize| and |trace| is necessary because if we
+// assign either of those hooks to a local variable and then call it -- as is
+// done with the other hooks -- the GC hazard analysis gets confused.
+#define JS_CLASS_MEMBERS(ClassOpsType, FreeOpType) \
+ const char* name; \
+ uint32_t flags; \
+ const ClassOpsType* cOps; \
+ \
+ JSAddPropertyOp getAddProperty() const { return cOps ? cOps->addProperty : nullptr; } \
+ JSDeletePropertyOp getDelProperty() const { return cOps ? cOps->delProperty : nullptr; } \
+ JSGetterOp getGetProperty() const { return cOps ? cOps->getProperty : nullptr; } \
+ JSSetterOp getSetProperty() const { return cOps ? cOps->setProperty : nullptr; } \
+ JSEnumerateOp getEnumerate() const { return cOps ? cOps->enumerate : nullptr; } \
+ JSResolveOp getResolve() const { return cOps ? cOps->resolve : nullptr; } \
+ JSMayResolveOp getMayResolve() const { return cOps ? cOps->mayResolve : nullptr; } \
+ JSNative getCall() const { return cOps ? cOps->call : nullptr; } \
+ JSHasInstanceOp getHasInstance() const { return cOps ? cOps->hasInstance : nullptr; } \
+ JSNative getConstruct() const { return cOps ? cOps->construct : nullptr; } \
+ \
+ bool hasFinalize() const { return cOps && cOps->finalize; } \
+ bool hasTrace() const { return cOps && cOps->trace; } \
+ \
+ bool isTrace(JSTraceOp trace) const { return cOps && cOps->trace == trace; } \
+ \
+ void doFinalize(FreeOpType* fop, JSObject* obj) const { \
+ MOZ_ASSERT(cOps && cOps->finalize); \
+ cOps->finalize(fop, obj); \
+ } \
+ void doTrace(JSTracer* trc, JSObject* obj) const { \
+ MOZ_ASSERT(cOps && cOps->trace); \
+ cOps->trace(trc, obj); \
+ }
+
+struct ClassOps
+{
+ /* Function pointer members (may be null). */
+ JSAddPropertyOp addProperty;
+ JSDeletePropertyOp delProperty;
+ JSGetterOp getProperty;
+ JSSetterOp setProperty;
+ JSEnumerateOp enumerate;
+ JSResolveOp resolve;
+ JSMayResolveOp mayResolve;
+ FinalizeOp finalize;
+ JSNative call;
+ JSHasInstanceOp hasInstance;
+ JSNative construct;
+ JSTraceOp trace;
+};
/** Callback for the creation of constructor and prototype objects. */
typedef JSObject* (*ClassObjectCreationOp)(JSContext* cx, JSProtoKey key);
@@ -516,11 +554,11 @@
FinishClassInitOp finishInit_;
uintptr_t flags;
- static const size_t ParentKeyWidth = JSCLASS_CACHED_PROTO_WIDTH;
+ static const size_t ProtoKeyWidth = JSCLASS_CACHED_PROTO_WIDTH;
- static const uintptr_t ParentKeyMask = (1 << ParentKeyWidth) - 1;
- static const uintptr_t DontDefineConstructor = 1 << ParentKeyWidth;
- static const uintptr_t IsDelegated = 1 << (ParentKeyWidth + 1);
+ static const uintptr_t ProtoKeyMask = (1 << ProtoKeyWidth) - 1;
+ static const uintptr_t DontDefineConstructor = 1 << ProtoKeyWidth;
+ static const uintptr_t IsDelegated = 1 << (ProtoKeyWidth + 1);
bool defined() const { return !!createConstructor_; }
@@ -528,14 +566,16 @@
return (flags & IsDelegated);
}
- bool dependent() const {
+ // The ProtoKey this class inherits from.
+ JSProtoKey inheritanceProtoKey() const {
MOZ_ASSERT(defined());
- return (flags & ParentKeyMask);
- }
-
- JSProtoKey parentKey() const {
static_assert(JSProto_Null == 0, "zeroed key must be null");
- return JSProtoKey(flags & ParentKeyMask);
+
+ // Default: Inherit from Object.
+ if (!(flags & ProtoKeyMask))
+ return JSProto_Object;
+
+ return JSProtoKey(flags & ProtoKeyMask);
}
bool shouldDefineConstructor() const {
@@ -588,12 +628,6 @@
struct ClassExtension
{
/**
- * isWrappedNative is true only if the class is an XPCWrappedNative.
- * WeakMaps use this to override the wrapper disposal optimization.
- */
- bool isWrappedNative;
-
- /**
* If an object is used as a key in a weakmap, it may be desirable for the
* garbage collector to keep that object around longer than it otherwise
* would. A common case is when the key is a wrapper around an object in
@@ -624,28 +658,26 @@
return reinterpret_cast<ClassObjectCreationOp>(const_cast<ClassSpec*>(spec));
}
-#define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
-#define JS_NULL_CLASS_EXT {false,nullptr}
+#define JS_NULL_CLASS_SPEC nullptr
+#define JS_NULL_CLASS_EXT nullptr
struct ObjectOps
{
- LookupPropertyOp lookupProperty;
- DefinePropertyOp defineProperty;
- HasPropertyOp hasProperty;
- GetPropertyOp getProperty;
- SetPropertyOp setProperty;
- GetOwnPropertyOp getOwnPropertyDescriptor;
- DeletePropertyOp deleteProperty;
- WatchOp watch;
- UnwatchOp unwatch;
- GetElementsOp getElements;
- JSNewEnumerateOp enumerate;
- JSFunToStringOp funToString;
-};
-
-#define JS_NULL_OBJECT_OPS \
- {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, \
- nullptr, nullptr, nullptr, nullptr}
+ LookupPropertyOp lookupProperty;
+ DefinePropertyOp defineProperty;
+ HasPropertyOp hasProperty;
+ GetPropertyOp getProperty;
+ SetPropertyOp setProperty;
+ GetOwnPropertyOp getOwnPropertyDescriptor;
+ DeletePropertyOp deleteProperty;
+ WatchOp watch;
+ UnwatchOp unwatch;
+ GetElementsOp getElements;
+ JSNewEnumerateOp enumerate;
+ JSFunToStringOp funToString;
+};
+
+#define JS_NULL_OBJECT_OPS nullptr
} // namespace js
@@ -653,19 +685,54 @@
typedef void (*JSClassInternal)();
+struct JSClassOps
+{
+ /* Function pointer members (may be null). */
+ JSAddPropertyOp addProperty;
+ JSDeletePropertyOp delProperty;
+ JSGetterOp getProperty;
+ JSSetterOp setProperty;
+ JSEnumerateOp enumerate;
+ JSResolveOp resolve;
+ JSMayResolveOp mayResolve;
+ JSFinalizeOp finalize;
+ JSNative call;
+ JSHasInstanceOp hasInstance;
+ JSNative construct;
+ JSTraceOp trace;
+};
+
+#define JS_NULL_CLASS_OPS nullptr
+
struct JSClass {
- JS_CLASS_MEMBERS(JSFinalizeOp);
+ JS_CLASS_MEMBERS(JSClassOps, JSFreeOp);
- void* reserved[23];
+ void* reserved[3];
};
#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot
-#define JSCLASS_DELAY_METADATA_CALLBACK (1<<1) // class's initialization code
+#define JSCLASS_DELAY_METADATA_BUILDER (1<<1) // class's initialization code
// will call
// SetNewObjectMetadata itself
+#define JSCLASS_IS_WRAPPED_NATIVE (1<<2) // class is an XPCWrappedNative.
+ // WeakMaps use this to override
+ // the wrapper disposal
+ // mechanism.
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) // private is (nsISupports*)
#define JSCLASS_IS_DOMJSCLASS (1<<4) // objects are DOM
-// Bit 5 is unused.
+#define JSCLASS_HAS_XRAYED_CONSTRUCTOR (1<<5) // if wrapped by an xray
+ // wrapper, the builtin
+ // class's constructor won't
+ // be unwrapped and invoked.
+ // Instead, the constructor is
+ // resolved in the caller's
+ // compartment and invoked
+ // with a wrapped newTarget.
+ // The constructor has to
+ // detect and handle this
+ // situation.
+ // See PromiseConstructor for
+ // details.
#define JSCLASS_EMULATES_UNDEFINED (1<<6) // objects of this class act
// like the value undefined,
// in some contexts
@@ -700,6 +767,7 @@
#define JSCLASS_USERBIT3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+7))
#define JSCLASS_BACKGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+8))
+#define JSCLASS_FOREGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+9))
// Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see
// below.
@@ -719,7 +787,7 @@
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
#define JSCLASS_GLOBAL_SLOT_COUNT \
- (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 36)
+ (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 39)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
@@ -745,10 +813,10 @@
struct Class
{
- JS_CLASS_MEMBERS(FinalizeOp);
- ClassSpec spec;
- ClassExtension ext;
- ObjectOps ops;
+ JS_CLASS_MEMBERS(js::ClassOps, FreeOp);
+ const ClassSpec* spec;
+ const ClassExtension* ext;
+ const ObjectOps* oOps;
/*
* Objects of this class aren't native objects. They don't have Shapes that
@@ -777,7 +845,7 @@
bool nonProxyCallable() const {
MOZ_ASSERT(!isProxy());
- return isJSFunction() || call;
+ return isJSFunction() || getCall();
}
bool isProxy() const {
@@ -788,40 +856,89 @@
return flags & JSCLASS_IS_DOMJSCLASS;
}
- bool shouldDelayMetadataCallback() const {
- return flags & JSCLASS_DELAY_METADATA_CALLBACK;
+ bool shouldDelayMetadataBuilder() const {
+ return flags & JSCLASS_DELAY_METADATA_BUILDER;
+ }
+
+ bool isWrappedNative() const {
+ return flags & JSCLASS_IS_WRAPPED_NATIVE;
}
static size_t offsetOfFlags() { return offsetof(Class, flags); }
+
+ bool specDefined() const { return spec ? spec->defined() : false; }
+ JSProtoKey specInheritanceProtoKey()
+ const { return spec ? spec->inheritanceProtoKey() : JSProto_Null; }
+ bool specShouldDefineConstructor()
+ const { return spec ? spec->shouldDefineConstructor() : true; }
+ ClassObjectCreationOp specCreateConstructorHook()
+ const { return spec ? spec->createConstructorHook() : nullptr; }
+ ClassObjectCreationOp specCreatePrototypeHook()
+ const { return spec ? spec->createPrototypeHook() : nullptr; }
+ const JSFunctionSpec* specConstructorFunctions()
+ const { return spec ? spec->constructorFunctions() : nullptr; }
+ const JSPropertySpec* specConstructorProperties()
+ const { return spec ? spec->constructorProperties() : nullptr; }
+ const JSFunctionSpec* specPrototypeFunctions()
+ const { return spec ? spec->prototypeFunctions() : nullptr; }
+ const JSPropertySpec* specPrototypeProperties()
+ const { return spec ? spec->prototypeProperties() : nullptr; }
+ FinishClassInitOp specFinishInitHook()
+ const { return spec ? spec->finishInitHook() : nullptr; }
+
+ JSWeakmapKeyDelegateOp extWeakmapKeyDelegateOp()
+ const { return ext ? ext->weakmapKeyDelegateOp : nullptr; }
+ JSObjectMovedOp extObjectMovedOp()
+ const { return ext ? ext->objectMovedOp : nullptr; }
+
+ LookupPropertyOp getOpsLookupProperty() const { return oOps ? oOps->lookupProperty : nullptr; }
+ DefinePropertyOp getOpsDefineProperty() const { return oOps ? oOps->defineProperty : nullptr; }
+ HasPropertyOp getOpsHasProperty() const { return oOps ? oOps->hasProperty : nullptr; }
+ GetPropertyOp getOpsGetProperty() const { return oOps ? oOps->getProperty : nullptr; }
+ SetPropertyOp getOpsSetProperty() const { return oOps ? oOps->setProperty : nullptr; }
+ GetOwnPropertyOp getOpsGetOwnPropertyDescriptor()
+ const { return oOps ? oOps->getOwnPropertyDescriptor
+ : nullptr; }
+ DeletePropertyOp getOpsDeleteProperty() const { return oOps ? oOps->deleteProperty : nullptr; }
+ WatchOp getOpsWatch() const { return oOps ? oOps->watch : nullptr; }
+ UnwatchOp getOpsUnwatch() const { return oOps ? oOps->unwatch : nullptr; }
+ GetElementsOp getOpsGetElements() const { return oOps ? oOps->getElements : nullptr; }
+ JSNewEnumerateOp getOpsEnumerate() const { return oOps ? oOps->enumerate : nullptr; }
+ JSFunToStringOp getOpsFunToString() const { return oOps ? oOps->funToString : nullptr; }
};
+static_assert(offsetof(JSClassOps, addProperty) == offsetof(ClassOps, addProperty),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, delProperty) == offsetof(ClassOps, delProperty),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, getProperty) == offsetof(ClassOps, getProperty),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, setProperty) == offsetof(ClassOps, setProperty),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, enumerate) == offsetof(ClassOps, enumerate),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, resolve) == offsetof(ClassOps, resolve),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, mayResolve) == offsetof(ClassOps, mayResolve),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, finalize) == offsetof(ClassOps, finalize),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, call) == offsetof(ClassOps, call),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, construct) == offsetof(ClassOps, construct),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, hasInstance) == offsetof(ClassOps, hasInstance),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, trace) == offsetof(ClassOps, trace),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(sizeof(JSClassOps) == sizeof(ClassOps),
+ "ClassOps and JSClassOps must be consistent");
+
static_assert(offsetof(JSClass, name) == offsetof(Class, name),
"Class and JSClass must be consistent");
static_assert(offsetof(JSClass, flags) == offsetof(Class, flags),
"Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, addProperty) == offsetof(Class, addProperty),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, delProperty) == offsetof(Class, delProperty),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, getProperty) == offsetof(Class, getProperty),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, setProperty) == offsetof(Class, setProperty),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, enumerate) == offsetof(Class, enumerate),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, resolve) == offsetof(Class, resolve),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, mayResolve) == offsetof(Class, mayResolve),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, finalize) == offsetof(Class, finalize),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, call) == offsetof(Class, call),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, construct) == offsetof(Class, construct),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, trace) == offsetof(Class, trace),
+static_assert(offsetof(JSClass, cOps) == offsetof(Class, cOps),
"Class and JSClass must be consistent");
static_assert(sizeof(JSClass) == sizeof(Class),
"Class and JSClass must be consistent");
@@ -842,17 +959,30 @@
* Enumeration describing possible values of the [[Class]] internal property
* value of objects.
*/
-enum ESClassValue {
- ESClass_Object, ESClass_Array, ESClass_Number, ESClass_String,
- ESClass_Boolean, ESClass_RegExp, ESClass_ArrayBuffer, ESClass_SharedArrayBuffer,
- ESClass_Date, ESClass_Set, ESClass_Map,
+enum class ESClass {
+ Object,
+ Array,
+ Number,
+ String,
+ Boolean,
+ RegExp,
+ ArrayBuffer,
+ SharedArrayBuffer,
+ Date,
+ Set,
+ Map,
+ Promise,
+ MapIterator,
+ SetIterator,
+ Arguments,
+ Error,
/** None of the above. */
- ESClass_Other
+ Other
};
/* Fills |vp| with the unboxed value for boxed types, or undefined otherwise. */
-inline bool
+bool
Unbox(JSContext* cx, JS::HandleObject obj, JS::MutableHandleValue vp);
#ifdef DEBUG
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Conversions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Conversions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Conversions.h
@@ -30,12 +30,16 @@
/* DO NOT CALL THIS. Use JS::ToNumber. */
extern JS_PUBLIC_API(bool)
-ToNumberSlow(JSContext* cx, JS::Value v, double* dp);
+ToNumberSlow(JSContext* cx, JS::HandleValue v, double* dp);
/* DO NOT CALL THIS. Use JS::ToInt8. */
extern JS_PUBLIC_API(bool)
ToInt8Slow(JSContext *cx, JS::HandleValue v, int8_t *out);
+/* DO NOT CALL THIS. Use JS::ToUint8. */
+extern JS_PUBLIC_API(bool)
+ToUint8Slow(JSContext *cx, JS::HandleValue v, uint8_t *out);
+
/* DO NOT CALL THIS. Use JS::ToInt16. */
extern JS_PUBLIC_API(bool)
ToInt16Slow(JSContext *cx, JS::HandleValue v, int16_t *out);
@@ -215,6 +219,19 @@
return js::ToInt8Slow(cx, v, out);
}
+/* ES6 ECMA-262, 7.1.10 */
+MOZ_ALWAYS_INLINE bool
+ToUint8(JSContext *cx, JS::HandleValue v, uint8_t *out)
+{
+ detail::AssertArgumentsAreSane(cx, v);
+
+ if (v.isInt32()) {
+ *out = uint8_t(v.toInt32());
+ return true;
+ }
+ return js::ToUint8Slow(cx, v, out);
+}
+
/*
* Non-standard, with behavior similar to that of ToInt32, except in its
* producing an int64_t.
@@ -383,9 +400,9 @@
inline int32_t
ToInt32(double d)
{
- // clang crashes compiling this when targeting arm-darwin:
+ // clang crashes compiling this when targeting arm:
// https://llvm.org/bugs/show_bug.cgi?id=22974
-#if defined (__arm__) && defined (__GNUC__) && !defined(__APPLE__)
+#if defined (__arm__) && defined (__GNUC__) && !defined(__clang__)
int32_t i;
uint32_t tmp0;
uint32_t tmp1;
@@ -525,6 +542,13 @@
return detail::ToIntWidth<int8_t>(d);
}
+/* ECMA-262 7.1.10 ToUInt8() specialized for doubles. */
+inline int8_t
+ToUint8(double d)
+{
+ return detail::ToUintWidth<uint8_t>(d);
+}
+
/* WEBIDL 4.2.6 */
inline int16_t
ToInt16(double d)
@@ -532,6 +556,12 @@
return detail::ToIntWidth<int16_t>(d);
}
+inline uint16_t
+ToUint16(double d)
+{
+ return detail::ToUintWidth<uint16_t>(d);
+}
+
/* WEBIDL 4.2.10 */
inline int64_t
ToInt64(double d)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Date.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Date.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Date.h
@@ -149,6 +149,22 @@
JS_PUBLIC_API(double)
DayFromTime(double time);
+// Takes an integer year and returns the number of days from epoch to the given
+// year.
+// NOTE: The calculation performed by this function is literally that given in
+// the ECMAScript specification. Nonfinite years, years containing fractional
+// components, and years outside ECMAScript's date range are not handled with
+// any particular intelligence. Garbage in, garbage out.
+JS_PUBLIC_API(double)
+DayFromYear(double year);
+
+// Takes an integer number of milliseconds since the epoch and an integer year,
+// returns the number of days in that year. If |time| is nonfinite, returns NaN.
+// Otherwise |time| *must* correspond to a time within the valid year |year|.
+// This should usually be ensured by computing |year| as |JS::DayFromYear(time)|.
+JS_PUBLIC_API(double)
+DayWithinYear(double time, double year);
+
} // namespace JS
#endif /* js_Date_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Debug.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Debug.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Debug.h
@@ -12,7 +12,6 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
-#include "mozilla/UniquePtr.h"
#include "jsapi.h"
#include "jspubtd.h"
@@ -26,9 +25,6 @@
} // namespace js
namespace JS {
-
-using mozilla::UniquePtr;
-
namespace dbg {
// Helping embedding code build objects for Debugger
@@ -154,7 +150,7 @@
// A rooted reference to our value.
PersistentRooted<T> value;
- BuiltThing(JSContext* cx, Builder& owner_, T value_ = js::GCMethods<T>::initial())
+ BuiltThing(JSContext* cx, Builder& owner_, T value_ = GCPolicy<T>::initial())
: owner(owner_), value(cx, value_)
{
owner.assertBuilt(value_);
@@ -261,15 +257,15 @@
// and returns the number of bytes allocated to that block. SpiderMonkey itself
// doesn't know which function is appropriate to use, but the embedding does.
-// Tell Debuggers in |runtime| to use |mallocSizeOf| to find the size of
+// Tell Debuggers in |cx| to use |mallocSizeOf| to find the size of
// malloc'd blocks.
JS_PUBLIC_API(void)
-SetDebuggerMallocSizeOf(JSRuntime* runtime, mozilla::MallocSizeOf mallocSizeOf);
+SetDebuggerMallocSizeOf(JSContext* cx, mozilla::MallocSizeOf mallocSizeOf);
-// Get the MallocSizeOf function that the given runtime is using to find the
+// Get the MallocSizeOf function that the given context is using to find the
// size of malloc'd blocks.
JS_PUBLIC_API(mozilla::MallocSizeOf)
-GetDebuggerMallocSizeOf(JSRuntime* runtime);
+GetDebuggerMallocSizeOf(JSContext* cx);
@@ -344,7 +340,7 @@
// call the appropriate |Entry| member function to indicate where we've begun
// execution.
-class MOZ_STACK_CLASS AutoEntryMonitor {
+class MOZ_STACK_CLASS JS_PUBLIC_API(AutoEntryMonitor) {
JSRuntime* runtime_;
AutoEntryMonitor* savedMonitor_;
@@ -355,20 +351,25 @@
// SpiderMonkey reports the JavaScript entry points occuring within this
// AutoEntryMonitor's scope to the following member functions, which the
// embedding is expected to override.
+ //
+ // It is important to note that |asyncCause| is owned by the caller and its
+ // lifetime must outlive the lifetime of the AutoEntryMonitor object. It is
+ // strongly encouraged that |asyncCause| be a string constant or similar
+ // statically allocated string.
// We have begun executing |function|. Note that |function| may not be the
// actual closure we are running, but only the canonical function object to
// which the script refers.
virtual void Entry(JSContext* cx, JSFunction* function,
HandleValue asyncStack,
- HandleString asyncCause) = 0;
+ const char* asyncCause) = 0;
// Execution has begun at the entry point of |script|, which is not a
// function body. (This is probably being executed by 'eval' or some
// JSAPI equivalent.)
virtual void Entry(JSContext* cx, JSScript* script,
HandleValue asyncStack,
- HandleString asyncCause) = 0;
+ const char* asyncCause) = 0;
// Execution of the function or script has ended.
virtual void Exit(JSContext* cx) { }
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCAPI.h
@@ -7,10 +7,11 @@
#ifndef js_GCAPI_h
#define js_GCAPI_h
-#include "mozilla/UniquePtr.h"
#include "mozilla/Vector.h"
+#include "js/GCAnnotations.h"
#include "js/HeapAPI.h"
+#include "js/UniquePtr.h"
namespace js {
namespace gc {
@@ -25,12 +26,12 @@
/** Perform only global GCs. */
JSGC_MODE_GLOBAL = 0,
- /** Perform per-compartment GCs until too much garbage has accumulated. */
- JSGC_MODE_COMPARTMENT = 1,
+ /** Perform per-zone GCs until too much garbage has accumulated. */
+ JSGC_MODE_ZONE = 1,
/**
* Collect in short time slices rather than all at once. Implies
- * JSGC_MODE_COMPARTMENT.
+ * JSGC_MODE_ZONE.
*/
JSGC_MODE_INCREMENTAL = 2
} JSGCMode;
@@ -48,14 +49,12 @@
namespace JS {
-using mozilla::UniquePtr;
-
#define GCREASONS(D) \
/* Reasons internal to the JS engine */ \
D(API) \
D(EAGER_ALLOC_TRIGGER) \
D(DESTROY_RUNTIME) \
- D(DESTROY_CONTEXT) \
+ D(UNUSED0) \
D(LAST_DITCH) \
D(TOO_MUCH_MALLOC) \
D(ALLOC_TRIGGER) \
@@ -66,7 +65,7 @@
D(EVICT_NURSERY) \
D(FULL_STORE_BUFFER) \
D(SHARED_MEMORY_LIMIT) \
- D(PERIODIC_FULL_GC) \
+ D(UNUSED1) \
D(INCREMENTAL_TOO_SLOW) \
D(ABORT_GC) \
\
@@ -130,6 +129,12 @@
NUM_TELEMETRY_REASONS = 100
};
+/**
+ * Get a statically allocated C string explaining the given GC reason.
+ */
+extern JS_PUBLIC_API(const char*)
+ExplainReason(JS::gcreason::Reason reason);
+
} /* namespace gcreason */
/*
@@ -156,7 +161,7 @@
* Schedule all zones to be collected in the next GC.
*/
extern JS_PUBLIC_API(void)
-PrepareForFullGC(JSRuntime* rt);
+PrepareForFullGC(JSContext* cx);
/**
* When performing an incremental GC, the zones that were selected for the
@@ -164,14 +169,14 @@
* This function selects those slices automatically.
*/
extern JS_PUBLIC_API(void)
-PrepareForIncrementalGC(JSRuntime* rt);
+PrepareForIncrementalGC(JSContext* cx);
/**
* Returns true if any zone in the system has been scheduled for GC with one of
* the functions above or by the JS engine.
*/
extern JS_PUBLIC_API(bool)
-IsGCScheduled(JSRuntime* rt);
+IsGCScheduled(JSContext* cx);
/**
* Undoes the effect of the Prepare methods above. The given zone will not be
@@ -196,7 +201,7 @@
* the system.
*/
extern JS_PUBLIC_API(void)
-GCForReason(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason);
+GCForReason(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason);
/*
* Incremental GC:
@@ -222,43 +227,43 @@
* Begin an incremental collection and perform one slice worth of work. When
* this function returns, the collection may not be complete.
* IncrementalGCSlice() must be called repeatedly until
- * !IsIncrementalGCInProgress(rt).
+ * !IsIncrementalGCInProgress(cx).
*
* Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
* shorter than the requested interval.
*/
extern JS_PUBLIC_API(void)
-StartIncrementalGC(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason,
+StartIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason,
int64_t millis = 0);
/**
* Perform a slice of an ongoing incremental collection. When this function
* returns, the collection may not be complete. It must be called repeatedly
- * until !IsIncrementalGCInProgress(rt).
+ * until !IsIncrementalGCInProgress(cx).
*
* Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
* shorter than the requested interval.
*/
extern JS_PUBLIC_API(void)
-IncrementalGCSlice(JSRuntime* rt, gcreason::Reason reason, int64_t millis = 0);
+IncrementalGCSlice(JSContext* cx, gcreason::Reason reason, int64_t millis = 0);
/**
- * If IsIncrementalGCInProgress(rt), this call finishes the ongoing collection
- * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(rt),
+ * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
+ * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
* this is equivalent to GCForReason. When this function returns,
- * IsIncrementalGCInProgress(rt) will always be false.
+ * IsIncrementalGCInProgress(cx) will always be false.
*/
extern JS_PUBLIC_API(void)
-FinishIncrementalGC(JSRuntime* rt, gcreason::Reason reason);
+FinishIncrementalGC(JSContext* cx, gcreason::Reason reason);
/**
- * If IsIncrementalGCInProgress(rt), this call aborts the ongoing collection and
+ * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
* performs whatever work needs to be done to return the collector to its idle
* state. This may take an arbitrarily long time. When this function returns,
- * IsIncrementalGCInProgress(rt) will always be false.
+ * IsIncrementalGCInProgress(cx) will always be false.
*/
extern JS_PUBLIC_API(void)
-AbortIncrementalGC(JSRuntime* rt);
+AbortIncrementalGC(JSContext* cx);
namespace dbg {
@@ -300,7 +305,7 @@
, collections()
{ }
- using Ptr = UniquePtr<GarbageCollectionEvent, DeletePolicy<GarbageCollectionEvent>>;
+ using Ptr = js::UniquePtr<GarbageCollectionEvent>;
static Ptr Create(JSRuntime* rt, ::js::gcstats::Statistics& stats, uint64_t majorGCNumber);
JSObject* toJSObject(JSContext* cx) const;
@@ -328,22 +333,22 @@
};
struct JS_PUBLIC_API(GCDescription) {
- bool isCompartment_;
+ bool isZone_;
JSGCInvocationKind invocationKind_;
gcreason::Reason reason_;
- GCDescription(bool isCompartment, JSGCInvocationKind kind, gcreason::Reason reason)
- : isCompartment_(isCompartment), invocationKind_(kind), reason_(reason) {}
+ GCDescription(bool isZone, JSGCInvocationKind kind, gcreason::Reason reason)
+ : isZone_(isZone), invocationKind_(kind), reason_(reason) {}
- char16_t* formatSliceMessage(JSRuntime* rt) const;
- char16_t* formatSummaryMessage(JSRuntime* rt) const;
- char16_t* formatJSON(JSRuntime* rt, uint64_t timestamp) const;
+ char16_t* formatSliceMessage(JSContext* cx) const;
+ char16_t* formatSummaryMessage(JSContext* cx) const;
+ char16_t* formatJSON(JSContext* cx, uint64_t timestamp) const;
- JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSRuntime* rt) const;
+ JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSContext* cx) const;
};
typedef void
-(* GCSliceCallback)(JSRuntime* rt, GCProgress progress, const GCDescription& desc);
+(* GCSliceCallback)(JSContext* cx, GCProgress progress, const GCDescription& desc);
/**
* The GC slice callback is called at the beginning and end of each slice. This
@@ -351,7 +356,45 @@
* marking.
*/
extern JS_PUBLIC_API(GCSliceCallback)
-SetGCSliceCallback(JSRuntime* rt, GCSliceCallback callback);
+SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
+
+/**
+ * Describes the progress of an observed nursery collection.
+ */
+enum class GCNurseryProgress {
+ /**
+ * The nursery collection is starting.
+ */
+ GC_NURSERY_COLLECTION_START,
+ /**
+ * The nursery collection is ending.
+ */
+ GC_NURSERY_COLLECTION_END
+};
+
+/**
+ * A nursery collection callback receives the progress of the nursery collection
+ * and the reason for the collection.
+ */
+using GCNurseryCollectionCallback = void(*)(JSContext* cx, GCNurseryProgress progress,
+ gcreason::Reason reason);
+
+/**
+ * Set the nursery collection callback for the given runtime. When set, it will
+ * be called at the start and end of every nursery collection.
+ */
+extern JS_PUBLIC_API(GCNurseryCollectionCallback)
+SetGCNurseryCollectionCallback(JSContext* cx, GCNurseryCollectionCallback callback);
+
+typedef void
+(* DoCycleCollectionCallback)(JSContext* cx);
+
+/**
+ * The purge gray callback is called after any COMPARTMENT_REVIVED GC in which
+ * the majority of compartments have been marked gray.
+ */
+extern JS_PUBLIC_API(DoCycleCollectionCallback)
+SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback);
/**
* Incremental GC defaults to enabled, but may be disabled for testing or in
@@ -360,7 +403,7 @@
* disabled on the runtime.
*/
extern JS_PUBLIC_API(void)
-DisableIncrementalGC(JSRuntime* rt);
+DisableIncrementalGC(JSContext* cx);
/**
* Returns true if incremental GC is enabled. Simply having incremental GC
@@ -371,14 +414,14 @@
* collections are not happening incrementally when expected.
*/
extern JS_PUBLIC_API(bool)
-IsIncrementalGCEnabled(JSRuntime* rt);
+IsIncrementalGCEnabled(JSContext* cx);
/**
* Returns true while an incremental GC is ongoing, both when actively
* collecting and between slices.
*/
extern JS_PUBLIC_API(bool)
-IsIncrementalGCInProgress(JSRuntime* rt);
+IsIncrementalGCInProgress(JSContext* cx);
/*
* Returns true when writes to GC things must call an incremental (pre) barrier.
@@ -386,9 +429,6 @@
* At other times, the barrier may be elided for performance.
*/
extern JS_PUBLIC_API(bool)
-IsIncrementalBarrierNeeded(JSRuntime* rt);
-
-extern JS_PUBLIC_API(bool)
IsIncrementalBarrierNeeded(JSContext* cx);
/*
@@ -408,7 +448,7 @@
* Returns true if the most recent GC ran incrementally.
*/
extern JS_PUBLIC_API(bool)
-WasIncrementalGC(JSRuntime* rt);
+WasIncrementalGC(JSContext* cx);
/*
* Generational GC:
@@ -444,37 +484,35 @@
GetGCNumber();
/**
- * The GC does not immediately return the unused memory freed by a collection
- * back to the system incase it is needed soon afterwards. This call forces the
- * GC to return this memory immediately.
- */
-extern JS_PUBLIC_API(void)
-ShrinkGCBuffers(JSRuntime* rt);
+ * Pass a subclass of this "abstract" class to callees to require that they
+ * never GC. Subclasses can use assertions or the hazard analysis to ensure no
+ * GC happens.
+ */
+class JS_PUBLIC_API(AutoRequireNoGC)
+{
+ protected:
+ AutoRequireNoGC() {}
+ ~AutoRequireNoGC() {}
+};
/**
- * Assert if a GC occurs while this class is live. This class does not disable
- * the static rooting hazard analysis.
+ * Diagnostic assert (see MOZ_DIAGNOSTIC_ASSERT) that GC cannot occur while this
+ * class is live. This class does not disable the static rooting hazard
+ * analysis.
+ *
+ * This works by entering a GC unsafe region, which is checked on allocation and
+ * on GC.
*/
-class JS_PUBLIC_API(AutoAssertOnGC)
+class JS_PUBLIC_API(AutoAssertNoGC) : public AutoRequireNoGC
{
-#ifdef DEBUG
js::gc::GCRuntime* gc;
size_t gcNumber;
public:
- AutoAssertOnGC();
- explicit AutoAssertOnGC(JSRuntime* rt);
- ~AutoAssertOnGC();
-
- static void VerifyIsSafeToGC(JSRuntime* rt);
-#else
- public:
- AutoAssertOnGC() {}
- explicit AutoAssertOnGC(JSRuntime* rt) {}
- ~AutoAssertOnGC() {}
-
- static void VerifyIsSafeToGC(JSRuntime* rt) {}
-#endif
+ AutoAssertNoGC();
+ explicit AutoAssertNoGC(JSRuntime* rt);
+ explicit AutoAssertNoGC(JSContext* cx);
+ ~AutoAssertNoGC();
};
/**
@@ -488,18 +526,32 @@
public:
AutoAssertNoAlloc() : gc(nullptr) {}
- explicit AutoAssertNoAlloc(JSRuntime* rt);
+ explicit AutoAssertNoAlloc(JSContext* cx);
void disallowAlloc(JSRuntime* rt);
~AutoAssertNoAlloc();
#else
public:
AutoAssertNoAlloc() {}
- explicit AutoAssertNoAlloc(JSRuntime* rt) {}
+ explicit AutoAssertNoAlloc(JSContext* cx) {}
void disallowAlloc(JSRuntime* rt) {}
#endif
};
/**
+ * Assert if a GC barrier is invoked while this class is live. This class does
+ * not disable the static rooting hazard analysis.
+ */
+class JS_PUBLIC_API(AutoAssertOnBarrier)
+{
+ JSContext* context;
+ bool prev;
+
+ public:
+ explicit AutoAssertOnBarrier(JSContext* cx);
+ ~AutoAssertOnBarrier();
+};
+
+/**
* Disable the static rooting hazard analysis in the live region and assert if
* any allocation that could potentially trigger a GC occurs while this guard
* object is live. This is most useful to help the exact rooting hazard analysis
@@ -517,8 +569,8 @@
{
public:
AutoSuppressGCAnalysis() : AutoAssertNoAlloc() {}
- explicit AutoSuppressGCAnalysis(JSRuntime* rt) : AutoAssertNoAlloc(rt) {}
-};
+ explicit AutoSuppressGCAnalysis(JSContext* cx) : AutoAssertNoAlloc(cx) {}
+} JS_HAZ_GC_SUPPRESSED;
/**
* Assert that code is only ever called from a GC callback, disable the static
@@ -536,24 +588,36 @@
/**
* Place AutoCheckCannotGC in scopes that you believe can never GC. These
- * annotations will be verified both dynamically via AutoAssertOnGC, and
+ * annotations will be verified both dynamically via AutoAssertNoGC, and
* statically with the rooting hazard analysis (implemented by making the
* analysis consider AutoCheckCannotGC to be a GC pointer, and therefore
* complain if it is live across a GC call.) It is useful when dealing with
* internal pointers to GC things where the GC thing itself may not be present
* for the static analysis: e.g. acquiring inline chars from a JSString* on the
* heap.
+ *
+ * We only do the assertion checking in DEBUG builds.
*/
-class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertOnGC
+#ifdef DEBUG
+class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertNoGC
{
public:
- AutoCheckCannotGC() : AutoAssertOnGC() {}
- explicit AutoCheckCannotGC(JSRuntime* rt) : AutoAssertOnGC(rt) {}
-};
+ AutoCheckCannotGC() : AutoAssertNoGC() {}
+ explicit AutoCheckCannotGC(JSContext* cx) : AutoAssertNoGC(cx) {}
+} JS_HAZ_GC_INVALIDATED;
+#else
+class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoRequireNoGC
+{
+ public:
+ AutoCheckCannotGC() {}
+ explicit AutoCheckCannotGC(JSContext* cx) {}
+} JS_HAZ_GC_INVALIDATED;
+#endif
/**
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
- * JS::TraceKind::Shape. |thing| should be non-null.
+ * JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
+ * if anything was unmarked.
*/
extern JS_FRIEND_API(bool)
UnmarkGrayGCThingRecursively(GCCellPtr thing);
@@ -566,31 +630,42 @@
static MOZ_ALWAYS_INLINE void
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
{
- MOZ_ASSERT(thing.kind() != JS::TraceKind::Shape);
-
- /*
- * GC things residing in the nursery cannot be gray: they have no mark bits.
- * All live objects in the nursery are moved to tenured at the beginning of
- * each GC slice, so the gray marker never sees nursery things.
- */
+ // GC things residing in the nursery cannot be gray: they have no mark bits.
+ // All live objects in the nursery are moved to tenured at the beginning of
+ // each GC slice, so the gray marker never sees nursery things.
if (IsInsideNursery(thing.asCell()))
return;
- JS::shadow::Runtime* rt = detail::GetGCThingRuntime(thing.unsafeAsUIntPtr());
+
+ // There's nothing to do for permanent GC things that might be owned by
+ // another runtime.
+ if (thing.mayBeOwnedByOtherRuntime())
+ return;
+
+ JS::shadow::Runtime* rt = detail::GetCellRuntime(thing.asCell());
+ MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
+
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
JS::IncrementalReferenceBarrier(thing);
- else if (JS::GCThingIsMarkedGray(thing))
+ else if (!thing.mayBeOwnedByOtherRuntime() && js::gc::detail::CellIsMarkedGray(thing.asCell()))
JS::UnmarkGrayGCThingRecursively(thing);
}
static MOZ_ALWAYS_INLINE void
MarkGCThingAsLive(JSRuntime* aRt, JS::GCCellPtr thing)
{
- JS::shadow::Runtime* rt = JS::shadow::Runtime::asShadowRuntime(aRt);
- /*
- * Any object in the nursery will not be freed during any GC running at that time.
- */
+ // Any object in the nursery will not be freed during any GC running at that
+ // time.
if (IsInsideNursery(thing.asCell()))
return;
+
+ // There's nothing to do for permanent GC things that might be owned by
+ // another runtime.
+ if (thing.mayBeOwnedByOtherRuntime())
+ return;
+
+ JS::shadow::Runtime* rt = JS::shadow::Runtime::asShadowRuntime(aRt);
+ MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
+
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
JS::IncrementalReferenceBarrier(thing);
}
@@ -609,6 +684,7 @@
static MOZ_ALWAYS_INLINE void
ExposeObjectToActiveJS(JSObject* obj)
{
+ MOZ_ASSERT(obj);
js::gc::ExposeGCThingToActiveJS(GCCellPtr(obj));
}
@@ -634,13 +710,13 @@
* Note: this is not related to the PokeGC in nsJSEnvironment.
*/
extern JS_FRIEND_API(void)
-PokeGC(JSRuntime* rt);
+PokeGC(JSContext* cx);
/*
* Internal to Firefox.
*/
extern JS_FRIEND_API(void)
-NotifyDidPaint(JSRuntime* rt);
+NotifyDidPaint(JSContext* cx);
} /* namespace JS */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCAnnotations.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCAnnotations.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCAnnotations.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_GCAnnotations_h
+#define js_GCAnnotations_h
+
+// Set of annotations for the rooting hazard analysis, used to categorize types
+// and functions.
+#ifdef XGILL_PLUGIN
+
+// Mark a type as being a GC thing (eg js::gc::Cell has this annotation).
+# define JS_HAZ_GC_THING __attribute__((tag("GC Thing")))
+
+// Mark a type as holding a pointer to a GC thing (eg JS::Value has this
+// annotation.)
+# define JS_HAZ_GC_POINTER __attribute__((tag("GC Pointer")))
+
+// Mark a type as a rooted pointer, suitable for use on the stack (eg all
+// Rooted<T> instantiations should have this.)
+# define JS_HAZ_ROOTED __attribute__((tag("Rooted Pointer")))
+
+// Mark a type as something that should not be held live across a GC, but which
+// is not itself a GC pointer.
+# define JS_HAZ_GC_INVALIDATED __attribute__((tag("Invalidated by GC")))
+
+// Mark a type that would otherwise be considered a GC Pointer (eg because it
+// contains a JS::Value field) as a non-GC pointer. It is handled almost the
+// same in the analysis as a rooted pointer, except it will not be reported as
+// an unnecessary root if used across a GC call. This should rarely be used,
+// but makes sense for something like ErrorResult, which only contains a GC
+// pointer when it holds an exception (and it does its own rooting,
+// conditionally.)
+# define JS_HAZ_NON_GC_POINTER __attribute__((tag("Suppressed GC Pointer")))
+
+// Mark a function as something that runs a garbage collection, potentially
+// invalidating GC pointers.
+# define JS_HAZ_GC_CALL __attribute__((tag("GC Call")))
+
+// Mark an RAII class as suppressing GC within its scope.
+# define JS_HAZ_GC_SUPPRESSED __attribute__((tag("Suppress GC")))
+
+#else
+
+# define JS_HAZ_GC_THING
+# define JS_HAZ_GC_POINTER
+# define JS_HAZ_ROOTED
+# define JS_HAZ_GC_INVALIDATED
+# define JS_HAZ_NON_GC_POINTER
+# define JS_HAZ_GC_CALL
+# define JS_HAZ_GC_SUPPRESSED
+
+#endif
+
+#endif /* js_GCAnnotations_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCHashTable.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCHashTable.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCHashTable.h
@@ -7,54 +7,54 @@
#ifndef GCHashTable_h
#define GCHashTable_h
+#include "js/GCPolicyAPI.h"
#include "js/HashTable.h"
#include "js/RootingAPI.h"
+#include "js/SweepingAPI.h"
#include "js/TracingAPI.h"
-namespace js {
+namespace JS {
// Define a reasonable default GC policy for GC-aware Maps.
template <typename Key, typename Value>
-struct DefaultMapGCPolicy {
- using KeyPolicy = DefaultGCPolicy<Key>;
- using ValuePolicy = DefaultGCPolicy<Value>;
-
+struct DefaultMapSweepPolicy {
static bool needsSweep(Key* key, Value* value) {
- return KeyPolicy::needsSweep(key) || ValuePolicy::needsSweep(value);
+ return GCPolicy<Key>::needsSweep(key) || GCPolicy<Value>::needsSweep(value);
}
};
// A GCHashMap is a GC-aware HashMap, meaning that it has additional trace and
// sweep methods that know how to visit all keys and values in the table.
// HashMaps that contain GC pointers will generally want to use this GCHashMap
-// specialization in lieu of HashMap, either because those pointers must be
-// traced to be kept alive -- in which case, KeyPolicy and/or ValuePolicy
-// should do the appropriate tracing -- or because those pointers are weak and
-// must be swept during a GC -- in which case needsSweep should be set
-// appropriately.
+// specialization instead of HashMap, because this conveniently supports tracing
+// keys and values, and cleaning up weak entries.
//
-// Most types of GC pointers as keys and values can be traced with no extra
-// infrastructure. For structs, the DefaultGCPolicy<T> will call a trace()
-// method on the struct. For other structs and non-gc-pointer members, ensure
-// that there is a specialization of DefaultGCPolicy<T> with an appropriate
-// trace() static method available to handle the custom type. Generic helpers
-// can be found in js/public/TracingAPI.h.
+// GCHashMap::trace applies GCPolicy<T>::trace to each entry's key and value.
+// Most types of GC pointers already have appropriate specializations of
+// GCPolicy, so they should just work as keys and values. Any struct type with a
+// default constructor and trace and sweep functions should work as well. If you
+// need to define your own GCPolicy specialization, generic helpers can be found
+// in js/public/TracingAPI.h.
//
-// Note that this HashMap only knows *how* to trace and sweep (and the tracing
-// can handle keys that move), but it does not itself cause tracing or sweeping
-// to be invoked. For tracing, it must be used with Rooted or PersistentRooted,
-// or barriered and traced manually. For sweeping, currently it requires an
-// explicit call to <map>.sweep().
+// The MapSweepPolicy template parameter controls how the table drops entries
+// when swept. GCHashMap::sweep applies MapSweepPolicy::needsSweep to each table
+// entry; if it returns true, the entry is dropped. The default MapSweepPolicy
+// drops the entry if either the key or value is about to be finalized,
+// according to its GCPolicy<T>::needsSweep method. (This default is almost
+// always fine: it's hard to imagine keeping such an entry around anyway.)
//
+// Note that this HashMap only knows *how* to trace and sweep, but it does not
+// itself cause tracing or sweeping to be invoked. For tracing, it must be used
+// with Rooted or PersistentRooted, or barriered and traced manually. For
+// sweeping, currently it requires an explicit call to <map>.sweep().
template <typename Key,
typename Value,
- typename HashPolicy = DefaultHasher<Key>,
- typename AllocPolicy = TempAllocPolicy,
- typename GCPolicy = DefaultMapGCPolicy<Key, Value>>
-class GCHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>,
- public JS::Traceable
+ typename HashPolicy = js::DefaultHasher<Key>,
+ typename AllocPolicy = js::TempAllocPolicy,
+ typename MapSweepPolicy = DefaultMapSweepPolicy<Key, Value>>
+class GCHashMap : public js::HashMap<Key, Value, HashPolicy, AllocPolicy>
{
- using Base = HashMap<Key, Value, HashPolicy, AllocPolicy>;
+ using Base = js::HashMap<Key, Value, HashPolicy, AllocPolicy>;
public:
explicit GCHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {}
@@ -64,8 +64,8 @@
if (!this->initialized())
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
- GCPolicy::ValuePolicy::trace(trc, &e.front().value(), "hashmap value");
- GCPolicy::KeyPolicy::trace(trc, &e.front().mutableKey(), "hashmap key");
+ GCPolicy<Value>::trace(trc, &e.front().value(), "hashmap value");
+ GCPolicy<Key>::trace(trc, &e.front().mutableKey(), "hashmap key");
}
}
@@ -74,16 +74,16 @@
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
- if (GCPolicy::needsSweep(&e.front().mutableKey(), &e.front().value()))
+ if (MapSweepPolicy::needsSweep(&e.front().mutableKey(), &e.front().value()))
e.removeFront();
}
}
// GCHashMap is movable
- GCHashMap(GCHashMap&& rhs) : Base(mozilla::Forward<GCHashMap>(rhs)) {}
+ GCHashMap(GCHashMap&& rhs) : Base(mozilla::Move(rhs)) {}
void operator=(GCHashMap&& rhs) {
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
- Base::operator=(mozilla::Forward<GCHashMap>(rhs));
+ Base::operator=(mozilla::Move(rhs));
}
private:
@@ -92,19 +92,61 @@
GCHashMap& operator=(const GCHashMap& hm) = delete;
};
+} // namespace JS
+
+namespace js {
+
+// HashMap that supports rekeying.
+//
+// If your keys are pointers to something like JSObject that can be tenured or
+// compacted, prefer to use GCHashMap with MovableCellHasher, which takes
+// advantage of the Zone's stable id table to make rekeying unnecessary.
+template <typename Key,
+ typename Value,
+ typename HashPolicy = DefaultHasher<Key>,
+ typename AllocPolicy = TempAllocPolicy,
+ typename MapSweepPolicy = JS::DefaultMapSweepPolicy<Key, Value>>
+class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>
+{
+ using Base = JS::GCHashMap<Key, Value, HashPolicy, AllocPolicy>;
+
+ public:
+ explicit GCRekeyableHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {}
+
+ void sweep() {
+ if (!this->initialized())
+ return;
+
+ for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
+ Key key(e.front().key());
+ if (MapSweepPolicy::needsSweep(&key, &e.front().value()))
+ e.removeFront();
+ else if (!HashPolicy::match(key, e.front().key()))
+ e.rekeyFront(key);
+ }
+ }
+
+ // GCRekeyableHashMap is movable
+ GCRekeyableHashMap(GCRekeyableHashMap&& rhs) : Base(mozilla::Move(rhs)) {}
+ void operator=(GCRekeyableHashMap&& rhs) {
+ MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
+ Base::operator=(mozilla::Move(rhs));
+ }
+};
+
template <typename Outer, typename... Args>
class GCHashMapOperations
{
- using Map = GCHashMap<Args...>;
+ using Map = JS::GCHashMap<Args...>;
using Lookup = typename Map::Lookup;
- using Ptr = typename Map::Ptr;
- using AddPtr = typename Map::AddPtr;
- using Range = typename Map::Range;
- using Enum = typename Map::Enum;
const Map& map() const { return static_cast<const Outer*>(this)->get(); }
public:
+ using AddPtr = typename Map::AddPtr;
+ using Ptr = typename Map::Ptr;
+ using Range = typename Map::Range;
+
bool initialized() const { return map().initialized(); }
Ptr lookup(const Lookup& l) const { return map().lookup(l); }
AddPtr lookupForAdd(const Lookup& l) const { return map().lookupForAdd(l); }
@@ -113,22 +155,29 @@
uint32_t count() const { return map().count(); }
size_t capacity() const { return map().capacity(); }
bool has(const Lookup& l) const { return map().lookup(l).found(); }
+ size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return map().sizeOfExcludingThis(mallocSizeOf);
+ }
+ size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return mallocSizeOf(this) + map().sizeOfExcludingThis(mallocSizeOf);
+ }
};
template <typename Outer, typename... Args>
class MutableGCHashMapOperations
: public GCHashMapOperations<Outer, Args...>
{
- using Map = GCHashMap<Args...>;
+ using Map = JS::GCHashMap<Args...>;
using Lookup = typename Map::Lookup;
- using Ptr = typename Map::Ptr;
- using AddPtr = typename Map::AddPtr;
- using Range = typename Map::Range;
- using Enum = typename Map::Enum;
Map& map() { return static_cast<Outer*>(this)->get(); }
public:
+ using AddPtr = typename Map::AddPtr;
+ struct Enum : public Map::Enum { explicit Enum(Outer& o) : Map::Enum(o.map()) {} };
+ using Ptr = typename Map::Ptr;
+ using Range = typename Map::Range;
+
bool init(uint32_t len = 16) { return map().init(len); }
void clear() { map().clear(); }
void finish() { map().finish(); }
@@ -163,41 +212,48 @@
};
template <typename A, typename B, typename C, typename D, typename E>
-class RootedBase<GCHashMap<A,B,C,D,E>>
- : public MutableGCHashMapOperations<JS::Rooted<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
+class RootedBase<JS::GCHashMap<A,B,C,D,E>>
+ : public MutableGCHashMapOperations<JS::Rooted<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
+{};
+
+template <typename A, typename B, typename C, typename D, typename E>
+class MutableHandleBase<JS::GCHashMap<A,B,C,D,E>>
+ : public MutableGCHashMapOperations<JS::MutableHandle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
{};
template <typename A, typename B, typename C, typename D, typename E>
-class MutableHandleBase<GCHashMap<A,B,C,D,E>>
- : public MutableGCHashMapOperations<JS::MutableHandle<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
+class HandleBase<JS::GCHashMap<A,B,C,D,E>>
+ : public GCHashMapOperations<JS::Handle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
{};
template <typename A, typename B, typename C, typename D, typename E>
-class HandleBase<GCHashMap<A,B,C,D,E>>
- : public GCHashMapOperations<JS::Handle<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
+class WeakCacheBase<JS::GCHashMap<A,B,C,D,E>>
+ : public MutableGCHashMapOperations<JS::WeakCache<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
{};
+} // namespace js
+
+namespace JS {
+
// A GCHashSet is a HashSet with an additional trace method that knows
// be traced to be kept alive will generally want to use this GCHashSet
-// specializeation in lieu of HashSet.
+// specialization in lieu of HashSet.
//
// Most types of GC pointers can be traced with no extra infrastructure. For
// structs and non-gc-pointer members, ensure that there is a specialization of
-// DefaultGCPolicy<T> with an appropriate trace method available to handle the
-// custom type. Generic helpers can be found in js/public/TracingAPI.h.
+// GCPolicy<T> with an appropriate trace method available to handle the custom
+// type. Generic helpers can be found in js/public/TracingAPI.h.
//
// Note that although this HashSet's trace will deal correctly with moved
// elements, it does not itself know when to barrier or trace elements. To
// function properly it must either be used with Rooted or barriered and traced
// manually.
template <typename T,
- typename HashPolicy = DefaultHasher<T>,
- typename AllocPolicy = TempAllocPolicy,
- typename GCPolicy = DefaultGCPolicy<T>>
-class GCHashSet : public HashSet<T, HashPolicy, AllocPolicy>,
- public JS::Traceable
+ typename HashPolicy = js::DefaultHasher<T>,
+ typename AllocPolicy = js::TempAllocPolicy>
+class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy>
{
- using Base = HashSet<T, HashPolicy, AllocPolicy>;
+ using Base = js::HashSet<T, HashPolicy, AllocPolicy>;
public:
explicit GCHashSet(AllocPolicy a = AllocPolicy()) : Base(a) {}
@@ -207,23 +263,23 @@
if (!this->initialized())
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront())
- GCPolicy::trace(trc, &e.mutableFront(), "hashset element");
+ GCPolicy<T>::trace(trc, &e.mutableFront(), "hashset element");
}
void sweep() {
if (!this->initialized())
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
- if (GCPolicy::needsSweep(&e.mutableFront()))
+ if (GCPolicy<T>::needsSweep(&e.mutableFront()))
e.removeFront();
}
}
// GCHashSet is movable
- GCHashSet(GCHashSet&& rhs) : Base(mozilla::Forward<GCHashSet>(rhs)) {}
+ GCHashSet(GCHashSet&& rhs) : Base(mozilla::Move(rhs)) {}
void operator=(GCHashSet&& rhs) {
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
- Base::operator=(mozilla::Forward<GCHashSet>(rhs));
+ Base::operator=(mozilla::Move(rhs));
}
private:
@@ -232,19 +288,24 @@
GCHashSet& operator=(const GCHashSet& hs) = delete;
};
+} // namespace JS
+
+namespace js {
+
template <typename Outer, typename... Args>
class GCHashSetOperations
{
- using Set = GCHashSet<Args...>;
+ using Set = JS::GCHashSet<Args...>;
using Lookup = typename Set::Lookup;
- using Ptr = typename Set::Ptr;
- using AddPtr = typename Set::AddPtr;
- using Range = typename Set::Range;
- using Enum = typename Set::Enum;
- const Set& set() const { return static_cast<const Outer*>(this)->extract(); }
+ const Set& set() const { return static_cast<const Outer*>(this)->get(); }
public:
+ using AddPtr = typename Set::AddPtr;
+ using Entry = typename Set::Entry;
+ using Ptr = typename Set::Ptr;
+ using Range = typename Set::Range;
+
bool initialized() const { return set().initialized(); }
Ptr lookup(const Lookup& l) const { return set().lookup(l); }
AddPtr lookupForAdd(const Lookup& l) const { return set().lookupForAdd(l); }
@@ -253,25 +314,34 @@
uint32_t count() const { return set().count(); }
size_t capacity() const { return set().capacity(); }
bool has(const Lookup& l) const { return set().lookup(l).found(); }
+ size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return set().sizeOfExcludingThis(mallocSizeOf);
+ }
+ size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return mallocSizeOf(this) + set().sizeOfExcludingThis(mallocSizeOf);
+ }
};
template <typename Outer, typename... Args>
class MutableGCHashSetOperations
: public GCHashSetOperations<Outer, Args...>
{
- using Set = GCHashSet<Args...>;
+ using Set = JS::GCHashSet<Args...>;
using Lookup = typename Set::Lookup;
- using Ptr = typename Set::Ptr;
- using AddPtr = typename Set::AddPtr;
- using Range = typename Set::Range;
- using Enum = typename Set::Enum;
- Set& set() { return static_cast<Outer*>(this)->extract(); }
+ Set& set() { return static_cast<Outer*>(this)->get(); }
public:
+ using AddPtr = typename Set::AddPtr;
+ using Entry = typename Set::Entry;
+ struct Enum : public Set::Enum { explicit Enum(Outer& o) : Set::Enum(o.set()) {} };
+ using Ptr = typename Set::Ptr;
+ using Range = typename Set::Range;
+
bool init(uint32_t len = 16) { return set().init(len); }
void clear() { set().clear(); }
void finish() { set().finish(); }
+ void remove(Ptr p) { set().remove(p); }
void remove(const Lookup& l) { set().remove(l); }
template<typename TInput>
@@ -300,41 +370,28 @@
}
};
-template <typename T, typename HP, typename AP, typename GP>
-class RootedBase<GCHashSet<T, HP, AP, GP>>
- : public MutableGCHashSetOperations<JS::Rooted<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
+template <typename T, typename HP, typename AP>
+class RootedBase<JS::GCHashSet<T, HP, AP>>
+ : public MutableGCHashSetOperations<JS::Rooted<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
- using Set = GCHashSet<T, HP, AP, GP>;
-
- friend class GCHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>;
- const Set& extract() const { return *static_cast<const JS::Rooted<Set>*>(this)->address(); }
-
- friend class MutableGCHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>;
- Set& extract() { return *static_cast<JS::Rooted<Set>*>(this)->address(); }
};
-template <typename T, typename HP, typename AP, typename GP>
-class MutableHandleBase<GCHashSet<T, HP, AP, GP>>
- : public MutableGCHashSetOperations<JS::MutableHandle<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
+template <typename T, typename HP, typename AP>
+class MutableHandleBase<JS::GCHashSet<T, HP, AP>>
+ : public MutableGCHashSetOperations<JS::MutableHandle<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
- using Set = GCHashSet<T, HP, AP, GP>;
-
- friend class GCHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>;
- const Set& extract() const {
- return *static_cast<const JS::MutableHandle<Set>*>(this)->address();
- }
+};
- friend class MutableGCHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>;
- Set& extract() { return *static_cast<JS::MutableHandle<Set>*>(this)->address(); }
+template <typename T, typename HP, typename AP>
+class HandleBase<JS::GCHashSet<T, HP, AP>>
+ : public GCHashSetOperations<JS::Handle<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
+{
};
-template <typename T, typename HP, typename AP, typename GP>
-class HandleBase<GCHashSet<T, HP, AP, GP>>
- : public GCHashSetOperations<JS::Handle<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
+template <typename T, typename HP, typename AP>
+class WeakCacheBase<JS::GCHashSet<T, HP, AP>>
+ : public MutableGCHashSetOperations<JS::WeakCache<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
- using Set = GCHashSet<T, HP, AP, GP>;
- friend class GCHashSetOperations<JS::Handle<Set>, T, HP, AP, GP>;
- const Set& extract() const { return *static_cast<const JS::Handle<Set>*>(this)->address(); }
};
} /* namespace js */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCPolicyAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCPolicyAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCPolicyAPI.h
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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/. */
+
+// GC Policy Mechanism
+
+// A GCPolicy controls how the GC interacts with both direct pointers to GC
+// things (e.g. JSObject* or JSString*), tagged and/or optional pointers to GC
+// things (e.g. Value or jsid), and C++ container types (e.g.
+// JSPropertyDescriptor or GCHashMap).
+//
+// The GCPolicy provides at a minimum:
+//
+// static T initial()
+// - Construct and return an empty T.
+//
+// static void trace(JSTracer, T* tp, const char* name)
+// - Trace the edge |*tp|, calling the edge |name|. Containers like
+// GCHashMap and GCHashSet use this method to trace their children.
+//
+// static bool needsSweep(T* tp)
+// - Return true if |*tp| is about to be finalized. Otherwise, update the
+// edge for moving GC, and return false. Containers like GCHashMap and
+// GCHashSet use this method to decide when to remove an entry: if this
+// function returns true on a key/value/member/etc, its entry is dropped
+// from the container. Specializing this method is the standard way to
+// get custom weak behavior from a container type.
+//
+// The default GCPolicy<T> assumes that T has a default constructor and |trace|
+// and |needsSweep| methods, and forwards to them. GCPolicy has appropriate
+// specializations for pointers to GC things and pointer-like types like
+// JS::Heap<T> and mozilla::UniquePtr<T>.
+//
+// There are some stock structs your specializations can inherit from.
+// IgnoreGCPolicy<T> does nothing. StructGCPolicy<T> forwards the methods to the
+// referent type T.
+
+#ifndef GCPolicyAPI_h
+#define GCPolicyAPI_h
+
+#include "mozilla/UniquePtr.h"
+
+#include "js/TraceKind.h"
+#include "js/TracingAPI.h"
+
+// Expand the given macro D for each public GC pointer.
+#define FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \
+ D(JS::Symbol*) \
+ D(JSAtom*) \
+ D(JSFunction*) \
+ D(JSObject*) \
+ D(JSScript*) \
+ D(JSString*)
+
+// Expand the given macro D for each public tagged GC pointer type.
+#define FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(D) \
+ D(JS::Value) \
+ D(jsid)
+
+#define FOR_EACH_PUBLIC_AGGREGATE_GC_POINTER_TYPE(D) \
+ D(JSPropertyDescriptor)
+
+class JSAtom;
+class JSFunction;
+class JSObject;
+class JSScript;
+class JSString;
+namespace JS {
+class Symbol;
+}
+
+namespace JS {
+
+// Defines a policy for container types with non-GC, i.e. C storage. This
+// policy dispatches to the underlying struct for GC interactions.
+template <typename T>
+struct StructGCPolicy
+{
+ static T initial() {
+ return T();
+ }
+
+ static void trace(JSTracer* trc, T* tp, const char* name) {
+ tp->trace(trc);
+ }
+
+ static void sweep(T* tp) {
+ return tp->sweep();
+ }
+
+ static bool needsSweep(T* tp) {
+ return tp->needsSweep();
+ }
+};
+
+// The default GC policy attempts to defer to methods on the underlying type.
+// Most C++ structures that contain a default constructor, a trace function and
+// a sweep function will work out of the box with Rooted, Handle, GCVector,
+// and GCHash{Set,Map}.
+template <typename T> struct GCPolicy : public StructGCPolicy<T> {};
+
+// This policy ignores any GC interaction, e.g. for non-GC types.
+template <typename T>
+struct IgnoreGCPolicy {
+ static T initial() { return T(); }
+ static void trace(JSTracer* trc, T* t, const char* name) {}
+ static bool needsSweep(T* v) { return false; }
+};
+template <> struct GCPolicy<uint32_t> : public IgnoreGCPolicy<uint32_t> {};
+template <> struct GCPolicy<uint64_t> : public IgnoreGCPolicy<uint64_t> {};
+
+template <typename T>
+struct GCPointerPolicy
+{
+ static T initial() { return nullptr; }
+ static void trace(JSTracer* trc, T* vp, const char* name) {
+ if (*vp)
+ js::UnsafeTraceManuallyBarrieredEdge(trc, vp, name);
+ }
+ static bool needsSweep(T* vp) {
+ if (*vp)
+ return js::gc::IsAboutToBeFinalizedUnbarriered(vp);
+ return false;
+ }
+};
+template <> struct GCPolicy<JS::Symbol*> : public GCPointerPolicy<JS::Symbol*> {};
+template <> struct GCPolicy<JSAtom*> : public GCPointerPolicy<JSAtom*> {};
+template <> struct GCPolicy<JSFunction*> : public GCPointerPolicy<JSFunction*> {};
+template <> struct GCPolicy<JSObject*> : public GCPointerPolicy<JSObject*> {};
+template <> struct GCPolicy<JSScript*> : public GCPointerPolicy<JSScript*> {};
+template <> struct GCPolicy<JSString*> : public GCPointerPolicy<JSString*> {};
+
+template <typename T>
+struct GCPolicy<JS::Heap<T>>
+{
+ static void trace(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
+ TraceEdge(trc, thingp, name);
+ }
+ static bool needsSweep(JS::Heap<T>* thingp) {
+ return js::gc::EdgeNeedsSweep(thingp);
+ }
+};
+
+// GCPolicy<UniquePtr<T>> forwards the contained pointer to GCPolicy<T>.
+template <typename T, typename D>
+struct GCPolicy<mozilla::UniquePtr<T, D>>
+{
+ static mozilla::UniquePtr<T,D> initial() { return mozilla::UniquePtr<T,D>(); }
+ static void trace(JSTracer* trc, mozilla::UniquePtr<T,D>* tp, const char* name) {
+ if (tp->get())
+ GCPolicy<T>::trace(trc, tp->get(), name);
+ }
+ static bool needsSweep(mozilla::UniquePtr<T,D>* tp) {
+ if (tp->get())
+ return GCPolicy<T>::needsSweep(tp->get());
+ return false;
+ }
+};
+
+} // namespace JS
+
+#endif // GCPolicyAPI_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCVariant.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCVariant.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCVariant.h
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_GCVariant_h
+#define js_GCVariant_h
+
+#include "mozilla/Variant.h"
+
+#include "js/GCPolicyAPI.h"
+#include "js/RootingAPI.h"
+#include "js/TracingAPI.h"
+
+namespace JS {
+
+// These template specializations allow Variant to be used inside GC wrappers.
+//
+// When matching on GC wrappers around Variants, matching should be done on
+// the wrapper itself. The matcher class's methods should take Handles or
+// MutableHandles. For example,
+//
+// struct MyMatcher
+// {
+// using ReturnType = const char*;
+// ReturnType match(HandleObject o) { return "object"; }
+// ReturnType match(HandleScript s) { return "script"; }
+// };
+//
+// Rooted<Variant<JSObject*, JSScript*>> v(cx, someScript);
+// MyMatcher mm;
+// v.match(mm);
+//
+// If you get compile errors about inability to upcast subclasses (e.g., from
+// NativeObject* to JSObject*) and are inside js/src, be sure to also include
+// "gc/Policy.h".
+
+namespace detail {
+
+template <typename... Ts>
+struct GCVariantImplementation;
+
+// The base case.
+template <typename T>
+struct GCVariantImplementation<T>
+{
+ template <typename ConcreteVariant>
+ static void trace(JSTracer* trc, ConcreteVariant* v, const char* name) {
+ T& thing = v->template as<T>();
+ if (!mozilla::IsPointer<T>::value || thing)
+ GCPolicy<T>::trace(trc, &thing, name);
+ }
+
+ template <typename Matcher, typename ConcreteVariant>
+ static typename Matcher::ReturnType
+ match(Matcher& matcher, Handle<ConcreteVariant> v) {
+ const T& thing = v.get().template as<T>();
+ return matcher.match(Handle<T>::fromMarkedLocation(&thing));
+ }
+
+ template <typename Matcher, typename ConcreteVariant>
+ static typename Matcher::ReturnType
+ match(Matcher& matcher, MutableHandle<ConcreteVariant> v) {
+ T& thing = v.get().template as<T>();
+ return matcher.match(MutableHandle<T>::fromMarkedLocation(&thing));
+ }
+};
+
+// The inductive case.
+template <typename T, typename... Ts>
+struct GCVariantImplementation<T, Ts...>
+{
+ using Next = GCVariantImplementation<Ts...>;
+
+ template <typename ConcreteVariant>
+ static void trace(JSTracer* trc, ConcreteVariant* v, const char* name) {
+ if (v->template is<T>()) {
+ T& thing = v->template as<T>();
+ if (!mozilla::IsPointer<T>::value || thing)
+ GCPolicy<T>::trace(trc, &thing, name);
+ } else {
+ Next::trace(trc, v, name);
+ }
+ }
+
+ template <typename Matcher, typename ConcreteVariant>
+ static typename Matcher::ReturnType
+ match(Matcher& matcher, Handle<ConcreteVariant> v) {
+ if (v.get().template is<T>()) {
+ const T& thing = v.get().template as<T>();
+ return matcher.match(Handle<T>::fromMarkedLocation(&thing));
+ }
+ return Next::match(matcher, v);
+ }
+
+ template <typename Matcher, typename ConcreteVariant>
+ static typename Matcher::ReturnType
+ match(Matcher& matcher, MutableHandle<ConcreteVariant> v) {
+ if (v.get().template is<T>()) {
+ T& thing = v.get().template as<T>();
+ return matcher.match(MutableHandle<T>::fromMarkedLocation(&thing));
+ }
+ return Next::match(matcher, v);
+ }
+};
+
+} // namespace detail
+
+template <typename... Ts>
+struct GCPolicy<mozilla::Variant<Ts...>>
+{
+ using Impl = detail::GCVariantImplementation<Ts...>;
+
+ // Variants do not provide initial(). They do not have a default initial
+ // value and one must be provided.
+
+ static void trace(JSTracer* trc, mozilla::Variant<Ts...>* v, const char* name) {
+ Impl::trace(trc, v, name);
+ }
+};
+
+} // namespace JS
+
+namespace js {
+
+template <typename Outer, typename... Ts>
+class GCVariantOperations
+{
+ using Impl = JS::detail::GCVariantImplementation<Ts...>;
+ using Variant = mozilla::Variant<Ts...>;
+
+ const Variant& variant() const { return static_cast<const Outer*>(this)->get(); }
+
+ public:
+ template <typename T>
+ bool is() const {
+ return variant().template is<T>();
+ }
+
+ template <typename T>
+ JS::Handle<T> as() const {
+ return Handle<T>::fromMarkedLocation(&variant().template as<T>());
+ }
+
+ template <typename Matcher>
+ typename Matcher::ReturnType
+ match(Matcher& matcher) const {
+ return Impl::match(matcher, JS::Handle<Variant>::fromMarkedLocation(&variant()));
+ }
+};
+
+template <typename Outer, typename... Ts>
+class MutableGCVariantOperations
+ : public GCVariantOperations<Outer, Ts...>
+{
+ using Impl = JS::detail::GCVariantImplementation<Ts...>;
+ using Variant = mozilla::Variant<Ts...>;
+
+ const Variant& variant() const { return static_cast<const Outer*>(this)->get(); }
+ Variant& variant() { return static_cast<Outer*>(this)->get(); }
+
+ public:
+ template <typename T>
+ JS::MutableHandle<T> as() {
+ return JS::MutableHandle<T>::fromMarkedLocation(&variant().template as<T>());
+ }
+
+ template <typename Matcher>
+ typename Matcher::ReturnType
+ match(Matcher& matcher) {
+ return Impl::match(matcher, JS::MutableHandle<Variant>::fromMarkedLocation(&variant()));
+ }
+};
+
+template <typename... Ts>
+class RootedBase<mozilla::Variant<Ts...>>
+ : public MutableGCVariantOperations<JS::Rooted<mozilla::Variant<Ts...>>, Ts...>
+{ };
+
+template <typename... Ts>
+class MutableHandleBase<mozilla::Variant<Ts...>>
+ : public MutableGCVariantOperations<JS::MutableHandle<mozilla::Variant<Ts...>>, Ts...>
+{ };
+
+template <typename... Ts>
+class HandleBase<mozilla::Variant<Ts...>>
+ : public GCVariantOperations<JS::Handle<mozilla::Variant<Ts...>>, Ts...>
+{ };
+
+template <typename... Ts>
+class PersistentRootedBase<mozilla::Variant<Ts...>>
+ : public MutableGCVariantOperations<JS::PersistentRooted<mozilla::Variant<Ts...>>, Ts...>
+{ };
+
+} // namespace js
+
+#endif // js_GCVariant_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCVector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCVector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCVector.h
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_GCVector_h
+#define js_GCVector_h
+
+#include "mozilla/Vector.h"
+
+#include "js/GCPolicyAPI.h"
+#include "js/RootingAPI.h"
+#include "js/TracingAPI.h"
+#include "js/Vector.h"
+
+namespace JS {
+
+// A GCVector is a Vector with an additional trace method that knows how
+// to visit all of the items stored in the Vector. For vectors that contain GC
+// things, this is usually more convenient than manually iterating and marking
+// the contents.
+//
+// Most types of GC pointers as keys and values can be traced with no extra
+// infrastructure. For structs and non-gc-pointer members, ensure that there is
+// a specialization of GCPolicy<T> with an appropriate trace method available
+// to handle the custom type. Generic helpers can be found in
+// js/public/TracingAPI.h.
+//
+// Note that although this Vector's trace will deal correctly with moved items,
+// it does not itself know when to barrier or trace items. To function properly
+// it must either be used with Rooted, or barriered and traced manually.
+template <typename T,
+ size_t MinInlineCapacity = 0,
+ typename AllocPolicy = js::TempAllocPolicy>
+class GCVector
+{
+ mozilla::Vector<T, MinInlineCapacity, AllocPolicy> vector;
+
+ public:
+ explicit GCVector(AllocPolicy alloc = AllocPolicy())
+ : vector(alloc)
+ {}
+
+ GCVector(GCVector&& vec)
+ : vector(mozilla::Move(vec.vector))
+ {}
+
+ GCVector& operator=(GCVector&& vec) {
+ vector = mozilla::Move(vec.vector);
+ return *this;
+ }
+
+ size_t length() const { return vector.length(); }
+ bool empty() const { return vector.empty(); }
+ size_t capacity() const { return vector.capacity(); }
+
+ T* begin() { return vector.begin(); }
+ const T* begin() const { return vector.begin(); }
+
+ T* end() { return vector.end(); }
+ const T* end() const { return vector.end(); }
+
+ T& operator[](size_t i) { return vector[i]; }
+ const T& operator[](size_t i) const { return vector[i]; }
+
+ T& back() { return vector.back(); }
+ const T& back() const { return vector.back(); }
+
+ bool initCapacity(size_t cap) { return vector.initCapacity(cap); }
+ bool reserve(size_t req) { return vector.reserve(req); }
+ void shrinkBy(size_t amount) { return vector.shrinkBy(amount); }
+ bool growBy(size_t amount) { return vector.growBy(amount); }
+ bool resize(size_t newLen) { return vector.resize(newLen); }
+
+ void clear() { return vector.clear(); }
+
+ template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }
+
+ template<typename... Args>
+ bool
+ emplaceBack(Args&&... args) {
+ return vector.emplaceBack(mozilla::Forward<Args>(args)...);
+ }
+
+ template<typename U>
+ void infallibleAppend(U&& aU) {
+ return vector.infallibleAppend(mozilla::Forward<U>(aU));
+ }
+ void infallibleAppendN(const T& aT, size_t aN) {
+ return vector.infallibleAppendN(aT, aN);
+ }
+ template<typename U> void
+ infallibleAppend(const U* aBegin, const U* aEnd) {
+ return vector.infallibleAppend(aBegin, aEnd);
+ }
+ template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
+ return vector.infallibleAppend(aBegin, aLength);
+ }
+
+ template<typename U, size_t O, class BP>
+ bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vector.appendAll(aU); }
+ template<typename U, size_t O, class BP>
+ bool appendAll(const GCVector<U, O, BP>& aU) { return vector.append(aU.begin(), aU.length()); }
+
+ bool appendN(const T& val, size_t count) { return vector.appendN(val, count); }
+
+ template<typename U> bool append(const U* aBegin, const U* aEnd) {
+ return vector.append(aBegin, aEnd);
+ }
+ template<typename U> bool append(const U* aBegin, size_t aLength) {
+ return vector.append(aBegin, aLength);
+ }
+
+ void popBack() { return vector.popBack(); }
+ T popCopy() { return vector.popCopy(); }
+
+ size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return vector.sizeOfExcludingThis(mallocSizeOf);
+ }
+
+ size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return vector.sizeOfIncludingThis(mallocSizeOf);
+ }
+
+ static void trace(GCVector* vec, JSTracer* trc) { vec->trace(trc); }
+
+ void trace(JSTracer* trc) {
+ for (auto& elem : vector)
+ GCPolicy<T>::trace(trc, &elem, "vector element");
+ }
+};
+
+} // namespace JS
+
+namespace js {
+
+template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
+class GCVectorOperations
+{
+ using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
+ const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
+
+ public:
+ const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
+ size_t length() const { return vec().length(); }
+ bool empty() const { return vec().empty(); }
+ size_t capacity() const { return vec().capacity(); }
+ const T* begin() const { return vec().begin(); }
+ const T* end() const { return vec().end(); }
+ const T& back() const { return vec().back(); }
+
+ JS::Handle<T> operator[](size_t aIndex) const {
+ return JS::Handle<T>::fromMarkedLocation(&vec().operator[](aIndex));
+ }
+};
+
+template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
+class MutableGCVectorOperations
+ : public GCVectorOperations<Outer, T, Capacity, AllocPolicy>
+{
+ using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
+ const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
+ Vec& vec() { return static_cast<Outer*>(this)->get(); }
+
+ public:
+ const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
+ AllocPolicy& allocPolicy() { return vec().allocPolicy(); }
+ const T* begin() const { return vec().begin(); }
+ T* begin() { return vec().begin(); }
+ const T* end() const { return vec().end(); }
+ T* end() { return vec().end(); }
+ const T& back() const { return vec().back(); }
+ T& back() { return vec().back(); }
+
+ JS::Handle<T> operator[](size_t aIndex) const {
+ return JS::Handle<T>::fromMarkedLocation(&vec().operator[](aIndex));
+ }
+ JS::MutableHandle<T> operator[](size_t aIndex) {
+ return JS::MutableHandle<T>::fromMarkedLocation(&vec().operator[](aIndex));
+ }
+
+ bool initCapacity(size_t aRequest) { return vec().initCapacity(aRequest); }
+ bool reserve(size_t aRequest) { return vec().reserve(aRequest); }
+ void shrinkBy(size_t aIncr) { vec().shrinkBy(aIncr); }
+ bool growBy(size_t aIncr) { return vec().growBy(aIncr); }
+ bool resize(size_t aNewLength) { return vec().resize(aNewLength); }
+ bool growByUninitialized(size_t aIncr) { return vec().growByUninitialized(aIncr); }
+ void infallibleGrowByUninitialized(size_t aIncr) { vec().infallibleGrowByUninitialized(aIncr); }
+ bool resizeUninitialized(size_t aNewLength) { return vec().resizeUninitialized(aNewLength); }
+ void clear() { vec().clear(); }
+ void clearAndFree() { vec().clearAndFree(); }
+ template<typename U> bool append(U&& aU) { return vec().append(mozilla::Forward<U>(aU)); }
+ template<typename... Args> bool emplaceBack(Args&&... aArgs) {
+ return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
+ }
+ template<typename U, size_t O, class BP>
+ bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vec().appendAll(aU); }
+ template<typename U, size_t O, class BP>
+ bool appendAll(const JS::GCVector<U, O, BP>& aU) { return vec().appendAll(aU); }
+ bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
+ template<typename U> bool append(const U* aBegin, const U* aEnd) {
+ return vec().append(aBegin, aEnd);
+ }
+ template<typename U> bool append(const U* aBegin, size_t aLength) {
+ return vec().append(aBegin, aLength);
+ }
+ template<typename U> void infallibleAppend(U&& aU) {
+ vec().infallibleAppend(mozilla::Forward<U>(aU));
+ }
+ void infallibleAppendN(const T& aT, size_t aN) { vec().infallibleAppendN(aT, aN); }
+ template<typename U> void infallibleAppend(const U* aBegin, const U* aEnd) {
+ vec().infallibleAppend(aBegin, aEnd);
+ }
+ template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
+ vec().infallibleAppend(aBegin, aLength);
+ }
+ void popBack() { vec().popBack(); }
+ T popCopy() { return vec().popCopy(); }
+ template<typename U> T* insert(T* aP, U&& aVal) {
+ return vec().insert(aP, mozilla::Forward<U>(aVal));
+ }
+ void erase(T* aT) { vec().erase(aT); }
+ void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
+};
+
+template <typename T, size_t N, typename AP>
+class RootedBase<JS::GCVector<T,N,AP>>
+ : public MutableGCVectorOperations<JS::Rooted<JS::GCVector<T,N,AP>>, T,N,AP>
+{};
+
+template <typename T, size_t N, typename AP>
+class MutableHandleBase<JS::GCVector<T,N,AP>>
+ : public MutableGCVectorOperations<JS::MutableHandle<JS::GCVector<T,N,AP>>, T,N,AP>
+{};
+
+template <typename T, size_t N, typename AP>
+class HandleBase<JS::GCVector<T,N,AP>>
+ : public GCVectorOperations<JS::Handle<JS::GCVector<T,N,AP>>, T,N,AP>
+{};
+
+template <typename T, size_t N, typename AP>
+class PersistentRootedBase<JS::GCVector<T,N,AP>>
+ : public MutableGCVectorOperations<JS::PersistentRooted<JS::GCVector<T,N,AP>>, T,N,AP>
+{};
+
+} // namespace js
+
+#endif // js_GCVector_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/HashTable.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/HashTable.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/HashTable.h
@@ -11,6 +11,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Casting.h"
+#include "mozilla/HashFunctions.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
#include "mozilla/Opaque.h"
@@ -34,6 +35,16 @@
/*****************************************************************************/
+// The "generation" of a hash table is an opaque value indicating the state of
+// modification of the hash table through its lifetime. If the generation of
+// a hash table compares equal at times T1 and T2, then lookups in the hash
+// table, pointers to (or into) hash table entries, etc. at time T1 are valid
+// at time T2. If the generation compares unequal, these computations are all
+// invalid and must be performed again to be used.
+//
+// Generations are meaningfully comparable only with respect to a single hash
+// table. It's always nonsensical to compare the generation of distinct hash
+// tables H1 and H2.
using Generation = mozilla::Opaque<uint64_t>;
// A JS-friendly, STL-like container providing a hash-based map from keys to
@@ -61,6 +72,7 @@
struct MapHashPolicy : HashPolicy
{
+ using Base = HashPolicy;
typedef Key KeyType;
static const Key& getKey(TableEntry& e) { return e.key(); }
static void setKey(TableEntry& e, Key& k) { HashPolicy::rekey(e.mutableKey(), k); }
@@ -76,8 +88,8 @@
// HashMap construction is fallible (due to OOM); thus the user must call
// init after constructing a HashMap and check the return value.
explicit HashMap(AllocPolicy a = AllocPolicy()) : impl(a) {}
- bool init(uint32_t len = 16) { return impl.init(len); }
- bool initialized() const { return impl.initialized(); }
+ MOZ_MUST_USE bool init(uint32_t len = 16) { return impl.init(len); }
+ bool initialized() const { return impl.initialized(); }
// Return whether the given lookup value is present in the map. E.g.:
//
@@ -139,19 +151,19 @@
}
template<typename KeyInput, typename ValueInput>
- bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) {
+ MOZ_MUST_USE bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) {
return impl.add(p,
mozilla::Forward<KeyInput>(k),
mozilla::Forward<ValueInput>(v));
}
template<typename KeyInput>
- bool add(AddPtr& p, KeyInput&& k) {
+ MOZ_MUST_USE bool add(AddPtr& p, KeyInput&& k) {
return impl.add(p, mozilla::Forward<KeyInput>(k), Value());
}
template<typename KeyInput, typename ValueInput>
- bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) {
+ MOZ_MUST_USE bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) {
return impl.relookupOrAdd(p, k,
mozilla::Forward<KeyInput>(k),
mozilla::Forward<ValueInput>(v));
@@ -208,8 +220,6 @@
return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
}
- // If |generation()| is the same before and after a HashMap operation,
- // pointers into the table remain valid.
Generation generation() const {
return impl.generation();
}
@@ -222,7 +232,7 @@
// Overwrite existing value with v. Return false on oom.
template<typename KeyInput, typename ValueInput>
- bool put(KeyInput&& k, ValueInput&& v) {
+ MOZ_MUST_USE bool put(KeyInput&& k, ValueInput&& v) {
AddPtr p = lookupForAdd(k);
if (p) {
p->value() = mozilla::Forward<ValueInput>(v);
@@ -233,7 +243,7 @@
// Like put, but assert that the given key is not already present.
template<typename KeyInput, typename ValueInput>
- bool putNew(KeyInput&& k, ValueInput&& v) {
+ MOZ_MUST_USE bool putNew(KeyInput&& k, ValueInput&& v) {
return impl.putNew(k, mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v));
}
@@ -248,7 +258,9 @@
AddPtr p = lookupForAdd(k);
if (p)
return p;
- (void)add(p, k, defaultValue); // p is left false-y on oom.
+ bool ok = add(p, k, defaultValue);
+ MOZ_ASSERT_IF(!ok, !p); // p is left false-y on oom.
+ (void)ok;
return p;
}
@@ -313,6 +325,7 @@
{
struct SetOps : HashPolicy
{
+ using Base = HashPolicy;
typedef T KeyType;
static const KeyType& getKey(const T& t) { return t; }
static void setKey(T& t, KeyType& k) { HashPolicy::rekey(t, k); }
@@ -328,8 +341,8 @@
// HashSet construction is fallible (due to OOM); thus the user must call
// init after constructing a HashSet and check the return value.
explicit HashSet(AllocPolicy a = AllocPolicy()) : impl(a) {}
- bool init(uint32_t len = 16) { return impl.init(len); }
- bool initialized() const { return impl.initialized(); }
+ MOZ_MUST_USE bool init(uint32_t len = 16) { return impl.init(len); }
+ bool initialized() const { return impl.initialized(); }
// Return whether the given lookup value is present in the map. E.g.:
//
@@ -386,12 +399,12 @@
AddPtr lookupForAdd(const Lookup& l) const { return impl.lookupForAdd(l); }
template <typename U>
- bool add(AddPtr& p, U&& u) {
+ MOZ_MUST_USE bool add(AddPtr& p, U&& u) {
return impl.add(p, mozilla::Forward<U>(u));
}
template <typename U>
- bool relookupOrAdd(AddPtr& p, const Lookup& l, U&& u) {
+ MOZ_MUST_USE bool relookupOrAdd(AddPtr& p, const Lookup& l, U&& u) {
return impl.relookupOrAdd(p, l, mozilla::Forward<U>(u));
}
@@ -446,8 +459,6 @@
return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
}
- // If |generation()| is the same before and after a HashSet operation,
- // pointers into the table remain valid.
Generation generation() const {
return impl.generation();
}
@@ -460,19 +471,19 @@
// Add |u| if it is not present already. Return false on oom.
template <typename U>
- bool put(U&& u) {
+ MOZ_MUST_USE bool put(U&& u) {
AddPtr p = lookupForAdd(u);
return p ? true : add(p, mozilla::Forward<U>(u));
}
// Like put, but assert that the given key is not already present.
template <typename U>
- bool putNew(U&& u) {
+ MOZ_MUST_USE bool putNew(U&& u) {
return impl.putNew(u, mozilla::Forward<U>(u));
}
template <typename U>
- bool putNew(const Lookup& l, U&& u) {
+ MOZ_MUST_USE bool putNew(const Lookup& l, U&& u) {
return impl.putNew(l, mozilla::Forward<U>(u));
}
@@ -503,11 +514,16 @@
return false;
}
- // Infallibly rekey one entry with a new key that is equivalent.
- void rekeyInPlace(Ptr p, const T& new_value)
- {
+ // Infallibly replace the current key at |p| with an equivalent key.
+ // Specifically, both HashPolicy::hash and HashPolicy::match must return
+ // identical results for the new and old key when applied against all
+ // possible matching values.
+ void replaceKey(Ptr p, const T& new_value) {
+ MOZ_ASSERT(p.found());
+ MOZ_ASSERT(*p != new_value);
+ MOZ_ASSERT(HashPolicy::hash(*p) == HashPolicy::hash(new_value));
MOZ_ASSERT(HashPolicy::match(*p, new_value));
- impl.rekeyInPlace(p, new_value);
+ const_cast<T&>(*p) = new_value;
}
// HashSet is movable
@@ -606,21 +622,21 @@
struct DefaultHasher<T*> : PointerHasher<T*, mozilla::tl::FloorLog2<sizeof(void*)>::value>
{};
-// Specialize hashing policy for mozilla::UniquePtr<T> to proxy the UniquePtr's
+// Specialize hashing policy for mozilla::UniquePtr to proxy the UniquePtr's
// raw pointer to PointerHasher.
-template <class T>
-struct DefaultHasher<mozilla::UniquePtr<T>>
+template <class T, class D>
+struct DefaultHasher<mozilla::UniquePtr<T, D>>
{
- using Lookup = mozilla::UniquePtr<T>;
+ using Lookup = mozilla::UniquePtr<T, D>;
using PtrHasher = PointerHasher<T*, mozilla::tl::FloorLog2<sizeof(void*)>::value>;
static HashNumber hash(const Lookup& l) {
return PtrHasher::hash(l.get());
}
- static bool match(const mozilla::UniquePtr<T>& k, const Lookup& l) {
+ static bool match(const mozilla::UniquePtr<T, D>& k, const Lookup& l) {
return PtrHasher::match(k.get(), l.get());
}
- static void rekey(mozilla::UniquePtr<T>& k, mozilla::UniquePtr<T>&& newKey) {
+ static void rekey(mozilla::UniquePtr<T, D>& k, mozilla::UniquePtr<T, D>&& newKey) {
k = mozilla::Move(newKey);
}
};
@@ -655,6 +671,50 @@
}
};
+// A hash policy that compares C strings.
+struct CStringHasher
+{
+ typedef const char* Lookup;
+ static js::HashNumber hash(Lookup l) {
+ return mozilla::HashString(l);
+ }
+ static bool match(const char* key, Lookup lookup) {
+ return strcmp(key, lookup) == 0;
+ }
+};
+
+// Fallible hashing interface.
+//
+// Most of the time generating a hash code is infallible so this class provides
+// default methods that always succeed. Specialize this class for your own hash
+// policy to provide fallible hashing.
+//
+// This is used by MovableCellHasher to handle the fact that generating a unique
+// ID for cell pointer may fail due to OOM.
+template <typename HashPolicy>
+struct FallibleHashMethods
+{
+ // Return true if a hashcode is already available for its argument. Once
+ // this returns true for a specific argument it must continue to do so.
+ template <typename Lookup> static bool hasHash(Lookup&& l) { return true; }
+
+ // Fallible method to ensure a hashcode exists for its argument and create
+ // one if not. Returns false on error, e.g. out of memory.
+ template <typename Lookup> static bool ensureHash(Lookup&& l) { return true; }
+};
+
+template <typename HashPolicy, typename Lookup>
+static bool
+HasHash(Lookup&& l) {
+ return FallibleHashMethods<typename HashPolicy::Base>::hasHash(mozilla::Forward<Lookup>(l));
+}
+
+template <typename HashPolicy, typename Lookup>
+static bool
+EnsureHash(Lookup&& l) {
+ return FallibleHashMethods<typename HashPolicy::Base>::ensureHash(mozilla::Forward<Lookup>(l));
+}
+
/*****************************************************************************/
// Both HashMap and HashSet are implemented by a single HashTable that is even
@@ -684,6 +744,11 @@
value_(mozilla::Move(rhs.value_))
{}
+ void operator=(HashMapEntry&& rhs) {
+ key_ = mozilla::Move(rhs.key_);
+ value_ = mozilla::Move(rhs.value_);
+ }
+
typedef Key KeyType;
typedef Value ValueType;
@@ -754,8 +819,16 @@
}
void swap(HashTableEntry* other) {
+ if (this == other)
+ return;
+ MOZ_ASSERT(isLive());
+ if (other->isLive()) {
+ mozilla::Swap(*mem.addr(), *other->mem.addr());
+ } else {
+ *other->mem.addr() = mozilla::Move(*mem.addr());
+ destroy();
+ }
mozilla::Swap(keyHash, other->keyHash);
- mozilla::Swap(mem, other->mem);
}
T& get() { MOZ_ASSERT(isLive()); return *mem.addr(); }
@@ -819,14 +892,21 @@
{}
public:
- // Leaves Ptr uninitialized.
- Ptr() {
+ Ptr()
+ : entry_(nullptr)
#ifdef JS_DEBUG
- entry_ = (Entry*)0xbad;
+ , table_(nullptr)
+ , generation(0)
#endif
+ {}
+
+ bool isValid() const {
+ return !entry_;
}
bool found() const {
+ if (isValid())
+ return false;
#ifdef JS_DEBUG
MOZ_ASSERT(generation == table_->generation());
#endif
@@ -851,6 +931,7 @@
T& operator*() const {
#ifdef JS_DEBUG
+ MOZ_ASSERT(found());
MOZ_ASSERT(generation == table_->generation());
#endif
return entry_->get();
@@ -858,6 +939,7 @@
T* operator->() const {
#ifdef JS_DEBUG
+ MOZ_ASSERT(found());
MOZ_ASSERT(generation == table_->generation());
#endif
return &entry_->get();
@@ -882,8 +964,7 @@
{}
public:
- // Leaves AddPtr uninitialized.
- AddPtr() {}
+ AddPtr() : keyHash(0) {}
};
// A collection of hash table entries. The collection is enumerated by
@@ -1173,7 +1254,7 @@
#endif
{}
- MOZ_WARN_UNUSED_RESULT bool init(uint32_t length)
+ MOZ_MUST_USE bool init(uint32_t length)
{
MOZ_ASSERT(!initialized());
@@ -1543,6 +1624,33 @@
// which approach is best.
}
+ // Note: |l| may be a reference to a piece of |u|, so this function
+ // must take care not to use |l| after moving |u|.
+ //
+ // Prefer to use putNewInfallible; this function does not check
+ // invariants.
+ template <typename... Args>
+ void putNewInfallibleInternal(const Lookup& l, Args&&... args)
+ {
+ MOZ_ASSERT(table);
+
+ HashNumber keyHash = prepareHash(l);
+ Entry* entry = &findFreeEntry(keyHash);
+ MOZ_ASSERT(entry);
+
+ if (entry->isRemoved()) {
+ METER(stats.addOverRemoved++);
+ removedCount--;
+ keyHash |= sCollisionBit;
+ }
+
+ entry->setLive(keyHash, mozilla::Forward<Args>(args)...);
+ entryCount++;
+#ifdef JS_DEBUG
+ mutationCount++;
+#endif
+ }
+
public:
void clear()
{
@@ -1622,12 +1730,16 @@
Ptr lookup(const Lookup& l) const
{
mozilla::ReentrancyGuard g(*this);
+ if (!HasHash<HashPolicy>(l))
+ return Ptr();
HashNumber keyHash = prepareHash(l);
return Ptr(lookup(l, keyHash, 0), *this);
}
Ptr readonlyThreadsafeLookup(const Lookup& l) const
{
+ if (!HasHash<HashPolicy>(l))
+ return Ptr();
HashNumber keyHash = prepareHash(l);
return Ptr(lookup(l, keyHash, 0), *this);
}
@@ -1635,6 +1747,8 @@
AddPtr lookupForAdd(const Lookup& l) const
{
mozilla::ReentrancyGuard g(*this);
+ if (!EnsureHash<HashPolicy>(l))
+ return AddPtr();
HashNumber keyHash = prepareHash(l);
Entry& entry = lookup(l, keyHash, sCollisionBit);
AddPtr p(entry, *this, keyHash);
@@ -1642,13 +1756,17 @@
}
template <typename... Args>
- bool add(AddPtr& p, Args&&... args)
+ MOZ_MUST_USE bool add(AddPtr& p, Args&&... args)
{
mozilla::ReentrancyGuard g(*this);
MOZ_ASSERT(table);
MOZ_ASSERT(!p.found());
MOZ_ASSERT(!(p.keyHash & sCollisionBit));
+ // Check for error from ensureHash() here.
+ if (p.isValid())
+ return false;
+
// Changing an entry from removed to live does not affect whether we
// are overloaded and can be handled separately.
if (p.entry_->isRemoved()) {
@@ -1662,7 +1780,7 @@
RebuildStatus status = checkOverloaded();
if (status == RehashFailed)
return false;
- if (!this->checkSimulatedOOM())
+ if (status == NotOverloaded && !this->checkSimulatedOOM())
return false;
if (status == Rehashed)
p.entry_ = &findFreeEntry(p.keyHash);
@@ -1683,33 +1801,22 @@
template <typename... Args>
void putNewInfallible(const Lookup& l, Args&&... args)
{
- MOZ_ASSERT(table);
-
- HashNumber keyHash = prepareHash(l);
- Entry* entry = &findFreeEntry(keyHash);
- MOZ_ASSERT(entry);
-
- if (entry->isRemoved()) {
- METER(stats.addOverRemoved++);
- removedCount--;
- keyHash |= sCollisionBit;
- }
-
- entry->setLive(keyHash, mozilla::Forward<Args>(args)...);
- entryCount++;
-#ifdef JS_DEBUG
- mutationCount++;
-#endif
+ MOZ_ASSERT(!lookup(l).found());
+ mozilla::ReentrancyGuard g(*this);
+ putNewInfallibleInternal(l, mozilla::Forward<Args>(args)...);
}
// Note: |l| may be alias arguments in |args|, so this function must take
// care not to use |l| after moving |args|.
template <typename... Args>
- bool putNew(const Lookup& l, Args&&... args)
+ MOZ_MUST_USE bool putNew(const Lookup& l, Args&&... args)
{
if (!this->checkSimulatedOOM())
return false;
+ if (!EnsureHash<HashPolicy>(l))
+ return false;
+
if (checkOverloaded() == RehashFailed)
return false;
@@ -1720,8 +1827,12 @@
// Note: |l| may be a reference to a piece of |u|, so this function
// must take care not to use |l| after moving |u|.
template <typename... Args>
- bool relookupOrAdd(AddPtr& p, const Lookup& l, Args&&... args)
+ MOZ_MUST_USE bool relookupOrAdd(AddPtr& p, const Lookup& l, Args&&... args)
{
+ // Check for error from ensureHash() here.
+ if (p.isValid())
+ return false;
+
#ifdef JS_DEBUG
p.generation = generation();
p.mutationCount = mutationCount;
@@ -1751,7 +1862,7 @@
typename HashTableEntry<T>::NonConstT t(mozilla::Move(*p));
HashPolicy::setKey(t, const_cast<Key&>(k));
remove(*p.entry_);
- putNewInfallible(l, mozilla::Move(t));
+ putNewInfallibleInternal(l, mozilla::Move(t));
}
void rekeyAndMaybeRehash(Ptr p, const Lookup& l, const Key& k)
@@ -1760,14 +1871,6 @@
checkOverRemoved();
}
- void rekeyInPlace(Ptr p, const Key& k)
- {
- MOZ_ASSERT(table);
- mozilla::ReentrancyGuard g(*this);
- MOZ_ASSERT(p.found());
- HashPolicy::rekey(const_cast<Key&>(*p), const_cast<Key&>(k));
- }
-
#undef METER
};
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/HeapAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/HeapAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/HeapAPI.h
@@ -17,11 +17,6 @@
/* These values are private to the JS engine. */
namespace js {
-// Whether the current thread is permitted access to any part of the specified
-// runtime or zone.
-JS_FRIEND_API(bool)
-CurrentThreadCanAccessRuntime(JSRuntime* rt);
-
JS_FRIEND_API(bool)
CurrentThreadCanAccessZone(JS::Zone* zone);
@@ -56,7 +51,9 @@
const size_t ChunkRuntimeOffset = ChunkSize - sizeof(void*);
const size_t ChunkTrailerSize = 2 * sizeof(uintptr_t) + sizeof(uint64_t);
const size_t ChunkLocationOffset = ChunkSize - ChunkTrailerSize;
-const size_t ArenaZoneOffset = 0;
+const size_t ArenaZoneOffset = sizeof(size_t);
+const size_t ArenaHeaderSize = sizeof(size_t) + 2 * sizeof(uintptr_t) +
+ sizeof(size_t) + sizeof(uintptr_t);
/*
* Live objects are marked black. How many other additional colors are available
@@ -67,19 +64,15 @@
static const uint32_t GRAY = 1;
/*
- * The "location" field in the Chunk trailer is a bit vector indicting various
- * roles of the chunk.
- *
- * The value 0 for the "location" field is invalid, at least one bit must be
- * set.
- *
- * Some bits preclude others, for example, any "nursery" bit precludes any
- * "tenured" or "middle generation" bit.
+ * The "location" field in the Chunk trailer is a enum indicating various roles
+ * of the chunk.
*/
-const uintptr_t ChunkLocationBitNursery = 1; // Standard GGC nursery
-const uintptr_t ChunkLocationBitTenuredHeap = 2; // Standard GGC tenured generation
-
-const uintptr_t ChunkLocationAnyNursery = ChunkLocationBitNursery;
+enum class ChunkLocation : uint32_t
+{
+ Invalid = 0,
+ Nursery = 1,
+ TenuredHeap = 2
+};
#ifdef JS_DEBUG
/* When downcasting, ensure we are actually the right type. */
@@ -113,13 +106,20 @@
JSTracer* const barrierTracer_; // A pointer to the JSRuntime's |gcMarker|.
public:
+ // Stack GC roots for Rooted GC pointers.
+ js::RootedListHeads stackRoots_;
+ template <typename T> friend class JS::Rooted;
+
bool needsIncrementalBarrier_;
Zone(JSRuntime* runtime, JSTracer* barrierTracerArg)
: runtime_(runtime),
barrierTracer_(barrierTracerArg),
needsIncrementalBarrier_(false)
- {}
+ {
+ for (auto& stackRootPtr : stackRoots_)
+ stackRootPtr = nullptr;
+ }
bool needsIncrementalBarrier() const {
return needsIncrementalBarrier_;
@@ -142,7 +142,7 @@
return runtime_;
}
- static JS::shadow::Zone* asShadowZone(JS::Zone* zone) {
+ static MOZ_ALWAYS_INLINE JS::shadow::Zone* asShadowZone(JS::Zone* zone) {
return reinterpret_cast<JS::shadow::Zone*>(zone);
}
};
@@ -280,14 +280,6 @@
return reinterpret_cast<uintptr_t*>(bmap_addr);
}
-static MOZ_ALWAYS_INLINE JS::shadow::Runtime*
-GetGCThingRuntime(const uintptr_t addr)
-{
- MOZ_ASSERT(addr);
- const uintptr_t rt_addr = (addr & ~ChunkMask) | ChunkRuntimeOffset;
- return *reinterpret_cast<JS::shadow::Runtime**>(rt_addr);
-}
-
static MOZ_ALWAYS_INLINE void
GetGCThingMarkWordAndMask(const uintptr_t addr, uint32_t color,
uintptr_t** wordp, uintptr_t* maskp)
@@ -310,16 +302,30 @@
}
+static MOZ_ALWAYS_INLINE JS::shadow::Runtime*
+GetCellRuntime(const Cell* cell)
+{
+ MOZ_ASSERT(cell);
+ const uintptr_t addr = uintptr_t(cell);
+ const uintptr_t rt_addr = (addr & ~ChunkMask) | ChunkRuntimeOffset;
+ return *reinterpret_cast<JS::shadow::Runtime**>(rt_addr);
+}
+
static MOZ_ALWAYS_INLINE bool
CellIsMarkedGray(const Cell* cell)
{
MOZ_ASSERT(cell);
- MOZ_ASSERT(!js::gc::IsInsideNursery(cell));
+ if (js::gc::IsInsideNursery(cell))
+ return false;
+
uintptr_t* word, mask;
js::gc::detail::GetGCThingMarkWordAndMask(uintptr_t(cell), js::gc::GRAY, &word, &mask);
return *word & mask;
}
+extern JS_PUBLIC_API(bool)
+CellIsMarkedGrayIfKnown(const Cell* cell);
+
} /* namespace detail */
MOZ_ALWAYS_INLINE bool
@@ -330,9 +336,9 @@
uintptr_t addr = uintptr_t(cell);
addr &= ~js::gc::ChunkMask;
addr |= js::gc::ChunkLocationOffset;
- uint32_t location = *reinterpret_cast<uint32_t*>(addr);
- MOZ_ASSERT(location != 0);
- return location & ChunkLocationAnyNursery;
+ auto location = *reinterpret_cast<ChunkLocation*>(addr);
+ MOZ_ASSERT(location == ChunkLocation::Nursery || location == ChunkLocation::TenuredHeap);
+ return location == ChunkLocation::Nursery;
}
} /* namespace gc */
@@ -357,40 +363,16 @@
GetObjectZone(JSObject* obj);
static MOZ_ALWAYS_INLINE bool
-ObjectIsTenured(JSObject* obj)
-{
- return !js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(obj));
-}
-
-static MOZ_ALWAYS_INLINE bool
-ObjectIsMarkedGray(JSObject* obj)
-{
- /*
- * GC things residing in the nursery cannot be gray: they have no mark bits.
- * All live objects in the nursery are moved to tenured at the beginning of
- * each GC slice, so the gray marker never sees nursery things.
- */
- if (js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(obj)))
- return false;
- return js::gc::detail::CellIsMarkedGray(reinterpret_cast<js::gc::Cell*>(obj));
-}
-
-static MOZ_ALWAYS_INLINE bool
-ScriptIsMarkedGray(JSScript* script)
-{
- return js::gc::detail::CellIsMarkedGray(reinterpret_cast<js::gc::Cell*>(script));
-}
-
-static MOZ_ALWAYS_INLINE bool
GCThingIsMarkedGray(GCCellPtr thing)
{
- if (js::gc::IsInsideNursery(thing.asCell()))
- return false;
if (thing.mayBeOwnedByOtherRuntime())
return false;
- return js::gc::detail::CellIsMarkedGray(thing.asCell());
+ return js::gc::detail::CellIsMarkedGrayIfKnown(thing.asCell());
}
+extern JS_PUBLIC_API(JS::TraceKind)
+GCThingTraceKind(void* thing);
+
} /* namespace JS */
namespace js {
@@ -401,8 +383,11 @@
{
MOZ_ASSERT(thing);
MOZ_ASSERT(!js::gc::IsInsideNursery(thing.asCell()));
- if (rt->isHeapBusy())
- return false;
+
+ // TODO: I'd like to assert !isHeapBusy() here but this gets called while we
+ // are tracing the heap, e.g. during memory reporting (see bug 1313318).
+ MOZ_ASSERT(!rt->isHeapCollecting());
+
JS::Zone* zone = JS::GetTenuredGCThingZone(thing);
return JS::shadow::Zone::asShadowZone(zone)->needsIncrementalBarrier();
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Id.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Id.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Id.h
@@ -30,9 +30,9 @@
struct jsid
{
size_t asBits;
- bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
- bool operator!=(jsid rhs) const { return asBits != rhs.asBits; }
-};
+ bool operator==(const jsid& rhs) const { return asBits == rhs.asBits; }
+ bool operator!=(const jsid& rhs) const { return asBits != rhs.asBits; }
+} JS_HAZ_GC_POINTER;
#define JSID_BITS(id) (id.asBits)
#define JSID_TYPE_STRING 0x0
@@ -69,12 +69,6 @@
INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str);
static MOZ_ALWAYS_INLINE bool
-JSID_IS_ZERO(jsid id)
-{
- return JSID_BITS(id) == 0;
-}
-
-static MOZ_ALWAYS_INLINE bool
JSID_IS_INT(jsid id)
{
return !!(JSID_BITS(id) & JSID_TYPE_INT);
@@ -166,20 +160,36 @@
extern JS_PUBLIC_DATA(const JS::HandleId) JSID_VOIDHANDLE;
extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
-namespace js {
+namespace JS {
template <>
-struct GCMethods<jsid>
+struct GCPolicy<jsid>
{
static jsid initial() { return JSID_VOID; }
+ static void trace(JSTracer* trc, jsid* idp, const char* name) {
+ js::UnsafeTraceManuallyBarrieredEdge(trc, idp, name);
+ }
+};
+
+} // namespace JS
+
+namespace js {
+
+template <>
+struct BarrierMethods<jsid>
+{
static void postBarrier(jsid* idp, jsid prev, jsid next) {}
+ static void exposeToJS(jsid id) {
+ if (JSID_IS_GCTHING(id))
+ js::gc::ExposeGCThingToActiveJS(JSID_TO_GCTHING(id));
+ }
};
// If the jsid is a GC pointer type, convert to that type and call |f| with
// the pointer. If the jsid is not a GC type, calls F::defaultValue.
template <typename F, typename... Args>
auto
-DispatchTyped(F f, jsid& id, Args&&... args)
+DispatchTyped(F f, const jsid& id, Args&&... args)
-> decltype(f(static_cast<JSString*>(nullptr), mozilla::Forward<Args>(args)...))
{
if (JSID_IS_STRING(id))
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Initialization.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Initialization.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Initialization.h
@@ -25,6 +25,9 @@
extern JS_PUBLIC_DATA(InitState)
libraryInitState;
+extern JS_PUBLIC_API(const char*)
+InitWithFailureDiagnostic(bool isDebugBuild);
+
} // namespace detail
} // namespace JS
@@ -58,8 +61,46 @@
* is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
* again). This restriction may eventually be lifted.
*/
-extern JS_PUBLIC_API(bool)
-JS_Init(void);
+inline bool
+JS_Init(void)
+{
+#ifdef DEBUG
+ return !JS::detail::InitWithFailureDiagnostic(true);
+#else
+ return !JS::detail::InitWithFailureDiagnostic(false);
+#endif
+}
+
+/**
+ * A variant of JS_Init. On success it returns nullptr. On failure it returns a
+ * pointer to a string literal that describes how initialization failed, which
+ * can be useful for debugging purposes.
+ */
+inline const char*
+JS_InitWithFailureDiagnostic(void)
+{
+#ifdef DEBUG
+ return JS::detail::InitWithFailureDiagnostic(true);
+#else
+ return JS::detail::InitWithFailureDiagnostic(false);
+#endif
+}
+
+/*
+ * Returns true if SpiderMonkey has been initialized successfully, even if it has
+ * possibly been shut down.
+ *
+ * Note that it is the responsibility of the embedder to call JS_Init() and
+ * JS_ShutDown() at the correct times, and therefore this API should ideally not
+ * be necessary to use. This is only intended to be used in cases where the
+ * embedder isn't in full control of deciding whether to initialize SpiderMonkey
+ * or hand off the task to another consumer.
+ */
+inline bool
+JS_IsInitialized(void)
+{
+ return JS::detail::libraryInitState != JS::detail::InitState::Uninitialized;
+}
/**
* Destroy free-standing resources allocated by SpiderMonkey, not associated
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/MemoryMetrics.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/MemoryMetrics.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/MemoryMetrics.h
@@ -166,23 +166,17 @@
#define FOR_EACH_SIZE(macro) \
macro(Objects, GCHeapUsed, objectsGCHeap) \
macro(Objects, MallocHeap, objectsMallocHeapSlots) \
- macro(Objects, MallocHeap, objectsMallocHeapElementsNonAsmJS) \
+ macro(Objects, MallocHeap, objectsMallocHeapElementsNormal) \
macro(Objects, MallocHeap, objectsMallocHeapElementsAsmJS) \
- macro(Objects, NonHeap, objectsNonHeapElementsAsmJS) \
- macro(Objects, NonHeap, objectsNonHeapElementsMapped) \
- macro(Objects, NonHeap, objectsNonHeapCodeAsmJS) \
macro(Objects, MallocHeap, objectsMallocHeapMisc) \
- \
- macro(Other, GCHeapUsed, shapesGCHeapTree) \
- macro(Other, GCHeapUsed, shapesGCHeapDict) \
- macro(Other, GCHeapUsed, shapesGCHeapBase) \
- macro(Other, MallocHeap, shapesMallocHeapTreeTables) \
- macro(Other, MallocHeap, shapesMallocHeapDictTables) \
- macro(Other, MallocHeap, shapesMallocHeapTreeKids)
+ macro(Objects, NonHeap, objectsNonHeapElementsNormal) \
+ macro(Objects, NonHeap, objectsNonHeapElementsShared) \
+ macro(Objects, NonHeap, objectsNonHeapElementsWasm) \
+ macro(Objects, NonHeap, objectsNonHeapCodeWasm)
ClassInfo()
: FOR_EACH_SIZE(ZERO_SIZE)
- dummy()
+ wasmGuardPages(0)
{}
void add(const ClassInfo& other) {
@@ -219,6 +213,55 @@
}
FOR_EACH_SIZE(DECL_SIZE)
+ size_t wasmGuardPages;
+
+#undef FOR_EACH_SIZE
+};
+
+struct ShapeInfo
+{
+#define FOR_EACH_SIZE(macro) \
+ macro(Other, GCHeapUsed, shapesGCHeapTree) \
+ macro(Other, GCHeapUsed, shapesGCHeapDict) \
+ macro(Other, GCHeapUsed, shapesGCHeapBase) \
+ macro(Other, MallocHeap, shapesMallocHeapTreeTables) \
+ macro(Other, MallocHeap, shapesMallocHeapDictTables) \
+ macro(Other, MallocHeap, shapesMallocHeapTreeKids)
+
+ ShapeInfo()
+ : FOR_EACH_SIZE(ZERO_SIZE)
+ dummy()
+ {}
+
+ void add(const ShapeInfo& other) {
+ FOR_EACH_SIZE(ADD_OTHER_SIZE)
+ }
+
+ void subtract(const ShapeInfo& other) {
+ FOR_EACH_SIZE(SUB_OTHER_SIZE)
+ }
+
+ size_t sizeOfAllThings() const {
+ size_t n = 0;
+ FOR_EACH_SIZE(ADD_SIZE_TO_N)
+ return n;
+ }
+
+ size_t sizeOfLiveGCThings() const {
+ size_t n = 0;
+ FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
+ return n;
+ }
+
+ void addToTabSizes(TabSizes* sizes) const {
+ FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
+ }
+
+ void addToServoSizes(ServoSizes *sizes) const {
+ FOR_EACH_SIZE(ADD_TO_SERVO_SIZES)
+ }
+
+ FOR_EACH_SIZE(DECL_SIZE)
int dummy; // present just to absorb the trailing comma from FOR_EACH_SIZE(ZERO_SIZE)
#undef FOR_EACH_SIZE
@@ -282,7 +325,6 @@
#define FOR_EACH_SIZE(macro) \
macro(_, MallocHeap, marker) \
macro(_, NonHeap, nurseryCommitted) \
- macro(_, NonHeap, nurseryDecommitted) \
macro(_, MallocHeap, nurseryMallocedBuffers) \
macro(_, MallocHeap, storeBufferVals) \
macro(_, MallocHeap, storeBufferCells) \
@@ -396,8 +438,6 @@
struct ScriptSourceInfo
{
#define FOR_EACH_SIZE(macro) \
- macro(_, MallocHeap, compressed) \
- macro(_, MallocHeap, uncompressed) \
macro(_, MallocHeap, misc)
ScriptSourceInfo()
@@ -468,12 +508,12 @@
macro(_, MallocHeap, object) \
macro(_, MallocHeap, atomsTable) \
macro(_, MallocHeap, contexts) \
- macro(_, MallocHeap, dtoa) \
macro(_, MallocHeap, temporary) \
macro(_, MallocHeap, interpreterStack) \
macro(_, MallocHeap, mathCache) \
+ macro(_, MallocHeap, sharedImmutableStringsCache) \
+ macro(_, MallocHeap, sharedIntlData) \
macro(_, MallocHeap, uncompressedSourceCache) \
- macro(_, MallocHeap, compressedSourceSet) \
macro(_, MallocHeap, scriptData)
RuntimeSizes()
@@ -537,6 +577,7 @@
macro(Other, GCHeapUnused, string) \
macro(Other, GCHeapUnused, symbol) \
macro(Other, GCHeapUnused, jitcode) \
+ macro(Other, GCHeapUnused, scope)
UnusedGCThingSizes()
: FOR_EACH_SIZE(ZERO_SIZE)
@@ -559,6 +600,7 @@
case JS::TraceKind::JitCode: jitcode += n; break;
case JS::TraceKind::LazyScript: lazyScript += n; break;
case JS::TraceKind::ObjectGroup: objectGroup += n; break;
+ case JS::TraceKind::Scope: scope += n; break;
default:
MOZ_CRASH("Bad trace kind for UnusedGCThingSizes");
}
@@ -598,14 +640,18 @@
macro(Other, GCHeapUsed, jitCodesGCHeap) \
macro(Other, GCHeapUsed, objectGroupsGCHeap) \
macro(Other, MallocHeap, objectGroupsMallocHeap) \
+ macro(Other, GCHeapUsed, scopesGCHeap) \
+ macro(Other, MallocHeap, scopesMallocHeap) \
macro(Other, MallocHeap, typePool) \
macro(Other, MallocHeap, baselineStubsOptimized) \
- macro(Other, MallocHeap, uniqueIdMap)
+ macro(Other, MallocHeap, uniqueIdMap) \
+ macro(Other, MallocHeap, shapeTables)
ZoneStats()
: FOR_EACH_SIZE(ZERO_SIZE)
unusedGCThings(),
stringInfo(),
+ shapeInfo(),
extra(),
allStrings(nullptr),
notableStrings(),
@@ -616,6 +662,7 @@
: FOR_EACH_SIZE(COPY_OTHER_SIZE)
unusedGCThings(mozilla::Move(other.unusedGCThings)),
stringInfo(mozilla::Move(other.stringInfo)),
+ shapeInfo(mozilla::Move(other.shapeInfo)),
extra(other.extra),
allStrings(other.allStrings),
notableStrings(mozilla::Move(other.notableStrings)),
@@ -639,6 +686,7 @@
FOR_EACH_SIZE(ADD_OTHER_SIZE)
unusedGCThings.addSizes(other.unusedGCThings);
stringInfo.add(other.stringInfo);
+ shapeInfo.add(other.shapeInfo);
}
size_t sizeOfLiveGCThings() const {
@@ -646,6 +694,7 @@
size_t n = 0;
FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
n += stringInfo.sizeOfLiveGCThings();
+ n += shapeInfo.sizeOfLiveGCThings();
return n;
}
@@ -654,6 +703,7 @@
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
unusedGCThings.addToTabSizes(sizes);
stringInfo.addToTabSizes(sizes);
+ shapeInfo.addToTabSizes(sizes);
}
void addToServoSizes(JS::ServoSizes *sizes) const {
@@ -661,6 +711,7 @@
FOR_EACH_SIZE(ADD_TO_SERVO_SIZES)
unusedGCThings.addToServoSizes(sizes);
stringInfo.addToServoSizes(sizes);
+ shapeInfo.addToServoSizes(sizes);
}
// These string measurements are initially for all strings. At the end,
@@ -670,6 +721,7 @@
FOR_EACH_SIZE(DECL_SIZE)
UnusedGCThingSizes unusedGCThings;
StringInfo stringInfo;
+ ShapeInfo shapeInfo;
void* extra; // This field can be used by embedders.
typedef js::HashMap<JSString*, StringInfo,
@@ -712,7 +764,10 @@
macro(Other, MallocHeap, crossCompartmentWrappersTable) \
macro(Other, MallocHeap, regexpCompartment) \
macro(Other, MallocHeap, savedStacksSet) \
- macro(Other, MallocHeap, nonSyntacticLexicalScopesTable)
+ macro(Other, MallocHeap, varNamesSet) \
+ macro(Other, MallocHeap, nonSyntacticLexicalScopesTable) \
+ macro(Other, MallocHeap, jitCompartment) \
+ macro(Other, MallocHeap, privateData)
CompartmentStats()
: FOR_EACH_SIZE(ZERO_SIZE)
@@ -735,6 +790,8 @@
MOZ_ASSERT(!other.isTotals);
}
+ CompartmentStats(const CompartmentStats&) = delete; // disallow copying
+
~CompartmentStats() {
// |allClasses| is usually deleted and set to nullptr before this
// destructor runs. But there are failure cases due to OOMs that may
@@ -881,23 +938,23 @@
};
extern JS_PUBLIC_API(bool)
-CollectRuntimeStats(JSRuntime* rt, RuntimeStats* rtStats, ObjectPrivateVisitor* opv, bool anonymize);
+CollectRuntimeStats(JSContext* cx, RuntimeStats* rtStats, ObjectPrivateVisitor* opv, bool anonymize);
extern JS_PUBLIC_API(size_t)
-SystemCompartmentCount(JSRuntime* rt);
+SystemCompartmentCount(JSContext* cx);
extern JS_PUBLIC_API(size_t)
-UserCompartmentCount(JSRuntime* rt);
+UserCompartmentCount(JSContext* cx);
extern JS_PUBLIC_API(size_t)
-PeakSizeOfTemporary(const JSRuntime* rt);
+PeakSizeOfTemporary(const JSContext* cx);
extern JS_PUBLIC_API(bool)
-AddSizeOfTab(JSRuntime* rt, JS::HandleObject obj, mozilla::MallocSizeOf mallocSizeOf,
+AddSizeOfTab(JSContext* cx, JS::HandleObject obj, mozilla::MallocSizeOf mallocSizeOf,
ObjectPrivateVisitor* opv, TabSizes* sizes);
extern JS_PUBLIC_API(bool)
-AddServoSizeOf(JSRuntime *rt, mozilla::MallocSizeOf mallocSizeOf,
+AddServoSizeOf(JSContext* cx, mozilla::MallocSizeOf mallocSizeOf,
ObjectPrivateVisitor *opv, ServoSizes *sizes);
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Principals.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Principals.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Principals.h
@@ -18,7 +18,7 @@
#include "js/StructuredClone.h"
namespace js {
- struct PerformanceGroup;
+ struct JS_PUBLIC_API(PerformanceGroup);
} // namespace js
struct JSPrincipals {
@@ -55,7 +55,7 @@
JS_HoldPrincipals(JSPrincipals* principals);
extern JS_PUBLIC_API(void)
-JS_DropPrincipals(JSRuntime* rt, JSPrincipals* principals);
+JS_DropPrincipals(JSContext* cx, JSPrincipals* principals);
// Return whether the first principal subsumes the second. The exact meaning of
// 'subsumes' is left up to the browser. Subsumption is checked inside the JS
@@ -76,10 +76,10 @@
};
extern JS_PUBLIC_API(void)
-JS_SetSecurityCallbacks(JSRuntime* rt, const JSSecurityCallbacks* callbacks);
+JS_SetSecurityCallbacks(JSContext* cx, const JSSecurityCallbacks* callbacks);
extern JS_PUBLIC_API(const JSSecurityCallbacks*)
-JS_GetSecurityCallbacks(JSRuntime* rt);
+JS_GetSecurityCallbacks(JSContext* cx);
/*
* Code running with "trusted" principals will be given a deeper stack
@@ -87,14 +87,14 @@
* untrusted script has exhausted the stack. This function sets the
* runtime-wide trusted principal.
*
- * This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals) since
- * there is no available JSContext. Instead, the caller must ensure that the
- * given principals stays valid for as long as 'rt' may point to it. If the
- * principals would be destroyed before 'rt', JS_SetTrustedPrincipals must be
- * called again, passing nullptr for 'prin'.
+ * This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals).
+ * Instead, the caller must ensure that the given principals stays valid for as
+ * long as 'cx' may point to it. If the principals would be destroyed before
+ * 'cx', JS_SetTrustedPrincipals must be called again, passing nullptr for
+ * 'prin'.
*/
extern JS_PUBLIC_API(void)
-JS_SetTrustedPrincipals(JSRuntime* rt, JSPrincipals* prin);
+JS_SetTrustedPrincipals(JSContext* cx, JSPrincipals* prin);
typedef void
(* JSDestroyPrincipalsOp)(JSPrincipals* principals);
@@ -105,7 +105,7 @@
* only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
-JS_InitDestroyPrincipalsCallback(JSRuntime* rt, JSDestroyPrincipalsOp destroyPrincipals);
+JS_InitDestroyPrincipalsCallback(JSContext* cx, JSDestroyPrincipalsOp destroyPrincipals);
/*
* Read a JSPrincipals instance from the given |reader| and initialize the out
@@ -126,7 +126,7 @@
* buffer. The initialization can be done only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
-JS_InitReadPrincipalsCallback(JSRuntime* rt, JSReadPrincipalsOp read);
+JS_InitReadPrincipalsCallback(JSContext* cx, JSReadPrincipalsOp read);
#endif /* js_Principals_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/ProfilingFrameIterator.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/ProfilingFrameIterator.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/ProfilingFrameIterator.h
@@ -11,20 +11,24 @@
#include "mozilla/Maybe.h"
#include "jsbytecode.h"
+#include "js/GCAPI.h"
#include "js/TypeDecls.h"
#include "js/Utility.h"
+struct JSContext;
struct JSRuntime;
class JSScript;
namespace js {
class Activation;
- class AsmJSProfilingFrameIterator;
namespace jit {
class JitActivation;
class JitProfilingFrameIterator;
class JitcodeGlobalEntry;
} // namespace jit
+ namespace wasm {
+ class ProfilingFrameIterator;
+ } // namespace wasm
} // namespace js
namespace JS {
@@ -36,6 +40,10 @@
// arbitrary pc. To provide acurate results, profiling must have been enabled
// (via EnableRuntimeProfilingStack) before executing the callstack being
// unwound.
+//
+// Note that the caller must not do anything that could cause GC to happen while
+// the iterator is alive, since this could invalidate Ion code and cause its
+// contents to become out of date.
class JS_PUBLIC_API(ProfilingFrameIterator)
{
JSRuntime* rt_;
@@ -47,17 +55,19 @@
// activation (if any) comes around.
void* savedPrevJitTop_;
+ JS::AutoCheckCannotGC nogc_;
+
static const unsigned StorageSpace = 8 * sizeof(void*);
mozilla::AlignedStorage<StorageSpace> storage_;
- js::AsmJSProfilingFrameIterator& asmJSIter() {
+ js::wasm::ProfilingFrameIterator& wasmIter() {
MOZ_ASSERT(!done());
- MOZ_ASSERT(isAsmJS());
- return *reinterpret_cast<js::AsmJSProfilingFrameIterator*>(storage_.addr());
+ MOZ_ASSERT(isWasm());
+ return *reinterpret_cast<js::wasm::ProfilingFrameIterator*>(storage_.addr());
}
- const js::AsmJSProfilingFrameIterator& asmJSIter() const {
+ const js::wasm::ProfilingFrameIterator& wasmIter() const {
MOZ_ASSERT(!done());
- MOZ_ASSERT(isAsmJS());
- return *reinterpret_cast<const js::AsmJSProfilingFrameIterator*>(storage_.addr());
+ MOZ_ASSERT(isWasm());
+ return *reinterpret_cast<const js::wasm::ProfilingFrameIterator*>(storage_.addr());
}
js::jit::JitProfilingFrameIterator& jitIter() {
@@ -87,7 +97,7 @@
void* lr;
};
- ProfilingFrameIterator(JSRuntime* rt, const RegisterState& state,
+ ProfilingFrameIterator(JSContext* cx, const RegisterState& state,
uint32_t sampleBufferGen = UINT32_MAX);
~ProfilingFrameIterator();
void operator++();
@@ -104,7 +114,7 @@
{
Frame_Baseline,
Frame_Ion,
- Frame_AsmJS
+ Frame_Wasm
};
struct Frame
@@ -113,10 +123,10 @@
void* stackAddress;
void* returnAddress;
void* activation;
- const char* label;
+ UniqueChars label;
};
- bool isAsmJS() const;
+ bool isWasm() const;
bool isJit() const;
uint32_t extractStack(Frame* frames, uint32_t offset, uint32_t end) const;
@@ -133,7 +143,7 @@
};
JS_FRIEND_API(bool)
-IsProfilingEnabledForRuntime(JSRuntime* runtime);
+IsProfilingEnabledForContext(JSContext* cx);
/**
* After each sample run, this method should be called with the latest sample
@@ -144,7 +154,7 @@
* JSRuntime for documentation about what these values are used for.
*/
JS_FRIEND_API(void)
-UpdateJSRuntimeProfilerSampleBufferGen(JSRuntime* runtime, uint32_t generation,
+UpdateJSContextProfilerSampleBufferGen(JSContext* cx, uint32_t generation,
uint32_t lapCount);
struct ForEachProfiledFrameOp
@@ -153,7 +163,7 @@
// lookups on JitcodeGlobalTable.
class MOZ_STACK_CLASS FrameHandle
{
- friend JS_PUBLIC_API(void) ForEachProfiledFrame(JSRuntime* rt, void* addr,
+ friend JS_PUBLIC_API(void) ForEachProfiledFrame(JSContext* cx, void* addr,
ForEachProfiledFrameOp& op);
JSRuntime* rt_;
@@ -175,10 +185,13 @@
bool hasTrackedOptimizations() const { return optsIndex_.isSome(); }
void* canonicalAddress() const { return canonicalAddr_; }
- ProfilingFrameIterator::FrameKind frameKind() const;
- void forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op,
- JSScript** scriptOut, jsbytecode** pcOut) const;
- void forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const;
+ JS_PUBLIC_API(ProfilingFrameIterator::FrameKind) frameKind() const;
+ JS_PUBLIC_API(void) forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op,
+ JSScript** scriptOut,
+ jsbytecode** pcOut) const;
+
+ JS_PUBLIC_API(void)
+ forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const;
};
// Called once per frame.
@@ -186,7 +199,7 @@
};
JS_PUBLIC_API(void)
-ForEachProfiledFrame(JSRuntime* rt, void* addr, ForEachProfiledFrameOp& op);
+ForEachProfiledFrame(JSContext* cx, void* addr, ForEachProfiledFrameOp& op);
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/ProfilingStack.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/ProfilingStack.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/ProfilingStack.h
@@ -14,6 +14,7 @@
#include "js/Utility.h"
struct JSRuntime;
+class JSTracer;
namespace js {
@@ -42,14 +43,14 @@
void * volatile spOrScript;
// Line number for non-JS entries, the bytecode offset otherwise.
- int32_t volatile lineOrPc;
+ int32_t volatile lineOrPcOffset;
// General purpose storage describing this frame.
uint32_t volatile flags_;
public:
// These traits are bit masks. Make sure they're powers of 2.
- enum Flags {
+ enum Flags : uint32_t {
// Indicate whether a profile entry represents a CPP frame. If not set,
// a JS frame is assumed by default. You're not allowed to publicly
// change the frame type. Instead, initialize the ProfileEntry as either
@@ -75,7 +76,7 @@
CATEGORY_MASK = ~ALL
};
- // Keep these in sync with devtools/client/performance/modules/global.js
+ // Keep these in sync with devtools/client/performance/modules/categories.js
enum class Category : uint32_t {
OTHER = 0x10,
CSS = 0x20,
@@ -115,7 +116,7 @@
void initCppFrame(void* aSp, uint32_t aLine) volatile {
flags_ = IS_CPP_ENTRY;
spOrScript = aSp;
- lineOrPc = static_cast<int32_t>(aLine);
+ lineOrPcOffset = static_cast<int32_t>(aLine);
}
void setFlag(uint32_t flag) volatile {
@@ -160,19 +161,24 @@
MOZ_ASSERT(!isJs());
return spOrScript;
}
- JSScript* script() const volatile {
- MOZ_ASSERT(isJs());
- return (JSScript*)spOrScript;
- }
+ JS_PUBLIC_API(JSScript*) script() const volatile;
uint32_t line() const volatile {
MOZ_ASSERT(!isJs());
- return static_cast<uint32_t>(lineOrPc);
+ return static_cast<uint32_t>(lineOrPcOffset);
+ }
+
+ // Note that the pointer returned might be invalid.
+ JSScript* rawScript() const volatile {
+ MOZ_ASSERT(isJs());
+ return (JSScript*)spOrScript;
}
// We can't know the layout of JSScript, so look in vm/SPSProfiler.cpp.
JS_FRIEND_API(jsbytecode*) pc() const volatile;
JS_FRIEND_API(void) setPC(jsbytecode* pc) volatile;
+ void trace(JSTracer* trc);
+
// The offset of a pc into a script's code can actually be 0, so to
// signify a nullptr pc, use a -1 index. This is checked against in
// pc() and setPC() to set/get the right pc.
@@ -180,22 +186,22 @@
static size_t offsetOfLabel() { return offsetof(ProfileEntry, string); }
static size_t offsetOfSpOrScript() { return offsetof(ProfileEntry, spOrScript); }
- static size_t offsetOfLineOrPc() { return offsetof(ProfileEntry, lineOrPc); }
+ static size_t offsetOfLineOrPcOffset() { return offsetof(ProfileEntry, lineOrPcOffset); }
static size_t offsetOfFlags() { return offsetof(ProfileEntry, flags_); }
};
JS_FRIEND_API(void)
-SetRuntimeProfilingStack(JSRuntime* rt, ProfileEntry* stack, uint32_t* size,
+SetContextProfilingStack(JSContext* cx, ProfileEntry* stack, uint32_t* size,
uint32_t max);
JS_FRIEND_API(void)
-EnableRuntimeProfilingStack(JSRuntime* rt, bool enabled);
+EnableContextProfilingStack(JSContext* cx, bool enabled);
JS_FRIEND_API(void)
-RegisterRuntimeProfilingEventMarker(JSRuntime* rt, void (*fn)(const char*));
+RegisterContextProfilingEventMarker(JSContext* cx, void (*fn)(const char*));
JS_FRIEND_API(jsbytecode*)
-ProfilingGetPC(JSRuntime* rt, JSScript* script, void* ip);
+ProfilingGetPC(JSContext* cx, JSScript* script, void* ip);
} // namespace js
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Proxy.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Proxy.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Proxy.h
@@ -29,6 +29,7 @@
using JS::NativeImpl;
using JS::ObjectOpResult;
using JS::PrivateValue;
+using JS::PropertyDescriptor;
using JS::Value;
class RegExpGuard;
@@ -58,16 +59,15 @@
*
* ### Proxies and internal methods
*
- * ES6 draft rev 27 (24 August 2014) specifies 14 internal methods. The runtime
- * semantics of just about everything a script can do to an object is specified
- * in terms of these internal methods. For example:
+ * ES2016 specifies 13 internal methods. The runtime semantics of just
+ * about everything a script can do to an object is specified in terms
+ * of these internal methods. For example:
*
* JS code ES6 internal method that gets called
* --------------------------- --------------------------------
* obj.prop obj.[[Get]](obj, "prop")
* "prop" in obj obj.[[HasProperty]]("prop")
* new obj() obj.[[Construct]](<empty argument List>)
- * for (k in obj) {} obj.[[Enumerate]]()
*
* With regard to the implementation of these internal methods, there are three
* very different kinds of object in SpiderMonkey.
@@ -101,10 +101,8 @@
*
* BaseProxyHandler
* |
- * DirectProxyHandler // has a target
- * |
- * Wrapper // can be unwrapped, revealing target
- * | // (see js::CheckedUnwrap)
+ * Wrapper // has a target, can be unwrapped to reveal
+ * | // target (see js::CheckedUnwrap)
* |
* CrossCompartmentWrapper // target is in another compartment;
* // implements membrane between compartments
@@ -191,7 +189,7 @@
bool mHasSecurityPolicy;
public:
- explicit MOZ_CONSTEXPR BaseProxyHandler(const void* aFamily, bool aHasPrototype = false,
+ explicit constexpr BaseProxyHandler(const void* aFamily, bool aHasPrototype = false,
bool aHasSecurityPolicy = false)
: mFamily(aFamily),
mHasPrototype(aHasPrototype),
@@ -213,7 +211,7 @@
return offsetof(BaseProxyHandler, mFamily);
}
- virtual bool finalizeInBackground(Value priv) const {
+ virtual bool finalizeInBackground(const Value& priv) const {
/*
* Called on creation of a proxy to determine whether its finalize
* method can be finalized on the background thread.
@@ -221,6 +219,14 @@
return true;
}
+ virtual bool canNurseryAllocate() const {
+ /*
+ * Nursery allocation is allowed if and only if it is safe to not
+ * run |finalize| when the ProxyObject dies.
+ */
+ return false;
+ }
+
/* Policy enforcement methods.
*
* enter() allows the policy to specify whether the caller may perform |act|
@@ -251,9 +257,9 @@
/* Standard internal methods. */
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const = 0;
+ MutableHandle<PropertyDescriptor> desc) const = 0;
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
- Handle<JSPropertyDescriptor> desc,
+ Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const = 0;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const = 0;
@@ -261,14 +267,6 @@
ObjectOpResult& result) const = 0;
/*
- * Because [[Enumerate]] is one of the standard traps it should be overridden.
- * However for convenience BaseProxyHandler includes a pure virtual implementation,
- * that turns the properties returned by getOwnEnumerablePropertyKeys (and proto walking)
- * into an Iterator object.
- */
- virtual bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const = 0;
-
- /*
* These methods are standard, but the engine does not normally call them.
* They're opt-in. See "Proxy prototype chains" above.
*
@@ -278,7 +276,9 @@
virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
ObjectOpResult& result) const;
- /* Non-standard but conceptual kin to {g,s}etPrototype, so lives here. */
+ /* Non-standard but conceptual kin to {g,s}etPrototype, so these live here. */
+ virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
+ MutableHandleObject protop) const = 0;
virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy, bool* succeeded) const;
virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
@@ -314,8 +314,9 @@
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const;
/* SpiderMonkey extensions. */
+ virtual bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const;
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const;
+ MutableHandle<PropertyDescriptor> desc) const;
virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const;
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const;
@@ -323,7 +324,7 @@
const CallArgs& args) const;
virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v, bool* bp) const;
virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy,
- ESClassValue* classValue) const;
+ ESClass* cls) const;
virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const;
virtual const char* className(JSContext* cx, HandleObject proxy) const;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const;
@@ -354,79 +355,6 @@
virtual bool isScripted() const { return false; }
};
-/*
- * DirectProxyHandler includes a notion of a target object. All methods are
- * reimplemented such that they forward their behavior to the target. This
- * allows consumers of this class to forward to another object as transparently
- * and efficiently as possible.
- *
- * Important: If you add a method implementation here, you probably also need
- * to add an override in CrossCompartmentWrapper. If you don't, you risk
- * compartment mismatches. See bug 945826 comment 0.
- */
-class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
-{
- public:
- explicit MOZ_CONSTEXPR DirectProxyHandler(const void* aFamily, bool aHasPrototype = false,
- bool aHasSecurityPolicy = false)
- : BaseProxyHandler(aFamily, aHasPrototype, aHasSecurityPolicy)
- { }
-
- /* Standard internal methods. */
- virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
- virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
- Handle<JSPropertyDescriptor> desc,
- ObjectOpResult& result) const override;
- virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
- AutoIdVector& props) const override;
- virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
- ObjectOpResult& result) const override;
- virtual bool enumerate(JSContext* cx, HandleObject proxy,
- MutableHandleObject objp) const override;
- virtual bool getPrototype(JSContext* cx, HandleObject proxy,
- MutableHandleObject protop) const override;
- virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
- ObjectOpResult& result) const override;
- virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
- bool* succeeded) const override;
- virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
- ObjectOpResult& result) const override;
- virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
- virtual bool has(JSContext* cx, HandleObject proxy, HandleId id,
- bool* bp) const override;
- virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
- HandleId id, MutableHandleValue vp) const override;
- virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
- HandleValue receiver, ObjectOpResult& result) const override;
- virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
- virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
-
- /* SpiderMonkey extensions. */
- virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
- virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id,
- bool* bp) const override;
- virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
- AutoIdVector& props) const override;
- virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
- const CallArgs& args) const override;
- virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
- bool* bp) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy,
- ESClassValue* classValue) const override;
- virtual bool isArray(JSContext* cx, HandleObject proxy,
- JS::IsArrayAnswer* answer) const override;
- virtual const char* className(JSContext* cx, HandleObject proxy) const override;
- virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
- unsigned indent) const override;
- virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
- RegExpGuard* g) const override;
- virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
- virtual bool isCallable(JSObject* obj) const override;
- virtual JSObject* weakmapKeyDelegate(JSObject* proxy) const override;
-};
-
extern JS_FRIEND_DATA(const js::Class* const) ProxyClassPtr;
inline bool IsProxy(const JSObject* obj)
@@ -434,6 +362,7 @@
return GetObjectClass(obj)->isProxy();
}
+namespace detail {
const uint32_t PROXY_EXTRA_SLOTS = 2;
// Layout of the values stored by a proxy. Note that API clients require the
@@ -470,7 +399,6 @@
const uint32_t ProxyDataOffset = 2 * sizeof(void*);
-// This method should only be used internally and by the accessors below.
inline ProxyDataLayout*
GetProxyDataLayout(JSObject* obj)
{
@@ -478,16 +406,25 @@
return reinterpret_cast<ProxyDataLayout*>(reinterpret_cast<uint8_t*>(obj) + ProxyDataOffset);
}
+inline const ProxyDataLayout*
+GetProxyDataLayout(const JSObject* obj)
+{
+ MOZ_ASSERT(IsProxy(obj));
+ return reinterpret_cast<const ProxyDataLayout*>(reinterpret_cast<const uint8_t*>(obj) +
+ ProxyDataOffset);
+}
+} // namespace detail
+
inline const BaseProxyHandler*
-GetProxyHandler(JSObject* obj)
+GetProxyHandler(const JSObject* obj)
{
- return GetProxyDataLayout(obj)->handler;
+ return detail::GetProxyDataLayout(obj)->handler;
}
inline const Value&
-GetProxyPrivate(JSObject* obj)
+GetProxyPrivate(const JSObject* obj)
{
- return GetProxyDataLayout(obj)->values->privateSlot;
+ return detail::GetProxyDataLayout(obj)->values->privateSlot;
}
inline JSObject*
@@ -497,16 +434,16 @@
}
inline const Value&
-GetProxyExtra(JSObject* obj, size_t n)
+GetProxyExtra(const JSObject* obj, size_t n)
{
- MOZ_ASSERT(n < PROXY_EXTRA_SLOTS);
- return GetProxyDataLayout(obj)->values->extraSlots[n];
+ MOZ_ASSERT(n < detail::PROXY_EXTRA_SLOTS);
+ return detail::GetProxyDataLayout(obj)->values->extraSlots[n];
}
inline void
SetProxyHandler(JSObject* obj, const BaseProxyHandler* handler)
{
- GetProxyDataLayout(obj)->handler = handler;
+ detail::GetProxyDataLayout(obj)->handler = handler;
}
JS_FRIEND_API(void)
@@ -515,8 +452,8 @@
inline void
SetProxyExtra(JSObject* obj, size_t n, const Value& extra)
{
- MOZ_ASSERT(n < PROXY_EXTRA_SLOTS);
- Value* vp = &GetProxyDataLayout(obj)->values->extraSlots[n];
+ MOZ_ASSERT(n < detail::PROXY_EXTRA_SLOTS);
+ Value* vp = &detail::GetProxyDataLayout(obj)->values->extraSlots[n];
// Trigger a barrier before writing the slot.
if (vp->isMarkable() || extra.isMarkable())
@@ -526,13 +463,13 @@
}
inline bool
-IsScriptedProxy(JSObject* obj)
+IsScriptedProxy(const JSObject* obj)
{
return IsProxy(obj) && GetProxyHandler(obj)->isScripted();
}
inline const Value&
-GetReservedOrProxyPrivateSlot(JSObject* obj, size_t slot)
+GetReservedOrProxyPrivateSlot(const JSObject* obj, size_t slot)
{
MOZ_ASSERT(slot == 0);
MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)) || IsProxy(obj));
@@ -597,7 +534,7 @@
JSObject* proto, const ProxyOptions& options = ProxyOptions());
JSObject*
-RenewProxyObject(JSContext* cx, JSObject* obj, BaseProxyHandler* handler, Value priv);
+RenewProxyObject(JSContext* cx, JSObject* obj, BaseProxyHandler* handler, const Value& priv);
class JS_FRIEND_API(AutoEnterPolicy)
{
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Realm.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Realm.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Realm.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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/. */
+
+/*
+ * Ways to get various per-Realm objects. All the getters declared in this
+ * header operate on the Realm corresponding to the current compartment on the
+ * JSContext.
+ */
+
+#ifndef js_Realm_h
+#define js_Realm_h
+
+#include "jstypes.h"
+
+struct JSContext;
+class JSObject;
+
+namespace JS {
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmObjectPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmFunctionPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmArrayPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmErrorPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmIteratorPrototype(JSContext* cx);
+
+} // namespace JS
+
+#endif // js_Realm_h
+
+
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/RootingAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/RootingAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/RootingAPI.h
@@ -14,11 +14,16 @@
#include "mozilla/Move.h"
#include "mozilla/TypeTraits.h"
+#include <type_traits>
+
#include "jspubtd.h"
+#include "js/GCAnnotations.h"
#include "js/GCAPI.h"
+#include "js/GCPolicyAPI.h"
#include "js/HeapAPI.h"
#include "js/TypeDecls.h"
+#include "js/UniquePtr.h"
#include "js/Utility.h"
/*
@@ -105,8 +110,7 @@
namespace js {
template <typename T>
-struct GCMethods {
- static T initial() { return T(); }
+struct BarrierMethods {
};
template <typename T>
@@ -121,6 +125,14 @@
template <typename T>
class HeapBase {};
+// Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many macros into scope
+template <typename T> struct IsHeapConstructibleType { static constexpr bool value = false; };
+#define DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE(T) \
+ template <> struct IsHeapConstructibleType<T> { static constexpr bool value = true; };
+FOR_EACH_PUBLIC_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
+FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
+#undef DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
+
template <typename T>
class PersistentRootedBase {};
@@ -132,14 +144,14 @@
struct PersistentRootedMarker;
} /* namespace gc */
-#define DECLARE_POINTER_COMPARISON_OPS(T) \
+#define DECLARE_POINTER_COMPARISON_OPS(T) \
bool operator==(const T& other) const { return get() == other; } \
bool operator!=(const T& other) const { return get() != other; }
// Important: Return a reference so passing a Rooted<T>, etc. to
// something that takes a |const T&| is not a GC hazard.
-#define DECLARE_POINTER_CONSTREF_OPS(T) \
- operator const T&() const { return get(); } \
+#define DECLARE_POINTER_CONSTREF_OPS(T) \
+ operator const T&() const { return get(); } \
const T& operator->() const { return get(); }
// Assignment operators on a base class are hidden by the implicitly defined
@@ -150,12 +162,16 @@
set(p); \
return *this; \
} \
+ Wrapper<T>& operator=(T&& p) { \
+ set(mozilla::Move(p)); \
+ return *this; \
+ } \
Wrapper<T>& operator=(const Wrapper<T>& other) { \
set(other.get()); \
return *this; \
} \
-#define DELETE_ASSIGNMENT_OPS(Wrapper, T) \
+#define DELETE_ASSIGNMENT_OPS(Wrapper, T) \
template <typename S> Wrapper<T>& operator=(S) = delete; \
Wrapper<T>& operator=(const Wrapper<T>&) = delete;
@@ -212,18 +228,21 @@
* Heap<T> objects should only be used on the heap. GC references stored on the
* C/C++ stack must use Rooted/Handle/MutableHandle instead.
*
- * Type T must be one of: JS::Value, jsid, JSObject*, JSString*, JSScript*
+ * Type T must be a public GC pointer type.
*/
template <typename T>
-class Heap : public js::HeapBase<T>
+class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T>
{
+ // Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for legacy reasons.
+ static_assert(js::IsHeapConstructibleType<T>::value,
+ "Type T must be a public GC pointer type");
public:
Heap() {
static_assert(sizeof(T) == sizeof(Heap<T>),
"Heap<T> must be binary compatible with T.");
- init(js::GCMethods<T>::initial());
+ init(GCPolicy<T>::initial());
}
- explicit Heap(T p) { init(p); }
+ explicit Heap(const T& p) { init(p); }
/*
* For Heap, move semantics are equivalent to copy semantics. In C++, a
@@ -234,50 +253,91 @@
explicit Heap(const Heap<T>& p) { init(p.ptr); }
~Heap() {
- post(ptr, js::GCMethods<T>::initial());
+ post(ptr, GCPolicy<T>::initial());
}
DECLARE_POINTER_CONSTREF_OPS(T);
DECLARE_POINTER_ASSIGN_OPS(Heap, T);
- DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr);
- T* unsafeGet() { return &ptr; }
+ const T* address() const { return &ptr; }
- /*
- * Set the pointer to a value which will cause a crash if it is
- * dereferenced.
- */
- void setToCrashOnTouch() {
- ptr = reinterpret_cast<T>(crashOnTouchPointer);
+ void exposeToActiveJS() const {
+ js::BarrierMethods<T>::exposeToJS(ptr);
+ }
+ const T& get() const {
+ exposeToActiveJS();
+ return ptr;
+ }
+ const T& unbarrieredGet() const {
+ return ptr;
}
- bool isSetToCrashOnTouch() {
- return ptr == crashOnTouchPointer;
+ T* unsafeGet() { return &ptr; }
+
+ explicit operator bool() const {
+ return bool(js::BarrierMethods<T>::asGCThingOrNull(ptr));
+ }
+ explicit operator bool() {
+ return bool(js::BarrierMethods<T>::asGCThingOrNull(ptr));
}
private:
- void init(T newPtr) {
+ void init(const T& newPtr) {
ptr = newPtr;
- post(js::GCMethods<T>::initial(), ptr);
+ post(GCPolicy<T>::initial(), ptr);
}
- void set(T newPtr) {
+ void set(const T& newPtr) {
T tmp = ptr;
ptr = newPtr;
post(tmp, ptr);
}
void post(const T& prev, const T& next) {
- js::GCMethods<T>::postBarrier(&ptr, prev, next);
+ js::BarrierMethods<T>::postBarrier(&ptr, prev, next);
}
- enum {
- crashOnTouchPointer = 1
- };
-
T ptr;
};
+static MOZ_ALWAYS_INLINE bool
+ObjectIsTenured(JSObject* obj)
+{
+ return !js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(obj));
+}
+
+static MOZ_ALWAYS_INLINE bool
+ObjectIsTenured(const Heap<JSObject*>& obj)
+{
+ return ObjectIsTenured(obj.unbarrieredGet());
+}
+
+static MOZ_ALWAYS_INLINE bool
+ObjectIsMarkedGray(JSObject* obj)
+{
+ auto cell = reinterpret_cast<js::gc::Cell*>(obj);
+ return js::gc::detail::CellIsMarkedGrayIfKnown(cell);
+}
+
+static MOZ_ALWAYS_INLINE bool
+ObjectIsMarkedGray(const JS::Heap<JSObject*>& obj)
+{
+ return ObjectIsMarkedGray(obj.unbarrieredGet());
+}
+
+static MOZ_ALWAYS_INLINE bool
+ScriptIsMarkedGray(JSScript* script)
+{
+ auto cell = reinterpret_cast<js::gc::Cell*>(script);
+ return js::gc::detail::CellIsMarkedGrayIfKnown(cell);
+}
+
+static MOZ_ALWAYS_INLINE bool
+ScriptIsMarkedGray(const Heap<JSScript*>& script)
+{
+ return ScriptIsMarkedGray(script.unbarrieredGet());
+}
+
/**
* The TenuredHeap<T> class is similar to the Heap<T> class above in that it
* encapsulates the GC concerns of an on-heap reference to a JS object. However,
@@ -343,12 +403,27 @@
return (bits & flag) != 0;
}
- T getPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
+ T unbarrieredGetPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
uintptr_t getFlags() const { return bits & flagsMask; }
+ void exposeToActiveJS() const {
+ js::BarrierMethods<T>::exposeToJS(unbarrieredGetPtr());
+ }
+ T getPtr() const {
+ exposeToActiveJS();
+ return unbarrieredGetPtr();
+ }
+
operator T() const { return getPtr(); }
T operator->() const { return getPtr(); }
+ explicit operator bool() const {
+ return bool(js::BarrierMethods<T>::asGCThingOrNull(unbarrieredGetPtr()));
+ }
+ explicit operator bool() {
+ return bool(js::BarrierMethods<T>::asGCThingOrNull(unbarrieredGetPtr()));
+ }
+
TenuredHeap<T>& operator=(T p) {
setPtr(p);
return *this;
@@ -417,7 +492,7 @@
* for the lifetime of the handle, as its users may not expect its value
* to change underneath them.
*/
- static MOZ_CONSTEXPR Handle fromMarkedLocation(const T* p) {
+ static constexpr Handle fromMarkedLocation(const T* p) {
return Handle(p, DeliberatelyChoosingThisOverload,
ImUsingThisOnlyInFromFromMarkedLocation);
}
@@ -452,7 +527,7 @@
enum Disambiguator { DeliberatelyChoosingThisOverload = 42 };
enum CallerIdentity { ImUsingThisOnlyInFromFromMarkedLocation = 17 };
- MOZ_CONSTEXPR Handle(const T* p, Disambiguator, CallerIdentity) : ptr(p) {}
+ constexpr Handle(const T* p, Disambiguator, CallerIdentity) : ptr(p) {}
const T* ptr;
};
@@ -477,9 +552,12 @@
MutableHandle(decltype(nullptr)) = delete;
public:
- void set(T v) {
+ void set(const T& v) {
*ptr = v;
}
+ void set(T&& v) {
+ *ptr = mozilla::Move(v);
+ }
/*
* This may be called only if the location of the T is guaranteed
@@ -509,36 +587,28 @@
namespace js {
-/**
- * By default, things should use the inheritance hierarchy to find their
- * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
- * Rooted<T> may be used without the class definition being available.
- */
-template <typename T>
-struct RootKind
-{
- static ThingRootKind rootKind() { return T::rootKind(); }
-};
-
-template <typename T>
-struct RootKind<T*>
-{
- static ThingRootKind rootKind() { return T::rootKind(); }
-};
-
template <typename T>
-struct GCMethods<T*>
+struct BarrierMethods<T*>
{
static T* initial() { return nullptr; }
+ static gc::Cell* asGCThingOrNull(T* v) {
+ if (!v)
+ return nullptr;
+ MOZ_ASSERT(uintptr_t(v) > 32);
+ return reinterpret_cast<gc::Cell*>(v);
+ }
static void postBarrier(T** vp, T* prev, T* next) {
if (next)
JS::AssertGCThingIsNotAnObjectSubclass(reinterpret_cast<js::gc::Cell*>(next));
}
- static void relocate(T** vp) {}
+ static void exposeToJS(T* t) {
+ if (t)
+ js::gc::ExposeGCThingToActiveJS(JS::GCCellPtr(t));
+ }
};
template <>
-struct GCMethods<JSObject*>
+struct BarrierMethods<JSObject*>
{
static JSObject* initial() { return nullptr; }
static gc::Cell* asGCThingOrNull(JSObject* v) {
@@ -550,17 +620,31 @@
static void postBarrier(JSObject** vp, JSObject* prev, JSObject* next) {
JS::HeapObjectPostBarrier(vp, prev, next);
}
+ static void exposeToJS(JSObject* obj) {
+ if (obj)
+ JS::ExposeObjectToActiveJS(obj);
+ }
};
template <>
-struct GCMethods<JSFunction*>
+struct BarrierMethods<JSFunction*>
{
static JSFunction* initial() { return nullptr; }
+ static gc::Cell* asGCThingOrNull(JSFunction* v) {
+ if (!v)
+ return nullptr;
+ MOZ_ASSERT(uintptr_t(v) > 32);
+ return reinterpret_cast<gc::Cell*>(v);
+ }
static void postBarrier(JSFunction** vp, JSFunction* prev, JSFunction* next) {
JS::HeapObjectPostBarrier(reinterpret_cast<JSObject**>(vp),
reinterpret_cast<JSObject*>(prev),
reinterpret_cast<JSObject*>(next));
}
+ static void exposeToJS(JSFunction* fun) {
+ if (fun)
+ JS::ExposeObjectToActiveJS(reinterpret_cast<JSObject*>(fun));
+ }
};
// Provide hash codes for Cell kinds that may be relocated and, thus, not have
@@ -580,6 +664,8 @@
using Key = T;
using Lookup = T;
+ static bool hasHash(const Lookup& l);
+ static bool ensureHash(const Lookup& l);
static HashNumber hash(const Lookup& l);
static bool match(const Key& k, const Lookup& l);
static void rekey(Key& k, const Key& newKey) { k = newKey; }
@@ -591,47 +677,52 @@
using Key = JS::Heap<T>;
using Lookup = T;
+ static bool hasHash(const Lookup& l) { return MovableCellHasher<T>::hasHash(l); }
+ static bool ensureHash(const Lookup& l) { return MovableCellHasher<T>::ensureHash(l); }
static HashNumber hash(const Lookup& l) { return MovableCellHasher<T>::hash(l); }
- static bool match(const Key& k, const Lookup& l) { return MovableCellHasher<T>::match(k, l); }
+ static bool match(const Key& k, const Lookup& l) {
+ return MovableCellHasher<T>::match(k.unbarrieredGet(), l);
+ }
static void rekey(Key& k, const Key& newKey) { k.unsafeSet(newKey); }
};
-} /* namespace js */
-
-namespace JS {
-
-// Non pointer types -- structs or classes that contain GC pointers, either as
-// a member or in a more complex container layout -- can also be stored in a
-// [Persistent]Rooted if it derives from JS::Traceable. A JS::Traceable stored
-// in a [Persistent]Rooted must implement the method:
-// |static void trace(T*, JSTracer*)|
-class Traceable
+template <typename T>
+struct FallibleHashMethods<MovableCellHasher<T>>
{
- public:
- static js::ThingRootKind rootKind() { return js::THING_ROOT_TRACEABLE; }
+ template <typename Lookup> static bool hasHash(Lookup&& l) {
+ return MovableCellHasher<T>::hasHash(mozilla::Forward<Lookup>(l));
+ }
+ template <typename Lookup> static bool ensureHash(Lookup&& l) {
+ return MovableCellHasher<T>::ensureHash(mozilla::Forward<Lookup>(l));
+ }
};
-} /* namespace JS */
+} /* namespace js */
namespace js {
+// The alignment must be set because the Rooted and PersistentRooted ptr fields
+// may be accessed through reinterpret_cast<Rooted<ConcreteTraceable>*>, and
+// the compiler may choose a different alignment for the ptr field when it
+// knows the actual type stored in DispatchWrapper<T>.
+//
+// It would make more sense to align only those specific fields of type
+// DispatchWrapper, rather than DispatchWrapper itself, but that causes MSVC to
+// fail when Rooted is used in an IsConvertible test.
template <typename T>
-class DispatchWrapper
+class alignas(8) DispatchWrapper
{
- static_assert(mozilla::IsBaseOf<JS::Traceable, T>::value,
+ static_assert(JS::MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
"DispatchWrapper is intended only for usage with a Traceable");
- using TraceFn = void (*)(T*, JSTracer*);
+ using TraceFn = void (*)(JSTracer*, T*, const char*);
TraceFn tracer;
-#if JS_BITS_PER_WORD == 32
- uint32_t padding; // Ensure the storage fields have CellSize alignment.
-#endif
- T storage;
+ alignas(gc::CellSize) T storage;
public:
template <typename U>
MOZ_IMPLICIT DispatchWrapper(U&& initial)
- : tracer(&T::trace),
+ : tracer(&JS::GCPolicy<T>::trace),
storage(mozilla::Forward<U>(initial))
{ }
@@ -643,37 +734,13 @@
// Trace the contained storage (of unknown type) using the trace function
// we set aside when we did know the type.
- static void TraceWrapped(JSTracer* trc, JS::Traceable* thingp, const char* name) {
+ static void TraceWrapped(JSTracer* trc, T* thingp, const char* name) {
auto wrapper = reinterpret_cast<DispatchWrapper*>(
uintptr_t(thingp) - offsetof(DispatchWrapper, storage));
- wrapper->tracer(&wrapper->storage, trc);
+ wrapper->tracer(trc, &wrapper->storage, name);
}
};
-inline RootLists&
-RootListsForRootingContext(JSContext* cx)
-{
- return ContextFriendFields::get(cx)->roots;
-}
-
-inline RootLists&
-RootListsForRootingContext(js::ContextFriendFields* cx)
-{
- return cx->roots;
-}
-
-inline RootLists&
-RootListsForRootingContext(JSRuntime* rt)
-{
- return PerThreadDataFriendFields::getMainThread(rt)->roots;
-}
-
-inline RootLists&
-RootListsForRootingContext(js::PerThreadDataFriendFields* pt)
-{
- return pt->roots;
-}
-
} /* namespace js */
namespace JS {
@@ -689,30 +756,38 @@
template <typename T>
class MOZ_RAII Rooted : public js::RootedBase<T>
{
- static_assert(!mozilla::IsConvertible<T, Traceable*>::value,
- "Rooted takes pointer or Traceable types but not Traceable* type");
-
- /* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */
- void registerWithRootLists(js::RootLists& roots) {
- js::ThingRootKind kind = js::RootKind<T>::rootKind();
- this->stack = &roots.stackRoots_[kind];
+ inline void registerWithRootLists(js::RootedListHeads& roots) {
+ this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
this->prev = *stack;
*stack = reinterpret_cast<Rooted<void*>*>(this);
}
+ inline js::RootedListHeads& rootLists(JS::RootingContext* cx) {
+ return rootLists(static_cast<js::ContextFriendFields*>(cx));
+ }
+ inline js::RootedListHeads& rootLists(js::ContextFriendFields* cx) {
+ if (JS::Zone* zone = cx->zone_)
+ return JS::shadow::Zone::asShadowZone(zone)->stackRoots_;
+ MOZ_ASSERT(cx->isJSContext);
+ return cx->roots.stackRoots_;
+ }
+ inline js::RootedListHeads& rootLists(JSContext* cx) {
+ return rootLists(js::ContextFriendFields::get(cx));
+ }
+
public:
template <typename RootingContext>
explicit Rooted(const RootingContext& cx)
- : ptr(js::GCMethods<T>::initial())
+ : ptr(GCPolicy<T>::initial())
{
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
template <typename RootingContext, typename S>
Rooted(const RootingContext& cx, S&& initial)
: ptr(mozilla::Forward<S>(initial))
{
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
~Rooted() {
@@ -726,9 +801,12 @@
* This method is public for Rooted so that Codegen.py can use a Rooted
* interchangeably with a MutableHandleValue.
*/
- void set(T value) {
+ void set(const T& value) {
ptr = value;
}
+ void set(T&& value) {
+ ptr = mozilla::Move(value);
+ }
DECLARE_POINTER_COMPARISON_OPS(T);
DECLARE_POINTER_CONSTREF_OPS(T);
@@ -747,20 +825,20 @@
/*
* For pointer types, the TraceKind for tracing is based on the list it is
- * in (selected via rootKind), so no additional storage is required here.
- * All Traceable, however, share the same list, so the function to
- * call for tracing is stored adjacent to the struct. Since C++ cannot
- * templatize on storage class, this is implemented via the wrapper class
- * DispatchWrapper.
+ * in (selected via MapTypeToRootKind), so no additional storage is
+ * required here. Non-pointer types, however, share the same list, so the
+ * function to call for tracing is stored adjacent to the struct. Since C++
+ * cannot templatize on storage class, this is implemented via the wrapper
+ * class DispatchWrapper.
*/
using MaybeWrapped = typename mozilla::Conditional<
- mozilla::IsBaseOf<Traceable, T>::value,
+ MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
js::DispatchWrapper<T>,
T>::Type;
MaybeWrapped ptr;
Rooted(const Rooted&) = delete;
-};
+} JS_HAZ_ROOTED;
} /* namespace JS */
@@ -808,7 +886,7 @@
{
public:
template <typename CX>
- explicit FakeRooted(CX* cx) : ptr(GCMethods<T>::initial()) {}
+ explicit FakeRooted(CX* cx) : ptr(JS::GCPolicy<T>::initial()) {}
template <typename CX>
FakeRooted(CX* cx, T initial) : ptr(initial) {}
@@ -842,7 +920,7 @@
ptr = root->address();
}
- void set(T v) {
+ void set(const T& v) {
*ptr = v;
}
@@ -899,7 +977,7 @@
template <typename T> class MaybeRooted<T, NoGC>
{
public:
- typedef T HandleType;
+ typedef const T& HandleType;
typedef FakeRooted<T> RootType;
typedef FakeMutableHandle<T> MutableHandleType;
@@ -970,7 +1048,7 @@
* These roots can be used in heap-allocated data structures, so they are not
* associated with any particular JSContext or stack. They are registered with
* the JSRuntime itself, without locking, so they require a full JSContext to be
- * initialized, not one of its more restricted superclasses. Initialization may
+ * initialized, not one of its more restricted superclasses. Initialization may
* take place on construction, or in two phases if the no-argument constructor
* is called followed by init().
*
@@ -1001,45 +1079,43 @@
class PersistentRooted : public js::PersistentRootedBase<T>,
private mozilla::LinkedListElement<PersistentRooted<T>>
{
- typedef mozilla::LinkedListElement<PersistentRooted<T>> ListBase;
+ using ListBase = mozilla::LinkedListElement<PersistentRooted<T>>;
friend class mozilla::LinkedList<PersistentRooted>;
friend class mozilla::LinkedListElement<PersistentRooted>;
- friend struct js::gc::PersistentRootedMarker<T>;
-
- friend void js::gc::FinishPersistentRootedChains(js::RootLists&);
-
void registerWithRootLists(js::RootLists& roots) {
MOZ_ASSERT(!initialized());
- js::ThingRootKind kind = js::RootKind<T>::rootKind();
+ JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
roots.heapRoots_[kind].insertBack(reinterpret_cast<JS::PersistentRooted<void*>*>(this));
- // Until marking and destruction support the full set, we assert that
- // we don't try to add any unsupported types.
- MOZ_ASSERT(kind == js::THING_ROOT_OBJECT ||
- kind == js::THING_ROOT_SCRIPT ||
- kind == js::THING_ROOT_STRING ||
- kind == js::THING_ROOT_SYMBOL ||
- kind == js::THING_ROOT_ID ||
- kind == js::THING_ROOT_VALUE ||
- kind == js::THING_ROOT_TRACEABLE);
}
+ js::RootLists& rootLists(JSContext* cx) {
+ return rootLists(JS::RootingContext::get(cx));
+ }
+ js::RootLists& rootLists(JS::RootingContext* cx) {
+ MOZ_ASSERT(cx->isJSContext);
+ return cx->roots;
+ }
+
+ // Disallow ExclusiveContext*.
+ js::RootLists& rootLists(js::ContextFriendFields* cx) = delete;
+
public:
- PersistentRooted() : ptr(js::GCMethods<T>::initial()) {}
+ PersistentRooted() : ptr(GCPolicy<T>::initial()) {}
template <typename RootingContext>
explicit PersistentRooted(const RootingContext& cx)
- : ptr(js::GCMethods<T>::initial())
+ : ptr(GCPolicy<T>::initial())
{
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
template <typename RootingContext, typename U>
PersistentRooted(const RootingContext& cx, U&& initial)
: ptr(mozilla::Forward<U>(initial))
{
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
PersistentRooted(const PersistentRooted& rhs)
@@ -1063,18 +1139,18 @@
template <typename RootingContext>
void init(const RootingContext& cx) {
- init(cx, js::GCMethods<T>::initial());
+ init(cx, GCPolicy<T>::initial());
}
template <typename RootingContext, typename U>
void init(const RootingContext& cx, U&& initial) {
ptr = mozilla::Forward<U>(initial);
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
void reset() {
if (initialized()) {
- set(js::GCMethods<T>::initial());
+ set(GCPolicy<T>::initial());
ListBase::remove();
}
}
@@ -1097,19 +1173,19 @@
}
private:
- void set(T value) {
+ template <typename U>
+ void set(U&& value) {
MOZ_ASSERT(initialized());
- ptr = value;
+ ptr = mozilla::Forward<U>(value);
}
// See the comment above Rooted::ptr.
using MaybeWrapped = typename mozilla::Conditional<
- mozilla::IsBaseOf<Traceable, T>::value,
+ MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
js::DispatchWrapper<T>,
T>::Type;
-
MaybeWrapped ptr;
-};
+} JS_HAZ_ROOTED;
class JS_PUBLIC_API(ObjectPtr)
{
@@ -1120,20 +1196,26 @@
explicit ObjectPtr(JSObject* obj) : value(obj) {}
+ ObjectPtr(const ObjectPtr& other) : value(other.value) {}
+
+ ObjectPtr(ObjectPtr&& other)
+ : value(other.value)
+ {
+ other.value = nullptr;
+ }
+
/* Always call finalize before the destructor. */
~ObjectPtr() { MOZ_ASSERT(!value); }
- void finalize(JSRuntime* rt) {
- if (IsIncrementalBarrierNeeded(rt))
- IncrementalObjectBarrier(value);
- value = nullptr;
- }
+ void finalize(JSRuntime* rt);
+ void finalize(JSContext* cx);
void init(JSObject* obj) { value = obj; }
JSObject* get() const { return value; }
+ JSObject* unbarrieredGet() const { return value.unbarrieredGet(); }
- void writeBarrierPre(JSRuntime* rt) {
+ void writeBarrierPre(JSContext* cx) {
IncrementalObjectBarrier(value);
}
@@ -1150,11 +1232,57 @@
JSObject& operator*() const { return *value; }
JSObject* operator->() const { return value; }
operator JSObject*() const { return value; }
+
+ explicit operator bool() const { return value.unbarrieredGet(); }
+ explicit operator bool() { return value.unbarrieredGet(); }
};
} /* namespace JS */
namespace js {
+
+template <typename Outer, typename T, typename D>
+class UniquePtrOperations
+{
+ const UniquePtr<T, D>& uniquePtr() const { return static_cast<const Outer*>(this)->get(); }
+
+ public:
+ explicit operator bool() const { return !!uniquePtr(); }
+ T* get() const { return uniquePtr().get(); }
+ T* operator->() const { return get(); }
+ T& operator*() const { return *uniquePtr(); }
+};
+
+template <typename Outer, typename T, typename D>
+class MutableUniquePtrOperations : public UniquePtrOperations<Outer, T, D>
+{
+ UniquePtr<T, D>& uniquePtr() { return static_cast<Outer*>(this)->get(); }
+
+ public:
+ MOZ_MUST_USE typename UniquePtr<T, D>::Pointer release() { return uniquePtr().release(); }
+ void reset(T* ptr = T()) { uniquePtr().reset(ptr); }
+};
+
+template <typename T, typename D>
+class RootedBase<UniquePtr<T, D>>
+ : public MutableUniquePtrOperations<JS::Rooted<UniquePtr<T, D>>, T, D>
+{ };
+
+template <typename T, typename D>
+class MutableHandleBase<UniquePtr<T, D>>
+ : public MutableUniquePtrOperations<JS::MutableHandle<UniquePtr<T, D>>, T, D>
+{ };
+
+template <typename T, typename D>
+class HandleBase<UniquePtr<T, D>>
+ : public UniquePtrOperations<JS::Handle<UniquePtr<T, D>>, T, D>
+{ };
+
+template <typename T, typename D>
+class PersistentRootedBase<UniquePtr<T, D>>
+ : public MutableUniquePtrOperations<JS::PersistentRooted<UniquePtr<T, D>>, T, D>
+{ };
+
namespace gc {
template <typename T, typename TraceCallbacks>
@@ -1163,7 +1291,7 @@
{
static_assert(sizeof(T) == sizeof(JS::Heap<T>), "T and Heap<T> must be compatible.");
MOZ_ASSERT(v);
- mozilla::DebugOnly<Cell*> cell = GCMethods<T>::asGCThingOrNull(*v);
+ mozilla::DebugOnly<Cell*> cell = BarrierMethods<T>::asGCThingOrNull(*v);
MOZ_ASSERT(cell);
MOZ_ASSERT(!IsInsideNursery(cell));
JS::Heap<T>* asHeapT = reinterpret_cast<JS::Heap<T>*>(v);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/StructuredClone.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/StructuredClone.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/StructuredClone.h
@@ -7,6 +7,10 @@
#ifndef js_StructuredClone_h
#define js_StructuredClone_h
+#include "mozilla/Attributes.h"
+#include "mozilla/BufferList.h"
+#include "mozilla/Move.h"
+
#include <stdint.h>
#include "jstypes.h"
@@ -22,6 +26,41 @@
// API for the HTML5 internal structured cloning algorithm.
namespace JS {
+
+enum class StructuredCloneScope : uint32_t {
+ SameProcessSameThread,
+ SameProcessDifferentThread,
+
+ /**
+ * When writing, this means we're writing for an audience in a different
+ * process. Produce serialized data that can be sent to other processes,
+ * bitwise copied, or even stored as bytes in a database and read by later
+ * versions of Firefox years from now. The HTML5 spec refers to this as
+ * "ForStorage" as in StructuredSerializeForStorage, though we use
+ * DifferentProcess for IPC as well as storage.
+ *
+ * Transferable objects are limited to ArrayBuffers, whose contents are
+ * copied into the serialized data (rather than just writing a pointer).
+ */
+ DifferentProcess,
+
+ /**
+ * Handle a backwards-compatibility case with IndexedDB (bug 1434308): when
+ * reading, this means to treat legacy SameProcessSameThread data as if it
+ * were DifferentProcess.
+ *
+ * Do not use this for writing; use DifferentProcess instead.
+ */
+ DifferentProcessForIndexedDB,
+
+ /**
+ * Existing code wants to be able to create an uninitialized
+ * JSStructuredCloneData without knowing the scope, then populate it with
+ * data (at which point the scope *is* known.)
+ */
+ Unassigned
+};
+
enum TransferableOwnership {
/** Transferable data has not been filled in yet */
SCTAG_TMO_UNFILLED = 0,
@@ -35,23 +74,54 @@
/** Data is a pointer that can be freed */
SCTAG_TMO_ALLOC_DATA = 2,
- /** Data is a SharedArrayBufferObject's buffer */
- SCTAG_TMO_SHARED_BUFFER = 3,
-
/** Data is a memory mapped pointer */
- SCTAG_TMO_MAPPED_DATA = 4,
+ SCTAG_TMO_MAPPED_DATA = 3,
/**
* Data is embedding-specific. The engine can free it by calling the
* freeTransfer op. The embedding can also use SCTAG_TMO_USER_MIN and
* greater, up to 32 bits, to distinguish specific ownership variants.
*/
- SCTAG_TMO_CUSTOM = 5,
+ SCTAG_TMO_CUSTOM = 4,
SCTAG_TMO_USER_MIN
};
+
+class CloneDataPolicy
+{
+ bool sharedArrayBuffer_;
+
+ public:
+ // The default is to allow all policy-controlled aspects.
+
+ CloneDataPolicy() :
+ sharedArrayBuffer_(true)
+ {}
+
+ // In the JS engine, SharedArrayBuffers can only be cloned intra-process
+ // because the shared memory areas are allocated in process-private memory.
+ // Clients should therefore deny SharedArrayBuffers when cloning data that
+ // are to be transmitted inter-process.
+ //
+ // Clients should also deny SharedArrayBuffers when cloning data that are to
+ // be transmitted intra-process if policy needs dictate such denial.
+
+ CloneDataPolicy& denySharedArrayBuffer() {
+ sharedArrayBuffer_ = false;
+ return *this;
+ }
+
+ bool isSharedArrayBufferAllowed() const {
+ return sharedArrayBuffer_;
+ }
+};
+
} /* namespace JS */
+namespace js {
+template <typename T, typename AllocPolicy> struct BufferIterator;
+}
+
/**
* Read structured data from the reader r. This hook is used to read a value
* previously serialized by a call to the WriteStructuredCloneOp hook.
@@ -123,9 +193,9 @@
uint64_t* extraData);
/**
- * Called when JS_ClearStructuredClone has to free an unknown transferable
- * object. Note that it should never trigger a garbage collection (and will
- * assert in a debug build if it does.)
+ * Called when freeing an unknown transferable object. Note that it
+ * should never trigger a garbage collection (and will assert in a
+ * debug build if it does.)
*/
typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwnership ownership,
void* content, uint64_t extraData, void* closure);
@@ -134,7 +204,7 @@
// Increment this when anything at all changes in the serialization format.
// (Note that this does not need to be bumped for Transferable-only changes,
// since they are never saved to persistent storage.)
-#define JS_STRUCTURED_CLONE_VERSION 6
+#define JS_STRUCTURED_CLONE_VERSION 8
struct JSStructuredCloneCallbacks {
ReadStructuredCloneOp read;
@@ -145,97 +215,239 @@
FreeTransferStructuredCloneOp freeTransfer;
};
+enum OwnTransferablePolicy {
+ OwnsTransferablesIfAny,
+ IgnoreTransferablesIfAny,
+ NoTransferables
+};
+
+/**
+ * JSStructuredCloneData represents structured clone data together with the
+ * information needed to read/write/transfer/free the records within it, in the
+ * form of a set of callbacks.
+ */
+class MOZ_NON_MEMMOVABLE JS_PUBLIC_API(JSStructuredCloneData) {
+ public:
+ using BufferList = mozilla::BufferList<js::SystemAllocPolicy>;
+ using Iterator = BufferList::IterImpl;
+
+ private:
+ static const size_t kStandardCapacity = 4096;
+
+ BufferList bufList_;
+
+ // The (address space, thread) scope within which this clone is valid. Note
+ // that this must be either set during construction, or start out as
+ // Unassigned and transition once to something else.
+ JS::StructuredCloneScope scope_;
+
+ const JSStructuredCloneCallbacks* callbacks_;
+ void* closure_;
+ OwnTransferablePolicy ownTransferables_;
+
+ friend struct JSStructuredCloneWriter;
+ friend class JS_PUBLIC_API(JSAutoStructuredCloneBuffer);
+ template <typename T, typename AllocPolicy> friend struct js::BufferIterator;
+
+ public:
+ // The constructor must be infallible but SystemAllocPolicy is not, so both
+ // the initial size and initial capacity of the BufferList must be zero.
+ explicit JSStructuredCloneData(JS::StructuredCloneScope aScope)
+ : bufList_(0, 0, kStandardCapacity, js::SystemAllocPolicy())
+ , scope_(aScope)
+ , callbacks_(nullptr)
+ , closure_(nullptr)
+ , ownTransferables_(OwnTransferablePolicy::NoTransferables)
+ {}
+
+ // Steal the raw data from a BufferList. In this case, we don't know the
+ // scope and none of the callback info is assigned yet.
+ JSStructuredCloneData(BufferList&& buffers, JS::StructuredCloneScope aScope)
+ : bufList_(mozilla::Move(buffers))
+ , scope_(aScope)
+ , callbacks_(nullptr)
+ , closure_(nullptr)
+ , ownTransferables_(OwnTransferablePolicy::NoTransferables)
+ {}
+ MOZ_IMPLICIT JSStructuredCloneData(BufferList&& buffers)
+ : JSStructuredCloneData(mozilla::Move(buffers), JS::StructuredCloneScope::Unassigned)
+ {}
+ JSStructuredCloneData(JSStructuredCloneData&& other) = default;
+ JSStructuredCloneData& operator=(JSStructuredCloneData&& other) = default;
+ ~JSStructuredCloneData() { discardTransferables(); }
+
+ void setCallbacks(const JSStructuredCloneCallbacks* callbacks,
+ void* closure,
+ OwnTransferablePolicy policy)
+ {
+ callbacks_ = callbacks;
+ closure_ = closure;
+ ownTransferables_ = policy;
+ }
+
+ JS::StructuredCloneScope scope() const { return scope_; }
+
+ void initScope(JS::StructuredCloneScope aScope) {
+ MOZ_ASSERT(Size() == 0, "initScope() of nonempty JSStructuredCloneData");
+ if (scope_ != JS::StructuredCloneScope::Unassigned)
+ MOZ_ASSERT(scope_ == aScope, "Cannot change scope after it has been initialized");
+ scope_ = aScope;
+ }
+
+ size_t Size() const { return bufList_.Size(); }
+
+ const Iterator Start() const { return bufList_.Iter(); }
+
+ bool Advance(Iterator& iter, size_t distance) const {
+ return iter.AdvanceAcrossSegments(bufList_, distance);
+ }
+
+ bool ReadBytes(Iterator& iter, char* buffer, size_t size) const {
+ return bufList_.ReadBytes(iter, buffer, size);
+ }
+
+ // Append new data to the end of the buffer.
+ bool AppendBytes(const char* data, size_t size) {
+ MOZ_ASSERT(scope_ != JS::StructuredCloneScope::Unassigned);
+ return bufList_.WriteBytes(data, size);
+ }
+
+ // Update data stored within the existing buffer. There must be at least
+ // 'size' bytes between the position of 'iter' and the end of the buffer.
+ bool UpdateBytes(Iterator& iter, const char* data, size_t size) const {
+ MOZ_ASSERT(scope_ != JS::StructuredCloneScope::Unassigned);
+ while (size > 0) {
+ size_t remaining = iter.RemainingInSegment();
+ size_t nbytes = std::min(remaining, size);
+ memcpy(iter.Data(), data, nbytes);
+ data += nbytes;
+ size -= nbytes;
+ iter.Advance(bufList_, nbytes);
+ }
+ return true;
+ }
+
+ void Clear() {
+ discardTransferables();
+ bufList_.Clear();
+ }
+
+ // Return a new read-only JSStructuredCloneData that "borrows" the contents
+ // of |this|. Its lifetime should not exceed the donor's. This is only
+ // allowed for DifferentProcess clones, so finalization of the borrowing
+ // clone will do nothing.
+ JSStructuredCloneData Borrow(Iterator& iter, size_t size, bool* success) const
+ {
+ MOZ_ASSERT(scope_ == JS::StructuredCloneScope::DifferentProcess);
+ return JSStructuredCloneData(bufList_.Borrow<js::SystemAllocPolicy>(iter, size, success),
+ scope_);
+ }
+
+ // Iterate over all contained data, one BufferList segment's worth at a
+ // time, and invoke the given FunctionToApply with the data pointer and
+ // size. The function should return a bool value, and this loop will exit
+ // with false if the function ever returns false.
+ template <typename FunctionToApply>
+ bool ForEachDataChunk(FunctionToApply&& function) const {
+ Iterator iter = bufList_.Iter();
+ while (!iter.Done()) {
+ if (!function(iter.Data(), iter.RemainingInSegment()))
+ return false;
+ iter.Advance(bufList_, iter.RemainingInSegment());
+ }
+ return true;
+ }
+
+ // Append the entire contents of other's bufList_ to our own.
+ bool Append(const JSStructuredCloneData& other) {
+ MOZ_ASSERT(scope_ == other.scope_);
+ return other.ForEachDataChunk([&](const char* data, size_t size) {
+ return AppendBytes(data, size);
+ });
+ }
+
+ void discardTransferables();
+};
+
/** Note: if the *data contains transferable objects, it can be read only once. */
JS_PUBLIC_API(bool)
-JS_ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes, uint32_t version,
+JS_ReadStructuredClone(JSContext* cx, JSStructuredCloneData& data, uint32_t version,
+ JS::StructuredCloneScope scope,
JS::MutableHandleValue vp,
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure);
-/**
- * Note: On success, the caller is responsible for calling
- * JS_ClearStructuredClone(*datap, nbytes, optionalCallbacks, closure).
- */
JS_PUBLIC_API(bool)
-JS_WriteStructuredClone(JSContext* cx, JS::HandleValue v, uint64_t** datap, size_t* nbytesp,
+JS_WriteStructuredClone(JSContext* cx, JS::HandleValue v, JSStructuredCloneData* data,
+ JS::StructuredCloneScope scope,
+ JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* optionalCallbacks,
void* closure, JS::HandleValue transferable);
JS_PUBLIC_API(bool)
-JS_ClearStructuredClone(uint64_t* data, size_t nbytes,
- const JSStructuredCloneCallbacks* optionalCallbacks,
- void *closure, bool freeData = true);
-
-JS_PUBLIC_API(bool)
-JS_StructuredCloneHasTransferables(const uint64_t* data, size_t nbytes, bool* hasTransferable);
+JS_StructuredCloneHasTransferables(JSStructuredCloneData& data, bool* hasTransferable);
JS_PUBLIC_API(bool)
JS_StructuredClone(JSContext* cx, JS::HandleValue v, JS::MutableHandleValue vp,
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure);
-/** RAII sugar for JS_WriteStructuredClone. */
+/**
+ * The C-style API calls to read and write structured clones are fragile --
+ * they rely on the caller to properly handle ownership of the clone data, and
+ * the handling of the input data as well as the interpretation of the contents
+ * of the clone buffer are dependent on the callbacks passed in. If you
+ * serialize and deserialize with different callbacks, the results are
+ * questionable.
+ *
+ * JSAutoStructuredCloneBuffer wraps things up in an RAII class for data
+ * management, and uses the same callbacks for both writing and reading
+ * (serializing and deserializing).
+ */
class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
- uint64_t* data_;
- size_t nbytes_;
+ const JS::StructuredCloneScope scope_;
+ JSStructuredCloneData data_;
uint32_t version_;
- enum {
- OwnsTransferablesIfAny,
- IgnoreTransferablesIfAny,
- NoTransferables
- } ownTransferables_;
-
- const JSStructuredCloneCallbacks* callbacks_;
- void* closure_;
public:
- JSAutoStructuredCloneBuffer()
- : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
- ownTransferables_(NoTransferables),
- callbacks_(nullptr), closure_(nullptr)
- {}
-
- JSAutoStructuredCloneBuffer(const JSStructuredCloneCallbacks* callbacks, void* closure)
- : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
- ownTransferables_(NoTransferables),
- callbacks_(callbacks), closure_(closure)
- {}
+ JSAutoStructuredCloneBuffer(JS::StructuredCloneScope aScope,
+ const JSStructuredCloneCallbacks* callbacks, void* closure)
+ : scope_(aScope), data_(aScope), version_(JS_STRUCTURED_CLONE_VERSION)
+ {
+ data_.setCallbacks(callbacks, closure, OwnTransferablePolicy::NoTransferables);
+ }
JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other);
JSAutoStructuredCloneBuffer& operator=(JSAutoStructuredCloneBuffer&& other);
~JSAutoStructuredCloneBuffer() { clear(); }
- uint64_t* data() const { return data_; }
- size_t nbytes() const { return nbytes_; }
+ JSStructuredCloneData& data() { return data_; }
+ bool empty() const { return !data_.Size(); }
- void clear(const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
+ void clear();
- /** Copy some memory. It will be automatically freed by the destructor. */
- bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
- const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
+ JS::StructuredCloneScope scope() const { return scope_; }
/**
* Adopt some memory. It will be automatically freed by the destructor.
* data must have been allocated by the JS engine (e.g., extracted via
* JSAutoStructuredCloneBuffer::steal).
*/
- void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
+ void adopt(JSStructuredCloneData&& data, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
/**
- * Release the buffer and transfer ownership to the caller. The caller is
- * responsible for calling JS_ClearStructuredClone or feeding the memory
- * back to JSAutoStructuredCloneBuffer::adopt.
+ * Release the buffer and transfer ownership to the caller.
*/
- void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr,
+ void steal(JSStructuredCloneData* data, uint32_t* versionp=nullptr,
const JSStructuredCloneCallbacks** callbacks=nullptr, void** closure=nullptr);
/**
* Abandon ownership of any transferable objects stored in the buffer,
* without freeing the buffer itself. Useful when copying the data out into
- * an external container, though note that you will need to use adopt() or
- * JS_ClearStructuredClone to properly release that data eventually.
+ * an external container, though note that you will need to use adopt() to
+ * properly release that data eventually.
*/
- void abandon() { ownTransferables_ = IgnoreTransferablesIfAny; }
+ void abandon() { data_.ownTransferables_ = OwnTransferablePolicy::IgnoreTransferablesIfAny; }
bool read(JSContext* cx, JS::MutableHandleValue vp,
const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
@@ -244,6 +456,7 @@
const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
bool write(JSContext* cx, JS::HandleValue v, JS::HandleValue transferable,
+ JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
private:
@@ -259,6 +472,7 @@
#define JS_SCERR_RECURSION 0
#define JS_SCERR_TRANSFERABLE 1
#define JS_SCERR_DUP_TRANSFERABLE 2
+#define JS_SCERR_UNSUPPORTED_TYPE 3
JS_PUBLIC_API(bool)
JS_ReadUint32Pair(JSStructuredCloneReader* r, uint32_t* p1, uint32_t* p2);
@@ -281,4 +495,10 @@
JS_PUBLIC_API(bool)
JS_WriteTypedArray(JSStructuredCloneWriter* w, JS::HandleValue v);
+JS_PUBLIC_API(bool)
+JS_ObjectNotWritten(JSStructuredCloneWriter* w, JS::HandleObject obj);
+
+JS_PUBLIC_API(JS::StructuredCloneScope)
+JS_GetStructuredCloneScope(JSStructuredCloneWriter* w);
+
#endif /* js_StructuredClone_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/SweepingAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/SweepingAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/SweepingAPI.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_SweepingAPI_h
+#define js_SweepingAPI_h
+
+#include "js/HeapAPI.h"
+
+namespace js {
+template <typename T>
+class WeakCacheBase {};
+} // namespace js
+
+namespace JS {
+template <typename T> class WeakCache;
+
+namespace shadow {
+JS_PUBLIC_API(void)
+RegisterWeakCache(JS::Zone* zone, JS::WeakCache<void*>* cachep);
+} // namespace shadow
+
+// A WeakCache stores the given Sweepable container and links itself into a
+// list of such caches that are swept during each GC.
+template <typename T>
+class WeakCache : public js::WeakCacheBase<T>,
+ private mozilla::LinkedListElement<WeakCache<T>>
+{
+ friend class mozilla::LinkedListElement<WeakCache<T>>;
+ friend class mozilla::LinkedList<WeakCache<T>>;
+
+ WeakCache() = delete;
+ WeakCache(const WeakCache&) = delete;
+
+ using SweepFn = void (*)(T*);
+ SweepFn sweeper;
+ T cache;
+
+ public:
+ using Type = T;
+
+ template <typename U>
+ WeakCache(Zone* zone, U&& initial)
+ : cache(mozilla::Forward<U>(initial))
+ {
+ sweeper = GCPolicy<T>::sweep;
+ shadow::RegisterWeakCache(zone, reinterpret_cast<WeakCache<void*>*>(this));
+ }
+ WeakCache(WeakCache&& other)
+ : sweeper(other.sweeper),
+ cache(mozilla::Move(other.cache))
+ {
+ }
+
+ const T& get() const { return cache; }
+ T& get() { return cache; }
+
+ void sweep() { sweeper(&cache); }
+};
+
+} // namespace JS
+
+#endif // js_SweepingAPI_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TraceKind.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TraceKind.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TraceKind.h
@@ -7,6 +7,8 @@
#ifndef js_TraceKind_h
#define js_TraceKind_h
+#include "mozilla/UniquePtr.h"
+
#include "js/TypeDecls.h"
// Forward declarations of all the types a TraceKind can denote.
@@ -15,6 +17,7 @@
class LazyScript;
class ObjectGroup;
class Shape;
+class Scope;
namespace jit {
class JitCode;
} // namespace jit
@@ -53,18 +56,31 @@
// The following kinds do not have an exposed C++ idiom.
BaseShape = 0x0F,
JitCode = 0x1F,
- LazyScript = 0x2F
+ LazyScript = 0x2F,
+ Scope = 0x3F
};
const static uintptr_t OutOfLineTraceKindMask = 0x07;
static_assert(uintptr_t(JS::TraceKind::BaseShape) & OutOfLineTraceKindMask, "mask bits are set");
static_assert(uintptr_t(JS::TraceKind::JitCode) & OutOfLineTraceKindMask, "mask bits are set");
static_assert(uintptr_t(JS::TraceKind::LazyScript) & OutOfLineTraceKindMask, "mask bits are set");
+static_assert(uintptr_t(JS::TraceKind::Scope) & OutOfLineTraceKindMask, "mask bits are set");
+
+// When this header is imported inside SpiderMonkey, the class definitions are
+// available and we can query those definitions to find the correct kind
+// directly from the class hierarchy.
+template <typename T>
+struct MapTypeToTraceKind {
+ static const JS::TraceKind kind = T::TraceKind;
+};
+// When this header is used outside SpiderMonkey, the class definitions are not
+// available, so the following table containing all public GC types is used.
#define JS_FOR_EACH_TRACEKIND(D) \
/* PrettyName TypeName AddToCCKind */ \
D(BaseShape, js::BaseShape, true) \
D(JitCode, js::jit::JitCode, true) \
D(LazyScript, js::LazyScript, true) \
+ D(Scope, js::Scope, true) \
D(Object, JSObject, true) \
D(ObjectGroup, js::ObjectGroup, true) \
D(Script, JSScript, true) \
@@ -72,8 +88,7 @@
D(String, JSString, false) \
D(Symbol, JS::Symbol, false)
-// Map from base trace type to the trace kind.
-template <typename T> struct MapTypeToTraceKind {};
+// Map from all public types to their trace kind.
#define JS_EXPAND_DEF(name, type, _) \
template <> struct MapTypeToTraceKind<type> { \
static const JS::TraceKind kind = JS::TraceKind::name; \
@@ -81,6 +96,60 @@
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
#undef JS_EXPAND_DEF
+// RootKind is closely related to TraceKind. Whereas TraceKind's indices are
+// laid out for convenient embedding as a pointer tag, the indicies of RootKind
+// are designed for use as array keys via EnumeratedArray.
+enum class RootKind : int8_t
+{
+ // These map 1:1 with trace kinds.
+#define EXPAND_ROOT_KIND(name, _0, _1) \
+ name,
+JS_FOR_EACH_TRACEKIND(EXPAND_ROOT_KIND)
+#undef EXPAND_ROOT_KIND
+
+ // These tagged pointers are special-cased for performance.
+ Id,
+ Value,
+
+ // Everything else.
+ Traceable,
+
+ Limit
+};
+
+// Most RootKind correspond directly to a trace kind.
+template <TraceKind traceKind> struct MapTraceKindToRootKind {};
+#define JS_EXPAND_DEF(name, _0, _1) \
+ template <> struct MapTraceKindToRootKind<JS::TraceKind::name> { \
+ static const JS::RootKind kind = JS::RootKind::name; \
+ };
+JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF)
+#undef JS_EXPAND_DEF
+
+// Specify the RootKind for all types. Value and jsid map to special cases;
+// pointer types we can derive directly from the TraceKind; everything else
+// should go in the Traceable list and use GCPolicy<T>::trace for tracing.
+template <typename T>
+struct MapTypeToRootKind {
+ static const JS::RootKind kind = JS::RootKind::Traceable;
+};
+template <typename T>
+struct MapTypeToRootKind<T*> {
+ static const JS::RootKind kind =
+ JS::MapTraceKindToRootKind<JS::MapTypeToTraceKind<T>::kind>::kind;
+};
+template <typename T>
+struct MapTypeToRootKind<mozilla::UniquePtr<T>> {
+ static const JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
+};
+template <> struct MapTypeToRootKind<JS::Value> {
+ static const JS::RootKind kind = JS::RootKind::Value;
+};
+template <> struct MapTypeToRootKind<jsid> {
+ static const JS::RootKind kind = JS::RootKind::Id;
+};
+template <> struct MapTypeToRootKind<JSFunction*> : public MapTypeToRootKind<JSObject*> {};
+
// Fortunately, few places in the system need to deal with fully abstract
// cells. In those places that do, we generally want to move to a layout
// templated function as soon as possible. This template wraps the upcast
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TraceableVector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TraceableVector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TraceableVector.h
@@ -1,239 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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 js_TraceableVector_h
-#define js_TraceableVector_h
-
-#include "mozilla/Vector.h"
-
-#include "js/RootingAPI.h"
-#include "js/TracingAPI.h"
-#include "js/Vector.h"
-
-namespace js {
-
-// A TraceableVector is a Vector with an additional trace method that knows how
-// to visit all of the items stored in the Vector. For vectors that contain GC
-// things, this is usually more convenient than manually iterating and marking
-// the contents.
-//
-// Most types of GC pointers as keys and values can be traced with no extra
-// infrastructure. For structs and non-gc-pointer members, ensure that there
-// is a specialization of DefaultGCPolicy<T> with an appropriate trace method
-// available to handle the custom type. Generic helpers can be found in
-// js/public/TracingAPI.h.
-//
-// Note that although this Vector's trace will deal correctly with moved items,
-// it does not itself know when to barrier or trace items. To function properly
-// it must either be used with Rooted, or barriered and traced manually.
-template <typename T,
- size_t MinInlineCapacity = 0,
- typename AllocPolicy = TempAllocPolicy,
- typename GCPolicy = DefaultGCPolicy<T>>
-class TraceableVector : public JS::Traceable
-{
- mozilla::Vector<T, MinInlineCapacity, AllocPolicy> vector;
-
- public:
- explicit TraceableVector(AllocPolicy alloc = AllocPolicy())
- : vector(alloc)
- {}
-
- TraceableVector(TraceableVector&& vec)
- : vector(mozilla::Move(vec.vector))
- {}
-
- TraceableVector& operator=(TraceableVector&& vec) {
- vector = mozilla::Move(vec.vector);
- return *this;
- }
-
- size_t length() const { return vector.length(); }
- bool empty() const { return vector.empty(); }
- size_t capacity() const { return vector.capacity(); }
-
- T* begin() { return vector.begin(); }
- const T* begin() const { return vector.begin(); }
-
- T* end() { return vector.end(); }
- const T* end() const { return vector.end(); }
-
- T& operator[](size_t i) { return vector[i]; }
- const T& operator[](size_t i) const { return vector[i]; }
-
- T& back() { return vector.back(); }
- const T& back() const { return vector.back(); }
-
- bool initCapacity(size_t cap) { return vector.initCapacity(cap); }
- bool reserve(size_t req) { return vector.reserve(req); }
- void shrinkBy(size_t amount) { return vector.shrinkBy(amount); }
- bool growBy(size_t amount) { return vector.growBy(amount); }
- bool resize(size_t newLen) { return vector.resize(newLen); }
-
- void clear() { return vector.clear(); }
-
- template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }
-
- template<typename... Args>
- bool
- emplaceBack(Args&&... args) {
- return vector.emplaceBack(mozilla::Forward<Args>(args)...);
- }
-
- template<typename U>
- void infallibleAppend(U&& aU) {
- return vector.infallibleAppend(mozilla::Forward<U>(aU));
- }
- void infallibleAppendN(const T& aT, size_t aN) {
- return vector.infallibleAppendN(aT, aN);
- }
- template<typename U> void
- infallibleAppend(const U* aBegin, const U* aEnd) {
- return vector.infallibleAppend(aBegin, aEnd);
- }
- template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
- return vector.infallibleAppend(aBegin, aLength);
- }
-
- bool appendN(const T& val, size_t count) { return vector.appendN(val, count); }
-
- template<typename U> bool append(const U* aBegin, const U* aEnd) {
- return vector.append(aBegin, aEnd);
- }
- template<typename U> bool append(const U* aBegin, size_t aLength) {
- return vector.append(aBegin, aLength);
- }
-
- void popBack() { return vector.popBack(); }
- T popCopy() { return vector.popCopy(); }
-
- size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
- return vector.sizeOfExcludingThis(mallocSizeOf);
- }
-
- size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
- return vector.sizeOfIncludingThis(mallocSizeOf);
- }
-
- static void trace(TraceableVector* vec, JSTracer* trc) { vec->trace(trc); }
-
- void trace(JSTracer* trc) {
- for (auto& elem : vector)
- GCPolicy::trace(trc, &elem, "vector element");
- }
-};
-
-template <typename Outer, typename T, size_t Capacity, typename AllocPolicy, typename GCPolicy>
-class TraceableVectorOperations
-{
- using Vec = TraceableVector<T, Capacity, AllocPolicy, GCPolicy>;
- const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
-
- public:
- const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
- size_t length() const { return vec().length(); }
- bool empty() const { return vec().empty(); }
- size_t capacity() const { return vec().capacity(); }
- const T* begin() const { return vec().begin(); }
- const T* end() const { return vec().end(); }
- const T& back() const { return vec().back(); }
- bool canAppendWithoutRealloc(size_t aNeeded) const { return vec().canAppendWithoutRealloc(); }
-
- JS::Handle<T> operator[](size_t aIndex) const {
- return JS::Handle<T>::fromMarkedLocation(&vec().operator[](aIndex));
- }
-};
-
-template <typename Outer, typename T, size_t Capacity, typename AllocPolicy, typename GCPolicy>
-class MutableTraceableVectorOperations
- : public TraceableVectorOperations<Outer, T, Capacity, AllocPolicy, GCPolicy>
-{
- using Vec = TraceableVector<T, Capacity, AllocPolicy, GCPolicy>;
- const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
- Vec& vec() { return static_cast<Outer*>(this)->get(); }
-
- public:
- const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
- AllocPolicy& allocPolicy() { return vec().allocPolicy(); }
- const T* begin() const { return vec().begin(); }
- T* begin() { return vec().begin(); }
- const T* end() const { return vec().end(); }
- T* end() { return vec().end(); }
- const T& operator[](size_t aIndex) const { return vec().operator[](aIndex); }
- const T& back() const { return vec().back(); }
- T& back() { return vec().back(); }
-
- JS::MutableHandle<T> operator[](size_t aIndex) {
- return JS::MutableHandle<T>::fromMarkedLocation(&vec().operator[](aIndex));
- }
-
- bool initCapacity(size_t aRequest) { return vec().initCapacity(aRequest); }
- bool reserve(size_t aRequest) { return vec().reserve(aRequest); }
- void shrinkBy(size_t aIncr) { vec().shrinkBy(aIncr); }
- bool growBy(size_t aIncr) { return vec().growBy(aIncr); }
- bool resize(size_t aNewLength) { return vec().resize(aNewLength); }
- bool growByUninitialized(size_t aIncr) { return vec().growByUninitialized(aIncr); }
- void infallibleGrowByUninitialized(size_t aIncr) { vec().infallibleGrowByUninitialized(aIncr); }
- bool resizeUninitialized(size_t aNewLength) { return vec().resizeUninitialized(aNewLength); }
- void clear() { vec().clear(); }
- void clearAndFree() { vec().clearAndFree(); }
- template<typename U> bool append(U&& aU) { return vec().append(mozilla::Forward<U>(aU)); }
- template<typename... Args> bool emplaceBack(Args&&... aArgs) {
- return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
- }
- template<typename U, size_t O, class BP>
- bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vec().appendAll(aU); }
- bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
- template<typename U> bool append(const U* aBegin, const U* aEnd) {
- return vec().append(aBegin, aEnd);
- }
- template<typename U> bool append(const U* aBegin, size_t aLength) {
- return vec().append(aBegin, aLength);
- }
- template<typename U> void infallibleAppend(U&& aU) {
- vec().infallibleAppend(mozilla::Forward<U>(aU));
- }
- void infallibleAppendN(const T& aT, size_t aN) { vec().infallibleAppendN(aT, aN); }
- template<typename U> void infallibleAppend(const U* aBegin, const U* aEnd) {
- vec().infallibleAppend(aBegin, aEnd);
- }
- template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
- vec().infallibleAppend(aBegin, aLength);
- }
- void popBack() { vec().popBack(); }
- T popCopy() { return vec().popCopy(); }
- template<typename U> T* insert(T* aP, U&& aVal) {
- return vec().insert(aP, mozilla::Forward<U>(aVal));
- }
- void erase(T* aT) { vec().erase(aT); }
- void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
-};
-
-template <typename T, size_t N, typename AP, typename GP>
-class RootedBase<TraceableVector<T,N,AP,GP>>
- : public MutableTraceableVectorOperations<JS::Rooted<TraceableVector<T,N,AP,GP>>, T,N,AP,GP>
-{};
-
-template <typename T, size_t N, typename AP, typename GP>
-class MutableHandleBase<TraceableVector<T,N,AP,GP>>
- : public MutableTraceableVectorOperations<JS::MutableHandle<TraceableVector<T,N,AP,GP>>,
- T,N,AP,GP>
-{};
-
-template <typename T, size_t N, typename AP, typename GP>
-class HandleBase<TraceableVector<T,N,AP,GP>>
- : public TraceableVectorOperations<JS::Handle<TraceableVector<T,N,AP,GP>>, T,N,AP,GP>
-{};
-
-template <typename T, size_t N, typename AP, typename GP>
-class PersistentRootedBase<TraceableVector<T,N,AP,GP>>
- : public MutableTraceableVectorOperations<JS::PersistentRooted<TraceableVector<T,N,AP,GP>>,
- T,N,AP,GP>
-{};
-
-} // namespace js
-
-#endif // js_TraceableVector_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TracingAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TracingAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TracingAPI.h
@@ -27,13 +27,15 @@
} // namespace JS
enum WeakMapTraceKind {
- /** Do true ephemeron marking with an iterative weak marking phase. */
+ /**
+ * Do not trace into weak map keys or values during traversal. Users must
+ * handle weak maps manually.
+ */
DoNotTraceWeakMaps,
/**
* Do true ephemeron marking with a weak key lookup marking phase. This is
- * expected to be constant for the lifetime of a JSTracer; it does not
- * change when switching from "plain" marking to weak marking.
+ * the default for GCMarker.
*/
ExpandWeakMaps,
@@ -59,11 +61,24 @@
// Return the weak map tracing behavior currently set on this tracer.
WeakMapTraceKind weakMapAction() const { return weakMapAction_; }
- // An intermediate state on the road from C to C++ style dispatch.
enum class TracerKindTag {
+ // Marking path: a tracer used only for marking liveness of cells, not
+ // for moving them. The kind will transition to WeakMarking after
+ // everything reachable by regular edges has been marked.
Marking,
- WeakMarking, // In weak marking phase: looking up every marked obj/script.
+
+ // Same as Marking, except we have now moved on to the "weak marking
+ // phase", in which every marked obj/script is immediately looked up to
+ // see if it is a weak map key (and therefore might require marking its
+ // weak map value).
+ WeakMarking,
+
+ // A tracer that traverses the graph for the purposes of moving objects
+ // from the nursery to the tenured area.
Tenuring,
+
+ // General-purpose traversal that invokes a callback on each cell.
+ // Traversing children is the responsibility of the callback.
Callback
};
bool isMarkingTracer() const { return tag_ == TracerKindTag::Marking || tag_ == TracerKindTag::WeakMarking; }
@@ -71,19 +86,37 @@
bool isTenuringTracer() const { return tag_ == TracerKindTag::Tenuring; }
bool isCallbackTracer() const { return tag_ == TracerKindTag::Callback; }
inline JS::CallbackTracer* asCallbackTracer();
+#ifdef DEBUG
+ bool checkEdges() { return checkEdges_; }
+#endif
protected:
JSTracer(JSRuntime* rt, TracerKindTag tag,
WeakMapTraceKind weakTraceKind = TraceWeakMapValues)
- : runtime_(rt), weakMapAction_(weakTraceKind), tag_(tag)
+ : runtime_(rt)
+ , weakMapAction_(weakTraceKind)
+#ifdef DEBUG
+ , checkEdges_(true)
+#endif
+ , tag_(tag)
{}
+#ifdef DEBUG
+ // Set whether to check edges are valid in debug builds.
+ void setCheckEdges(bool check) {
+ checkEdges_ = check;
+ }
+#endif
+
private:
- JSRuntime* runtime_;
- WeakMapTraceKind weakMapAction_;
+ JSRuntime* runtime_;
+ WeakMapTraceKind weakMapAction_;
+#ifdef DEBUG
+ bool checkEdges_;
+#endif
protected:
- TracerKindTag tag_;
+ TracerKindTag tag_;
};
namespace JS {
@@ -99,6 +132,7 @@
: JSTracer(rt, JSTracer::TracerKindTag::Callback, weakTraceKind),
contextName_(nullptr), contextIndex_(InvalidIndex), contextFunctor_(nullptr)
{}
+ CallbackTracer(JSContext* cx, WeakMapTraceKind weakTraceKind = TraceWeakMapValues);
// Override these methods to receive notification when an edge is visited
// with the type contained in the callback. The default implementation
@@ -124,6 +158,9 @@
virtual void onLazyScriptEdge(js::LazyScript** lazyp) {
onChild(JS::GCCellPtr(*lazyp, JS::TraceKind::LazyScript));
}
+ virtual void onScopeEdge(js::Scope** scopep) {
+ onChild(JS::GCCellPtr(*scopep, JS::TraceKind::Scope));
+ }
// Override this method to receive notification when a node in the GC
// heap graph is visited.
@@ -193,6 +230,7 @@
void dispatchToOnEdge(js::BaseShape** basep) { onBaseShapeEdge(basep); }
void dispatchToOnEdge(js::jit::JitCode** codep) { onJitCodeEdge(codep); }
void dispatchToOnEdge(js::LazyScript** lazyp) { onLazyScriptEdge(lazyp); }
+ void dispatchToOnEdge(js::Scope** scopep) { onScopeEdge(scopep); }
private:
friend class AutoTracingName;
@@ -281,151 +319,85 @@
return static_cast<JS::CallbackTracer*>(this);
}
-// The JS_Call*Tracer family of functions traces the given GC thing reference.
-// This performs the tracing action configured on the given JSTracer:
-// typically calling the JSTracer::callback or marking the thing as live.
+namespace JS {
+
+// The JS::TraceEdge family of functions traces the given GC thing reference.
+// This performs the tracing action configured on the given JSTracer: typically
+// calling the JSTracer::callback or marking the thing as live.
//
-// The argument to JS_Call*Tracer is an in-out param: when the function
-// returns, the garbage collector might have moved the GC thing. In this case,
-// the reference passed to JS_Call*Tracer will be updated to the object's new
-// location. Callers of this method are responsible for updating any state
-// that is dependent on the object's address. For example, if the object's
-// address is used as a key in a hashtable, then the object must be removed
-// and re-inserted with the correct hash.
+// The argument to JS::TraceEdge is an in-out param: when the function returns,
+// the garbage collector might have moved the GC thing. In this case, the
+// reference passed to JS::TraceEdge will be updated to the thing's new
+// location. Callers of this method are responsible for updating any state that
+// is dependent on the object's address. For example, if the object's address
+// is used as a key in a hashtable, then the object must be removed and
+// re-inserted with the correct hash.
//
-extern JS_PUBLIC_API(void)
-JS_CallValueTracer(JSTracer* trc, JS::Heap<JS::Value>* valuep, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallIdTracer(JSTracer* trc, JS::Heap<jsid>* idp, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallObjectTracer(JSTracer* trc, JS::Heap<JSObject*>* objp, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallStringTracer(JSTracer* trc, JS::Heap<JSString*>* strp, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallScriptTracer(JSTracer* trc, JS::Heap<JSScript*>* scriptp, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallFunctionTracer(JSTracer* trc, JS::Heap<JSFunction*>* funp, const char* name);
-
-namespace JS {
+// Note that while |edgep| must never be null, it is fine for |*edgep| to be
+// nullptr.
template <typename T>
extern JS_PUBLIC_API(void)
TraceEdge(JSTracer* trc, JS::Heap<T>* edgep, const char* name);
-} // namespace JS
-
-// The following JS_CallUnbarriered*Tracer functions should only be called where
-// you know for sure that a heap post barrier is not required. Use with extreme
-// caution!
-extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredValueTracer(JSTracer* trc, JS::Value* valuep, const char* name);
extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredIdTracer(JSTracer* trc, jsid* idp, const char* name);
+TraceEdge(JSTracer* trc, JS::TenuredHeap<JSObject*>* edgep, const char* name);
+// Edges that are always traced as part of root marking do not require
+// incremental barriers. This function allows for marking non-barriered
+// pointers, but asserts that this happens during root marking.
+//
+// Note that while |edgep| must never be null, it is fine for |*edgep| to be
+// nullptr.
+template <typename T>
extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredObjectTracer(JSTracer* trc, JSObject** objp, const char* name);
+UnsafeTraceRoot(JSTracer* trc, T* edgep, const char* name);
extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredStringTracer(JSTracer* trc, JSString** strp, const char* name);
+TraceChildren(JSTracer* trc, GCCellPtr thing);
-extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredScriptTracer(JSTracer* trc, JSScript** scriptp, const char* name);
+using ZoneSet = js::HashSet<Zone*, js::DefaultHasher<Zone*>, js::SystemAllocPolicy>;
+using CompartmentSet = js::HashSet<JSCompartment*, js::DefaultHasher<JSCompartment*>,
+ js::SystemAllocPolicy>;
/**
- * Trace an object that is known to always be tenured. No post barriers are
- * required in this case.
+ * Trace every value within |compartments| that is wrapped by a
+ * cross-compartment wrapper from a compartment that is not an element of
+ * |compartments|.
*/
extern JS_PUBLIC_API(void)
-JS_CallTenuredObjectTracer(JSTracer* trc, JS::TenuredHeap<JSObject*>* objp, const char* name);
+TraceIncomingCCWs(JSTracer* trc, const JS::CompartmentSet& compartments);
-extern JS_PUBLIC_API(void)
-JS_TraceRuntime(JSTracer* trc);
-
-namespace JS {
-extern JS_PUBLIC_API(void)
-TraceChildren(JSTracer* trc, GCCellPtr thing);
-
-typedef js::HashSet<Zone*, js::DefaultHasher<Zone*>, js::SystemAllocPolicy> ZoneSet;
} // namespace JS
-/**
- * Trace every value within |zones| that is wrapped by a cross-compartment
- * wrapper from a zone that is not an element of |zones|.
- */
-extern JS_PUBLIC_API(void)
-JS_TraceIncomingCCWs(JSTracer* trc, const JS::ZoneSet& zones);
-
extern JS_PUBLIC_API(void)
JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc,
void* thing, JS::TraceKind kind, bool includeDetails);
namespace js {
-namespace gc {
-template <typename T>
-extern JS_PUBLIC_API(bool)
-EdgeNeedsSweep(JS::Heap<T>* edgep);
-} // namespace gc
-// Automates static dispatch for GC interaction with TraceableContainers.
-template <typename>
-struct DefaultGCPolicy;
-
-// This policy dispatches GC methods to a method on the type.
+// Trace an edge that is not a GC root and is not wrapped in a barriered
+// wrapper for some reason.
+//
+// This method does not check if |*edgep| is non-null before tracing through
+// it, so callers must check any nullable pointer before calling this method.
template <typename T>
-struct StructGCPolicy {
- static void trace(JSTracer* trc, T* t, const char* name) {
- // This is the default GC policy for storing GC things in containers.
- // If your build is failing here, it means you either need an
- // implementation of DefaultGCPolicy<T> for your type or, if this is
- // the right policy for you, your struct or container is missing a
- // trace method.
- t->trace(trc);
- }
-
- static bool needsSweep(T* t) {
- return t->needsSweep();
- }
-};
+extern JS_PUBLIC_API(void)
+UnsafeTraceManuallyBarrieredEdge(JSTracer* trc, T* edgep, const char* name);
-// This policy ignores any GC interaction, e.g. for non-GC types.
-template <typename T>
-struct IgnoreGCPolicy {
- static void trace(JSTracer* trc, T* t, const char* name) {}
- static bool needsSweep(T* v) { return false; }
-};
+namespace gc {
-// The default policy when no other more specific policy fits (e.g. for a
-// direct GC pointer), is to assume a struct type that implements the needed
-// methods.
+// Return true if the given edge is not live and is about to be swept.
template <typename T>
-struct DefaultGCPolicy : public StructGCPolicy<T> {};
-
-template <>
-struct DefaultGCPolicy<jsid>
-{
- static void trace(JSTracer* trc, jsid* id, const char* name) {
- JS_CallUnbarrieredIdTracer(trc, id, name);
- }
-};
-
-template <> struct DefaultGCPolicy<uint32_t> : public IgnoreGCPolicy<uint32_t> {};
-template <> struct DefaultGCPolicy<uint64_t> : public IgnoreGCPolicy<uint64_t> {};
+extern JS_PUBLIC_API(bool)
+EdgeNeedsSweep(JS::Heap<T>* edgep);
+// Not part of the public API, but declared here so we can use it in GCPolicy
+// which is.
template <typename T>
-struct DefaultGCPolicy<JS::Heap<T>>
-{
- static void trace(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
- JS::TraceEdge(trc, thingp, name);
- }
- static bool needsSweep(JS::Heap<T>* thingp) {
- return gc::EdgeNeedsSweep(thingp);
- }
-};
+bool
+IsAboutToBeFinalizedUnbarriered(T* thingp);
+} // namespace gc
} // namespace js
#endif /* js_TracingAPI_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TrackedOptimizationInfo.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TrackedOptimizationInfo.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/TrackedOptimizationInfo.h
@@ -16,6 +16,7 @@
_(GetProp_ArgumentsCallee) \
_(GetProp_InferredConstant) \
_(GetProp_Constant) \
+ _(GetProp_NotDefined) \
_(GetProp_StaticName) \
_(GetProp_SimdGetter) \
_(GetProp_TypedObject) \
@@ -51,6 +52,12 @@
_(SetElem_Arguments) \
_(SetElem_InlineCache) \
\
+ _(BinaryArith_Concat) \
+ _(BinaryArith_SpecializedTypes) \
+ _(BinaryArith_SpecializedOnBaselineTypes) \
+ _(BinaryArith_SharedCache) \
+ _(BinaryArith_Call) \
+ \
_(InlineCache_OptimizedStub) \
\
_(Call_Inline)
@@ -74,6 +81,7 @@
_(NotObject) \
_(NotStruct) \
_(NotUnboxed) \
+ _(NotUndefined) \
_(UnboxedConvertedToNative) \
_(StructNoField) \
_(InconsistentFieldType) \
@@ -88,13 +96,17 @@
_(ArrayDoubleConversion) \
_(ArrayRange) \
_(ArraySeenNegativeIndex) \
- _(TypedObjectNeutered) \
+ _(TypedObjectHasDetachedBuffer) \
_(TypedObjectArrayRange) \
_(AccessNotDense) \
_(AccessNotSimdObject) \
_(AccessNotTypedObject) \
_(AccessNotTypedArray) \
_(AccessNotString) \
+ _(OperandNotString) \
+ _(OperandNotNumber) \
+ _(OperandNotStringOrNumber) \
+ _(OperandNotSimpleArith) \
_(StaticTypedArrayUint32) \
_(StaticTypedArrayCantComputeMask) \
_(OutOfBounds) \
@@ -144,6 +156,7 @@
\
_(ICNameStub_ReadSlot) \
_(ICNameStub_CallGetter) \
+ _(ICNameStub_TypeOfNoProperty) \
\
_(CantInlineGeneric) \
_(CantInlineNoTarget) \
@@ -180,6 +193,7 @@
#define TRACKED_TYPESITE_LIST(_) \
_(Receiver) \
+ _(Operand) \
_(Index) \
_(Value) \
_(Call_Target) \
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNode.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNode.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNode.h
@@ -15,7 +15,6 @@
#include "mozilla/Move.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/TypeTraits.h"
-#include "mozilla/UniquePtr.h"
#include "mozilla/Variant.h"
#include "jspubtd.h"
@@ -25,6 +24,7 @@
#include "js/RootingAPI.h"
#include "js/TracingAPI.h"
#include "js/TypeDecls.h"
+#include "js/UniquePtr.h"
#include "js/Value.h"
#include "js/Vector.h"
@@ -71,7 +71,7 @@
// One can construct a ubi::Node value given a pointer to a type that ubi::Node
// supports. In the other direction, one can convert a ubi::Node back to a
// pointer; these downcasts are checked dynamically. In particular, one can
-// convert a 'JSRuntime*' to a ubi::Node, yielding a node with an outgoing edge
+// convert a 'JSContext*' to a ubi::Node, yielding a node with an outgoing edge
// for every root registered with the runtime; starting from this, one can walk
// the entire heap. (Of course, one could also start traversal at any other kind
// of type to which one has a pointer.)
@@ -174,16 +174,6 @@
} // namespace ubi
} // namespace JS
-namespace mozilla {
-
-template<>
-class DefaultDelete<JS::ubi::EdgeRange> : public JS::DeletePolicy<JS::ubi::EdgeRange> { };
-
-template<>
-class DefaultDelete<JS::ubi::StackFrame> : public JS::DeletePolicy<JS::ubi::StackFrame> { };
-
-} // namespace mozilla
-
namespace JS {
namespace ubi {
@@ -191,9 +181,11 @@
using mozilla::Maybe;
using mozilla::Move;
using mozilla::RangedPtr;
-using mozilla::UniquePtr;
using mozilla::Variant;
+template <typename T>
+using Vector = mozilla::Vector<T, 0, js::SystemAllocPolicy>;
+
/*** ubi::StackFrame ******************************************************************************/
// Concrete JS::ubi::StackFrame instances backed by a live SavedFrame object
@@ -201,7 +193,7 @@
// heap snapshots store their strings as const char16_t*. In order to provide
// zero-cost accessors to these strings in a single interface that works with
// both cases, we use this variant type.
-class AtomOrTwoByteChars : public Variant<JSAtom*, const char16_t*> {
+class JS_PUBLIC_API(AtomOrTwoByteChars) : public Variant<JSAtom*, const char16_t*> {
using Base = Variant<JSAtom*, const char16_t*>;
public:
@@ -267,7 +259,7 @@
// Return true if this frame's function is a self-hosted JavaScript builtin,
// false otherwise.
- virtual bool isSelfHosted() const = 0;
+ virtual bool isSelfHosted(JSContext* cx) const = 0;
// Construct a SavedFrame stack for the stack starting with this frame and
// containing all of its parents. The SavedFrame objects will be placed into
@@ -294,8 +286,9 @@
// simplifies the principals check into the boolean isSystem() state. This
// is fine because we only expose JS::ubi::Stack to devtools and chrome
// code, and not to the web platform.
- virtual bool constructSavedFrameStack(JSContext* cx,
- MutableHandleObject outSavedFrameStack) const = 0;
+ virtual MOZ_MUST_USE bool constructSavedFrameStack(JSContext* cx,
+ MutableHandleObject outSavedFrameStack)
+ const = 0;
// Trace the concrete implementation of JS::ubi::StackFrame.
virtual void trace(JSTracer* trc) = 0;
@@ -319,7 +312,7 @@
// valid within the scope of an AutoCheckCannotGC; if the graph being analyzed
// is an offline heap snapshot, the JS::ubi::StackFrame is valid as long as the
// offline heap snapshot is alive.
-class StackFrame : public JS::Traceable {
+class StackFrame {
// Storage in which we allocate BaseStackFrame subclasses.
mozilla::AlignedStorage2<BaseStackFrame> storage;
@@ -409,12 +402,6 @@
size_t sourceLength();
size_t functionDisplayNameLength();
- // JS::Traceable implementation just forwards to our virtual trace method.
- static void trace(StackFrame* frame, JSTracer* trc) {
- if (frame)
- frame->trace(trc);
- }
-
// Methods that forward to virtual calls through BaseStackFrame.
void trace(JSTracer* trc) { base()->trace(trc); }
@@ -429,9 +416,9 @@
AtomOrTwoByteChars functionDisplayName() const { return base()->functionDisplayName(); }
StackFrame parent() const { return base()->parent(); }
bool isSystem() const { return base()->isSystem(); }
- bool isSelfHosted() const { return base()->isSelfHosted(); }
- bool constructSavedFrameStack(JSContext* cx,
- MutableHandleObject outSavedFrameStack) const {
+ bool isSelfHosted(JSContext* cx) const { return base()->isSelfHosted(cx); }
+ MOZ_MUST_USE bool constructSavedFrameStack(JSContext* cx,
+ MutableHandleObject outSavedFrameStack) const {
return base()->constructSavedFrameStack(cx, outSavedFrameStack);
}
@@ -463,7 +450,9 @@
uint64_t identifier() const override { return 0; }
void trace(JSTracer* trc) override { }
- bool constructSavedFrameStack(JSContext* cx, MutableHandleObject out) const override {
+ MOZ_MUST_USE bool constructSavedFrameStack(JSContext* cx, MutableHandleObject out)
+ const override
+ {
out.set(nullptr);
return true;
}
@@ -474,11 +463,13 @@
AtomOrTwoByteChars functionDisplayName() const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
StackFrame parent() const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
bool isSystem() const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
- bool isSelfHosted() const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
+ bool isSelfHosted(JSContext* cx) const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
};
-bool ConstructSavedFrameStackSlow(JSContext* cx, JS::ubi::StackFrame& frame,
- MutableHandleObject outSavedFrameStack);
+MOZ_MUST_USE JS_PUBLIC_API(bool)
+ConstructSavedFrameStackSlow(JSContext* cx,
+ JS::ubi::StackFrame& frame,
+ MutableHandleObject outSavedFrameStack);
/*** ubi::Node ************************************************************************************/
@@ -529,7 +520,7 @@
// The base class implemented by each ubi::Node referent type. Subclasses must
// not add data members to this class.
-class Base {
+class JS_PUBLIC_API(Base) {
friend class Node;
// For performance's sake, we'd prefer to avoid a virtual destructor; and
@@ -579,7 +570,7 @@
virtual CoarseType coarseType() const { return CoarseType::Other; }
// Return a human-readable name for the referent's type. The result should
- // be statically allocated. (You can use MOZ_UTF16("strings") for this.)
+ // be statically allocated. (You can use u"strings" for this.)
//
// This must always return Concrete<T>::concreteTypeName; we use that
// pointer as a tag for this particular referent type.
@@ -589,6 +580,11 @@
// node owns exclusively that are not exposed as their own ubi::Nodes.
// |mallocSizeOf| should be a malloc block sizing function; see
// |mfbt/MemoryReporting.h|.
+ //
+ // Because we can use |JS::ubi::Node|s backed by a snapshot that was taken
+ // on a 64-bit platform when we are currently on a 32-bit platform, we
+ // cannot rely on |size_t| for node sizes. Instead, |Size| is uint64_t on
+ // all platforms.
using Size = uint64_t;
virtual Size size(mozilla::MallocSizeOf mallocSizeof) const { return 1; }
@@ -597,7 +593,7 @@
//
// If wantNames is true, compute names for edges. Doing so can be expensive
// in time and memory.
- virtual UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const = 0;
+ virtual js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const = 0;
// Return the Zone to which this node's referent belongs, or nullptr if the
// referent is not of a type allocated in SpiderMonkey Zones.
@@ -633,8 +629,9 @@
// Otherwise, place nullptr in the out parameter. Caller maintains ownership
// of the out parameter. True is returned on success, false is returned on
// OOM.
- virtual bool jsObjectConstructorName(JSContext* cx,
- UniquePtr<char16_t[], JS::FreePolicy>& outName) const {
+ virtual MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& outName)
+ const
+ {
outName.reset(nullptr);
return true;
}
@@ -651,28 +648,28 @@
};
// A traits template with a specialization for each referent type that
-// ubi::Node supports. The specialization must be the concrete subclass of
-// Base that represents a pointer to the referent type. It must also
-// include the members described here.
+// ubi::Node supports. The specialization must be the concrete subclass of Base
+// that represents a pointer to the referent type. It must include these
+// members:
+//
+// // The specific char16_t array returned by Concrete<T>::typeName().
+// static const char16_t concreteTypeName[];
+//
+// // Construct an instance of this concrete class in |storage| referring
+// // to |referent|. Implementations typically use a placement 'new'.
+// //
+// // In some cases, |referent| will contain dynamic type information that
+// // identifies it a some more specific subclass of |Referent|. For
+// // example, when |Referent| is |JSObject|, then |referent->getClass()|
+// // could tell us that it's actually a JSFunction. Similarly, if
+// // |Referent| is |nsISupports|, we would like a ubi::Node that knows its
+// // final implementation type.
+// //
+// // So we delegate the actual construction to this specialization, which
+// // knows Referent's details.
+// static void construct(void* storage, Referent* referent);
template<typename Referent>
-struct Concrete {
- // The specific char16_t array returned by Concrete<T>::typeName.
- static const char16_t concreteTypeName[];
-
- // Construct an instance of this concrete class in |storage| referring
- // to |referent|. Implementations typically use a placement 'new'.
- //
- // In some cases, |referent| will contain dynamic type information that
- // identifies it a some more specific subclass of |Referent|. For example,
- // when |Referent| is |JSObject|, then |referent->getClass()| could tell us
- // that it's actually a JSFunction. Similarly, if |Referent| is
- // |nsISupports|, we would like a ubi::Node that knows its final
- // implementation type.
- //
- // So, we delegate the actual construction to this specialization, which
- // knows Referent's details.
- static void construct(void* storage, Referent* referent);
-};
+class Concrete;
// A container for a Base instance; all members simply forward to the contained
// instance. This container allows us to pass ubi::Node instances by value.
@@ -686,6 +683,8 @@
void construct(T* ptr) {
static_assert(sizeof(Concrete<T>) == sizeof(*base()),
"ubi::Base specializations must be the same size as ubi::Base");
+ static_assert(mozilla::IsBaseOf<Base, Concrete<T>>::value,
+ "ubi::Concrete<T> must inherit from ubi::Base");
Concrete<T>::construct(base(), ptr);
}
struct ConstructFunctor;
@@ -780,8 +779,7 @@
JS::Zone* zone() const { return base()->zone(); }
JSCompartment* compartment() const { return base()->compartment(); }
const char* jsObjectClassName() const { return base()->jsObjectClassName(); }
- bool jsObjectConstructorName(JSContext* cx,
- UniquePtr<char16_t[], JS::FreePolicy>& outName) const {
+ MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& outName) const {
return base()->jsObjectConstructorName(cx, outName);
}
@@ -796,8 +794,8 @@
return size;
}
- UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames = true) const {
- return base()->edges(rt, wantNames);
+ js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames = true) const {
+ return base()->edges(cx, wantNames);
}
bool hasAllocationStack() const { return base()->hasAllocationStack(); }
@@ -827,10 +825,12 @@
};
};
+using NodeSet = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
+using NodeSetPtr = mozilla::UniquePtr<NodeSet, JS::DeletePolicy<NodeSet>>;
/*** Edge and EdgeRange ***************************************************************************/
-using EdgeName = UniquePtr<const char16_t[], JS::FreePolicy>;
+using EdgeName = UniqueTwoByteChars;
// An outgoing edge to a referent node.
class Edge {
@@ -863,7 +863,8 @@
// false as the wantNames parameter.
//
// The storage is owned by this Edge, and will be freed when this Edge is
- // destructed.
+ // destructed. You may take ownership of the name by `mozilla::Move`ing it
+ // out of the edge; it is just a UniquePtr.
//
// (In real life we'll want a better representation for names, to avoid
// creating tons of strings when the names follow a pattern; and we'll need
@@ -959,7 +960,7 @@
//
// {
// mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC;
-// JS::ubi::RootList rootList(rt, maybeNoGC);
+// JS::ubi::RootList rootList(cx, maybeNoGC);
// if (!rootList.init())
// return false;
//
@@ -970,22 +971,23 @@
//
// ...
// }
-class MOZ_STACK_CLASS RootList {
+class MOZ_STACK_CLASS JS_PUBLIC_API(RootList) {
Maybe<AutoCheckCannotGC>& noGC;
public:
- JSRuntime* rt;
+ JSContext* cx;
EdgeVector edges;
bool wantNames;
- RootList(JSRuntime* rt, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
+ RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
// Find all GC roots.
- bool init();
- // Find only GC roots in the provided set of |Zone|s.
- bool init(ZoneSet& debuggees);
- // Find only GC roots in the given Debugger object's set of debuggee zones.
- bool init(HandleObject debuggees);
+ MOZ_MUST_USE bool init();
+ // Find only GC roots in the provided set of |JSCompartment|s.
+ MOZ_MUST_USE bool init(CompartmentSet& debuggees);
+ // Find only GC roots in the given Debugger object's set of debuggee
+ // compartments.
+ MOZ_MUST_USE bool init(HandleObject debuggees);
// Returns true if the RootList has been initialized successfully, false
// otherwise.
@@ -994,64 +996,53 @@
// Explicitly add the given Node as a root in this RootList. If wantNames is
// true, you must pass an edgeName. The RootList does not take ownership of
// edgeName.
- bool addRoot(Node node, const char16_t* edgeName = nullptr);
+ MOZ_MUST_USE bool addRoot(Node node, const char16_t* edgeName = nullptr);
};
/*** Concrete classes for ubi::Node referent types ************************************************/
template<>
-struct Concrete<RootList> : public Base {
- UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
- const char16_t* typeName() const override { return concreteTypeName; }
-
+class JS_PUBLIC_API(Concrete<RootList>) : public Base {
protected:
explicit Concrete(RootList* ptr) : Base(ptr) { }
RootList& get() const { return *static_cast<RootList*>(ptr); }
public:
- static const char16_t concreteTypeName[];
static void construct(void* storage, RootList* ptr) { new (storage) Concrete(ptr); }
+
+ js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
+
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
};
// A reusable ubi::Concrete specialization base class for types supported by
// JS::TraceChildren.
template<typename Referent>
-class TracerConcrete : public Base {
- const char16_t* typeName() const override { return concreteTypeName; }
- UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
+class JS_PUBLIC_API(TracerConcrete) : public Base {
+ js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
JS::Zone* zone() const override;
protected:
explicit TracerConcrete(Referent* ptr) : Base(ptr) { }
Referent& get() const { return *static_cast<Referent*>(ptr); }
-
- public:
- static const char16_t concreteTypeName[];
- static void construct(void* storage, Referent* ptr) { new (storage) TracerConcrete(ptr); }
};
// For JS::TraceChildren-based types that have a 'compartment' method.
template<typename Referent>
-class TracerConcreteWithCompartment : public TracerConcrete<Referent> {
+class JS_PUBLIC_API(TracerConcreteWithCompartment) : public TracerConcrete<Referent> {
typedef TracerConcrete<Referent> TracerBase;
JSCompartment* compartment() const override;
protected:
explicit TracerConcreteWithCompartment(Referent* ptr) : TracerBase(ptr) { }
-
- public:
- static void construct(void* storage, Referent* ptr) {
- new (storage) TracerConcreteWithCompartment(ptr);
- }
};
// Define specializations for some commonly-used public JSAPI types.
// These can use the generic templates above.
template<>
-struct Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> {
- Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
-
+class JS_PUBLIC_API(Concrete<JS::Symbol>) : TracerConcrete<JS::Symbol> {
protected:
explicit Concrete(JS::Symbol* ptr) : TracerConcrete(ptr) { }
@@ -1059,33 +1050,32 @@
static void construct(void* storage, JS::Symbol* ptr) {
new (storage) Concrete(ptr);
}
-};
-template<> struct Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> {
- CoarseType coarseType() const final { return CoarseType::Script; }
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
- const char* scriptFilename() const final;
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
+};
+
+template<>
+class JS_PUBLIC_API(Concrete<JSScript>) : TracerConcreteWithCompartment<JSScript> {
protected:
explicit Concrete(JSScript *ptr) : TracerConcreteWithCompartment<JSScript>(ptr) { }
public:
static void construct(void *storage, JSScript *ptr) { new (storage) Concrete(ptr); }
-};
-// The JSObject specialization.
-template<>
-class Concrete<JSObject> : public TracerConcreteWithCompartment<JSObject> {
- const char* jsObjectClassName() const override;
- bool jsObjectConstructorName(JSContext* cx,
- UniquePtr<char16_t[], JS::FreePolicy>& outName) const override;
+ CoarseType coarseType() const final { return CoarseType::Script; }
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
+ const char* scriptFilename() const final;
- bool hasAllocationStack() const override;
- StackFrame allocationStack() const override;
-
- CoarseType coarseType() const final { return CoarseType::Object; }
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
+};
+// The JSObject specialization.
+template<>
+class JS_PUBLIC_API(Concrete<JSObject>) : public TracerConcreteWithCompartment<JSObject> {
protected:
explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { }
@@ -1093,27 +1083,44 @@
static void construct(void* storage, JSObject* ptr) {
new (storage) Concrete(ptr);
}
-};
-// For JSString, we extend the generic template with a 'size' implementation.
-template<> struct Concrete<JSString> : TracerConcrete<JSString> {
+ const char* jsObjectClassName() const override;
+ MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& outName)
+ const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
- CoarseType coarseType() const final { return CoarseType::String; }
+ bool hasAllocationStack() const override;
+ StackFrame allocationStack() const override;
+
+ CoarseType coarseType() const final { return CoarseType::Object; }
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
+};
+
+// For JSString, we extend the generic template with a 'size' implementation.
+template<>
+class JS_PUBLIC_API(Concrete<JSString>) : TracerConcrete<JSString> {
protected:
explicit Concrete(JSString *ptr) : TracerConcrete<JSString>(ptr) { }
public:
static void construct(void *storage, JSString *ptr) { new (storage) Concrete(ptr); }
+
+ Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
+
+ CoarseType coarseType() const final { return CoarseType::String; }
+
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
};
// The ubi::Node null pointer. Any attempt to operate on a null ubi::Node asserts.
template<>
-class Concrete<void> : public Base {
+class JS_PUBLIC_API(Concrete<void>) : public Base {
const char16_t* typeName() const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
- UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
+ js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
JS::Zone* zone() const override;
JSCompartment* compartment() const override;
CoarseType coarseType() const final;
@@ -1122,7 +1129,6 @@
public:
static void construct(void* storage, void* ptr) { new (storage) Concrete(ptr); }
- static const char16_t concreteTypeName[];
};
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeBreadthFirst.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeBreadthFirst.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeBreadthFirst.h
@@ -83,8 +83,8 @@
//
// We do nothing with noGC, other than require it to exist, with a lifetime
// that encloses our own.
- BreadthFirst(JSRuntime* rt, Handler& handler, const JS::AutoCheckCannotGC& noGC)
- : wantNames(true), rt(rt), visited(), handler(handler), pending(),
+ BreadthFirst(JSContext* cx, Handler& handler, const JS::AutoCheckCannotGC& noGC)
+ : wantNames(true), cx(cx), visited(), handler(handler), pending(),
traversalBegun(false), stopRequested(false), abandonRequested(false)
{ }
@@ -126,7 +126,7 @@
pending.popFront();
// Get a range containing all origin's outgoing edges.
- auto range = origin.edges(rt, wantNames);
+ auto range = origin.edges(cx, wantNames);
if (!range)
return false;
@@ -134,7 +134,7 @@
for (; !range->empty(); range->popFront()) {
MOZ_ASSERT(!stopRequested);
- const Edge& edge = range->front();
+ Edge& edge = range->front();
typename NodeMap::AddPtr a = visited.lookupForAdd(edge.referent);
bool first = !a;
@@ -181,8 +181,8 @@
// Other edges *to* that referent will still be traversed.
void abandonReferent() { abandonRequested = true; }
- // The runtime with which we were constructed.
- JSRuntime* rt;
+ // The context with which we were constructed.
+ JSContext* cx;
// A map associating each node N that we have reached with a
// Handler::NodeData, for |handler|'s use. This is public, so that
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeCensus.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeCensus.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeCensus.h
@@ -7,8 +7,11 @@
#ifndef js_UbiNodeCensus_h
#define js_UbiNodeCensus_h
+#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
+#include <algorithm>
+
#include "jsapi.h"
#include "js/UbiNode.h"
@@ -80,14 +83,14 @@
class CountBase;
struct CountDeleter {
- void operator()(CountBase*);
+ JS_PUBLIC_API(void) operator()(CountBase*);
};
-using CountBasePtr = UniquePtr<CountBase, CountDeleter>;
+using CountBasePtr = js::UniquePtr<CountBase, CountDeleter>;
// Abstract base class for CountType nodes.
struct CountType {
- explicit CountType(Census& census) : census(census) { }
+ explicit CountType() { }
virtual ~CountType() { }
// Destruct a count tree node that this type instance constructed.
@@ -102,17 +105,17 @@
// Implement the 'count' method for counts returned by this CountType
// instance's 'newCount' method.
- virtual bool count(CountBase& count, const Node& node) = 0;
+ virtual MOZ_MUST_USE bool count(CountBase& count,
+ mozilla::MallocSizeOf mallocSizeOf,
+ const Node& node) = 0;
// Implement the 'report' method for counts returned by this CountType
// instance's 'newCount' method.
- virtual bool report(CountBase& count, MutableHandleValue report) = 0;
-
- protected:
- Census& census;
+ virtual MOZ_MUST_USE bool report(JSContext* cx, CountBase& count,
+ MutableHandleValue report) = 0;
};
-using CountTypePtr = UniquePtr<CountType, JS::DeletePolicy<CountType>>;
+using CountTypePtr = js::UniquePtr<CountType>;
// An abstract base class for count tree nodes.
class CountBase {
@@ -126,15 +129,39 @@
~CountBase() { }
public:
- explicit CountBase(CountType& type) : type(type), total_(0) { }
+ explicit CountBase(CountType& type)
+ : type(type)
+ , total_(0)
+ , smallestNodeIdCounted_(SIZE_MAX)
+ { }
// Categorize and count |node| as appropriate for this count's type.
- bool count(const Node& node) { return type.count(*this, node); }
+ MOZ_MUST_USE bool count(mozilla::MallocSizeOf mallocSizeOf, const Node& node) {
+ total_++;
+
+ auto id = node.identifier();
+ if (id < smallestNodeIdCounted_) {
+ smallestNodeIdCounted_ = id;
+ }
+
+#ifdef DEBUG
+ size_t oldTotal = total_;
+#endif
+
+ bool ret = type.count(*this, mallocSizeOf, node);
+
+ MOZ_ASSERT(total_ == oldTotal,
+ "CountType::count should not increment total_, CountBase::count handles that");
+
+ return ret;
+ }
// Construct a JavaScript object reporting the counts recorded in this
// count, and store it in |report|. Return true on success, or false on
// failure.
- bool report(MutableHandleValue report) { return type.report(*this, report); }
+ MOZ_MUST_USE bool report(JSContext* cx, MutableHandleValue report) {
+ return type.report(cx, *this, report);
+ }
// Down-cast this CountBase to its true type, based on its 'type' member,
// and run its destructor.
@@ -144,6 +171,10 @@
void trace(JSTracer* trc) { type.traceCount(*this, trc); }
size_t total_;
+
+ // The smallest JS::ubi::Node::identifier() passed to this instance's
+ // count() method. This provides a stable way to sort sets.
+ Node::Id smallestNodeIdCounted_;
};
class RootedCount : JS::CustomAutoRooter {
@@ -172,19 +203,7 @@
explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
- bool init();
-
- // A 'new' work-alike that behaves like TempAllocPolicy: report OOM on this
- // census's context, but don't charge the memory allocated to our context's
- // GC pressure counters.
- template<typename T, typename... Args>
- T* new_(Args&&... args) MOZ_HEAP_ALLOCATOR {
- void* memory = js_malloc(sizeof(T));
- if (MOZ_UNLIKELY(!memory)) {
- return nullptr;
- }
- return new(memory) T(mozilla::Forward<Args>(args)...);
- }
+ MOZ_MUST_USE JS_PUBLIC_API(bool) init();
};
// A BreadthFirst handler type that conducts a census, using a CountBase to
@@ -192,31 +211,40 @@
class CensusHandler {
Census& census;
CountBasePtr& rootCount;
+ mozilla::MallocSizeOf mallocSizeOf;
public:
- CensusHandler(Census& census, CountBasePtr& rootCount)
+ CensusHandler(Census& census, CountBasePtr& rootCount, mozilla::MallocSizeOf mallocSizeOf)
: census(census),
- rootCount(rootCount)
+ rootCount(rootCount),
+ mallocSizeOf(mallocSizeOf)
{ }
- bool report(MutableHandleValue report) {
- return rootCount->report(report);
+ MOZ_MUST_USE bool report(JSContext* cx, MutableHandleValue report) {
+ return rootCount->report(cx, report);
}
// This class needs to retain no per-node data.
class NodeData { };
- bool operator() (BreadthFirst<CensusHandler>& traversal,
- Node origin, const Edge& edge,
- NodeData* referentData, bool first);
+ MOZ_MUST_USE JS_PUBLIC_API(bool) operator() (BreadthFirst<CensusHandler>& traversal,
+ Node origin, const Edge& edge,
+ NodeData* referentData, bool first);
};
using CensusTraversal = BreadthFirst<CensusHandler>;
-// Examine the census options supplied by the API consumer, and use that to
-// build a CountType tree.
-bool ParseCensusOptions(JSContext* cx, Census& census, HandleObject options,
- CountTypePtr& outResult);
+// Examine the census options supplied by the API consumer, and (among other
+// things) use that to build a CountType tree.
+MOZ_MUST_USE JS_PUBLIC_API(bool) ParseCensusOptions(JSContext* cx,
+ Census& census, HandleObject options,
+ CountTypePtr& outResult);
+
+// Parse the breakdown language (as described in
+// js/src/doc/Debugger/Debugger.Memory.md) into a CountTypePtr. A null pointer
+// is returned on error and is reported to the cx.
+JS_PUBLIC_API(CountTypePtr) ParseBreakdown(JSContext* cx, HandleValue breakdownValue);
+
} // namespace ubi
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeDominatorTree.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeDominatorTree.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeDominatorTree.h
@@ -7,6 +7,7 @@
#ifndef js_UbiNodeDominatorTree_h
#define js_UbiNodeDominatorTree_h
+#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Maybe.h"
#include "mozilla/Move.h"
@@ -71,8 +72,6 @@
private:
// Types.
- using NodeSet = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
- using NodeSetPtr = mozilla::UniquePtr<NodeSet, JS::DeletePolicy<NodeSet>>;
using PredecessorSets = js::HashMap<Node, NodeSetPtr, js::DefaultHasher<Node>,
js::SystemAllocPolicy>;
using NodeToIndexMap = js::HashMap<Node, uint32_t, js::DefaultHasher<Node>,
@@ -95,10 +94,10 @@
{
friend class DominatedSetRange;
- const mozilla::Vector<Node>& postOrder;
+ const JS::ubi::Vector<Node>& postOrder;
const uint32_t* ptr;
- DominatedNodePtr(const mozilla::Vector<Node>& postOrder, const uint32_t* ptr)
+ DominatedNodePtr(const JS::ubi::Vector<Node>& postOrder, const uint32_t* ptr)
: postOrder(postOrder)
, ptr(ptr)
{ }
@@ -119,11 +118,11 @@
{
friend class DominatedSets;
- const mozilla::Vector<Node>& postOrder;
+ const JS::ubi::Vector<Node>& postOrder;
const uint32_t* beginPtr;
const uint32_t* endPtr;
- DominatedSetRange(mozilla::Vector<Node>& postOrder, const uint32_t* begin, const uint32_t* end)
+ DominatedSetRange(JS::ubi::Vector<Node>& postOrder, const uint32_t* begin, const uint32_t* end)
: postOrder(postOrder)
, beginPtr(begin)
, endPtr(end)
@@ -180,10 +179,10 @@
*/
class DominatedSets
{
- mozilla::Vector<uint32_t> dominated;
- mozilla::Vector<uint32_t> indices;
+ JS::ubi::Vector<uint32_t> dominated;
+ JS::ubi::Vector<uint32_t> indices;
- DominatedSets(mozilla::Vector<uint32_t>&& dominated, mozilla::Vector<uint32_t>&& indices)
+ DominatedSets(JS::ubi::Vector<uint32_t>&& dominated, JS::ubi::Vector<uint32_t>&& indices)
: dominated(mozilla::Move(dominated))
, indices(mozilla::Move(indices))
{ }
@@ -211,7 +210,7 @@
* immediate dominator. Returns `Some` on success, `Nothing` on OOM
* failure.
*/
- static mozilla::Maybe<DominatedSets> Create(const mozilla::Vector<uint32_t>& doms) {
+ static mozilla::Maybe<DominatedSets> Create(const JS::ubi::Vector<uint32_t>& doms) {
auto length = doms.length();
MOZ_ASSERT(length < UINT32_MAX);
@@ -236,8 +235,8 @@
// filled in. After having filled in all of a bucket's entries,
// the index points to the start of the bucket.
- mozilla::Vector<uint32_t> dominated;
- mozilla::Vector<uint32_t> indices;
+ JS::ubi::Vector<uint32_t> dominated;
+ JS::ubi::Vector<uint32_t> indices;
if (!dominated.growBy(length) || !indices.growBy(length))
return mozilla::Nothing();
@@ -279,7 +278,7 @@
* Get the set of nodes immediately dominated by the node at
* `postOrder[nodeIndex]`.
*/
- DominatedSetRange dominatedSet(mozilla::Vector<Node>& postOrder, uint32_t nodeIndex) const {
+ DominatedSetRange dominatedSet(JS::ubi::Vector<Node>& postOrder, uint32_t nodeIndex) const {
MOZ_ASSERT(postOrder.length() == indices.length());
MOZ_ASSERT(nodeIndex < indices.length());
auto end = nodeIndex == indices.length() - 1
@@ -291,11 +290,11 @@
private:
// Data members.
- mozilla::Vector<Node> postOrder;
+ JS::ubi::Vector<Node> postOrder;
NodeToIndexMap nodeToPostOrderIndex;
- mozilla::Vector<uint32_t> doms;
+ JS::ubi::Vector<uint32_t> doms;
DominatedSets dominatedSets;
- mozilla::Maybe<mozilla::Vector<JS::ubi::Node::Size>> retainedSizes;
+ mozilla::Maybe<JS::ubi::Vector<JS::ubi::Node::Size>> retainedSizes;
private:
// We use `UNDEFINED` as a sentinel value in the `doms` vector to signal
@@ -303,8 +302,8 @@
// index in `postOrder` yet.
static const uint32_t UNDEFINED = UINT32_MAX;
- DominatorTree(mozilla::Vector<Node>&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex,
- mozilla::Vector<uint32_t>&& doms, DominatedSets&& dominatedSets)
+ DominatorTree(JS::ubi::Vector<Node>&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex,
+ JS::ubi::Vector<uint32_t>&& doms, DominatedSets&& dominatedSets)
: postOrder(mozilla::Move(postOrder))
, nodeToPostOrderIndex(mozilla::Move(nodeToPostOrderIndex))
, doms(mozilla::Move(doms))
@@ -312,7 +311,7 @@
, retainedSizes(mozilla::Nothing())
{ }
- static uint32_t intersect(mozilla::Vector<uint32_t>& doms, uint32_t finger1, uint32_t finger2) {
+ static uint32_t intersect(JS::ubi::Vector<uint32_t>& doms, uint32_t finger1, uint32_t finger2) {
while (finger1 != finger2) {
if (finger1 < finger2)
finger1 = doms[finger1];
@@ -324,8 +323,9 @@
// Do the post order traversal of the heap graph and populate our
// predecessor sets.
- static bool doTraversal(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root,
- mozilla::Vector<Node>& postOrder, PredecessorSets& predecessorSets) {
+ static MOZ_MUST_USE bool doTraversal(JSContext* cx, AutoCheckCannotGC& noGC, const Node& root,
+ JS::ubi::Vector<Node>& postOrder,
+ PredecessorSets& predecessorSets) {
uint32_t nodeCount = 0;
auto onNode = [&](const Node& node) {
nodeCount++;
@@ -349,7 +349,7 @@
return p->value()->put(origin);
};
- PostOrder traversal(rt, noGC);
+ PostOrder traversal(cx, noGC);
return traversal.init() &&
traversal.addStart(root) &&
traversal.traverse(onNode, onEdge);
@@ -357,7 +357,8 @@
// Populates the given `map` with an entry for each node to its index in
// `postOrder`.
- static bool mapNodesToTheirIndices(mozilla::Vector<Node>& postOrder, NodeToIndexMap& map) {
+ static MOZ_MUST_USE bool mapNodesToTheirIndices(JS::ubi::Vector<Node>& postOrder,
+ NodeToIndexMap& map) {
MOZ_ASSERT(!map.initialized());
MOZ_ASSERT(postOrder.length() < UINT32_MAX);
uint32_t length = postOrder.length();
@@ -370,12 +371,12 @@
// Convert the Node -> NodeSet predecessorSets to a index -> Vector<index>
// form.
- static bool convertPredecessorSetsToVectors(
+ static MOZ_MUST_USE bool convertPredecessorSetsToVectors(
const Node& root,
- mozilla::Vector<Node>& postOrder,
+ JS::ubi::Vector<Node>& postOrder,
PredecessorSets& predecessorSets,
NodeToIndexMap& nodeToPostOrderIndex,
- mozilla::Vector<mozilla::Vector<uint32_t>>& predecessorVectors)
+ JS::ubi::Vector<JS::ubi::Vector<uint32_t>>& predecessorVectors)
{
MOZ_ASSERT(postOrder.length() < UINT32_MAX);
uint32_t length = postOrder.length();
@@ -409,7 +410,8 @@
// Initialize `doms` such that the immediate dominator of the `root` is the
// `root` itself and all others are `UNDEFINED`.
- static bool initializeDominators(mozilla::Vector<uint32_t>& doms, uint32_t length) {
+ static MOZ_MUST_USE bool initializeDominators(JS::ubi::Vector<uint32_t>& doms,
+ uint32_t length) {
MOZ_ASSERT(doms.length() == 0);
if (!doms.growByUninitialized(length))
return false;
@@ -425,7 +427,7 @@
MOZ_ASSERT_IF(retainedSizes.isSome(), postOrder.length() == retainedSizes->length());
}
- bool computeRetainedSizes(mozilla::MallocSizeOf mallocSizeOf) {
+ MOZ_MUST_USE bool computeRetainedSizes(mozilla::MallocSizeOf mallocSizeOf) {
MOZ_ASSERT(retainedSizes.isNothing());
auto length = postOrder.length();
@@ -511,10 +513,10 @@
* responsibility to handle and report the OOM.
*/
static mozilla::Maybe<DominatorTree>
- Create(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root) {
- mozilla::Vector<Node> postOrder;
+ Create(JSContext* cx, AutoCheckCannotGC& noGC, const Node& root) {
+ JS::ubi::Vector<Node> postOrder;
PredecessorSets predecessorSets;
- if (!predecessorSets.init() || !doTraversal(rt, noGC, root, postOrder, predecessorSets))
+ if (!predecessorSets.init() || !doTraversal(cx, noGC, root, postOrder, predecessorSets))
return mozilla::Nothing();
MOZ_ASSERT(postOrder.length() < UINT32_MAX);
@@ -531,12 +533,12 @@
if (!mapNodesToTheirIndices(postOrder, nodeToPostOrderIndex))
return mozilla::Nothing();
- mozilla::Vector<mozilla::Vector<uint32_t>> predecessorVectors;
+ JS::ubi::Vector<JS::ubi::Vector<uint32_t>> predecessorVectors;
if (!convertPredecessorSetsToVectors(root, postOrder, predecessorSets, nodeToPostOrderIndex,
predecessorVectors))
return mozilla::Nothing();
- mozilla::Vector<uint32_t> doms;
+ JS::ubi::Vector<uint32_t> doms;
if (!initializeDominators(doms, length))
return mozilla::Nothing();
@@ -650,8 +652,8 @@
* `outSize`, or 0 if `node` is not a member of the dominator tree. Returns
* false on OOM failure, leaving `outSize` unchanged.
*/
- bool getRetainedSize(const Node& node, mozilla::MallocSizeOf mallocSizeOf,
- Node::Size& outSize) {
+ MOZ_MUST_USE bool getRetainedSize(const Node& node, mozilla::MallocSizeOf mallocSizeOf,
+ Node::Size& outSize) {
assertSanity();
auto ptr = nodeToPostOrderIndex.lookup(node);
if (!ptr) {
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodePostOrder.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodePostOrder.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodePostOrder.h
@@ -7,7 +7,7 @@
#ifndef js_UbiNodePostOrder_h
#define js_UbiNodePostOrder_h
-#include "mozilla/DebugOnly.h"
+#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/Move.h"
@@ -83,13 +83,15 @@
using Stack = js::Vector<OriginAndEdges, 256, js::SystemAllocPolicy>;
using Set = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
- JSRuntime* rt;
+ JSContext* cx;
Set seen;
Stack stack;
- mozilla::DebugOnly<bool> traversed;
+#ifdef DEBUG
+ bool traversed;
+#endif
private:
- bool fillEdgesFromRange(EdgeVector& edges, UniquePtr<EdgeRange>& range) {
+ MOZ_MUST_USE bool fillEdgesFromRange(EdgeVector& edges, js::UniquePtr<EdgeRange>& range) {
MOZ_ASSERT(range);
for ( ; !range->empty(); range->popFront()) {
if (!edges.append(mozilla::Move(range->front())))
@@ -98,9 +100,9 @@
return true;
}
- bool pushForTraversing(const Node& node) {
+ MOZ_MUST_USE bool pushForTraversing(const Node& node) {
EdgeVector edges;
- auto range = node.edges(rt, /* wantNames */ false);
+ auto range = node.edges(cx, /* wantNames */ false);
return range &&
fillEdgesFromRange(edges, range) &&
stack.append(OriginAndEdges(node, mozilla::Move(edges)));
@@ -113,19 +115,21 @@
// The traversal asserts that no GC happens in its runtime during its
// lifetime via the `AutoCheckCannotGC&` parameter. We do nothing with it,
// other than require it to exist with a lifetime that encloses our own.
- PostOrder(JSRuntime* rt, AutoCheckCannotGC&)
- : rt(rt)
+ PostOrder(JSContext* cx, AutoCheckCannotGC&)
+ : cx(cx)
, seen()
, stack()
+#ifdef DEBUG
, traversed(false)
+#endif
{ }
// Initialize this traversal object. Return false on OOM.
- bool init() { return seen.init(); }
+ MOZ_MUST_USE bool init() { return seen.init(); }
// Add `node` as a starting point for the traversal. You may add
// as many starting points as you like. Returns false on OOM.
- bool addStart(const Node& node) {
+ MOZ_MUST_USE bool addStart(const Node& node) {
if (!seen.put(node))
return false;
return pushForTraversing(node);
@@ -141,9 +145,11 @@
// Return false on OOM or error return from `onNode::operator()` or
// `onEdge::operator()`.
template<typename NodeVisitor, typename EdgeVisitor>
- bool traverse(NodeVisitor onNode, EdgeVisitor onEdge) {
+ MOZ_MUST_USE bool traverse(NodeVisitor onNode, EdgeVisitor onEdge) {
+#ifdef DEBUG
MOZ_ASSERT(!traversed, "Can only traverse() once!");
traversed = true;
+#endif
while (!stack.empty()) {
auto& origin = stack.back().origin;
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeShortestPaths.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeShortestPaths.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UbiNodeShortestPaths.h
@@ -0,0 +1,350 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_UbiNodeShortestPaths_h
+#define js_UbiNodeShortestPaths_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Move.h"
+
+#include "jsalloc.h"
+
+#include "js/UbiNodeBreadthFirst.h"
+#include "js/Vector.h"
+
+namespace JS {
+namespace ubi {
+
+/**
+ * A back edge along a path in the heap graph.
+ */
+struct JS_PUBLIC_API(BackEdge)
+{
+ private:
+ Node predecessor_;
+ EdgeName name_;
+
+ public:
+ using Ptr = mozilla::UniquePtr<BackEdge, JS::DeletePolicy<BackEdge>>;
+
+ BackEdge() : predecessor_(), name_(nullptr) { }
+
+ MOZ_MUST_USE bool init(const Node& predecessor, Edge& edge) {
+ MOZ_ASSERT(!predecessor_);
+ MOZ_ASSERT(!name_);
+
+ predecessor_ = predecessor;
+ name_ = mozilla::Move(edge.name);
+ return true;
+ }
+
+ BackEdge(const BackEdge&) = delete;
+ BackEdge& operator=(const BackEdge&) = delete;
+
+ BackEdge(BackEdge&& rhs)
+ : predecessor_(rhs.predecessor_)
+ , name_(mozilla::Move(rhs.name_))
+ {
+ MOZ_ASSERT(&rhs != this);
+ }
+
+ BackEdge& operator=(BackEdge&& rhs) {
+ this->~BackEdge();
+ new(this) BackEdge(Move(rhs));
+ return *this;
+ }
+
+ Ptr clone() const;
+
+ const EdgeName& name() const { return name_; }
+ EdgeName& name() { return name_; }
+
+ const JS::ubi::Node& predecessor() const { return predecessor_; }
+};
+
+/**
+ * A path is a series of back edges from which we discovered a target node.
+ */
+using Path = JS::ubi::Vector<BackEdge*>;
+
+/**
+ * The `JS::ubi::ShortestPaths` type represents a collection of up to N shortest
+ * retaining paths for each of a target set of nodes, starting from the same
+ * root node.
+ */
+struct JS_PUBLIC_API(ShortestPaths)
+{
+ private:
+ // Types, type aliases, and data members.
+
+ using BackEdgeVector = JS::ubi::Vector<BackEdge::Ptr>;
+ using NodeToBackEdgeVectorMap = js::HashMap<Node, BackEdgeVector, js::DefaultHasher<Node>,
+ js::SystemAllocPolicy>;
+
+ struct Handler;
+ using Traversal = BreadthFirst<Handler>;
+
+ /**
+ * A `JS::ubi::BreadthFirst` traversal handler that records back edges for
+ * how we reached each node, allowing us to reconstruct the shortest
+ * retaining paths after the traversal.
+ */
+ struct Handler
+ {
+ using NodeData = BackEdge;
+
+ ShortestPaths& shortestPaths;
+ size_t totalMaxPathsToRecord;
+ size_t totalPathsRecorded;
+
+ explicit Handler(ShortestPaths& shortestPaths)
+ : shortestPaths(shortestPaths)
+ , totalMaxPathsToRecord(shortestPaths.targets_.count() * shortestPaths.maxNumPaths_)
+ , totalPathsRecorded(0)
+ {
+ }
+
+ bool
+ operator()(Traversal& traversal, JS::ubi::Node origin, JS::ubi::Edge& edge,
+ BackEdge* back, bool first)
+ {
+ MOZ_ASSERT(back);
+ MOZ_ASSERT(origin == shortestPaths.root_ || traversal.visited.has(origin));
+ MOZ_ASSERT(totalPathsRecorded < totalMaxPathsToRecord);
+
+ if (first && !back->init(origin, edge))
+ return false;
+
+ if (!shortestPaths.targets_.has(edge.referent))
+ return true;
+
+ // If `first` is true, then we moved the edge's name into `back` in
+ // the above call to `init`. So clone that back edge to get the
+ // correct edge name. If `first` is not true, then our edge name is
+ // still in `edge`. This accounts for the asymmetry between
+ // `back->clone()` in the first branch, and the `init` call in the
+ // second branch.
+
+ if (first) {
+ BackEdgeVector paths;
+ if (!paths.reserve(shortestPaths.maxNumPaths_))
+ return false;
+ auto cloned = back->clone();
+ if (!cloned)
+ return false;
+ paths.infallibleAppend(mozilla::Move(cloned));
+ if (!shortestPaths.paths_.putNew(edge.referent, mozilla::Move(paths)))
+ return false;
+ totalPathsRecorded++;
+ } else {
+ auto ptr = shortestPaths.paths_.lookup(edge.referent);
+ MOZ_ASSERT(ptr,
+ "This isn't the first time we have seen the target node `edge.referent`. "
+ "We should have inserted it into shortestPaths.paths_ the first time we "
+ "saw it.");
+
+ if (ptr->value().length() < shortestPaths.maxNumPaths_) {
+ BackEdge::Ptr thisBackEdge(js_new<BackEdge>());
+ if (!thisBackEdge || !thisBackEdge->init(origin, edge))
+ return false;
+ ptr->value().infallibleAppend(mozilla::Move(thisBackEdge));
+ totalPathsRecorded++;
+ }
+ }
+
+ MOZ_ASSERT(totalPathsRecorded <= totalMaxPathsToRecord);
+ if (totalPathsRecorded == totalMaxPathsToRecord)
+ traversal.stop();
+
+ return true;
+ }
+
+ };
+
+ // The maximum number of paths to record for each node.
+ uint32_t maxNumPaths_;
+
+ // The root node we are starting the search from.
+ Node root_;
+
+ // The set of nodes we are searching for paths to.
+ NodeSet targets_;
+
+ // The resulting paths.
+ NodeToBackEdgeVectorMap paths_;
+
+ // Need to keep alive the traversal's back edges so we can walk them later
+ // when the traversal is over when recreating the shortest paths.
+ Traversal::NodeMap backEdges_;
+
+ private:
+ // Private methods.
+
+ ShortestPaths(uint32_t maxNumPaths, const Node& root, NodeSet&& targets)
+ : maxNumPaths_(maxNumPaths)
+ , root_(root)
+ , targets_(mozilla::Move(targets))
+ , paths_()
+ , backEdges_()
+ {
+ MOZ_ASSERT(maxNumPaths_ > 0);
+ MOZ_ASSERT(root_);
+ MOZ_ASSERT(targets_.initialized());
+ }
+
+ bool initialized() const {
+ return targets_.initialized() &&
+ paths_.initialized() &&
+ backEdges_.initialized();
+ }
+
+ public:
+ // Public methods.
+
+ ShortestPaths(ShortestPaths&& rhs)
+ : maxNumPaths_(rhs.maxNumPaths_)
+ , root_(rhs.root_)
+ , targets_(mozilla::Move(rhs.targets_))
+ , paths_(mozilla::Move(rhs.paths_))
+ , backEdges_(mozilla::Move(rhs.backEdges_))
+ {
+ MOZ_ASSERT(this != &rhs, "self-move is not allowed");
+ }
+
+ ShortestPaths& operator=(ShortestPaths&& rhs) {
+ this->~ShortestPaths();
+ new (this) ShortestPaths(mozilla::Move(rhs));
+ return *this;
+ }
+
+ ShortestPaths(const ShortestPaths&) = delete;
+ ShortestPaths& operator=(const ShortestPaths&) = delete;
+
+ /**
+ * Construct a new `JS::ubi::ShortestPaths`, finding up to `maxNumPaths`
+ * shortest retaining paths for each target node in `targets` starting from
+ * `root`.
+ *
+ * The resulting `ShortestPaths` instance must not outlive the
+ * `JS::ubi::Node` graph it was constructed from.
+ *
+ * - For `JS::ubi::Node` graphs backed by the live heap graph, this means
+ * that the `ShortestPaths`'s lifetime _must_ be contained within the
+ * scope of the provided `AutoCheckCannotGC` reference because a GC will
+ * invalidate the nodes.
+ *
+ * - For `JS::ubi::Node` graphs backed by some other offline structure
+ * provided by the embedder, the resulting `ShortestPaths`'s lifetime is
+ * bounded by that offline structure's lifetime.
+ *
+ * Returns `mozilla::Nothing()` on OOM failure. It is the caller's
+ * responsibility to handle and report the OOM.
+ */
+ static mozilla::Maybe<ShortestPaths>
+ Create(JSContext* cx, AutoCheckCannotGC& noGC, uint32_t maxNumPaths, const Node& root, NodeSet&& targets) {
+ MOZ_ASSERT(targets.count() > 0);
+ MOZ_ASSERT(maxNumPaths > 0);
+
+ size_t count = targets.count();
+ ShortestPaths paths(maxNumPaths, root, mozilla::Move(targets));
+ if (!paths.paths_.init(count))
+ return mozilla::Nothing();
+
+ Handler handler(paths);
+ Traversal traversal(cx, handler, noGC);
+ traversal.wantNames = true;
+ if (!traversal.init() || !traversal.addStart(root) || !traversal.traverse())
+ return mozilla::Nothing();
+
+ // Take ownership of the back edges we created while traversing the
+ // graph so that we can follow them from `paths_` and don't
+ // use-after-free.
+ paths.backEdges_ = mozilla::Move(traversal.visited);
+
+ MOZ_ASSERT(paths.initialized());
+ return mozilla::Some(mozilla::Move(paths));
+ }
+
+ /**
+ * Get a range that iterates over each target node we searched for retaining
+ * paths for. The returned range must not outlive the `ShortestPaths`
+ * instance.
+ */
+ NodeSet::Range eachTarget() const {
+ MOZ_ASSERT(initialized());
+ return targets_.all();
+ }
+
+ /**
+ * Invoke the provided functor/lambda/callable once for each retaining path
+ * discovered for `target`. The `func` is passed a single `JS::ubi::Path&`
+ * argument, which contains each edge along the path ordered starting from
+ * the root and ending at the target, and must not outlive the scope of the
+ * call.
+ *
+ * Note that it is possible that we did not find any paths from the root to
+ * the given target, in which case `func` will not be invoked.
+ */
+ template <class Func>
+ MOZ_MUST_USE bool forEachPath(const Node& target, Func func) {
+ MOZ_ASSERT(initialized());
+ MOZ_ASSERT(targets_.has(target));
+
+ auto ptr = paths_.lookup(target);
+
+ // We didn't find any paths to this target, so nothing to do here.
+ if (!ptr)
+ return true;
+
+ MOZ_ASSERT(ptr->value().length() <= maxNumPaths_);
+
+ Path path;
+ for (const auto& backEdge : ptr->value()) {
+ path.clear();
+
+ if (!path.append(backEdge.get()))
+ return false;
+
+ Node here = backEdge->predecessor();
+ MOZ_ASSERT(here);
+
+ while (here != root_) {
+ auto p = backEdges_.lookup(here);
+ MOZ_ASSERT(p);
+ if (!path.append(&p->value()))
+ return false;
+ here = p->value().predecessor();
+ MOZ_ASSERT(here);
+ }
+
+ path.reverse();
+
+ if (!func(path))
+ return false;
+ }
+
+ return true;
+ }
+};
+
+#ifdef DEBUG
+// A helper function to dump the first `maxNumPaths` shortest retaining paths to
+// `node` from the GC roots. Useful when GC things you expect to have been
+// reclaimed by the collector haven't been!
+//
+// Usage:
+//
+// JSObject* foo = ...;
+// JS::ubi::dumpPaths(rt, JS::ubi::Node(foo));
+JS_PUBLIC_API(void)
+dumpPaths(JSRuntime* rt, Node node, uint32_t maxNumPaths = 10);
+#endif
+
+} // namespace ubi
+} // namespace JS
+
+#endif // js_UbiNodeShortestPaths_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UniquePtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UniquePtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/UniquePtr.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_UniquePtr_h
+#define js_UniquePtr_h
+
+#include "mozilla/UniquePtr.h"
+
+#include "js/Utility.h"
+
+namespace js {
+
+// Replacement for mozilla::UniquePtr that defaults to js::DefaultDelete.
+template <typename T, typename D = JS::DeletePolicy<T>>
+using UniquePtr = mozilla::UniquePtr<T, D>;
+
+namespace detail {
+
+template<typename T>
+struct UniqueSelector
+{
+ typedef UniquePtr<T> SingleObject;
+};
+
+template<typename T>
+struct UniqueSelector<T[]>
+{
+ typedef UniquePtr<T[]> UnknownBound;
+};
+
+template<typename T, decltype(sizeof(int)) N>
+struct UniqueSelector<T[N]>
+{
+ typedef UniquePtr<T[N]> KnownBound;
+};
+
+} // namespace detail
+
+// Replacement for mozilla::MakeUnique that correctly calls js_new and produces
+// a js::UniquePtr.
+template<typename T, typename... Args>
+typename detail::UniqueSelector<T>::SingleObject
+MakeUnique(Args&&... aArgs)
+{
+ return UniquePtr<T>(js_new<T>(mozilla::Forward<Args>(aArgs)...));
+}
+
+template<typename T>
+typename detail::UniqueSelector<T>::UnknownBound
+MakeUnique(decltype(sizeof(int)) aN) = delete;
+
+template<typename T, typename... Args>
+typename detail::UniqueSelector<T>::KnownBound
+MakeUnique(Args&&... aArgs) = delete;
+
+} // namespace js
+
+#endif /* js_UniquePtr_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Utility.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Utility.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Utility.h
@@ -8,6 +8,7 @@
#define js_Utility_h
#include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/Compiler.h"
#include "mozilla/Move.h"
@@ -34,22 +35,6 @@
/* The private JS engine namespace. */
namespace js {}
-/*
- * Patterns used by SpiderMonkey to overwrite unused memory. If you are
- * accessing an object with one of these pattern, you probably have a dangling
- * pointer.
- */
-#define JS_FRESH_NURSERY_PATTERN 0x2F
-#define JS_SWEPT_NURSERY_PATTERN 0x2B
-#define JS_ALLOCATED_NURSERY_PATTERN 0x2D
-#define JS_FRESH_TENURED_PATTERN 0x4F
-#define JS_MOVED_TENURED_PATTERN 0x49
-#define JS_SWEPT_TENURED_PATTERN 0x4B
-#define JS_ALLOCATED_TENURED_PATTERN 0x4D
-#define JS_EMPTY_STOREBUFFER_PATTERN 0x1B
-#define JS_SWEPT_CODE_PATTERN 0x3B
-#define JS_SWEPT_FRAME_PATTERN 0x5B
-
#define JS_STATIC_ASSERT(cond) static_assert(cond, "JS_STATIC_ASSERT")
#define JS_STATIC_ASSERT_IF(cond, expr) MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
@@ -81,6 +66,7 @@
THREAD_TYPE_COMPRESS, // 5
THREAD_TYPE_GCHELPER, // 6
THREAD_TYPE_GCPARALLEL, // 7
+ THREAD_TYPE_PROMISE_TASK, // 8
THREAD_TYPE_MAX // Used to check shell function arguments
};
@@ -103,15 +89,6 @@
# if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
-/*
- * In order to test OOM conditions, when the testing function
- * oomAfterAllocations COUNT is passed, we fail continuously after the NUM'th
- * allocation from now.
- */
-extern JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations; /* set in builtin/TestingFunctions.cpp */
-extern JS_PUBLIC_DATA(uint32_t) OOM_counter; /* data race, who cares. */
-extern JS_PUBLIC_DATA(bool) OOM_failAlways;
-
#ifdef JS_OOM_BREAKPOINT
static MOZ_NEVER_INLINE void js_failedAllocBreakpoint() { asm(""); }
#define JS_OOM_CALL_BP_FUNC() js_failedAllocBreakpoint()
@@ -122,28 +99,42 @@
namespace js {
namespace oom {
+/*
+ * Out of memory testing support. We provide various testing functions to
+ * simulate OOM conditions and so we can test that they are handled correctly.
+ */
+
extern JS_PUBLIC_DATA(uint32_t) targetThread;
+extern JS_PUBLIC_DATA(uint64_t) maxAllocations;
+extern JS_PUBLIC_DATA(uint64_t) counter;
+extern JS_PUBLIC_DATA(bool) failAlways;
-static inline bool
+extern void
+SimulateOOMAfter(uint64_t allocations, uint32_t thread, bool always);
+
+extern void
+ResetSimulatedOOM();
+
+inline bool
IsThreadSimulatingOOM()
{
return js::oom::targetThread && js::oom::targetThread == js::oom::GetThreadType();
}
-static inline bool
+inline bool
IsSimulatedOOMAllocation()
{
- return IsThreadSimulatingOOM() && (OOM_counter == OOM_maxAllocations ||
- (OOM_counter > OOM_maxAllocations && OOM_failAlways));
+ return IsThreadSimulatingOOM() &&
+ (counter == maxAllocations || (counter > maxAllocations && failAlways));
}
-static inline bool
+inline bool
ShouldFailWithOOM()
{
if (!IsThreadSimulatingOOM())
return false;
- OOM_counter++;
+ counter++;
if (IsSimulatedOOMAllocation()) {
JS_OOM_CALL_BP_FUNC();
return true;
@@ -151,6 +142,11 @@
return false;
}
+inline bool
+HadSimulatedOOM() {
+ return counter >= maxAllocations;
+}
+
} /* namespace oom */
} /* namespace js */
@@ -182,32 +178,44 @@
namespace js {
/* Disable OOM testing in sections which are not OOM safe. */
-struct MOZ_RAII AutoEnterOOMUnsafeRegion
+struct MOZ_RAII JS_PUBLIC_DATA(AutoEnterOOMUnsafeRegion)
{
MOZ_NORETURN MOZ_COLD void crash(const char* reason);
+ MOZ_NORETURN MOZ_COLD void crash(size_t size, const char* reason);
+
+ using AnnotateOOMAllocationSizeCallback = void(*)(size_t);
+ static AnnotateOOMAllocationSizeCallback annotateOOMSizeCallback;
+ static void setAnnotateOOMAllocationSizeCallback(AnnotateOOMAllocationSizeCallback callback) {
+ annotateOOMSizeCallback = callback;
+ }
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
AutoEnterOOMUnsafeRegion()
- : oomEnabled_(oom::IsThreadSimulatingOOM() && OOM_maxAllocations != UINT32_MAX),
+ : oomEnabled_(oom::IsThreadSimulatingOOM() && oom::maxAllocations != UINT64_MAX),
oomAfter_(0)
{
if (oomEnabled_) {
- oomAfter_ = int64_t(OOM_maxAllocations) - OOM_counter;
- OOM_maxAllocations = UINT32_MAX;
+ MOZ_ALWAYS_TRUE(owner_.compareExchange(nullptr, this));
+ oomAfter_ = int64_t(oom::maxAllocations) - int64_t(oom::counter);
+ oom::maxAllocations = UINT64_MAX;
}
}
~AutoEnterOOMUnsafeRegion() {
if (oomEnabled_) {
- MOZ_ASSERT(OOM_maxAllocations == UINT32_MAX);
- int64_t maxAllocations = OOM_counter + oomAfter_;
- MOZ_ASSERT(maxAllocations >= 0 && maxAllocations < UINT32_MAX,
+ MOZ_ASSERT(oom::maxAllocations == UINT64_MAX);
+ int64_t maxAllocations = int64_t(oom::counter) + oomAfter_;
+ MOZ_ASSERT(maxAllocations >= 0,
"alloc count + oom limit exceeds range, your oom limit is probably too large");
- OOM_maxAllocations = uint32_t(maxAllocations);
+ oom::maxAllocations = uint64_t(maxAllocations);
+ MOZ_ALWAYS_TRUE(owner_.compareExchange(this, nullptr));
}
}
private:
+ // Used to catch concurrent use from other threads.
+ static mozilla::Atomic<AutoEnterOOMUnsafeRegion*> owner_;
+
bool oomEnabled_;
int64_t oomAfter_;
#endif
@@ -235,6 +243,11 @@
static inline void* js_realloc(void* p, size_t bytes)
{
+ // realloc() with zero size is not portable, as some implementations may
+ // return nullptr on success and free |p| for this. We assume nullptr
+ // indicates failure and that |p| is still valid.
+ MOZ_ASSERT(bytes != 0);
+
JS_OOM_POSSIBLY_FAIL();
return realloc(p, bytes);
}
@@ -302,14 +315,14 @@
* Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
* or the build will break.
*/
-#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
+#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS) \
template <class T, typename... Args> \
QUALIFIERS T * \
NEWNAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
void* memory = ALLOCATOR(sizeof(T)); \
- return memory \
- ? new(memory) T(mozilla::Forward<Args>(args)...) \
- : nullptr; \
+ return MOZ_LIKELY(memory) \
+ ? new(memory) T(mozilla::Forward<Args>(args)...) \
+ : nullptr; \
}
/*
@@ -339,7 +352,7 @@
* instances of type |T|. Return false if the calculation overflowed.
*/
template <typename T>
-MOZ_WARN_UNUSED_RESULT inline bool
+MOZ_MUST_USE inline bool
CalculateAllocSize(size_t numElems, size_t* bytesOut)
{
*bytesOut = numElems * sizeof(T);
@@ -352,7 +365,7 @@
* false if the calculation overflowed.
*/
template <typename T, typename Extra>
-MOZ_WARN_UNUSED_RESULT inline bool
+MOZ_MUST_USE inline bool
CalculateAllocSizeWithExtra(size_t numExtra, size_t* bytesOut)
{
*bytesOut = sizeof(T) + numExtra * sizeof(Extra);
@@ -460,6 +473,14 @@
template<typename T>
struct DeletePolicy
{
+ constexpr DeletePolicy() {}
+
+ template<typename U>
+ MOZ_IMPLICIT DeletePolicy(DeletePolicy<U> other,
+ typename mozilla::EnableIf<mozilla::IsConvertible<U*, T*>::value,
+ int>::Type dummy = 0)
+ {}
+
void operator()(const T* ptr) {
js_delete(const_cast<T*>(ptr));
}
@@ -472,6 +493,9 @@
}
};
+typedef mozilla::UniquePtr<char[], JS::FreePolicy> UniqueChars;
+typedef mozilla::UniquePtr<char16_t[], JS::FreePolicy> UniqueTwoByteChars;
+
} // namespace JS
namespace js {
@@ -480,13 +504,6 @@
typedef uint32_t HashNumber;
const unsigned HashNumberSizeBits = 32;
-typedef mozilla::UniquePtr<char, JS::FreePolicy> UniqueChars;
-
-static inline UniqueChars make_string_copy(const char* str)
-{
- return UniqueChars(js_strdup(str));
-}
-
namespace detail {
/*
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Value.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Value.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Value.h
@@ -10,6 +10,7 @@
#define js_Value_h
#include "mozilla/Attributes.h"
+#include "mozilla/Casting.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Likely.h"
@@ -29,34 +30,12 @@
#define JSVAL_INT_MIN ((int32_t)0x80000000)
#define JSVAL_INT_MAX ((int32_t)0x7fffffff)
-/*
- * Try to get jsvals 64-bit aligned. We could almost assert that all values are
- * aligned, but MSVC and GCC occasionally break alignment.
- */
-#if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__)
-# define JSVAL_ALIGNMENT __attribute__((aligned (8)))
-#elif defined(_MSC_VER)
- /*
- * Structs can be aligned with MSVC, but not if they are used as parameters,
- * so we just don't try to align.
- */
-# define JSVAL_ALIGNMENT
-#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-# define JSVAL_ALIGNMENT
-#elif defined(__HP_cc) || defined(__HP_aCC)
-# define JSVAL_ALIGNMENT
-#endif
-
#if defined(JS_PUNBOX64)
# define JSVAL_TAG_SHIFT 47
#endif
-/*
- * We try to use enums so that printing a jsval_layout in the debugger shows
- * nice symbolic type tags, however we can only do this when we can force the
- * underlying type of the enum to be the desired size.
- */
-#if !defined(__SUNPRO_CC) && !defined(__xlC__)
+// Use enums so that printing a JS::Value in the debugger shows nice
+// symbolic type tags.
#if defined(_MSC_VER)
# define JS_ENUM_HEADER(id, type) enum id : type
@@ -76,8 +55,9 @@
JSVAL_TYPE_MAGIC = 0x04,
JSVAL_TYPE_STRING = 0x05,
JSVAL_TYPE_SYMBOL = 0x06,
- JSVAL_TYPE_NULL = 0x07,
- JSVAL_TYPE_OBJECT = 0x08,
+ JSVAL_TYPE_PRIVATE_GCTHING = 0x07,
+ JSVAL_TYPE_NULL = 0x08,
+ JSVAL_TYPE_OBJECT = 0x0c,
/* These never appear in a jsval; they are only provided as an out-of-band value. */
JSVAL_TYPE_UNKNOWN = 0x20,
@@ -100,7 +80,8 @@
JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN,
JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC,
JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL,
- JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT
+ JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT,
+ JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_CLEAR | JSVAL_TYPE_PRIVATE_GCTHING
} JS_ENUM_FOOTER(JSValueTag);
static_assert(sizeof(JSValueTag) == sizeof(uint32_t),
@@ -119,7 +100,8 @@
JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN,
JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC,
JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL,
- JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT
+ JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT,
+ JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_PRIVATE_GCTHING
} JS_ENUM_FOOTER(JSValueTag);
static_assert(sizeof(JSValueTag) == sizeof(uint32_t),
@@ -127,15 +109,16 @@
JS_ENUM_HEADER(JSValueShiftedTag, uint64_t)
{
- JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
- JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
+ JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
+ JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_PRIVATE_GCTHING = (((uint64_t)JSVAL_TAG_PRIVATE_GCTHING) << JSVAL_TAG_SHIFT)
} JS_ENUM_FOOTER(JSValueShiftedTag);
static_assert(sizeof(JSValueShiftedTag) == sizeof(uint64_t),
@@ -153,64 +136,12 @@
#undef JS_ENUM_HEADER
#undef JS_ENUM_FOOTER
-#else /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
-
-typedef uint8_t JSValueType;
-#define JSVAL_TYPE_DOUBLE ((uint8_t)0x00)
-#define JSVAL_TYPE_INT32 ((uint8_t)0x01)
-#define JSVAL_TYPE_UNDEFINED ((uint8_t)0x02)
-#define JSVAL_TYPE_BOOLEAN ((uint8_t)0x03)
-#define JSVAL_TYPE_MAGIC ((uint8_t)0x04)
-#define JSVAL_TYPE_STRING ((uint8_t)0x05)
-#define JSVAL_TYPE_SYMBOL ((uint8_t)0x06)
-#define JSVAL_TYPE_NULL ((uint8_t)0x07)
-#define JSVAL_TYPE_OBJECT ((uint8_t)0x08)
-#define JSVAL_TYPE_UNKNOWN ((uint8_t)0x20)
-
-#if defined(JS_NUNBOX32)
-
-typedef uint32_t JSValueTag;
-#define JSVAL_TAG_CLEAR ((uint32_t)(0xFFFFFF80))
-#define JSVAL_TAG_INT32 ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32))
-#define JSVAL_TAG_UNDEFINED ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED))
-#define JSVAL_TAG_STRING ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING))
-#define JSVAL_TAG_SYMBOL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL))
-#define JSVAL_TAG_BOOLEAN ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
-#define JSVAL_TAG_MAGIC ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
-#define JSVAL_TAG_NULL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
-#define JSVAL_TAG_OBJECT ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
-
-#elif defined(JS_PUNBOX64)
-
-typedef uint32_t JSValueTag;
-#define JSVAL_TAG_MAX_DOUBLE ((uint32_t)(0x1FFF0))
-#define JSVAL_TAG_INT32 (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32)
-#define JSVAL_TAG_UNDEFINED (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED)
-#define JSVAL_TAG_STRING (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING)
-#define JSVAL_TAG_SYMBOL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL)
-#define JSVAL_TAG_BOOLEAN (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
-#define JSVAL_TAG_MAGIC (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
-#define JSVAL_TAG_NULL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
-#define JSVAL_TAG_OBJECT (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
-
-typedef uint64_t JSValueShiftedTag;
-#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
-#define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_SYMBOL (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
-
-#endif /* JS_PUNBOX64 */
-#endif /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
-
#if defined(JS_NUNBOX32)
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
+#define JSVAL_RAW64_UNDEFINED (uint64_t(JSVAL_TAG_UNDEFINED) << 32)
+
#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT
#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
@@ -218,6 +149,8 @@
#elif defined(JS_PUNBOX64)
+#define JSVAL_RAW64_UNDEFINED (uint64_t(JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
+
#define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL
#define JSVAL_TAG_MASK 0xFFFF800000000000LL
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
@@ -267,9 +200,6 @@
/** magic value passed to natives to indicate construction */
JS_IS_CONSTRUCTING,
- /** arguments.callee has been overwritten */
- JS_OVERWRITTEN_CALLEE,
-
/** value of static block object slot */
JS_BLOCK_NEEDS_CLONE,
@@ -294,686 +224,22 @@
JS_WHY_MAGIC_COUNT
} JSWhyMagic;
-#if defined(IS_LITTLE_ENDIAN)
-# if defined(JS_NUNBOX32)
-typedef union jsval_layout
-{
- uint64_t asBits;
- struct {
- union {
- int32_t i32;
- uint32_t u32;
- uint32_t boo; // Don't use |bool| -- it must be four bytes.
- JSString* str;
- JS::Symbol* sym;
- JSObject* obj;
- js::gc::Cell* cell;
- void* ptr;
- JSWhyMagic why;
- size_t word;
- uintptr_t uintptr;
- } payload;
- JSValueTag tag;
- } s;
- double asDouble;
- void* asPtr;
-} JSVAL_ALIGNMENT jsval_layout;
-# elif defined(JS_PUNBOX64)
-typedef union jsval_layout
-{
- uint64_t asBits;
-#if !defined(_WIN64)
- /* MSVC does not pack these correctly :-( */
- struct {
- uint64_t payload47 : 47;
- JSValueTag tag : 17;
- } debugView;
-#endif
- struct {
- union {
- int32_t i32;
- uint32_t u32;
- JSWhyMagic why;
- } payload;
- } s;
- double asDouble;
- void* asPtr;
- size_t asWord;
- uintptr_t asUIntPtr;
-} JSVAL_ALIGNMENT jsval_layout;
-# endif /* JS_PUNBOX64 */
-#else /* defined(IS_LITTLE_ENDIAN) */
-# if defined(JS_NUNBOX32)
-typedef union jsval_layout
-{
- uint64_t asBits;
- struct {
- JSValueTag tag;
- union {
- int32_t i32;
- uint32_t u32;
- uint32_t boo; // Don't use |bool| -- it must be four bytes.
- JSString* str;
- JS::Symbol* sym;
- JSObject* obj;
- js::gc::Cell* cell;
- void* ptr;
- JSWhyMagic why;
- size_t word;
- uintptr_t uintptr;
- } payload;
- } s;
- double asDouble;
- void* asPtr;
-} JSVAL_ALIGNMENT jsval_layout;
-# elif defined(JS_PUNBOX64)
-typedef union jsval_layout
-{
- uint64_t asBits;
- struct {
- JSValueTag tag : 17;
- uint64_t payload47 : 47;
- } debugView;
- struct {
- uint32_t padding;
- union {
- int32_t i32;
- uint32_t u32;
- JSWhyMagic why;
- } payload;
- } s;
- double asDouble;
- void* asPtr;
- size_t asWord;
- uintptr_t asUIntPtr;
-} JSVAL_ALIGNMENT jsval_layout;
-# endif /* JS_PUNBOX64 */
-#endif /* defined(IS_LITTLE_ENDIAN) */
-
-JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
-
-/*
- * For codesize purposes on some platforms, it's important that the
- * compiler know that JS::Values constructed from constant values can be
- * folded to constant bit patterns at compile time, rather than
- * constructed at runtime. Doing this requires a fair amount of C++11
- * features, which are not supported on all of our compilers. Set up
- * some defines and helper macros in an attempt to confine the ugliness
- * here, rather than scattering it all about the file. The important
- * features are:
- *
- * - constexpr;
- * - defaulted functions;
- * - C99-style designated initializers.
- */
-#if defined(__clang__)
-# if __has_feature(cxx_constexpr) && __has_feature(cxx_defaulted_functions)
-# define JS_VALUE_IS_CONSTEXPR
-# endif
-#elif defined(__GNUC__)
-/*
- * We need 4.5 for defaulted functions, 4.6 for constexpr, 4.7 because 4.6
- * doesn't understand |(X) { .field = ... }| syntax, and 4.7.3 because
- * versions prior to that have bugs in the C++ front-end that cause crashes.
- */
-# if MOZ_GCC_VERSION_AT_LEAST(4, 7, 3)
-# define JS_VALUE_IS_CONSTEXPR
-# endif
-#endif
-
-#if defined(JS_VALUE_IS_CONSTEXPR)
-# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
- return (jsval_layout) { .asBits = (BITS) }
-# define JS_VALUE_CONSTEXPR MOZ_CONSTEXPR
-# define JS_VALUE_CONSTEXPR_VAR MOZ_CONSTEXPR_VAR
-#else
-# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
- jsval_layout l; \
- l.asBits = (BITS); \
- return l;
-# define JS_VALUE_CONSTEXPR
-# define JS_VALUE_CONSTEXPR_VAR const
-#endif
-
-#if defined(JS_NUNBOX32)
-
-/*
- * N.B. GCC, in some but not all cases, chooses to emit signed comparison of
- * JSValueTag even though its underlying type has been forced to be uint32_t.
- * Thus, all comparisons should explicitly cast operands to uint32_t.
- */
-
-static inline JS_VALUE_CONSTEXPR jsval_layout
-BUILD_JSVAL(JSValueTag tag, uint32_t payload)
-{
- JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << 32) | payload);
-}
-
-static inline bool
-JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
-{
- return (uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_CLEAR;
-}
-
-static inline jsval_layout
-DOUBLE_TO_JSVAL_IMPL(double d)
-{
- jsval_layout l;
- l.asDouble = d;
- MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
- return l;
-}
-
-static inline bool
-JSVAL_IS_INT32_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_INT32;
-}
-
-static inline int32_t
-JSVAL_TO_INT32_IMPL(jsval_layout l)
-{
- return l.s.payload.i32;
-}
-
-static inline JS_VALUE_CONSTEXPR jsval_layout
-INT32_TO_JSVAL_IMPL(int32_t i)
-{
-#if defined(JS_VALUE_IS_CONSTEXPR)
- return BUILD_JSVAL(JSVAL_TAG_INT32, i);
-#else
- jsval_layout l;
- l.s.tag = JSVAL_TAG_INT32;
- l.s.payload.i32 = i;
- return l;
-#endif
-}
-
-static inline bool
-JSVAL_IS_NUMBER_IMPL(jsval_layout l)
-{
- JSValueTag tag = l.s.tag;
- MOZ_ASSERT(tag != JSVAL_TAG_CLEAR);
- return (uint32_t)tag <= (uint32_t)JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET;
-}
-
-static inline bool
-JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_UNDEFINED;
-}
-
-static inline bool
-JSVAL_IS_STRING_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_STRING;
-}
-
-static inline jsval_layout
-STRING_TO_JSVAL_IMPL(JSString* str)
-{
- jsval_layout l;
- MOZ_ASSERT(uintptr_t(str) > 0x1000);
- l.s.tag = JSVAL_TAG_STRING;
- l.s.payload.str = str;
- return l;
-}
-
-static inline JSString*
-JSVAL_TO_STRING_IMPL(jsval_layout l)
-{
- return l.s.payload.str;
-}
-
-static inline bool
-JSVAL_IS_SYMBOL_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_SYMBOL;
-}
-
-static inline jsval_layout
-SYMBOL_TO_JSVAL_IMPL(JS::Symbol* sym)
-{
- jsval_layout l;
- MOZ_ASSERT(uintptr_t(sym) > 0x1000);
- l.s.tag = JSVAL_TAG_SYMBOL;
- l.s.payload.sym = sym;
- return l;
-}
-
-static inline JS::Symbol*
-JSVAL_TO_SYMBOL_IMPL(jsval_layout l)
-{
- return l.s.payload.sym;
-}
-
-static inline bool
-JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_BOOLEAN;
-}
-
-static inline bool
-JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
-{
- return l.s.payload.boo;
-}
-
-static inline jsval_layout
-BOOLEAN_TO_JSVAL_IMPL(bool b)
-{
- jsval_layout l;
- l.s.tag = JSVAL_TAG_BOOLEAN;
- l.s.payload.boo = b;
- return l;
-}
-
-static inline bool
-JSVAL_IS_MAGIC_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_MAGIC;
-}
-
-static inline bool
-JSVAL_IS_OBJECT_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_OBJECT;
-}
-
-static inline bool
-JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
-{
- return (uint32_t)l.s.tag < (uint32_t)JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET;
-}
-
-static inline bool
-JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
-{
- MOZ_ASSERT((uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_OBJECT);
- return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET;
-}
-
-static inline JSObject*
-JSVAL_TO_OBJECT_IMPL(jsval_layout l)
-{
- return l.s.payload.obj;
-}
-
-static inline jsval_layout
-OBJECT_TO_JSVAL_IMPL(JSObject* obj)
-{
- jsval_layout l;
- MOZ_ASSERT(uintptr_t(obj) > 0x1000 || uintptr_t(obj) == 0x42);
- l.s.tag = JSVAL_TAG_OBJECT;
- l.s.payload.obj = obj;
- return l;
-}
-
-static inline bool
-JSVAL_IS_NULL_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_NULL;
-}
-
-static inline jsval_layout
-PRIVATE_PTR_TO_JSVAL_IMPL(void* ptr)
-{
- jsval_layout l;
- MOZ_ASSERT(((uint32_t)ptr & 1) == 0);
- l.s.tag = (JSValueTag)0;
- l.s.payload.ptr = ptr;
- MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
- return l;
-}
-
-static inline void*
-JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
-{
- return l.s.payload.ptr;
-}
-
-static inline bool
-JSVAL_IS_GCTHING_IMPL(jsval_layout l)
-{
- /* gcc sometimes generates signed < without explicit casts. */
- return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET;
-}
-
-static inline js::gc::Cell*
-JSVAL_TO_GCTHING_IMPL(jsval_layout l)
-{
- return l.s.payload.cell;
-}
-
-static inline uint32_t
-JSVAL_TRACE_KIND_IMPL(jsval_layout l)
-{
- static_assert((JSVAL_TAG_STRING & 0x03) == size_t(JS::TraceKind::String),
- "Value type tags must correspond with JS::TraceKinds.");
- static_assert((JSVAL_TAG_SYMBOL & 0x03) == size_t(JS::TraceKind::Symbol),
- "Value type tags must correspond with JS::TraceKinds.");
- static_assert((JSVAL_TAG_OBJECT & 0x03) == size_t(JS::TraceKind::Object),
- "Value type tags must correspond with JS::TraceKinds.");
- return l.s.tag & 0x03;
-}
-
-static inline bool
-JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
-{
- return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
-}
-
-static inline bool
-JSVAL_IS_SPECIFIC_BOOLEAN_IMPL(jsval_layout l, bool b)
-{
- return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == uint32_t(b));
-}
-
-static inline jsval_layout
-MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
-{
- jsval_layout l;
- l.s.tag = JSVAL_TAG_MAGIC;
- l.s.payload.why = why;
- return l;
-}
-
-static inline jsval_layout
-MAGIC_UINT32_TO_JSVAL_IMPL(uint32_t payload)
-{
- jsval_layout l;
- l.s.tag = JSVAL_TAG_MAGIC;
- l.s.payload.u32 = payload;
- return l;
-}
-
-static inline bool
-JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
-{
- JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
- return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
-}
-
-static inline JSValueType
-JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
-{
- uint32_t type = l.s.tag & 0xF;
- MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
- return (JSValueType)type;
-}
-
-#elif defined(JS_PUNBOX64)
-
-static inline JS_VALUE_CONSTEXPR jsval_layout
-BUILD_JSVAL(JSValueTag tag, uint64_t payload)
-{
- JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << JSVAL_TAG_SHIFT) | payload);
-}
-
-static inline bool
-JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
-{
- return l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
-}
-
-static inline jsval_layout
-DOUBLE_TO_JSVAL_IMPL(double d)
-{
- jsval_layout l;
- l.asDouble = d;
- MOZ_ASSERT(l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE);
- return l;
-}
-
-static inline bool
-JSVAL_IS_INT32_IMPL(jsval_layout l)
-{
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_INT32;
-}
-
-static inline int32_t
-JSVAL_TO_INT32_IMPL(jsval_layout l)
-{
- return (int32_t)l.asBits;
-}
-
-static inline JS_VALUE_CONSTEXPR jsval_layout
-INT32_TO_JSVAL_IMPL(int32_t i32)
-{
- JS_RETURN_LAYOUT_FROM_BITS(((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
-}
-
-static inline bool
-JSVAL_IS_NUMBER_IMPL(jsval_layout l)
-{
- return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
-}
-
-static inline bool
-JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
-{
- return l.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
-}
-
-static inline bool
-JSVAL_IS_STRING_IMPL(jsval_layout l)
-{
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_STRING;
-}
-
-static inline jsval_layout
-STRING_TO_JSVAL_IMPL(JSString* str)
-{
- jsval_layout l;
- uint64_t strBits = (uint64_t)str;
- MOZ_ASSERT(uintptr_t(str) > 0x1000);
- MOZ_ASSERT((strBits >> JSVAL_TAG_SHIFT) == 0);
- l.asBits = strBits | JSVAL_SHIFTED_TAG_STRING;
- return l;
-}
-
-static inline JSString*
-JSVAL_TO_STRING_IMPL(jsval_layout l)
-{
- return (JSString*)(l.asBits & JSVAL_PAYLOAD_MASK);
-}
-
-static inline bool
-JSVAL_IS_SYMBOL_IMPL(jsval_layout l)
-{
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_SYMBOL;
-}
-
-static inline jsval_layout
-SYMBOL_TO_JSVAL_IMPL(JS::Symbol* sym)
-{
- jsval_layout l;
- uint64_t symBits = (uint64_t)sym;
- MOZ_ASSERT(uintptr_t(sym) > 0x1000);
- MOZ_ASSERT((symBits >> JSVAL_TAG_SHIFT) == 0);
- l.asBits = symBits | JSVAL_SHIFTED_TAG_SYMBOL;
- return l;
-}
-
-static inline JS::Symbol*
-JSVAL_TO_SYMBOL_IMPL(jsval_layout l)
-{
- return (JS::Symbol*)(l.asBits & JSVAL_PAYLOAD_MASK);
-}
-
-static inline bool
-JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
-{
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_BOOLEAN;
-}
-
-static inline bool
-JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
-{
- return (bool)(l.asBits & JSVAL_PAYLOAD_MASK);
-}
-
-static inline jsval_layout
-BOOLEAN_TO_JSVAL_IMPL(bool b)
-{
- jsval_layout l;
- l.asBits = ((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
- return l;
-}
-
-static inline bool
-JSVAL_IS_MAGIC_IMPL(jsval_layout l)
-{
- return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_MAGIC;
-}
-
-static inline bool
-JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
-{
- return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
-}
-
-static inline bool
-JSVAL_IS_OBJECT_IMPL(jsval_layout l)
-{
- MOZ_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
- return l.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
-}
-
-static inline bool
-JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
-{
- MOZ_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
- return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET;
-}
-
-static inline JSObject*
-JSVAL_TO_OBJECT_IMPL(jsval_layout l)
-{
- uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
- MOZ_ASSERT((ptrBits & 0x7) == 0);
- return (JSObject*)ptrBits;
-}
-
-static inline jsval_layout
-OBJECT_TO_JSVAL_IMPL(JSObject* obj)
-{
- jsval_layout l;
- uint64_t objBits = (uint64_t)obj;
- MOZ_ASSERT(uintptr_t(obj) > 0x1000 || uintptr_t(obj) == 0x42);
- MOZ_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
- l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
- return l;
-}
-
-static inline bool
-JSVAL_IS_NULL_IMPL(jsval_layout l)
-{
- return l.asBits == JSVAL_SHIFTED_TAG_NULL;
-}
-
-static inline bool
-JSVAL_IS_GCTHING_IMPL(jsval_layout l)
-{
- return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
-}
-
-static inline js::gc::Cell*
-JSVAL_TO_GCTHING_IMPL(jsval_layout l)
-{
- uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
- MOZ_ASSERT((ptrBits & 0x7) == 0);
- return reinterpret_cast<js::gc::Cell*>(ptrBits);
-}
-
-static inline uint32_t
-JSVAL_TRACE_KIND_IMPL(jsval_layout l)
-{
- static_assert((JSVAL_TAG_STRING & 0x03) == size_t(JS::TraceKind::String),
- "Value type tags must correspond with JS::TraceKinds.");
- static_assert((JSVAL_TAG_SYMBOL & 0x03) == size_t(JS::TraceKind::Symbol),
- "Value type tags must correspond with JS::TraceKinds.");
- static_assert((JSVAL_TAG_OBJECT & 0x03) == size_t(JS::TraceKind::Object),
- "Value type tags must correspond with JS::TraceKinds.");
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) & 0x03;
-}
-
-static inline jsval_layout
-PRIVATE_PTR_TO_JSVAL_IMPL(void* ptr)
-{
- jsval_layout l;
- uint64_t ptrBits = (uint64_t)ptr;
- MOZ_ASSERT((ptrBits & 1) == 0);
- l.asBits = ptrBits >> 1;
- MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
- return l;
-}
-
-static inline void*
-JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
-{
- MOZ_ASSERT((l.asBits & 0x8000000000000000LL) == 0);
- return (void*)(l.asBits << 1);
-}
-
-static inline bool
-JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
-{
- return l.asBits == (((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
-}
-
-static inline bool
-JSVAL_IS_SPECIFIC_BOOLEAN_IMPL(jsval_layout l, bool b)
-{
- return l.asBits == (((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
-}
-
-static inline jsval_layout
-MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
-{
- jsval_layout l;
- l.asBits = ((uint64_t)(uint32_t)why) | JSVAL_SHIFTED_TAG_MAGIC;
- return l;
-}
-
-static inline jsval_layout
-MAGIC_UINT32_TO_JSVAL_IMPL(uint32_t payload)
-{
- jsval_layout l;
- l.asBits = ((uint64_t)payload) | JSVAL_SHIFTED_TAG_MAGIC;
- return l;
-}
-
-static inline bool
-JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
-{
- uint64_t lbits = lhs.asBits, rbits = rhs.asBits;
- return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
- (((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
-}
-
-static inline JSValueType
-JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
-{
- uint64_t type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
- MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
- return (JSValueType)type;
-}
+namespace JS {
-#endif /* JS_PUNBOX64 */
+static inline constexpr JS::Value UndefinedValue();
+static inline JS::Value PoisonedObjectValue(JSObject* obj);
-static inline bool
-JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
-{
- return JSVAL_IS_GCTHING_IMPL(l) && !JSVAL_IS_NULL_IMPL(l);
-}
+namespace detail {
-static inline jsval_layout JSVAL_TO_IMPL(JS::Value v);
-static inline JS_VALUE_CONSTEXPR JS::Value IMPL_TO_JSVAL(jsval_layout l);
+constexpr int CanonicalizedNaNSignBit = 0;
+constexpr uint64_t CanonicalizedNaNSignificand = 0x8000000000000ULL;
-namespace JS {
+constexpr uint64_t CanonicalizedNaNBits =
+ mozilla::SpecificNaNBits<double,
+ detail::CanonicalizedNaNSignBit,
+ detail::CanonicalizedNaNSignificand>::value;
-static inline JS_VALUE_CONSTEXPR JS::Value UndefinedValue();
+} // namespace detail
/**
* Returns a generic quiet NaN value, with all payload bits set to zero.
@@ -984,7 +250,8 @@
static MOZ_ALWAYS_INLINE double
GenericNaN()
{
- return mozilla::SpecificNaN<double>(0, 0x8000000000000ULL);
+ return mozilla::SpecificNaN<double>(detail::CanonicalizedNaNSignBit,
+ detail::CanonicalizedNaNSignificand);
}
/* MSVC with PGO miscompiles this function. */
@@ -1033,17 +300,21 @@
* 32-bit user code should avoid copying jsval/JS::Value as much as possible,
* preferring to pass by const Value&.
*/
-class Value
+class MOZ_NON_PARAM alignas(8) Value
{
public:
+#if defined(JS_NUNBOX32)
+ using PayloadType = uint32_t;
+#elif defined(JS_PUNBOX64)
+ using PayloadType = uint64_t;
+#endif
+
/*
* N.B. the default constructor leaves Value unitialized. Adding a default
* constructor prevents Value from being stored in a union.
*/
-#if defined(JS_VALUE_IS_CONSTEXPR)
Value() = default;
Value(const Value& v) = default;
-#endif
/**
* Returns false if creating a NumberValue containing the given type would
@@ -1057,15 +328,15 @@
/*** Mutators ***/
void setNull() {
- data.asBits = BUILD_JSVAL(JSVAL_TAG_NULL, 0).asBits;
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_NULL, 0);
}
void setUndefined() {
- data.asBits = BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0).asBits;
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_UNDEFINED, 0);
}
void setInt32(int32_t i) {
- data = INT32_TO_JSVAL_IMPL(i);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
}
int32_t& getInt32Ref() {
@@ -1074,7 +345,10 @@
}
void setDouble(double d) {
- data = DOUBLE_TO_JSVAL_IMPL(d);
+ // Don't assign to data.asDouble to fix a miscompilation with
+ // GCC 5.2.1 and 5.3.1. See bug 1312488.
+ data = layout(d);
+ MOZ_ASSERT(isDouble());
}
void setNaN() {
@@ -1087,27 +361,45 @@
}
void setString(JSString* str) {
- data = STRING_TO_JSVAL_IMPL(str);
+ MOZ_ASSERT(uintptr_t(str) > 0x1000);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_STRING, PayloadType(str));
}
void setSymbol(JS::Symbol* sym) {
- data = SYMBOL_TO_JSVAL_IMPL(sym);
+ MOZ_ASSERT(uintptr_t(sym) > 0x1000);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym));
}
void setObject(JSObject& obj) {
- data = OBJECT_TO_JSVAL_IMPL(&obj);
+ MOZ_ASSERT(uintptr_t(&obj) > 0x1000 || uintptr_t(&obj) == 0x48);
+#if defined(JS_PUNBOX64)
+ // VisualStudio cannot contain parenthesized C++ style cast and shift
+ // inside decltype in template parameter:
+ // AssertionConditionType<decltype((uintptr_t(x) >> 1))>
+ // It throws syntax error.
+ MOZ_ASSERT((((uintptr_t)&obj) >> JSVAL_TAG_SHIFT) == 0);
+#endif
+ setObjectNoCheck(&obj);
+ }
+
+ private:
+ void setObjectNoCheck(JSObject* obj) {
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_OBJECT, PayloadType(obj));
}
+ friend inline Value PoisonedObjectValue(JSObject* obj);
+
+ public:
void setBoolean(bool b) {
- data = BOOLEAN_TO_JSVAL_IMPL(b);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(b));
}
void setMagic(JSWhyMagic why) {
- data = MAGIC_TO_JSVAL_IMPL(why);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, uint32_t(why));
}
void setMagicUint32(uint32_t payload) {
- data = MAGIC_UINT32_TO_JSVAL_IMPL(payload);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, payload);
}
bool setNumber(uint32_t ui) {
@@ -1144,14 +436,54 @@
data.asBits = tmp;
}
+ private:
+ JSValueTag toTag() const {
+#if defined(JS_NUNBOX32)
+ return data.s.tag;
+#elif defined(JS_PUNBOX64)
+ return JSValueTag(data.asBits >> JSVAL_TAG_SHIFT);
+#endif
+ }
+
+ public:
+ /*** JIT-only interfaces to interact with and create raw Values ***/
+#if defined(JS_NUNBOX32)
+ PayloadType toNunboxPayload() const {
+ return data.s.payload.i32;
+ }
+
+ JSValueTag toNunboxTag() const {
+ return data.s.tag;
+ }
+#elif defined(JS_PUNBOX64)
+ const void* bitsAsPunboxPointer() const {
+ return reinterpret_cast<void*>(data.asBits);
+ }
+#endif
+
/*** Value type queries ***/
+ /*
+ * N.B. GCC, in some but not all cases, chooses to emit signed comparison
+ * of JSValueTag even though its underlying type has been forced to be
+ * uint32_t. Thus, all comparisons should explicitly cast operands to
+ * uint32_t.
+ */
+
bool isUndefined() const {
- return JSVAL_IS_UNDEFINED_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return toTag() == JSVAL_TAG_UNDEFINED;
+#elif defined(JS_PUNBOX64)
+ return data.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
+#endif
}
bool isNull() const {
- return JSVAL_IS_NULL_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return toTag() == JSVAL_TAG_NULL;
+#elif defined(JS_PUNBOX64)
+ return data.asBits == JSVAL_SHIFTED_TAG_NULL;
+#endif
}
bool isNullOrUndefined() const {
@@ -1159,73 +491,109 @@
}
bool isInt32() const {
- return JSVAL_IS_INT32_IMPL(data);
+ return toTag() == JSVAL_TAG_INT32;
}
bool isInt32(int32_t i32) const {
- return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
+ return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i32));
}
bool isDouble() const {
- return JSVAL_IS_DOUBLE_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return uint32_t(toTag()) <= uint32_t(JSVAL_TAG_CLEAR);
+#elif defined(JS_PUNBOX64)
+ return (data.asBits | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
+#endif
}
bool isNumber() const {
- return JSVAL_IS_NUMBER_IMPL(data);
+#if defined(JS_NUNBOX32)
+ MOZ_ASSERT(toTag() != JSVAL_TAG_CLEAR);
+ return uint32_t(toTag()) <= uint32_t(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET);
+#elif defined(JS_PUNBOX64)
+ return data.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
+#endif
}
bool isString() const {
- return JSVAL_IS_STRING_IMPL(data);
+ return toTag() == JSVAL_TAG_STRING;
}
bool isSymbol() const {
- return JSVAL_IS_SYMBOL_IMPL(data);
+ return toTag() == JSVAL_TAG_SYMBOL;
}
bool isObject() const {
- return JSVAL_IS_OBJECT_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return toTag() == JSVAL_TAG_OBJECT;
+#elif defined(JS_PUNBOX64)
+ MOZ_ASSERT((data.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
+ return data.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
+#endif
}
bool isPrimitive() const {
- return JSVAL_IS_PRIMITIVE_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return uint32_t(toTag()) < uint32_t(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET);
+#elif defined(JS_PUNBOX64)
+ return data.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
+#endif
}
bool isObjectOrNull() const {
- return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
+ MOZ_ASSERT(uint32_t(toTag()) <= uint32_t(JSVAL_TAG_OBJECT));
+#if defined(JS_NUNBOX32)
+ return uint32_t(toTag()) >= uint32_t(JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET);
+#elif defined(JS_PUNBOX64)
+ return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET;
+#endif
}
bool isGCThing() const {
- return JSVAL_IS_GCTHING_IMPL(data);
+#if defined(JS_NUNBOX32)
+ /* gcc sometimes generates signed < without explicit casts. */
+ return uint32_t(toTag()) >= uint32_t(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET);
+#elif defined(JS_PUNBOX64)
+ return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
+#endif
}
bool isBoolean() const {
- return JSVAL_IS_BOOLEAN_IMPL(data);
+ return toTag() == JSVAL_TAG_BOOLEAN;
}
bool isTrue() const {
- return JSVAL_IS_SPECIFIC_BOOLEAN_IMPL(data, true);
+ return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(true));
}
bool isFalse() const {
- return JSVAL_IS_SPECIFIC_BOOLEAN_IMPL(data, false);
+ return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(false));
}
bool isMagic() const {
- return JSVAL_IS_MAGIC_IMPL(data);
+ return toTag() == JSVAL_TAG_MAGIC;
}
bool isMagic(JSWhyMagic why) const {
MOZ_ASSERT_IF(isMagic(), data.s.payload.why == why);
- return JSVAL_IS_MAGIC_IMPL(data);
+ return isMagic();
}
bool isMarkable() const {
- return JSVAL_IS_TRACEABLE_IMPL(data);
+ return isGCThing() && !isNull();
}
JS::TraceKind traceKind() const {
MOZ_ASSERT(isMarkable());
- return JS::TraceKind(JSVAL_TRACE_KIND_IMPL(data));
+ static_assert((JSVAL_TAG_STRING & 0x03) == size_t(JS::TraceKind::String),
+ "Value type tags must correspond with JS::TraceKinds.");
+ static_assert((JSVAL_TAG_SYMBOL & 0x03) == size_t(JS::TraceKind::Symbol),
+ "Value type tags must correspond with JS::TraceKinds.");
+ static_assert((JSVAL_TAG_OBJECT & 0x03) == size_t(JS::TraceKind::Object),
+ "Value type tags must correspond with JS::TraceKinds.");
+ if (MOZ_UNLIKELY(isPrivateGCThing()))
+ return JS::GCThingTraceKind(toGCThing());
+ return JS::TraceKind(toTag() & 0x03);
}
JSWhyMagic whyMagic() const {
@@ -1254,7 +622,11 @@
int32_t toInt32() const {
MOZ_ASSERT(isInt32());
- return JSVAL_TO_INT32_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.i32;
+#elif defined(JS_PUNBOX64)
+ return int32_t(data.asBits);
+#endif
}
double toDouble() const {
@@ -1269,27 +641,56 @@
JSString* toString() const {
MOZ_ASSERT(isString());
- return JSVAL_TO_STRING_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.str;
+#elif defined(JS_PUNBOX64)
+ return reinterpret_cast<JSString*>(data.asBits & JSVAL_PAYLOAD_MASK);
+#endif
}
JS::Symbol* toSymbol() const {
MOZ_ASSERT(isSymbol());
- return JSVAL_TO_SYMBOL_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.sym;
+#elif defined(JS_PUNBOX64)
+ return reinterpret_cast<JS::Symbol*>(data.asBits & JSVAL_PAYLOAD_MASK);
+#endif
}
JSObject& toObject() const {
MOZ_ASSERT(isObject());
- return *JSVAL_TO_OBJECT_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return *data.s.payload.obj;
+#elif defined(JS_PUNBOX64)
+ return *toObjectOrNull();
+#endif
}
JSObject* toObjectOrNull() const {
MOZ_ASSERT(isObjectOrNull());
- return JSVAL_TO_OBJECT_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.obj;
+#elif defined(JS_PUNBOX64)
+ uint64_t ptrBits = data.asBits & JSVAL_PAYLOAD_MASK;
+ MOZ_ASSERT((ptrBits & 0x7) == 0);
+ return reinterpret_cast<JSObject*>(ptrBits);
+#endif
}
js::gc::Cell* toGCThing() const {
MOZ_ASSERT(isGCThing());
- return JSVAL_TO_GCTHING_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.cell;
+#elif defined(JS_PUNBOX64)
+ uint64_t ptrBits = data.asBits & JSVAL_PAYLOAD_MASK;
+ MOZ_ASSERT((ptrBits & 0x7) == 0);
+ return reinterpret_cast<js::gc::Cell*>(ptrBits);
+#endif
+ }
+
+ js::gc::Cell* toMarkablePointer() const {
+ MOZ_ASSERT(isMarkable());
+ return toGCThing();
}
GCCellPtr toGCCellPtr() const {
@@ -1298,7 +699,11 @@
bool toBoolean() const {
MOZ_ASSERT(isBoolean());
- return JSVAL_TO_BOOLEAN_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return bool(data.s.payload.boo);
+#elif defined(JS_PUNBOX64)
+ return bool(data.asBits & JSVAL_PAYLOAD_MASK);
+#endif
}
uint32_t payloadAsRawUint32() const {
@@ -1311,7 +716,9 @@
}
JSValueType extractNonDoubleType() const {
- return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
+ uint32_t type = toTag() & 0xF;
+ MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
+ return JSValueType(type);
}
/*
@@ -1324,12 +731,24 @@
*/
void setPrivate(void* ptr) {
- data = PRIVATE_PTR_TO_JSVAL_IMPL(ptr);
+ MOZ_ASSERT((uintptr_t(ptr) & 1) == 0);
+#if defined(JS_NUNBOX32)
+ data.s.tag = JSValueTag(0);
+ data.s.payload.ptr = ptr;
+#elif defined(JS_PUNBOX64)
+ data.asBits = uintptr_t(ptr) >> 1;
+#endif
+ MOZ_ASSERT(isDouble());
}
void* toPrivate() const {
- MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
- return JSVAL_TO_PRIVATE_PTR_IMPL(data);
+ MOZ_ASSERT(isDouble());
+#if defined(JS_NUNBOX32)
+ return data.s.payload.ptr;
+#elif defined(JS_PUNBOX64)
+ MOZ_ASSERT((data.asBits & 0x8000000000000000ULL) == 0);
+ return reinterpret_cast<void*>(data.asBits << 1);
+#endif
}
void setPrivateUint32(uint32_t ui) {
@@ -1342,17 +761,35 @@
}
/*
- * An unmarked value is just a void* cast as a Value. Thus, the Value is
- * not safe for GC and must not be marked. This API avoids raw casts
- * and the ensuing strict-aliasing warnings.
+ * Private GC Thing API
+ *
+ * Non-JSObject, JSString, and JS::Symbol cells may be put into the 64-bit
+ * payload as private GC things. Such Values are considered isMarkable()
+ * and isGCThing(), and as such, automatically marked. Their traceKind()
+ * is gotten via their cells.
*/
- void setUnmarkedPtr(void* ptr) {
- data.asPtr = ptr;
+ void setPrivateGCThing(js::gc::Cell* cell) {
+ MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::String,
+ "Private GC thing Values must not be strings. Make a StringValue instead.");
+ MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Symbol,
+ "Private GC thing Values must not be symbols. Make a SymbolValue instead.");
+ MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Object,
+ "Private GC thing Values must not be objects. Make an ObjectValue instead.");
+
+ MOZ_ASSERT(uintptr_t(cell) > 0x1000);
+#if defined(JS_PUNBOX64)
+ // VisualStudio cannot contain parenthesized C++ style cast and shift
+ // inside decltype in template parameter:
+ // AssertionConditionType<decltype((uintptr_t(x) >> 1))>
+ // It throws syntax error.
+ MOZ_ASSERT((((uintptr_t)cell) >> JSVAL_TAG_SHIFT) == 0);
+#endif
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_PRIVATE_GCTHING, PayloadType(cell));
}
- void* toUnmarkedPtr() const {
- return data.asPtr;
+ bool isPrivateGCThing() const {
+ return toTag() == JSVAL_TAG_PRIVATE_GCTHING;
}
const size_t* payloadWord() const {
@@ -1378,12 +815,117 @@
private:
#endif
- jsval_layout data;
+#if MOZ_LITTLE_ENDIAN
+# if defined(JS_NUNBOX32)
+ union layout {
+ uint64_t asBits;
+ struct {
+ union {
+ int32_t i32;
+ uint32_t u32;
+ uint32_t boo; // Don't use |bool| -- it must be four bytes.
+ JSString* str;
+ JS::Symbol* sym;
+ JSObject* obj;
+ js::gc::Cell* cell;
+ void* ptr;
+ JSWhyMagic why;
+ size_t word;
+ uintptr_t uintptr;
+ } payload;
+ JSValueTag tag;
+ } s;
+ double asDouble;
+ void* asPtr;
+
+ layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
+ explicit constexpr layout(uint64_t bits) : asBits(bits) {}
+ explicit constexpr layout(double d) : asDouble(d) {}
+ } data;
+# elif defined(JS_PUNBOX64)
+ union layout {
+ uint64_t asBits;
+#if !defined(_WIN64)
+ /* MSVC does not pack these correctly :-( */
+ struct {
+ uint64_t payload47 : 47;
+ JSValueTag tag : 17;
+ } debugView;
+#endif
+ struct {
+ union {
+ int32_t i32;
+ uint32_t u32;
+ JSWhyMagic why;
+ } payload;
+ } s;
+ double asDouble;
+ void* asPtr;
+ size_t asWord;
+ uintptr_t asUIntPtr;
+
+ layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
+ explicit constexpr layout(uint64_t bits) : asBits(bits) {}
+ explicit constexpr layout(double d) : asDouble(d) {}
+ } data;
+# endif /* JS_PUNBOX64 */
+#else /* MOZ_LITTLE_ENDIAN */
+# if defined(JS_NUNBOX32)
+ union layout {
+ uint64_t asBits;
+ struct {
+ JSValueTag tag;
+ union {
+ int32_t i32;
+ uint32_t u32;
+ uint32_t boo; // Don't use |bool| -- it must be four bytes.
+ JSString* str;
+ JS::Symbol* sym;
+ JSObject* obj;
+ js::gc::Cell* cell;
+ void* ptr;
+ JSWhyMagic why;
+ size_t word;
+ uintptr_t uintptr;
+ } payload;
+ } s;
+ double asDouble;
+ void* asPtr;
+
+ layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
+ explicit constexpr layout(uint64_t bits) : asBits(bits) {}
+ explicit constexpr layout(double d) : asDouble(d) {}
+ } data;
+# elif defined(JS_PUNBOX64)
+ union layout {
+ uint64_t asBits;
+ struct {
+ JSValueTag tag : 17;
+ uint64_t payload47 : 47;
+ } debugView;
+ struct {
+ uint32_t padding;
+ union {
+ int32_t i32;
+ uint32_t u32;
+ JSWhyMagic why;
+ } payload;
+ } s;
+ double asDouble;
+ void* asPtr;
+ size_t asWord;
+ uintptr_t asUIntPtr;
+
+ layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
+ explicit constexpr layout(uint64_t bits) : asBits(bits) {}
+ explicit constexpr layout(double d) : asDouble(d) {}
+ } data;
+# endif /* JS_PUNBOX64 */
+#endif /* MOZ_LITTLE_ENDIAN */
private:
-#if defined(JS_VALUE_IS_CONSTEXPR)
- MOZ_IMPLICIT JS_VALUE_CONSTEXPR Value(jsval_layout layout) : data(layout) {}
-#endif
+ explicit constexpr Value(uint64_t asBits) : data(asBits) {}
+ explicit constexpr Value(double d) : data(d) {}
void staticAssertions() {
JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
@@ -1392,11 +934,86 @@
JS_STATIC_ASSERT(sizeof(Value) == 8);
}
- friend jsval_layout (::JSVAL_TO_IMPL)(Value);
- friend Value JS_VALUE_CONSTEXPR (::IMPL_TO_JSVAL)(jsval_layout l);
- friend Value JS_VALUE_CONSTEXPR (JS::UndefinedValue)();
+ friend constexpr Value JS::UndefinedValue();
+
+ public:
+ static constexpr uint64_t
+ bitsFromTagAndPayload(JSValueTag tag, PayloadType payload)
+ {
+#if defined(JS_NUNBOX32)
+ return (uint64_t(uint32_t(tag)) << 32) | payload;
+#elif defined(JS_PUNBOX64)
+ return (uint64_t(uint32_t(tag)) << JSVAL_TAG_SHIFT) | payload;
+#endif
+ }
+
+ static constexpr Value
+ fromTagAndPayload(JSValueTag tag, PayloadType payload)
+ {
+ return fromRawBits(bitsFromTagAndPayload(tag, payload));
+ }
+
+ static constexpr Value
+ fromRawBits(uint64_t asBits) {
+ return Value(asBits);
+ }
+
+ static constexpr Value
+ fromInt32(int32_t i) {
+ return fromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
+ }
+
+ static constexpr Value
+ fromDouble(double d) {
+ return Value(d);
+ }
+} JS_HAZ_GC_POINTER;
+
+/**
+ * This is a null-constructible structure that can convert to and from
+ * a Value, allowing UninitializedValue to be stored in unions.
+ */
+struct MOZ_NON_PARAM alignas(8) UninitializedValue
+{
+ private:
+ uint64_t bits;
+
+ public:
+ UninitializedValue() = default;
+ UninitializedValue(const UninitializedValue&) = default;
+ MOZ_IMPLICIT UninitializedValue(const Value& val) : bits(val.asRawBits()) {}
+
+ inline uint64_t asRawBits() const {
+ return bits;
+ }
+
+ inline Value& asValueRef() {
+ return *reinterpret_cast<Value*>(this);
+ }
+ inline const Value& asValueRef() const {
+ return *reinterpret_cast<const Value*>(this);
+ }
+
+ inline operator Value&() {
+ return asValueRef();
+ }
+ inline operator Value const&() const {
+ return asValueRef();
+ }
+ inline operator Value() const {
+ return asValueRef();
+ }
+
+ inline void operator=(Value const& other) {
+ asValueRef() = other;
+ }
};
+static_assert(sizeof(Value) == 8, "Value size must leave three tag bits, be a binary power, and is ubiquitously depended upon everywhere");
+
+static_assert(sizeof(UninitializedValue) == sizeof(Value), "Value and UninitializedValue must be the same size");
+static_assert(alignof(UninitializedValue) == alignof(Value), "Value and UninitializedValue must have same alignment");
+
inline bool
IsOptimizedPlaceholderMagicValue(const Value& v)
{
@@ -1424,22 +1041,16 @@
return v;
}
-static inline JS_VALUE_CONSTEXPR Value
+static inline constexpr Value
UndefinedValue()
{
-#if defined(JS_VALUE_IS_CONSTEXPR)
- return Value(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
-#else
- JS::Value v;
- v.setUndefined();
- return v;
-#endif
+ return Value::fromTagAndPayload(JSVAL_TAG_UNDEFINED, 0);
}
-static inline JS_VALUE_CONSTEXPR Value
+static inline constexpr Value
Int32Value(int32_t i32)
{
- return IMPL_TO_JSVAL(INT32_TO_JSVAL_IMPL(i32));
+ return Value::fromInt32(i32);
}
static inline Value
@@ -1450,27 +1061,23 @@
return v;
}
-static inline JS_VALUE_CONSTEXPR Value
+static inline Value
CanonicalizedDoubleValue(double d)
{
- /*
- * This is a manually inlined version of:
- * d = JS_CANONICALIZE_NAN(d);
- * return IMPL_TO_JSVAL(DOUBLE_TO_JSVAL_IMPL(d));
- * because GCC from XCode 3.1.4 miscompiles the above code.
- */
-#if defined(JS_VALUE_IS_CONSTEXPR)
- return IMPL_TO_JSVAL(MOZ_UNLIKELY(mozilla::IsNaN(d))
- ? (jsval_layout) { .asBits = 0x7FF8000000000000LL }
- : (jsval_layout) { .asDouble = d });
-#else
- jsval_layout l;
- if (MOZ_UNLIKELY(d != d))
- l.asBits = 0x7FF8000000000000LL;
- else
- l.asDouble = d;
- return IMPL_TO_JSVAL(l);
-#endif
+ return MOZ_UNLIKELY(mozilla::IsNaN(d))
+ ? Value::fromRawBits(detail::CanonicalizedNaNBits)
+ : Value::fromDouble(d);
+}
+
+static inline bool
+IsCanonicalized(double d)
+{
+ if (mozilla::IsInfinite(d) || mozilla::IsFinite(d))
+ return true;
+
+ uint64_t bits;
+ mozilla::BitwiseCast<uint64_t>(d, &bits);
+ return (bits & ~mozilla::DoubleTypeTraits::kSignBit) == detail::CanonicalizedNaNBits;
}
static inline Value
@@ -1541,7 +1148,7 @@
ObjectValueCrashOnTouch()
{
Value v;
- v.setObject(*reinterpret_cast<JSObject*>(0x42));
+ v.setObject(*reinterpret_cast<JSObject*>(0x48));
return v;
}
@@ -1607,12 +1214,12 @@
return Int32Value(i);
}
-static inline JS_VALUE_CONSTEXPR Value
+static inline constexpr Value
NumberValue(uint32_t i)
{
return i <= JSVAL_INT_MAX
? Int32Value(int32_t(i))
- : CanonicalizedDoubleValue(double(i));
+ : Value::fromDouble(double(i));
}
namespace detail {
@@ -1683,10 +1290,32 @@
return v;
}
+static inline Value
+PrivateGCThingValue(js::gc::Cell* cell)
+{
+ Value v;
+ v.setPrivateGCThing(cell);
+ return v;
+}
+
+static inline Value
+PoisonedObjectValue(JSObject* obj)
+{
+ Value v;
+ v.setObjectNoCheck(obj);
+ return v;
+}
+
inline bool
SameType(const Value& lhs, const Value& rhs)
{
- return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
+#if defined(JS_NUNBOX32)
+ JSValueTag ltag = lhs.toTag(), rtag = rhs.toTag();
+ return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
+#elif defined(JS_PUNBOX64)
+ return (lhs.isDouble() && rhs.isDouble()) ||
+ (((lhs.data.asBits ^ rhs.data.asBits) & 0xFFFF800000000000ULL) == 0);
+#endif
}
} // namespace JS
@@ -1695,24 +1324,35 @@
namespace JS {
JS_PUBLIC_API(void) HeapValuePostBarrier(Value* valuep, const Value& prev, const Value& next);
-} // namespace JS
-namespace js {
-
-template <> struct GCMethods<const JS::Value>
+template <>
+struct GCPolicy<JS::Value>
{
- static JS::Value initial() { return JS::UndefinedValue(); }
+ static Value initial() { return UndefinedValue(); }
+ static void trace(JSTracer* trc, Value* v, const char* name) {
+ js::UnsafeTraceManuallyBarrieredEdge(trc, v, name);
+ }
+ static bool isTenured(const Value& thing) {
+ return !thing.isGCThing() || !IsInsideNursery(thing.toGCThing());
+ }
};
-template <> struct GCMethods<JS::Value>
+} // namespace JS
+
+namespace js {
+
+template <>
+struct BarrierMethods<JS::Value>
{
- static JS::Value initial() { return JS::UndefinedValue(); }
static gc::Cell* asGCThingOrNull(const JS::Value& v) {
return v.isMarkable() ? v.toGCThing() : nullptr;
}
static void postBarrier(JS::Value* v, const JS::Value& prev, const JS::Value& next) {
JS::HeapValuePostBarrier(v, prev, next);
}
+ static void exposeToJS(const JS::Value& v) {
+ JS::ExposeValueToActiveJS(v);
+ }
};
template <class Outer> class MutableValueOperations;
@@ -1762,10 +1402,11 @@
JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }
gc::Cell* toGCThing() const { return value().toGCThing(); }
JS::TraceKind traceKind() const { return value().traceKind(); }
- uint64_t asRawBits() const { return value().asRawBits(); }
+ void* toPrivate() const { return value().toPrivate(); }
+ uint32_t toPrivateUint32() const { return value().toPrivateUint32(); }
+ uint64_t asRawBits() const { return value().asRawBits(); }
JSValueType extractNonDoubleType() const { return value().extractNonDoubleType(); }
- uint32_t toPrivateUint32() const { return value().toPrivateUint32(); }
JSWhyMagic whyMagic() const { return value().whyMagic(); }
uint32_t magicUint32() const { return value().magicUint32(); }
@@ -1796,6 +1437,9 @@
void setSymbol(JS::Symbol* sym) { this->value().setSymbol(sym); }
void setObject(JSObject& obj) { this->value().setObject(obj); }
void setObjectOrNull(JSObject* arg) { this->value().setObjectOrNull(arg); }
+ void setPrivate(void* ptr) { this->value().setPrivate(ptr); }
+ void setPrivateUint32(uint32_t ui) { this->value().setPrivateUint32(ui); }
+ void setPrivateGCThing(js::gc::Cell* cell) { this->value().setPrivateGCThing(cell); }
};
/*
@@ -1824,6 +1468,7 @@
void setString(JSString* str) { setBarriered(JS::StringValue(str)); }
void setSymbol(JS::Symbol* sym) { setBarriered(JS::SymbolValue(sym)); }
void setObject(JSObject& obj) { setBarriered(JS::ObjectValue(obj)); }
+ void setPrivateGCThing(js::gc::Cell* cell) { setBarriered(JS::PrivateGCThingValue(cell)); }
bool setNumber(uint32_t ui) {
if (ui > JSVAL_INT_MAX) {
@@ -1885,55 +1530,18 @@
return f(&val.toObject(), mozilla::Forward<Args>(args)...);
if (val.isSymbol())
return f(val.toSymbol(), mozilla::Forward<Args>(args)...);
+ if (MOZ_UNLIKELY(val.isPrivateGCThing()))
+ return DispatchTyped(f, val.toGCCellPtr(), mozilla::Forward<Args>(args)...);
MOZ_ASSERT(!val.isMarkable());
return F::defaultValue(val);
}
-template <class S> struct VoidDefaultAdaptor { static void defaultValue(S) {} };
+template <class S> struct VoidDefaultAdaptor { static void defaultValue(const S&) {} };
template <class S> struct IdentityDefaultAdaptor { static S defaultValue(const S& v) {return v;} };
-template <class S, bool v> struct BoolDefaultAdaptor { static bool defaultValue(S) { return v; } };
+template <class S, bool v> struct BoolDefaultAdaptor { static bool defaultValue(const S&) { return v; } };
} // namespace js
-inline jsval_layout
-JSVAL_TO_IMPL(JS::Value v)
-{
- return v.data;
-}
-
-inline JS_VALUE_CONSTEXPR JS::Value
-IMPL_TO_JSVAL(jsval_layout l)
-{
-#if defined(JS_VALUE_IS_CONSTEXPR)
- return JS::Value(l);
-#else
- JS::Value v;
- v.data = l;
- return v;
-#endif
-}
-
-namespace JS {
-
-#ifdef JS_DEBUG
-namespace detail {
-
-struct ValueAlignmentTester { char c; JS::Value v; };
-static_assert(sizeof(ValueAlignmentTester) == 16,
- "JS::Value must be 16-byte-aligned");
-
-struct LayoutAlignmentTester { char c; jsval_layout l; };
-static_assert(sizeof(LayoutAlignmentTester) == 16,
- "jsval_layout must be 16-byte-aligned");
-
-} // namespace detail
-#endif /* JS_DEBUG */
-
-} // namespace JS
-
-static_assert(sizeof(jsval_layout) == sizeof(JS::Value),
- "jsval_layout and JS::Value must have identical layouts");
-
/************************************************************************/
namespace JS {
@@ -1945,7 +1553,4 @@
} // namespace JS
-#undef JS_VALUE_IS_CONSTEXPR
-#undef JS_RETURN_LAYOUT_FROM_BITS
-
#endif /* js_Value_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Vector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Vector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/Vector.h
@@ -34,15 +34,9 @@
template <typename T,
size_t MinInlineCapacity = 0,
- class AllocPolicy = TempAllocPolicy
-// 1800 is MSVC2013. Optimistically assume MSVC2015 (1900) is fixed.
-// If you're porting to MSVC2015 and this doesn't work, extend the
-// condition to encompass that additional version (but *do* keep the
-// version-check so we know when MSVC's fixed).
-#if !defined(_MSC_VER) || (1800 <= _MSC_VER && _MSC_VER <= 1800)
+ class AllocPolicy = TempAllocPolicy,
// Don't use this with JS::Value! Use JS::AutoValueVector instead.
- , typename = typename mozilla::EnableIf<!detail::TypeIsGCThing<T>::value>::Type
-#endif
+ typename = typename mozilla::EnableIf<!detail::TypeIsGCThing<T>::value>::Type
>
using Vector = mozilla::Vector<T, MinInlineCapacity, AllocPolicy>;
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsalloc.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsalloc.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsalloc.h
@@ -51,7 +51,7 @@
};
class ExclusiveContext;
-void ReportOutOfMemory(ExclusiveContext* cxArg);
+JS_FRIEND_API(void) ReportOutOfMemory(ExclusiveContext* cxArg);
/*
* Allocation policy that calls the system memory functions and reports errors
@@ -132,7 +132,7 @@
bool checkSimulatedOOM() const {
if (js::oom::ShouldFailWithOOM()) {
- JS_ReportOutOfMemory(reinterpret_cast<JSContext*>(cx_));
+ js::ReportOutOfMemory(reinterpret_cast<ExclusiveContext*>(cx_));
return false;
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsapi.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsapi.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsapi.h
@@ -14,7 +14,9 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Range.h"
#include "mozilla/RangedPtr.h"
+#include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h"
+#include "mozilla/Variant.h"
#include <stdarg.h>
#include <stddef.h>
@@ -25,12 +27,14 @@
#include "jspubtd.h"
#include "js/CallArgs.h"
+#include "js/CharacterEncoding.h"
#include "js/Class.h"
+#include "js/GCVector.h"
#include "js/HashTable.h"
#include "js/Id.h"
#include "js/Principals.h"
+#include "js/Realm.h"
#include "js/RootingAPI.h"
-#include "js/TraceableVector.h"
#include "js/TracingAPI.h"
#include "js/Utility.h"
#include "js/Value.h"
@@ -123,14 +127,14 @@
size_t length() const { return vector.length(); }
bool empty() const { return vector.empty(); }
- bool append(const T& v) { return vector.append(v); }
- bool appendN(const T& v, size_t len) { return vector.appendN(v, len); }
- bool append(const T* ptr, size_t len) { return vector.append(ptr, len); }
- bool appendAll(const AutoVectorRooterBase<T>& other) {
+ MOZ_MUST_USE bool append(const T& v) { return vector.append(v); }
+ MOZ_MUST_USE bool appendN(const T& v, size_t len) { return vector.appendN(v, len); }
+ MOZ_MUST_USE bool append(const T* ptr, size_t len) { return vector.append(ptr, len); }
+ MOZ_MUST_USE bool appendAll(const AutoVectorRooterBase<T>& other) {
return vector.appendAll(other.vector);
}
- bool insert(T* p, const T& val) { return vector.insert(p, val); }
+ MOZ_MUST_USE bool insert(T* p, const T& val) { return vector.insert(p, val); }
/* For use when space has already been reserved. */
void infallibleAppend(const T& v) { vector.infallibleAppend(v); }
@@ -138,7 +142,7 @@
void popBack() { vector.popBack(); }
T popCopy() { return vector.popCopy(); }
- bool growBy(size_t inc) {
+ MOZ_MUST_USE bool growBy(size_t inc) {
size_t oldLength = vector.length();
if (!vector.growByUninitialized(inc))
return false;
@@ -146,7 +150,7 @@
return true;
}
- bool resize(size_t newLength) {
+ MOZ_MUST_USE bool resize(size_t newLength) {
size_t oldLength = vector.length();
if (newLength <= oldLength) {
vector.shrinkBy(oldLength - newLength);
@@ -160,7 +164,7 @@
void clear() { vector.clear(); }
- bool reserve(size_t newLength) {
+ MOZ_MUST_USE bool reserve(size_t newLength) {
return vector.reserve(newLength);
}
@@ -214,13 +218,36 @@
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
-typedef AutoVectorRooter<Value> AutoValueVector;
-typedef AutoVectorRooter<jsid> AutoIdVector;
-typedef AutoVectorRooter<JSObject*> AutoObjectVector;
-
-using ValueVector = js::TraceableVector<JS::Value>;
-using IdVector = js::TraceableVector<jsid>;
-using ScriptVector = js::TraceableVector<JSScript*>;
+class AutoValueVector : public Rooted<GCVector<Value, 8>> {
+ using Vec = GCVector<Value, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoValueVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoValueVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+};
+
+class AutoIdVector : public Rooted<GCVector<jsid, 8>> {
+ using Vec = GCVector<jsid, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoIdVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoIdVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+
+ bool appendAll(const AutoIdVector& other) { return this->Base::appendAll(other.get()); }
+};
+
+class AutoObjectVector : public Rooted<GCVector<JSObject*, 8>> {
+ using Vec = GCVector<JSObject*, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoObjectVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoObjectVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+};
+
+using ValueVector = JS::GCVector<JS::Value>;
+using IdVector = JS::GCVector<jsid>;
+using ScriptVector = JS::GCVector<JSScript*>;
+using StringVector = JS::GCVector<JSString*>;
template<class Key, class Value>
class MOZ_RAII AutoHashMapRooter : protected AutoGCRooter
@@ -454,7 +481,7 @@
{
public:
template <typename CX>
- explicit CustomAutoRooter(CX* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ explicit CustomAutoRooter(const CX& cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, CUSTOM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
@@ -463,6 +490,8 @@
friend void AutoGCRooter::trace(JSTracer* trc);
protected:
+ virtual ~CustomAutoRooter() {}
+
/** Supplied by derived class to trace roots. */
virtual void trace(JSTracer* trc) = 0;
@@ -518,15 +547,15 @@
/************************************************************************/
struct JSFreeOp {
- private:
+ protected:
JSRuntime* runtime_;
- protected:
explicit JSFreeOp(JSRuntime* rt)
: runtime_(rt) { }
public:
JSRuntime* runtime() const {
+ MOZ_ASSERT(runtime_);
return runtime_;
}
};
@@ -535,46 +564,28 @@
/************************************************************************/
-typedef enum JSContextOp {
- JSCONTEXT_NEW,
- JSCONTEXT_DESTROY
-} JSContextOp;
-
-/**
- * The possible values for contextOp when the runtime calls the callback are:
- * JSCONTEXT_NEW JS_NewContext successfully created a new JSContext
- * instance. The callback can initialize the instance as
- * required. If the callback returns false, the instance
- * will be destroyed and JS_NewContext returns null. In
- * this case the callback is not called again.
- * JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The
- * callback may perform its own cleanup and must always
- * return true.
- * Any other value For future compatibility the callback must do nothing
- * and return true in this case.
- */
-typedef bool
-(* JSContextCallback)(JSContext* cx, unsigned contextOp, void* data);
-
typedef enum JSGCStatus {
JSGC_BEGIN,
JSGC_END
} JSGCStatus;
typedef void
-(* JSGCCallback)(JSRuntime* rt, JSGCStatus status, void* data);
+(* JSGCCallback)(JSContext* cx, JSGCStatus status, void* data);
+
+typedef void
+(* JSObjectsTenuredCallback)(JSContext* cx, void* data);
typedef enum JSFinalizeStatus {
/**
- * Called when preparing to sweep a group of compartments, before anything
- * has been swept. The collector will not yield to the mutator before
- * calling the callback with JSFINALIZE_GROUP_END status.
+ * Called when preparing to sweep a group of zones, before anything has been
+ * swept. The collector will not yield to the mutator before calling the
+ * callback with JSFINALIZE_GROUP_END status.
*/
JSFINALIZE_GROUP_START,
/**
- * Called when preparing to sweep a group of compartments. Weak references
- * to unmarked things have been removed and things that are not swept
+ * Called when preparing to sweep a group of zones. Weak references to
+ * unmarked things have been removed and things that are not swept
* incrementally have been finalized at this point. The collector may yield
* to the mutator after this point.
*/
@@ -587,28 +598,48 @@
} JSFinalizeStatus;
typedef void
-(* JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status, bool isCompartment, void* data);
+(* JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status, bool isZoneGC, void* data);
typedef void
-(* JSWeakPointerZoneGroupCallback)(JSRuntime* rt, void* data);
+(* JSWeakPointerZoneGroupCallback)(JSContext* cx, void* data);
typedef void
-(* JSWeakPointerCompartmentCallback)(JSRuntime* rt, JSCompartment* comp, void* data);
+(* JSWeakPointerCompartmentCallback)(JSContext* cx, JSCompartment* comp, void* data);
typedef bool
(* JSInterruptCallback)(JSContext* cx);
+typedef JSObject*
+(* JSGetIncumbentGlobalCallback)(JSContext* cx);
+
+typedef bool
+(* JSEnqueuePromiseJobCallback)(JSContext* cx, JS::HandleObject job,
+ JS::HandleObject allocationSite, JS::HandleObject incumbentGlobal,
+ void* data);
+
+enum class PromiseRejectionHandlingState {
+ Unhandled,
+ Handled
+};
+
typedef void
-(* JSErrorReporter)(JSContext* cx, const char* message, JSErrorReport* report);
+(* JSPromiseRejectionTrackerCallback)(JSContext* cx, JS::HandleObject promise,
+ PromiseRejectionHandlingState state, void* data);
+
+typedef void
+(* JSProcessPromiseCallback)(JSContext* cx, JS::HandleObject promise);
/**
* Possible exception types. These types are part of a JSErrorFormatString
* structure. They define which error to throw in case of a runtime error.
- * JSEXN_NONE marks an unthrowable error.
+ *
+ * JSEXN_WARN is used for warnings in js.msg files (for instance because we
+ * don't want to prepend 'Error:' to warning messages). This value can go away
+ * if we ever decide to use an entirely separate mechanism for warnings.
*/
typedef enum JSExnType {
- JSEXN_NONE = -1,
- JSEXN_ERR,
+ JSEXN_ERR,
+ JSEXN_FIRST = JSEXN_ERR,
JSEXN_INTERNALERR,
JSEXN_EVALERR,
JSEXN_RANGEERR,
@@ -616,10 +647,17 @@
JSEXN_SYNTAXERR,
JSEXN_TYPEERR,
JSEXN_URIERR,
- JSEXN_LIMIT
+ JSEXN_DEBUGGEEWOULDRUN,
+ JSEXN_WASMCOMPILEERROR,
+ JSEXN_WASMRUNTIMEERROR,
+ JSEXN_WARN,
+ JSEXN_LIMIT
} JSExnType;
typedef struct JSErrorFormatString {
+ /** The error message name in ASCII. */
+ const char* name;
+
/** The error format string in ASCII. */
const char* format;
@@ -663,9 +701,10 @@
* for wrapping in a context. This might include unwrapping other wrappers
* or even finding a more suitable object for the new compartment.
*/
-typedef JSObject*
+typedef void
(* JSPreWrapCallback)(JSContext* cx, JS::HandleObject scope, JS::HandleObject obj,
- JS::HandleObject objectPassedToWrap);
+ JS::HandleObject objectPassedToWrap,
+ JS::MutableHandleObject retObj);
struct JSWrapObjectCallbacks
{
@@ -676,11 +715,15 @@
typedef void
(* JSDestroyCompartmentCallback)(JSFreeOp* fop, JSCompartment* compartment);
+typedef size_t
+(* JSSizeOfIncludingThisCompartmentCallback)(mozilla::MallocSizeOf mallocSizeOf,
+ JSCompartment* compartment);
+
typedef void
(* JSZoneCallback)(JS::Zone* zone);
typedef void
-(* JSCompartmentNameCallback)(JSRuntime* rt, JSCompartment* compartment,
+(* JSCompartmentNameCallback)(JSContext* cx, JSCompartment* compartment,
char* buf, size_t bufsize);
/************************************************************************/
@@ -746,6 +789,16 @@
}
}
+ SourceBufferHolder(SourceBufferHolder&& other)
+ : data_(other.data_),
+ length_(other.length_),
+ ownsChars_(other.ownsChars_)
+ {
+ other.data_ = nullptr;
+ other.length_ = 0;
+ other.ownsChars_ = false;
+ }
+
~SourceBufferHolder() {
if (ownsChars_)
js_free(const_cast<char16_t*>(data_));
@@ -815,29 +868,17 @@
object that delegates to a prototype
containing this property */
#define JSPROP_INTERNAL_USE_BIT 0x80 /* internal JS engine use only */
-#define JSPROP_DEFINE_LATE 0x100 /* Don't define property when initially creating
- the constructor. Some objects like Function/Object
- have self-hosted functions that can only be defined
- after the initialization is already finished. */
#define JSFUN_STUB_GSOPS 0x200 /* use JS_PropertyStub getter/setter
instead of defaulting to class gsops
for property holding function */
#define JSFUN_CONSTRUCTOR 0x400 /* native that can be called as a ctor */
-/*
- * Specify a generic native prototype methods, i.e., methods of a class
- * prototype that are exposed as static methods taking an extra leading
- * argument: the generic |this| parameter.
- *
- * If you set this flag in a JSFunctionSpec struct's flags initializer, then
- * that struct must live at least as long as the native static method object
- * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically
- * JSFunctionSpec structs are allocated in static arrays.
- */
-#define JSFUN_GENERIC_NATIVE 0x800
+// 0x800 /* Unused */
+
+#define JSFUN_HAS_REST 0x1000 /* function has ...rest parameter. */
-#define JSFUN_FLAGS_MASK 0xe00 /* | of all the JSFUN_* flags */
+#define JSFUN_FLAGS_MASK 0x1e00 /* | of all the JSFUN_* flags */
/*
* If set, will allow redefining a non-configurable property, but only on a
@@ -873,17 +914,6 @@
specified when passed to Object.defineProperty
from script. */
-/**
- * The first call to JS_CallOnce by any thread in a process will call 'func'.
- * Later calls to JS_CallOnce with the same JSCallOnceType object will be
- * suppressed.
- *
- * Equivalently: each distinct JSCallOnceType object will allow one JS_CallOnce
- * to invoke its JSInitCallback.
- */
-extern JS_PUBLIC_API(bool)
-JS_CallOnce(JSCallOnceType* once, JSInitCallback func);
-
/** Microseconds since the epoch, midnight, January 1, 1970 UTC. */
extern JS_PUBLIC_API(int64_t)
JS_Now(void);
@@ -902,7 +932,7 @@
JS_GetEmptyStringValue(JSContext* cx);
extern JS_PUBLIC_API(JSString*)
-JS_GetEmptyString(JSRuntime* rt);
+JS_GetEmptyString(JSContext* cx);
extern JS_PUBLIC_API(bool)
JS_ValueToObject(JSContext* cx, JS::HandleValue v, JS::MutableHandleObject objp);
@@ -922,6 +952,13 @@
extern JS_PUBLIC_API(JSType)
JS_TypeOfValue(JSContext* cx, JS::Handle<JS::Value> v);
+namespace JS {
+
+extern JS_PUBLIC_API(const char*)
+InformalValueTypeName(const JS::Value& v);
+
+} /* namespace JS */
+
extern JS_PUBLIC_API(bool)
JS_StrictlyEqual(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* equal);
@@ -944,19 +981,19 @@
/*
* Locking, contexts, and memory allocation.
*
- * It is important that SpiderMonkey be initialized, and the first runtime and
- * first context be created, in a single-threaded fashion. Otherwise the
- * behavior of the library is undefined.
+ * It is important that SpiderMonkey be initialized, and the first context
+ * be created, in a single-threaded fashion. Otherwise the behavior of the
+ * library is undefined.
* See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
*/
-extern JS_PUBLIC_API(JSRuntime*)
-JS_NewRuntime(uint32_t maxbytes,
+extern JS_PUBLIC_API(JSContext*)
+JS_NewContext(uint32_t maxbytes,
uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
- JSRuntime* parentRuntime = nullptr);
+ JSContext* parentContext = nullptr);
extern JS_PUBLIC_API(void)
-JS_DestroyRuntime(JSRuntime* rt);
+JS_DestroyContext(JSContext* cx);
typedef double (*JS_CurrentEmbedderTimeFunction)();
@@ -978,16 +1015,13 @@
JS_GetCurrentEmbedderTime();
JS_PUBLIC_API(void*)
-JS_GetRuntimePrivate(JSRuntime* rt);
-
-extern JS_PUBLIC_API(JSRuntime*)
-JS_GetRuntime(JSContext* cx);
-
-extern JS_PUBLIC_API(JSRuntime*)
-JS_GetParentRuntime(JSContext* cx);
+JS_GetContextPrivate(JSContext* cx);
JS_PUBLIC_API(void)
-JS_SetRuntimePrivate(JSRuntime* rt, void* data);
+JS_SetContextPrivate(JSContext* cx, void* data);
+
+extern JS_PUBLIC_API(JSContext*)
+JS_GetParentContext(JSContext* cx);
extern JS_PUBLIC_API(void)
JS_BeginRequest(JSContext* cx);
@@ -995,14 +1029,14 @@
extern JS_PUBLIC_API(void)
JS_EndRequest(JSContext* cx);
+extern JS_PUBLIC_API(void)
+JS_SetFutexCanWait(JSContext* cx);
+
namespace js {
void
AssertHeapIsIdle(JSRuntime* rt);
-void
-AssertHeapIsIdle(JSContext* cx);
-
} /* namespace js */
class MOZ_RAII JSAutoRequest
@@ -1030,36 +1064,6 @@
#endif
};
-extern JS_PUBLIC_API(void)
-JS_SetContextCallback(JSRuntime* rt, JSContextCallback cxCallback, void* data);
-
-extern JS_PUBLIC_API(JSContext*)
-JS_NewContext(JSRuntime* rt, size_t stackChunkSize);
-
-extern JS_PUBLIC_API(void)
-JS_DestroyContext(JSContext* cx);
-
-extern JS_PUBLIC_API(void)
-JS_DestroyContextNoGC(JSContext* cx);
-
-extern JS_PUBLIC_API(void*)
-JS_GetContextPrivate(JSContext* cx);
-
-extern JS_PUBLIC_API(void)
-JS_SetContextPrivate(JSContext* cx, void* data);
-
-extern JS_PUBLIC_API(void*)
-JS_GetSecondContextPrivate(JSContext* cx);
-
-extern JS_PUBLIC_API(void)
-JS_SetSecondContextPrivate(JSContext* cx, void* data);
-
-extern JS_PUBLIC_API(JSRuntime*)
-JS_GetRuntime(JSContext* cx);
-
-extern JS_PUBLIC_API(JSContext*)
-JS_ContextIterator(JSRuntime* rt, JSContext** iterp);
-
extern JS_PUBLIC_API(JSVersion)
JS_GetVersion(JSContext* cx);
@@ -1082,16 +1086,20 @@
namespace JS {
-class JS_PUBLIC_API(RuntimeOptions) {
+class JS_PUBLIC_API(ContextOptions) {
public:
- RuntimeOptions()
+ ContextOptions()
: baseline_(true),
ion_(true),
asmJS_(true),
+ wasm_(false),
+ wasmAlwaysBaseline_(false),
throwOnAsmJSValidationFailure_(false),
nativeRegExp_(true),
unboxedArrays_(false),
asyncStack_(true),
+ throwOnDebuggeeWouldRun_(true),
+ dumpStackOnDebuggeeWouldRun_(false),
werror_(false),
strictMode_(false),
extraWarnings_(false)
@@ -1099,89 +1107,121 @@
}
bool baseline() const { return baseline_; }
- RuntimeOptions& setBaseline(bool flag) {
+ ContextOptions& setBaseline(bool flag) {
baseline_ = flag;
return *this;
}
- RuntimeOptions& toggleBaseline() {
+ ContextOptions& toggleBaseline() {
baseline_ = !baseline_;
return *this;
}
bool ion() const { return ion_; }
- RuntimeOptions& setIon(bool flag) {
+ ContextOptions& setIon(bool flag) {
ion_ = flag;
return *this;
}
- RuntimeOptions& toggleIon() {
+ ContextOptions& toggleIon() {
ion_ = !ion_;
return *this;
}
bool asmJS() const { return asmJS_; }
- RuntimeOptions& setAsmJS(bool flag) {
+ ContextOptions& setAsmJS(bool flag) {
asmJS_ = flag;
return *this;
}
- RuntimeOptions& toggleAsmJS() {
+ ContextOptions& toggleAsmJS() {
asmJS_ = !asmJS_;
return *this;
}
+ bool wasm() const { return wasm_; }
+ ContextOptions& setWasm(bool flag) {
+ wasm_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleWasm() {
+ wasm_ = !wasm_;
+ return *this;
+ }
+
+ bool wasmAlwaysBaseline() const { return wasmAlwaysBaseline_; }
+ ContextOptions& setWasmAlwaysBaseline(bool flag) {
+ wasmAlwaysBaseline_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleWasmAlwaysBaseline() {
+ wasmAlwaysBaseline_ = !wasmAlwaysBaseline_;
+ return *this;
+ }
+
bool throwOnAsmJSValidationFailure() const { return throwOnAsmJSValidationFailure_; }
- RuntimeOptions& setThrowOnAsmJSValidationFailure(bool flag) {
+ ContextOptions& setThrowOnAsmJSValidationFailure(bool flag) {
throwOnAsmJSValidationFailure_ = flag;
return *this;
}
- RuntimeOptions& toggleThrowOnAsmJSValidationFailure() {
+ ContextOptions& toggleThrowOnAsmJSValidationFailure() {
throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
return *this;
}
bool nativeRegExp() const { return nativeRegExp_; }
- RuntimeOptions& setNativeRegExp(bool flag) {
+ ContextOptions& setNativeRegExp(bool flag) {
nativeRegExp_ = flag;
return *this;
}
bool unboxedArrays() const { return unboxedArrays_; }
- RuntimeOptions& setUnboxedArrays(bool flag) {
+ ContextOptions& setUnboxedArrays(bool flag) {
unboxedArrays_ = flag;
return *this;
}
bool asyncStack() const { return asyncStack_; }
- RuntimeOptions& setAsyncStack(bool flag) {
+ ContextOptions& setAsyncStack(bool flag) {
asyncStack_ = flag;
return *this;
}
+ bool throwOnDebuggeeWouldRun() const { return throwOnDebuggeeWouldRun_; }
+ ContextOptions& setThrowOnDebuggeeWouldRun(bool flag) {
+ throwOnDebuggeeWouldRun_ = flag;
+ return *this;
+ }
+
+ bool dumpStackOnDebuggeeWouldRun() const { return dumpStackOnDebuggeeWouldRun_; }
+ ContextOptions& setDumpStackOnDebuggeeWouldRun(bool flag) {
+ dumpStackOnDebuggeeWouldRun_ = flag;
+ return *this;
+ }
+
bool werror() const { return werror_; }
- RuntimeOptions& setWerror(bool flag) {
+ ContextOptions& setWerror(bool flag) {
werror_ = flag;
return *this;
}
- RuntimeOptions& toggleWerror() {
+ ContextOptions& toggleWerror() {
werror_ = !werror_;
return *this;
}
bool strictMode() const { return strictMode_; }
- RuntimeOptions& setStrictMode(bool flag) {
+ ContextOptions& setStrictMode(bool flag) {
strictMode_ = flag;
return *this;
}
- RuntimeOptions& toggleStrictMode() {
+ ContextOptions& toggleStrictMode() {
strictMode_ = !strictMode_;
return *this;
}
bool extraWarnings() const { return extraWarnings_; }
- RuntimeOptions& setExtraWarnings(bool flag) {
+ ContextOptions& setExtraWarnings(bool flag) {
extraWarnings_ = flag;
return *this;
}
- RuntimeOptions& toggleExtraWarnings() {
+ ContextOptions& toggleExtraWarnings() {
extraWarnings_ = !extraWarnings_;
return *this;
}
@@ -1190,94 +1230,36 @@
bool baseline_ : 1;
bool ion_ : 1;
bool asmJS_ : 1;
+ bool wasm_ : 1;
+ bool wasmAlwaysBaseline_ : 1;
bool throwOnAsmJSValidationFailure_ : 1;
bool nativeRegExp_ : 1;
bool unboxedArrays_ : 1;
bool asyncStack_ : 1;
+ bool throwOnDebuggeeWouldRun_ : 1;
+ bool dumpStackOnDebuggeeWouldRun_ : 1;
bool werror_ : 1;
bool strictMode_ : 1;
bool extraWarnings_ : 1;
};
-JS_PUBLIC_API(RuntimeOptions&)
-RuntimeOptionsRef(JSRuntime* rt);
-
-JS_PUBLIC_API(RuntimeOptions&)
-RuntimeOptionsRef(JSContext* cx);
-
-class JS_PUBLIC_API(ContextOptions) {
- public:
- ContextOptions()
- : privateIsNSISupports_(false),
- dontReportUncaught_(false),
- autoJSAPIOwnsErrorReporting_(false)
- {
- }
-
- bool privateIsNSISupports() const { return privateIsNSISupports_; }
- ContextOptions& setPrivateIsNSISupports(bool flag) {
- privateIsNSISupports_ = flag;
- return *this;
- }
- ContextOptions& togglePrivateIsNSISupports() {
- privateIsNSISupports_ = !privateIsNSISupports_;
- return *this;
- }
-
- bool dontReportUncaught() const { return dontReportUncaught_; }
- ContextOptions& setDontReportUncaught(bool flag) {
- dontReportUncaught_ = flag;
- return *this;
- }
- ContextOptions& toggleDontReportUncaught() {
- dontReportUncaught_ = !dontReportUncaught_;
- return *this;
- }
-
- bool autoJSAPIOwnsErrorReporting() const { return autoJSAPIOwnsErrorReporting_; }
- ContextOptions& setAutoJSAPIOwnsErrorReporting(bool flag) {
- autoJSAPIOwnsErrorReporting_ = flag;
- return *this;
- }
- ContextOptions& toggleAutoJSAPIOwnsErrorReporting() {
- autoJSAPIOwnsErrorReporting_ = !autoJSAPIOwnsErrorReporting_;
- return *this;
- }
-
-
- private:
- bool privateIsNSISupports_ : 1;
- bool dontReportUncaught_ : 1;
- // dontReportUncaught isn't respected by all JSAPI codepaths, particularly the
- // JS_ReportError* functions that eventually report the error even when dontReportUncaught is
- // set, if script is not running. We want a way to indicate that the embedder will always
- // handle any exceptions, and that SpiderMonkey should just leave them on the context. This is
- // the way we want to do all future error handling in Gecko - stealing the exception explicitly
- // from the context and handling it as per the situation. This will eventually become the
- // default and these 2 flags should go away.
- bool autoJSAPIOwnsErrorReporting_ : 1;
-};
-
JS_PUBLIC_API(ContextOptions&)
ContextOptionsRef(JSContext* cx);
-class JS_PUBLIC_API(AutoSaveContextOptions) {
- public:
- explicit AutoSaveContextOptions(JSContext* cx)
- : cx_(cx),
- oldOptions_(ContextOptionsRef(cx_))
- {
- }
-
- ~AutoSaveContextOptions()
- {
- ContextOptionsRef(cx_) = oldOptions_;
- }
+/**
+ * Initialize the runtime's self-hosted code. Embeddings should call this
+ * exactly once per runtime/context, before the first JS_NewGlobalObject
+ * call.
+ */
+JS_PUBLIC_API(bool)
+InitSelfHostedCode(JSContext* cx);
- private:
- JSContext* cx_;
- JS::ContextOptions oldOptions_;
-};
+/**
+ * Asserts (in debug and release builds) that `obj` belongs to the current
+ * thread's context.
+ */
+JS_PUBLIC_API(void)
+AssertObjectBelongsToCurrentThread(JSObject* obj);
} /* namespace JS */
@@ -1285,19 +1267,23 @@
JS_GetImplementationVersion(void);
extern JS_PUBLIC_API(void)
-JS_SetDestroyCompartmentCallback(JSRuntime* rt, JSDestroyCompartmentCallback callback);
+JS_SetDestroyCompartmentCallback(JSContext* cx, JSDestroyCompartmentCallback callback);
+
+extern JS_PUBLIC_API(void)
+JS_SetSizeOfIncludingThisCompartmentCallback(JSContext* cx,
+ JSSizeOfIncludingThisCompartmentCallback callback);
extern JS_PUBLIC_API(void)
-JS_SetDestroyZoneCallback(JSRuntime* rt, JSZoneCallback callback);
+JS_SetDestroyZoneCallback(JSContext* cx, JSZoneCallback callback);
extern JS_PUBLIC_API(void)
-JS_SetSweepZoneCallback(JSRuntime* rt, JSZoneCallback callback);
+JS_SetSweepZoneCallback(JSContext* cx, JSZoneCallback callback);
extern JS_PUBLIC_API(void)
-JS_SetCompartmentNameCallback(JSRuntime* rt, JSCompartmentNameCallback callback);
+JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback);
extern JS_PUBLIC_API(void)
-JS_SetWrapObjectCallbacks(JSRuntime* rt, const JSWrapObjectCallbacks* callbacks);
+JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks);
extern JS_PUBLIC_API(void)
JS_SetCompartmentPrivate(JSCompartment* compartment, void* data);
@@ -1391,7 +1377,7 @@
extern JS_PUBLIC_API(void)
JS_LeaveCompartment(JSContext* cx, JSCompartment* oldCompartment);
-typedef void (*JSIterateCompartmentCallback)(JSRuntime* rt, void* data, JSCompartment* compartment);
+typedef void (*JSIterateCompartmentCallback)(JSContext* cx, void* data, JSCompartment* compartment);
/**
* This function calls |compartmentCallback| on every compartment. Beware that
@@ -1399,7 +1385,7 @@
* returns. Also, barriers are disabled via the TraceSession.
*/
extern JS_PUBLIC_API(void)
-JS_IterateCompartments(JSRuntime* rt, void* data,
+JS_IterateCompartments(JSContext* cx, void* data,
JSIterateCompartmentCallback compartmentCallback);
/**
@@ -1509,13 +1495,13 @@
JS_IsGlobalObject(JSObject* obj);
extern JS_PUBLIC_API(JSObject*)
-JS_GlobalLexicalScope(JSObject* obj);
+JS_GlobalLexicalEnvironment(JSObject* obj);
extern JS_PUBLIC_API(bool)
-JS_HasExtensibleLexicalScope(JSObject* obj);
+JS_HasExtensibleLexicalEnvironment(JSObject* obj);
extern JS_PUBLIC_API(JSObject*)
-JS_ExtensibleLexicalScope(JSObject* obj);
+JS_ExtensibleLexicalEnvironment(JSObject* obj);
/**
* May return nullptr, if |c| never had a global (e.g. the atoms compartment),
@@ -1607,50 +1593,47 @@
extern JS_PUBLIC_API(void)
JS_freeop(JSFreeOp* fop, void* p);
-extern JS_PUBLIC_API(JSFreeOp*)
-JS_GetDefaultFreeOp(JSRuntime* rt);
-
extern JS_PUBLIC_API(void)
JS_updateMallocCounter(JSContext* cx, size_t nbytes);
extern JS_PUBLIC_API(char*)
JS_strdup(JSContext* cx, const char* s);
-/** Duplicate a string. Does not report an error on failure. */
-extern JS_PUBLIC_API(char*)
-JS_strdup(JSRuntime* rt, const char* s);
-
/**
* Register externally maintained GC roots.
*
* traceOp: the trace operation. For each root the implementation should call
- * JS_CallTracer whenever the root contains a traceable thing.
+ * JS::TraceEdge whenever the root contains a traceable thing.
* data: the data argument to pass to each invocation of traceOp.
*/
extern JS_PUBLIC_API(bool)
-JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
+JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
/** Undo a call to JS_AddExtraGCRootsTracer. */
extern JS_PUBLIC_API(void)
-JS_RemoveExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
+JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
/*
* Garbage collector API.
*/
extern JS_PUBLIC_API(void)
-JS_GC(JSRuntime* rt);
+JS_GC(JSContext* cx);
extern JS_PUBLIC_API(void)
JS_MaybeGC(JSContext* cx);
extern JS_PUBLIC_API(void)
-JS_SetGCCallback(JSRuntime* rt, JSGCCallback cb, void* data);
+JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data);
+
+extern JS_PUBLIC_API(void)
+JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb,
+ void* data);
extern JS_PUBLIC_API(bool)
-JS_AddFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb, void* data);
+JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data);
extern JS_PUBLIC_API(void)
-JS_RemoveFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb);
+JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb);
/*
* Weak pointers and garbage collection
@@ -1687,17 +1670,17 @@
*/
extern JS_PUBLIC_API(bool)
-JS_AddWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb, void* data);
+JS_AddWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb, void* data);
extern JS_PUBLIC_API(void)
-JS_RemoveWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb);
+JS_RemoveWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb);
extern JS_PUBLIC_API(bool)
-JS_AddWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb,
+JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb,
void* data);
extern JS_PUBLIC_API(void)
-JS_RemoveWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb);
+JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb);
extern JS_PUBLIC_API(void)
JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp);
@@ -1718,9 +1701,6 @@
/** Number of times GC has been invoked. Includes both major and minor GC. */
JSGC_NUMBER = 4,
- /** Max size of the code cache in bytes. */
- JSGC_MAX_CODE_CACHE_BYTES = 5,
-
/** Select GC mode. */
JSGC_MODE = 6,
@@ -1770,13 +1750,6 @@
JSGC_ALLOCATION_THRESHOLD = 19,
/**
- * We decommit memory lazily. If more than this number of megabytes is
- * available to be decommitted, then JS_MaybeGC will trigger a shrinking GC
- * to decommit it.
- */
- JSGC_DECOMMIT_THRESHOLD = 20,
-
- /**
* We try to keep at least this many unused chunks in the free chunk pool at
* all times, even after a shrinking GC.
*/
@@ -1786,23 +1759,20 @@
JSGC_MAX_EMPTY_CHUNK_COUNT = 22,
/** Whether compacting GC is enabled. */
- JSGC_COMPACTING_ENABLED = 23
-} JSGCParamKey;
-
-extern JS_PUBLIC_API(void)
-JS_SetGCParameter(JSRuntime* rt, JSGCParamKey key, uint32_t value);
+ JSGC_COMPACTING_ENABLED = 23,
-extern JS_PUBLIC_API(uint32_t)
-JS_GetGCParameter(JSRuntime* rt, JSGCParamKey key);
+ /** If true, painting can trigger IGC slices. */
+ JSGC_REFRESH_FRAME_SLICES_ENABLED = 24,
+} JSGCParamKey;
extern JS_PUBLIC_API(void)
-JS_SetGCParameterForThread(JSContext* cx, JSGCParamKey key, uint32_t value);
+JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value);
extern JS_PUBLIC_API(uint32_t)
-JS_GetGCParameterForThread(JSContext* cx, JSGCParamKey key);
+JS_GetGCParameter(JSContext* cx, JSGCParamKey key);
extern JS_PUBLIC_API(void)
-JS_SetGCParametersBasedOnAvailableMemory(JSRuntime* rt, uint32_t availMem);
+JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem);
/**
* Create a new JSString whose chars member refers to external memory, i.e.,
@@ -1844,7 +1814,7 @@
* and before any code is executed and/or interrupts requested.
*/
extern JS_PUBLIC_API(void)
-JS_SetNativeStackQuota(JSRuntime* cx, size_t systemCodeStackSize,
+JS_SetNativeStackQuota(JSContext* cx, size_t systemCodeStackSize,
size_t trustedScriptStackSize = 0,
size_t untrustedScriptStackSize = 0);
@@ -1927,22 +1897,42 @@
*/
struct JSPropertySpec {
struct SelfHostedWrapper {
- void* unused;
+ void* unused;
const char* funname;
};
+ struct ValueWrapper {
+ uintptr_t type;
+ union {
+ const char* string;
+ int32_t int32;
+ };
+ };
+
const char* name;
uint8_t flags;
union {
- JSNativeWrapper native;
- SelfHostedWrapper selfHosted;
- } getter;
- union {
- JSNativeWrapper native;
- SelfHostedWrapper selfHosted;
- } setter;
+ struct {
+ union {
+ JSNativeWrapper native;
+ SelfHostedWrapper selfHosted;
+ } getter;
+ union {
+ JSNativeWrapper native;
+ SelfHostedWrapper selfHosted;
+ } setter;
+ } accessors;
+ ValueWrapper value;
+ };
+
+ bool isAccessor() const {
+ return !(flags & JSPROP_INTERNAL_USE_BIT);
+ }
+ JS_PUBLIC_API(bool) getValue(JSContext* cx, JS::MutableHandleValue value) const;
bool isSelfHosted() const {
+ MOZ_ASSERT(isAccessor());
+
#ifdef DEBUG
// Verify that our accessors match our JSPROP_GETTER flag.
if (flags & JSPROP_GETTER)
@@ -1961,17 +1951,17 @@
"JSNativeWrapper::info");
private:
void checkAccessorsAreNative() const {
- MOZ_ASSERT(getter.native.op);
+ MOZ_ASSERT(accessors.getter.native.op);
// We may not have a setter at all. So all we can assert here, for the
// native case is that if we have a jitinfo for the setter then we have
// a setter op too. This is good enough to make sure we don't have a
// SelfHostedWrapper for the setter.
- MOZ_ASSERT_IF(setter.native.info, setter.native.op);
+ MOZ_ASSERT_IF(accessors.setter.native.info, accessors.setter.native.op);
}
void checkAccessorsAreSelfHosted() const {
- MOZ_ASSERT(!getter.selfHosted.unused);
- MOZ_ASSERT(!setter.selfHosted.unused);
+ MOZ_ASSERT(!accessors.getter.selfHosted.unused);
+ MOZ_ASSERT(!accessors.setter.selfHosted.unused);
}
};
@@ -1986,13 +1976,15 @@
inline int
CheckIsCharacterLiteral(const char (&arr)[N]);
+/* NEVER DEFINED, DON'T USE. For use by JS_CAST_INT32_TO only. */
+inline int CheckIsInt32(int32_t value);
+
/* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_GETTER only. */
inline int CheckIsGetterOp(JSGetterOp op);
/* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_SETTER only. */
inline int CheckIsSetterOp(JSSetterOp op);
-
} // namespace detail
} // namespace JS
@@ -2004,6 +1996,10 @@
(static_cast<void>(sizeof(JS::detail::CheckIsCharacterLiteral(s))), \
reinterpret_cast<To>(s))
+#define JS_CAST_INT32_TO(s, To) \
+ (static_cast<void>(sizeof(JS::detail::CheckIsInt32(s))), \
+ reinterpret_cast<To>(s))
+
#define JS_CHECK_ACCESSOR_FLAGS(flags) \
(static_cast<mozilla::EnableIf<((flags) & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT)) == 0>::Type>(0), \
(flags))
@@ -2020,37 +2016,50 @@
#define JS_STUBSETTER JS_PROPERTYOP_SETTER(JS_StrictPropertyStub)
+#define JS_PS_ACCESSOR_SPEC(name, getter, setter, flags, extraFlags) \
+ { name, uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | extraFlags), \
+ { { getter, setter } } }
+#define JS_PS_VALUE_SPEC(name, value, flags) \
+ { name, uint8_t(flags | JSPROP_INTERNAL_USE_BIT), \
+ { { value, JSNATIVE_WRAPPER(nullptr) } } }
+
+#define SELFHOSTED_WRAPPER(name) \
+ { { nullptr, JS_CAST_STRING_TO(name, const JSJitInfo*) } }
+#define STRINGVALUE_WRAPPER(value) \
+ { { reinterpret_cast<JSNative>(JSVAL_TYPE_STRING), JS_CAST_STRING_TO(value, const JSJitInfo*) } }
+#define INT32VALUE_WRAPPER(value) \
+ { { reinterpret_cast<JSNative>(JSVAL_TYPE_INT32), JS_CAST_INT32_TO(value, const JSJitInfo*) } }
+
/*
* JSPropertySpec uses JSNativeWrapper. These macros encapsulate the definition
* of JSNative-backed JSPropertySpecs, by defining the JSNativeWrappers for
* them.
*/
#define JS_PSG(name, getter, flags) \
- {name, \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
- JSNATIVE_WRAPPER(getter), \
- JSNATIVE_WRAPPER(nullptr)}
+ JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED)
#define JS_PSGS(name, getter, setter, flags) \
- {name, \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
- JSNATIVE_WRAPPER(getter), \
- JSNATIVE_WRAPPER(setter)}
+ JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(setter), flags, \
+ JSPROP_SHARED)
#define JS_SELF_HOSTED_GET(name, getterName, flags) \
- {name, \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
- { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
- JSNATIVE_WRAPPER(nullptr) }
+ JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED | JSPROP_GETTER)
#define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
- {name, \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER), \
- { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) }, \
- { nullptr, JS_CAST_STRING_TO(setterName, const JSJitInfo*) } }
-#define JS_PS_END { nullptr, 0, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr) }
+ JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), SELFHOSTED_WRAPPER(setterName), \
+ flags, JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER)
#define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \
- {reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
- { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
- JSNATIVE_WRAPPER(nullptr) }
+ JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
+ SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED | JSPROP_GETTER)
+#define JS_STRING_PS(name, string, flags) \
+ JS_PS_VALUE_SPEC(name, STRINGVALUE_WRAPPER(string), flags)
+#define JS_STRING_SYM_PS(symbol, string, flags) \
+ JS_PS_VALUE_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
+ STRINGVALUE_WRAPPER(string), flags)
+#define JS_INT32_PS(name, value, flags) \
+ JS_PS_VALUE_SPEC(name, INT32VALUE_WRAPPER(value), flags)
+#define JS_PS_END \
+ JS_PS_ACCESSOR_SPEC(nullptr, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr), 0, 0)
/**
* To define a native function, set call to a JSNativeWrapper. To define a
@@ -2128,6 +2137,17 @@
extern JS_PUBLIC_API(bool)
JS_HasInstance(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<JS::Value> v, bool* bp);
+namespace JS {
+
+// Implementation of
+// http://www.ecma-international.org/ecma-262/6.0/#sec-ordinaryhasinstance. If
+// you're looking for the equivalent of "instanceof", you want JS_HasInstance,
+// not this function.
+extern JS_PUBLIC_API(bool)
+OrdinaryHasInstance(JSContext* cx, HandleObject objArg, HandleValue v, bool* bp);
+
+} // namespace JS
+
extern JS_PUBLIC_API(void*)
JS_GetPrivate(JSObject* obj);
@@ -2148,7 +2168,121 @@
SystemZone = 1
};
-class JS_PUBLIC_API(CompartmentOptions)
+/**
+ * CompartmentCreationOptions specifies options relevant to creating a new
+ * compartment, that are either immutable characteristics of that compartment
+ * or that are discarded after the compartment has been created.
+ *
+ * Access to these options on an existing compartment is read-only: if you
+ * need particular selections, make them before you create the compartment.
+ */
+class JS_PUBLIC_API(CompartmentCreationOptions)
+{
+ public:
+ CompartmentCreationOptions()
+ : addonId_(nullptr),
+ traceGlobal_(nullptr),
+ invisibleToDebugger_(false),
+ mergeable_(false),
+ preserveJitCode_(false),
+ cloneSingletons_(false),
+ sharedMemoryAndAtomics_(false),
+ secureContext_(false)
+ {
+ zone_.spec = JS::FreshZone;
+ }
+
+ // A null add-on ID means that the compartment is not associated with an
+ // add-on.
+ JSAddonId* addonIdOrNull() const { return addonId_; }
+ CompartmentCreationOptions& setAddonId(JSAddonId* id) {
+ addonId_ = id;
+ return *this;
+ }
+
+ JSTraceOp getTrace() const {
+ return traceGlobal_;
+ }
+ CompartmentCreationOptions& setTrace(JSTraceOp op) {
+ traceGlobal_ = op;
+ return *this;
+ }
+
+ void* zonePointer() const {
+ MOZ_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
+ return zone_.pointer;
+ }
+ ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
+ CompartmentCreationOptions& setZone(ZoneSpecifier spec);
+ CompartmentCreationOptions& setSameZoneAs(JSObject* obj);
+
+ // Certain scopes (i.e. XBL compilation scopes) are implementation details
+ // of the embedding, and references to them should never leak out to script.
+ // This flag causes the this compartment to skip firing onNewGlobalObject
+ // and makes addDebuggee a no-op for this global.
+ bool invisibleToDebugger() const { return invisibleToDebugger_; }
+ CompartmentCreationOptions& setInvisibleToDebugger(bool flag) {
+ invisibleToDebugger_ = flag;
+ return *this;
+ }
+
+ // Compartments used for off-thread compilation have their contents merged
+ // into a target compartment when the compilation is finished. This is only
+ // allowed if this flag is set. The invisibleToDebugger flag must also be
+ // set for such compartments.
+ bool mergeable() const { return mergeable_; }
+ CompartmentCreationOptions& setMergeable(bool flag) {
+ mergeable_ = flag;
+ return *this;
+ }
+
+ // Determines whether this compartment should preserve JIT code on
+ // non-shrinking GCs.
+ bool preserveJitCode() const { return preserveJitCode_; }
+ CompartmentCreationOptions& setPreserveJitCode(bool flag) {
+ preserveJitCode_ = flag;
+ return *this;
+ }
+
+ bool cloneSingletons() const { return cloneSingletons_; }
+ CompartmentCreationOptions& setCloneSingletons(bool flag) {
+ cloneSingletons_ = flag;
+ return *this;
+ }
+
+ bool getSharedMemoryAndAtomicsEnabled() const;
+ CompartmentCreationOptions& setSharedMemoryAndAtomicsEnabled(bool flag);
+
+ // This flag doesn't affect JS engine behavior. It is used by Gecko to
+ // mark whether content windows and workers are "Secure Context"s. See
+ // https://w3c.github.io/webappsec-secure-contexts/
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1162772#c34
+ bool secureContext() const { return secureContext_; }
+ CompartmentCreationOptions& setSecureContext(bool flag) {
+ secureContext_ = flag;
+ return *this;
+ }
+
+ private:
+ JSAddonId* addonId_;
+ JSTraceOp traceGlobal_;
+ union {
+ ZoneSpecifier spec;
+ void* pointer; // js::Zone* is not exposed in the API.
+ } zone_;
+ bool invisibleToDebugger_;
+ bool mergeable_;
+ bool preserveJitCode_;
+ bool cloneSingletons_;
+ bool sharedMemoryAndAtomics_;
+ bool secureContext_;
+};
+
+/**
+ * CompartmentBehaviors specifies behaviors of a compartment that can be
+ * changed after the compartment's been created.
+ */
+class JS_PUBLIC_API(CompartmentBehaviors)
{
public:
class Override {
@@ -2179,140 +2313,119 @@
Mode mode_;
};
- explicit CompartmentOptions()
+ CompartmentBehaviors()
: version_(JSVERSION_UNKNOWN)
- , invisibleToDebugger_(false)
- , mergeable_(false)
, discardSource_(false)
, disableLazyParsing_(false)
- , cloneSingletons_(false)
- , traceGlobal_(nullptr)
, singletonsAsTemplates_(true)
- , addonId_(nullptr)
- , preserveJitCode_(false)
{
- zone_.spec = JS::FreshZone;
}
JSVersion version() const { return version_; }
- CompartmentOptions& setVersion(JSVersion aVersion) {
+ CompartmentBehaviors& setVersion(JSVersion aVersion) {
MOZ_ASSERT(aVersion != JSVERSION_UNKNOWN);
version_ = aVersion;
return *this;
}
- // Certain scopes (i.e. XBL compilation scopes) are implementation details
- // of the embedding, and references to them should never leak out to script.
- // This flag causes the this compartment to skip firing onNewGlobalObject
- // and makes addDebuggee a no-op for this global.
- bool invisibleToDebugger() const { return invisibleToDebugger_; }
- CompartmentOptions& setInvisibleToDebugger(bool flag) {
- invisibleToDebugger_ = flag;
- return *this;
- }
-
- // Compartments used for off-thread compilation have their contents merged
- // into a target compartment when the compilation is finished. This is only
- // allowed if this flag is set. The invisibleToDebugger flag must also be
- // set for such compartments.
- bool mergeable() const { return mergeable_; }
- CompartmentOptions& setMergeable(bool flag) {
- mergeable_ = flag;
- return *this;
- }
-
// For certain globals, we know enough about the code that will run in them
// that we can discard script source entirely.
bool discardSource() const { return discardSource_; }
- CompartmentOptions& setDiscardSource(bool flag) {
+ CompartmentBehaviors& setDiscardSource(bool flag) {
discardSource_ = flag;
return *this;
}
bool disableLazyParsing() const { return disableLazyParsing_; }
- CompartmentOptions& setDisableLazyParsing(bool flag) {
+ CompartmentBehaviors& setDisableLazyParsing(bool flag) {
disableLazyParsing_ = flag;
return *this;
}
- bool cloneSingletons() const { return cloneSingletons_; }
- CompartmentOptions& setCloneSingletons(bool flag) {
- cloneSingletons_ = flag;
- return *this;
- }
-
- bool extraWarnings(JSRuntime* rt) const;
bool extraWarnings(JSContext* cx) const;
Override& extraWarningsOverride() { return extraWarningsOverride_; }
- void* zonePointer() const {
- MOZ_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
- return zone_.pointer;
- }
- ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
- CompartmentOptions& setZone(ZoneSpecifier spec);
- CompartmentOptions& setSameZoneAs(JSObject* obj);
-
- void setSingletonsAsValues() {
- singletonsAsTemplates_ = false;
- }
bool getSingletonsAsTemplates() const {
return singletonsAsTemplates_;
}
-
- // A null add-on ID means that the compartment is not associated with an
- // add-on.
- JSAddonId* addonIdOrNull() const { return addonId_; }
- CompartmentOptions& setAddonId(JSAddonId* id) {
- addonId_ = id;
- return *this;
- }
-
- CompartmentOptions& setTrace(JSTraceOp op) {
- traceGlobal_ = op;
- return *this;
- }
- JSTraceOp getTrace() const {
- return traceGlobal_;
- }
-
- bool preserveJitCode() const { return preserveJitCode_; }
- CompartmentOptions& setPreserveJitCode(bool flag) {
- preserveJitCode_ = flag;
+ CompartmentBehaviors& setSingletonsAsValues() {
+ singletonsAsTemplates_ = false;
return *this;
}
private:
JSVersion version_;
- bool invisibleToDebugger_;
- bool mergeable_;
bool discardSource_;
bool disableLazyParsing_;
- bool cloneSingletons_;
Override extraWarningsOverride_;
- union {
- ZoneSpecifier spec;
- void* pointer; // js::Zone* is not exposed in the API.
- } zone_;
- JSTraceOp traceGlobal_;
// To XDR singletons, we need to ensure that all singletons are all used as
// templates, by making JSOP_OBJECT return a clone of the JSScript
// singleton, instead of returning the value which is baked in the JSScript.
bool singletonsAsTemplates_;
+};
- JSAddonId* addonId_;
- bool preserveJitCode_;
+/**
+ * CompartmentOptions specifies compartment characteristics: both those that
+ * can't be changed on a compartment once it's been created
+ * (CompartmentCreationOptions), and those that can be changed on an existing
+ * compartment (CompartmentBehaviors).
+ */
+class JS_PUBLIC_API(CompartmentOptions)
+{
+ public:
+ explicit CompartmentOptions()
+ : creationOptions_(),
+ behaviors_()
+ {}
+
+ CompartmentOptions(const CompartmentCreationOptions& compartmentCreation,
+ const CompartmentBehaviors& compartmentBehaviors)
+ : creationOptions_(compartmentCreation),
+ behaviors_(compartmentBehaviors)
+ {}
+
+ // CompartmentCreationOptions specify fundamental compartment
+ // characteristics that must be specified when the compartment is created,
+ // that can't be changed after the compartment is created.
+ CompartmentCreationOptions& creationOptions() {
+ return creationOptions_;
+ }
+ const CompartmentCreationOptions& creationOptions() const {
+ return creationOptions_;
+ }
+
+ // CompartmentBehaviors specify compartment characteristics that can be
+ // changed after the compartment is created.
+ CompartmentBehaviors& behaviors() {
+ return behaviors_;
+ }
+ const CompartmentBehaviors& behaviors() const {
+ return behaviors_;
+ }
+
+ private:
+ CompartmentCreationOptions creationOptions_;
+ CompartmentBehaviors behaviors_;
};
-JS_PUBLIC_API(CompartmentOptions&)
-CompartmentOptionsRef(JSCompartment* compartment);
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSCompartment* compartment);
+
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSObject* obj);
-JS_PUBLIC_API(CompartmentOptions&)
-CompartmentOptionsRef(JSObject* obj);
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSContext* cx);
-JS_PUBLIC_API(CompartmentOptions&)
-CompartmentOptionsRef(JSContext* cx);
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSCompartment* compartment);
+
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSObject* obj);
+
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSContext* cx);
/**
* During global creation, we fire notifications to callbacks registered
@@ -2346,7 +2459,7 @@
extern JS_PUBLIC_API(JSObject*)
JS_NewGlobalObject(JSContext* cx, const JSClass* clasp, JSPrincipals* principals,
JS::OnNewGlobalHookOption hookOption,
- const JS::CompartmentOptions& options = JS::CompartmentOptions());
+ const JS::CompartmentOptions& options);
/**
* Spidermonkey does not have a good way of keeping track of what compartments should be marked on
* their own. We can mark the roots unconditionally, but marking GC things only relevant in live
@@ -2368,9 +2481,6 @@
extern JS_PUBLIC_API(bool)
JS_IsNative(JSObject* obj);
-extern JS_PUBLIC_API(JSRuntime*)
-JS_GetObjectRuntime(JSObject* obj);
-
/**
* Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
* proto. If proto is nullptr, the JS object will have `null` as [[Prototype]].
@@ -2399,27 +2509,27 @@
/*** Property descriptors ************************************************************************/
-struct JS_PUBLIC_API(JSPropertyDescriptor) : public JS::Traceable {
+namespace JS {
+
+struct JS_PUBLIC_API(PropertyDescriptor) {
JSObject* obj;
unsigned attrs;
JSGetterOp getter;
JSSetterOp setter;
JS::Value value;
- JSPropertyDescriptor()
+ PropertyDescriptor()
: obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JS::UndefinedValue())
{}
- static void trace(JSPropertyDescriptor* self, JSTracer* trc) { self->trace(trc); }
+ static void trace(PropertyDescriptor* self, JSTracer* trc) { self->trace(trc); }
void trace(JSTracer* trc);
};
-namespace JS {
-
template <typename Outer>
class PropertyDescriptorOperations
{
- const JSPropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
+ const PropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
bool has(unsigned bit) const {
MOZ_ASSERT(bit != 0);
@@ -2551,7 +2661,7 @@
template <typename Outer>
class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<Outer>
{
- JSPropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
+ PropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
public:
void clear() {
@@ -2574,7 +2684,7 @@
setSetter(setterOp);
}
- void assign(JSPropertyDescriptor& other) {
+ void assign(PropertyDescriptor& other) {
object().set(other.obj);
setAttributes(other.attrs);
setGetter(other.getter);
@@ -2662,18 +2772,18 @@
namespace js {
template <>
-class RootedBase<JSPropertyDescriptor>
- : public JS::MutablePropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor>>
+class RootedBase<JS::PropertyDescriptor>
+ : public JS::MutablePropertyDescriptorOperations<JS::Rooted<JS::PropertyDescriptor>>
{};
template <>
-class HandleBase<JSPropertyDescriptor>
- : public JS::PropertyDescriptorOperations<JS::Handle<JSPropertyDescriptor>>
+class HandleBase<JS::PropertyDescriptor>
+ : public JS::PropertyDescriptorOperations<JS::Handle<JS::PropertyDescriptor>>
{};
template <>
-class MutableHandleBase<JSPropertyDescriptor>
- : public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JSPropertyDescriptor>>
+class MutableHandleBase<JS::PropertyDescriptor>
+ : public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JS::PropertyDescriptor>>
{};
} /* namespace js */
@@ -2684,7 +2794,17 @@
ObjectToCompletePropertyDescriptor(JSContext* cx,
JS::HandleObject obj,
JS::HandleValue descriptor,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<PropertyDescriptor> desc);
+
+/*
+ * ES6 draft rev 32 (2015 Feb 2) 6.2.4.4 FromPropertyDescriptor(Desc).
+ *
+ * If desc.object() is null, then vp is set to undefined.
+ */
+extern JS_PUBLIC_API(bool)
+FromPropertyDescriptor(JSContext* cx,
+ JS::Handle<JS::PropertyDescriptor> desc,
+ JS::MutableHandleValue vp);
} // namespace JS
@@ -2715,6 +2835,17 @@
JS_GetPrototype(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject result);
/**
+ * If |obj| (underneath any functionally-transparent wrapper proxies) has as
+ * its [[GetPrototypeOf]] trap the ordinary [[GetPrototypeOf]] behavior defined
+ * for ordinary objects, set |*isOrdinary = true| and store |obj|'s prototype
+ * in |result|. Otherwise set |*isOrdinary = false|. In case of error, both
+ * outparams have unspecified value.
+ */
+extern JS_PUBLIC_API(bool)
+JS_GetPrototypeIfOrdinary(JSContext* cx, JS::HandleObject obj, bool* isOrdinary,
+ JS::MutableHandleObject result);
+
+/**
* Change the prototype of obj.
*
* Implements: ES6 [[SetPrototypeOf]] internal method.
@@ -2771,15 +2902,15 @@
*/
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
/**
* Like JS_GetOwnPropertyDescriptorById, but also searches the prototype chain
@@ -2789,11 +2920,11 @@
*/
extern JS_PUBLIC_API(bool)
JS_GetPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
/**
* Define a property on obj.
@@ -2808,7 +2939,7 @@
*/
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::Handle<JSPropertyDescriptor> desc,
+ JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
/**
@@ -2817,7 +2948,7 @@
*/
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::Handle<JSPropertyDescriptor> desc);
+ JS::Handle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
@@ -2869,12 +3000,12 @@
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
- JS::Handle<JSPropertyDescriptor> desc,
+ JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
- JS::Handle<JSPropertyDescriptor> desc);
+ JS::Handle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
@@ -3099,8 +3230,8 @@
* This is the closest thing we currently have to the ES6 [[Enumerate]]
* internal method.
*
- * The JSIdArray returned by JS_Enumerate must be rooted to protect its
- * contents from garbage collection. Use JS::AutoIdArray.
+ * The array of ids returned by JS_Enumerate must be rooted to protect its
+ * contents from garbage collection. Use JS::Rooted<JS::IdVector>.
*/
extern JS_PUBLIC_API(bool)
JS_Enumerate(JSContext* cx, JS::HandleObject obj, JS::MutableHandle<JS::IdVector> props);
@@ -3213,21 +3344,18 @@
*/
extern JS_PUBLIC_API(bool)
Construct(JSContext* cx, JS::HandleValue fun, HandleObject newTarget,
- const JS::HandleValueArray &args, MutableHandleValue rval);
+ const JS::HandleValueArray &args, MutableHandleObject objp);
/**
* Invoke a constructor. This is the C++ equivalent of
* `rval = new fun(...args)`.
*
- * The value left in rval on success is always an object in practice,
- * though at the moment this is not enforced by the C++ type system.
- *
* Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]), when
* newTarget is omitted.
*/
extern JS_PUBLIC_API(bool)
Construct(JSContext* cx, JS::HandleValue fun, const JS::HandleValueArray& args,
- MutableHandleValue rval);
+ MutableHandleObject objp);
} /* namespace JS */
@@ -3304,6 +3432,30 @@
extern JS_PUBLIC_API(bool)
JS_SetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t length);
+namespace JS {
+
+/**
+ * Returns true and sets |*isMap| indicating whether |obj| is an Map object
+ * or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isMap == false| when passed a proxy whose
+ * target is an Map, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+IsMapObject(JSContext* cx, JS::HandleObject obj, bool* isMap);
+
+/**
+ * Returns true and sets |*isSet| indicating whether |obj| is an Set object
+ * or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isSet == false| when passed a proxy whose
+ * target is an Set, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+IsSetObject(JSContext* cx, JS::HandleObject obj, bool* isSet);
+
+} /* namespace JS */
+
/**
* Assign 'undefined' to all of the object's non-reserved slots. Note: this is
* done for all slots, regardless of the associated property descriptor.
@@ -3320,6 +3472,13 @@
JS_NewArrayBufferWithContents(JSContext* cx, size_t nbytes, void* contents);
/**
+ * Create a new array buffer with the given contents. The array buffer does not take ownership of
+ * contents, and JS_DetachArrayBuffer must be called before the contents are disposed of.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_NewArrayBufferWithExternalContents(JSContext* cx, size_t nbytes, void* contents);
+
+/**
* Steal the contents of the given array buffer. The array buffer has its
* length set to 0 and its contents array cleared. The caller takes ownership
* of the return value and must free it or transfer ownership via
@@ -3329,6 +3488,25 @@
JS_StealArrayBufferContents(JSContext* cx, JS::HandleObject obj);
/**
+ * Returns a pointer to the ArrayBuffer |obj|'s data. |obj| and its views will store and expose
+ * the data in the returned pointer: assigning into the returned pointer will affect values exposed
+ * by views of |obj| and vice versa.
+ *
+ * The caller must ultimately deallocate the returned pointer to avoid leaking. The memory is
+ * *not* garbage-collected with |obj|. These steps must be followed to deallocate:
+ *
+ * 1. The ArrayBuffer |obj| must be detached using JS_DetachArrayBuffer.
+ * 2. The returned pointer must be freed using JS_free.
+ *
+ * To perform step 1, callers *must* hold a reference to |obj| until they finish using the returned
+ * pointer. They *must not* attempt to let |obj| be GC'd, then JS_free the pointer.
+ *
+ * If |obj| isn't an ArrayBuffer, this function returns null and reports an error.
+ */
+extern JS_PUBLIC_API(void*)
+JS_ExternalizeArrayBufferContents(JSContext* cx, JS::HandleObject obj);
+
+/**
* Create a new mapped array buffer with the given memory mapped contents. It
* must be legal to free the contents pointer by unmapping it. On success,
* ownership is transferred to the new mapped array buffer.
@@ -3347,7 +3525,7 @@
* Release the allocated resource of mapped array buffer contents before the
* object is created.
* If a new object has been created by JS_NewMappedArrayBufferWithContents()
- * with this content, then JS_NeuterArrayBuffer() should be used instead to
+ * with this content, then JS_DetachArrayBuffer() should be used instead to
* release the resource used by the object.
*/
extern JS_PUBLIC_API(void)
@@ -3357,7 +3535,7 @@
JS_GetReservedSlot(JSObject* obj, uint32_t index);
extern JS_PUBLIC_API(void)
-JS_SetReservedSlot(JSObject* obj, uint32_t index, JS::Value v);
+JS_SetReservedSlot(JSObject* obj, uint32_t index, const JS::Value& v);
/************************************************************************/
@@ -3432,20 +3610,8 @@
extern JS_PUBLIC_API(bool)
JS_IsConstructor(JSFunction* fun);
-/**
- * This enum is used to select if properties with JSPROP_DEFINE_LATE flag
- * should be defined on the object.
- * Normal JSAPI consumers probably always want DefineAllProperties here.
- */
-enum PropertyDefinitionBehavior {
- DefineAllProperties,
- OnlyDefineLateProperties,
- DontDefineLateProperties
-};
-
extern JS_PUBLIC_API(bool)
-JS_DefineFunctions(JSContext* cx, JS::Handle<JSObject*> obj, const JSFunctionSpec* fs,
- PropertyDefinitionBehavior behavior = DefineAllProperties);
+JS_DefineFunctions(JSContext* cx, JS::Handle<JSObject*> obj, const JSFunctionSpec* fs);
extern JS_PUBLIC_API(JSFunction*)
JS_DefineFunction(JSContext* cx, JS::Handle<JSObject*> obj, const char* name, JSNative call,
@@ -3460,6 +3626,12 @@
JS_DefineFunctionById(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSNative call,
unsigned nargs, unsigned attrs);
+extern JS_PUBLIC_API(bool)
+JS_IsFunctionBound(JSFunction* fun);
+
+extern JS_PUBLIC_API(JSObject*)
+JS_GetBoundFunctionTarget(JSFunction* fun);
+
namespace JS {
/**
@@ -3680,7 +3852,6 @@
lineno(1),
column(0),
isRunOnce(false),
- forEval(false),
noScriptRval(false)
{ }
@@ -3704,7 +3875,6 @@
unsigned column;
// isRunOnce only applies to non-function scripts.
bool isRunOnce;
- bool forEval;
bool noScriptRval;
private:
@@ -3726,7 +3896,6 @@
*/
class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
{
- JSRuntime* runtime;
PersistentRootedObject elementRoot;
PersistentRootedString elementAttributeNameRoot;
PersistentRootedScript introductionScriptRoot;
@@ -3778,7 +3947,6 @@
OwningCompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
OwningCompileOptions& setColumn(unsigned c) { column = c; return *this; }
OwningCompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
- OwningCompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
OwningCompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
OwningCompileOptions& setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
OwningCompileOptions& setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
@@ -3808,7 +3976,7 @@
* create an instance of this type, it's up to you to guarantee that
* everything you store in it will outlive it.
*/
-class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOptions
+class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) final : public ReadOnlyCompileOptions
{
RootedObject elementRoot;
RootedString elementAttributeNameRoot;
@@ -3875,7 +4043,6 @@
CompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
CompileOptions& setColumn(unsigned c) { column = c; return *this; }
CompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
- CompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
CompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
CompileOptions& setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
CompileOptions& setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
@@ -3953,10 +4120,11 @@
* After successfully triggering an off thread compile of a script, the
* callback will eventually be invoked with the specified data and a token
* for the compilation. The callback will be invoked while off the main thread,
- * so must ensure that its operations are thread safe. Afterwards,
- * FinishOffThreadScript must be invoked on the main thread to get the result
- * script or nullptr. If maybecx is not specified, the resources will be freed,
- * but no script will be returned.
+ * so must ensure that its operations are thread safe. Afterwards, one of the
+ * following functions must be invoked on the main thread:
+ *
+ * - FinishOffThreadScript, to get the result script (or nullptr on failure).
+ * - CancelOffThreadScript, to free the resources without creating a script.
*
* The characters passed in to CompileOffThread must remain live until the
* callback is invoked, and the resulting script will be rooted until the call
@@ -3969,17 +4137,31 @@
OffThreadCompileCallback callback, void* callbackData);
extern JS_PUBLIC_API(JSScript*)
-FinishOffThreadScript(JSContext* maybecx, JSRuntime* rt, void* token);
+FinishOffThreadScript(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadScript(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(bool)
+CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char16_t* chars, size_t length,
+ OffThreadCompileCallback callback, void* callbackData);
+
+extern JS_PUBLIC_API(JSObject*)
+FinishOffThreadModule(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadModule(JSContext* cx, void* token);
/**
- * Compile a function with scopeChain plus the global as its scope chain.
- * scopeChain must contain objects in the current compartment of cx. The actual
+ * Compile a function with envChain plus the global as its scope chain.
+ * envChain must contain objects in the current compartment of cx. The actual
* scope chain used for the function will consist of With wrappers for those
* objects, followed by the current global of the compartment cx is in. This
* global must not be explicitly included in the scope chain.
*/
extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
const ReadOnlyCompileOptions& options,
const char* name, unsigned nargs, const char* const* argnames,
const char16_t* chars, size_t length, JS::MutableHandleFunction fun);
@@ -3988,7 +4170,7 @@
* Same as above, but taking a SourceBufferHolder for the function body.
*/
extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
const ReadOnlyCompileOptions& options,
const char* name, unsigned nargs, const char* const* argnames,
SourceBufferHolder& srcBuf, JS::MutableHandleFunction fun);
@@ -3997,7 +4179,7 @@
* Same as above, but taking a const char * for the function body.
*/
extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
const ReadOnlyCompileOptions& options,
const char* name, unsigned nargs, const char* const* argnames,
const char* bytes, size_t length, JS::MutableHandleFunction fun);
@@ -4029,7 +4211,7 @@
* Why a runtime option? The alternative is to add APIs duplicating those
* for the other value of flags, and that doesn't seem worth the code bloat
* cost. Such new entry points would probably have less obvious names, too, so
- * would not tend to be used. The RuntimeOptionsRef adjustment, OTOH, can be
+ * would not tend to be used. The ContextOptionsRef adjustment, OTOH, can be
* more easily hacked into existing code that does not depend on the bug; such
* code can continue to use the familiar JS::Evaluate, etc., entry points.
*/
@@ -4044,16 +4226,16 @@
JS_ExecuteScript(JSContext* cx, JS::HandleScript script);
/**
- * As above, but providing an explicit scope chain. scopeChain must not include
+ * As above, but providing an explicit scope chain. envChain must not include
* the global object on it; that's implicit. It needs to contain the other
* objects that should end up on the script's scope chain.
*/
extern JS_PUBLIC_API(bool)
-JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& scopeChain,
+JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain,
JS::HandleScript script, JS::MutableHandleValue rval);
extern JS_PUBLIC_API(bool)
-JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& scopeChain, JS::HandleScript script);
+JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain, JS::HandleScript script);
namespace JS {
@@ -4062,7 +4244,8 @@
* cross-compartment, it is cloned into the current compartment before executing.
*/
extern JS_PUBLIC_API(bool)
-CloneAndExecuteScript(JSContext* cx, JS::Handle<JSScript*> script);
+CloneAndExecuteScript(JSContext* cx, JS::Handle<JSScript*> script,
+ JS::MutableHandleValue rval);
} /* namespace JS */
@@ -4076,12 +4259,12 @@
SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
/**
- * As above, but providing an explicit scope chain. scopeChain must not include
+ * As above, but providing an explicit scope chain. envChain must not include
* the global object on it; that's implicit. It needs to contain the other
* objects that should end up on the script's scope chain.
*/
extern JS_PUBLIC_API(bool)
-Evaluate(JSContext* cx, AutoObjectVector& scopeChain, const ReadOnlyCompileOptions& options,
+Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
/**
@@ -4092,12 +4275,12 @@
const char16_t* chars, size_t length, JS::MutableHandleValue rval);
/**
- * As above, but providing an explicit scope chain. scopeChain must not include
+ * As above, but providing an explicit scope chain. envChain must not include
* the global object on it; that's implicit. It needs to contain the other
* objects that should end up on the script's scope chain.
*/
extern JS_PUBLIC_API(bool)
-Evaluate(JSContext* cx, AutoObjectVector& scopeChain, const ReadOnlyCompileOptions& options,
+Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, JS::MutableHandleValue rval);
/**
@@ -4114,6 +4297,80 @@
Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* filename, JS::MutableHandleValue rval);
+/**
+ * Get the HostResolveImportedModule hook for a global.
+ */
+extern JS_PUBLIC_API(JSFunction*)
+GetModuleResolveHook(JSContext* cx);
+
+/**
+ * Set the HostResolveImportedModule hook for a global to the given function.
+ */
+extern JS_PUBLIC_API(void)
+SetModuleResolveHook(JSContext* cx, JS::HandleFunction func);
+
+/**
+ * Parse the given source buffer as a module in the scope of the current global
+ * of cx and return a source text module record.
+ */
+extern JS_PUBLIC_API(bool)
+CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
+ SourceBufferHolder& srcBuf, JS::MutableHandleObject moduleRecord);
+
+/**
+ * Set the [[HostDefined]] field of a source text module record to the given
+ * value.
+ */
+extern JS_PUBLIC_API(void)
+SetModuleHostDefinedField(JSObject* module, const JS::Value& value);
+
+/**
+ * Get the [[HostDefined]] field of a source text module record.
+ */
+extern JS_PUBLIC_API(JS::Value)
+GetModuleHostDefinedField(JSObject* module);
+
+/*
+ * Perform the ModuleDeclarationInstantiation operation on on the give source
+ * text module record.
+ *
+ * This transitively resolves all module dependencies (calling the
+ * HostResolveImportedModule hook) and initializes the environment record for
+ * the module.
+ */
+extern JS_PUBLIC_API(bool)
+ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Perform the ModuleEvaluation operation on on the give source text module
+ * record.
+ *
+ * This does nothing if this module has already been evaluated. Otherwise, it
+ * transitively evaluates all dependences of this module and then evaluates this
+ * module.
+ *
+ * ModuleDeclarationInstantiation must have completed prior to calling this.
+ */
+extern JS_PUBLIC_API(bool)
+ModuleEvaluation(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Get a list of the module specifiers used by a source text module
+ * record to request importation of modules.
+ *
+ * The result is a JavaScript array of string values. To extract the individual
+ * values use only JS_GetArrayLength and JS_GetElement with indices 0 to
+ * length - 1.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetRequestedModules(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Get the script associated with a module.
+ */
+extern JS_PUBLIC_API(JSScript*)
+GetModuleScript(JSContext* cx, JS::HandleObject moduleRecord);
+
} /* namespace JS */
extern JS_PUBLIC_API(bool)
@@ -4122,7 +4379,7 @@
/*
* These functions allow setting an interrupt callback that will be called
* from the JS thread some time after any thread triggered the callback using
- * JS_RequestInterruptCallback(rt).
+ * JS_RequestInterruptCallback(cx).
*
* To schedule the GC and for other activities the engine internally triggers
* interrupt callbacks. The embedding should thus not rely on callbacks being
@@ -4132,34 +4389,257 @@
* if it re-enters the JS engine. The embedding must ensure that the callback
* is disconnected before attempting such re-entry.
*/
-extern JS_PUBLIC_API(JSInterruptCallback)
-JS_SetInterruptCallback(JSRuntime* rt, JSInterruptCallback callback);
+extern JS_PUBLIC_API(bool)
+JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback);
+
+extern JS_PUBLIC_API(bool)
+JS_DisableInterruptCallback(JSContext* cx);
+
+extern JS_PUBLIC_API(void)
+JS_ResetInterruptCallback(JSContext* cx, bool enable);
+
+extern JS_PUBLIC_API(void)
+JS_RequestInterruptCallback(JSContext* cx);
+
+namespace JS {
+
+/**
+ * Sets the callback that's invoked whenever an incumbent global is required.
+ *
+ * SpiderMonkey doesn't itself have a notion of incumbent globals as defined
+ * by the html spec, so we need the embedding to provide this.
+ * See dom/base/ScriptSettings.h for details.
+ */
+extern JS_PUBLIC_API(void)
+SetGetIncumbentGlobalCallback(JSContext* cx, JSGetIncumbentGlobalCallback callback);
-extern JS_PUBLIC_API(JSInterruptCallback)
-JS_GetInterruptCallback(JSRuntime* rt);
+/**
+ * Sets the callback that's invoked whenever a Promise job should be enqeued.
+ *
+ * SpiderMonkey doesn't schedule Promise resolution jobs itself; instead,
+ * using this function the embedding can provide a callback to do that
+ * scheduling. The provided `callback` is invoked with the promise job,
+ * the corresponding Promise's allocation stack, and the `data` pointer
+ * passed here as arguments.
+ */
+extern JS_PUBLIC_API(void)
+SetEnqueuePromiseJobCallback(JSContext* cx, JSEnqueuePromiseJobCallback callback,
+ void* data = nullptr);
+/**
+ * Sets the callback that's invoked whenever a Promise is rejected without
+ * a rejection handler, and when a Promise that was previously rejected
+ * without a handler gets a handler attached.
+ */
extern JS_PUBLIC_API(void)
-JS_RequestInterruptCallback(JSRuntime* rt);
+SetPromiseRejectionTrackerCallback(JSContext* cx, JSPromiseRejectionTrackerCallback callback,
+ void* data = nullptr);
+/**
+ * Returns a new instance of the Promise builtin class in the current
+ * compartment, with the right slot layout. If a `proto` is passed, that gets
+ * set as the instance's [[Prototype]] instead of the original value of
+ * `Promise.prototype`.
+ */
+extern JS_PUBLIC_API(JSObject*)
+NewPromiseObject(JSContext* cx, JS::HandleObject executor, JS::HandleObject proto = nullptr);
+
+/**
+ * Returns true if the given object is an unwrapped PromiseObject, false
+ * otherwise.
+ */
extern JS_PUBLIC_API(bool)
-JS_IsRunning(JSContext* cx);
+IsPromiseObject(JS::HandleObject obj);
-/*
- * Saving and restoring frame chains.
+/**
+ * Returns the current compartment's original Promise constructor.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseConstructor(JSContext* cx);
+
+/**
+ * Returns the current compartment's original Promise.prototype.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromisePrototype(JSContext* cx);
+
+// Keep this in sync with the PROMISE_STATE defines in SelfHostingDefines.h.
+enum class PromiseState {
+ Pending,
+ Fulfilled,
+ Rejected
+};
+
+/**
+ * Returns the given Promise's state as a JS::PromiseState enum value.
+ *
+ * Returns JS::PromiseState::Pending if the given object is a wrapper that
+ * can't safely be unwrapped.
+ */
+extern JS_PUBLIC_API(PromiseState)
+GetPromiseState(JS::HandleObject promise);
+
+/**
+ * Returns the given Promise's process-unique ID.
+ */
+JS_PUBLIC_API(uint64_t)
+GetPromiseID(JS::HandleObject promise);
+
+/**
+ * Returns the given Promise's result: either the resolution value for
+ * fulfilled promises, or the rejection reason for rejected ones.
+ */
+extern JS_PUBLIC_API(JS::Value)
+GetPromiseResult(JS::HandleObject promise);
+
+/**
+ * Returns a js::SavedFrame linked list of the stack that lead to the given
+ * Promise's allocation.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseAllocationSite(JS::HandleObject promise);
+
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseResolutionSite(JS::HandleObject promise);
+
+#ifdef DEBUG
+extern JS_PUBLIC_API(void)
+DumpPromiseAllocationSite(JSContext* cx, JS::HandleObject promise);
+
+extern JS_PUBLIC_API(void)
+DumpPromiseResolutionSite(JSContext* cx, JS::HandleObject promise);
+#endif
+
+/**
+ * Calls the current compartment's original Promise.resolve on the original
+ * Promise constructor, with `resolutionValue` passed as an argument.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseResolve(JSContext* cx, JS::HandleValue resolutionValue);
+
+/**
+ * Calls the current compartment's original Promise.reject on the original
+ * Promise constructor, with `resolutionValue` passed as an argument.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseReject(JSContext* cx, JS::HandleValue rejectionValue);
+
+/**
+ * Resolves the given Promise with the given `resolutionValue`.
+ *
+ * Calls the `resolve` function that was passed to the executor function when
+ * the Promise was created.
+ */
+extern JS_PUBLIC_API(bool)
+ResolvePromise(JSContext* cx, JS::HandleObject promise, JS::HandleValue resolutionValue);
+
+/**
+ * Rejects the given `promise` with the given `rejectionValue`.
+ *
+ * Calls the `reject` function that was passed to the executor function when
+ * the Promise was created.
+ */
+extern JS_PUBLIC_API(bool)
+RejectPromise(JSContext* cx, JS::HandleObject promise, JS::HandleValue rejectionValue);
+
+/**
+ * Calls the current compartment's original Promise.prototype.then on the
+ * given `promise`, with `onResolve` and `onReject` passed as arguments.
+ *
+ * Asserts if the passed-in `promise` object isn't an unwrapped instance of
+ * `Promise` or a subclass or `onResolve` and `onReject` aren't both either
+ * `nullptr` or callable objects.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseThen(JSContext* cx, JS::HandleObject promise,
+ JS::HandleObject onResolve, JS::HandleObject onReject);
+
+/**
+ * Unforgeable, optimized version of the JS builtin Promise.prototype.then.
*
- * These two functions are used to set aside cx's call stack while that stack
- * is inactive. After a call to JS_SaveFrameChain, it looks as if there is no
- * code running on cx. Before calling JS_RestoreFrameChain, cx's call stack
- * must be balanced and all nested calls to JS_SaveFrameChain must have had
- * matching JS_RestoreFrameChain calls.
+ * Takes a Promise instance and `onResolve`, `onReject` callables to enqueue
+ * as reactions for that promise. In difference to Promise.prototype.then,
+ * this doesn't create and return a new Promise instance.
*
- * JS_SaveFrameChain deals with cx not having any code running on it.
+ * Asserts if the passed-in `promise` object isn't an unwrapped instance of
+ * `Promise` or a subclass or `onResolve` and `onReject` aren't both callable
+ * objects.
*/
extern JS_PUBLIC_API(bool)
-JS_SaveFrameChain(JSContext* cx);
+AddPromiseReactions(JSContext* cx, JS::HandleObject promise,
+ JS::HandleObject onResolve, JS::HandleObject onReject);
+
+/**
+ * Unforgeable version of the JS builtin Promise.all.
+ *
+ * Takes an AutoObjectVector of Promise objects and returns a promise that's
+ * resolved with an array of resolution values when all those promises have
+ * been resolved, or rejected with the rejection value of the first rejected
+ * promise.
+ *
+ * Asserts that all objects in the `promises` vector are, maybe wrapped,
+ * instances of `Promise` or a subclass of `Promise`.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises);
+
+/**
+ * An AsyncTask represents a SpiderMonkey-internal operation that starts on a
+ * JSContext's owner thread, possibly executes on other threads, completes, and
+ * then needs to be scheduled to run again on the JSContext's owner thread. The
+ * embedding provides for this final dispatch back to the JSContext's owner
+ * thread by calling methods on this interface when requested.
+ */
+struct JS_PUBLIC_API(AsyncTask)
+{
+ AsyncTask() : user(nullptr) {}
+ virtual ~AsyncTask() {}
+
+ /**
+ * After the FinishAsyncTaskCallback is called and succeeds, one of these
+ * two functions will be called on the original JSContext's owner thread.
+ */
+ virtual void finish(JSContext* cx) = 0;
+ virtual void cancel(JSContext* cx) = 0;
+
+ /* The embedding may use this field to attach arbitrary data to a task. */
+ void* user;
+};
+
+/**
+ * A new AsyncTask object, created inside SpiderMonkey on the JSContext's owner
+ * thread, will be passed to the StartAsyncTaskCallback before it is dispatched
+ * to another thread. The embedding may use the AsyncTask::user field to attach
+ * additional task state.
+ *
+ * If this function succeeds, SpiderMonkey will call the FinishAsyncTaskCallback
+ * at some point in the future. Otherwise, FinishAsyncTaskCallback will *not*
+ * be called. SpiderMonkey assumes that, if StartAsyncTaskCallback fails, it is
+ * because the JSContext is being shut down.
+ */
+typedef bool
+(*StartAsyncTaskCallback)(JSContext* cx, AsyncTask* task);
+/**
+ * The FinishAsyncTaskCallback may be called from any thread and will only be
+ * passed AsyncTasks that have already been started via StartAsyncTaskCallback.
+ * If the embedding returns 'true', indicating success, the embedding must call
+ * either task->finish() or task->cancel() on the JSContext's owner thread at
+ * some point in the future.
+ */
+typedef bool
+(*FinishAsyncTaskCallback)(AsyncTask* task);
+
+/**
+ * Set the above callbacks for the given context.
+ */
extern JS_PUBLIC_API(void)
-JS_RestoreFrameChain(JSContext* cx);
+SetAsyncTaskCallbacks(JSContext* cx, StartAsyncTaskCallback start, FinishAsyncTaskCallback finish);
+
+} // namespace JS
+
+extern JS_PUBLIC_API(bool)
+JS_IsRunning(JSContext* cx);
namespace JS {
@@ -4184,7 +4664,7 @@
{
JSContext* cx;
RootedObject oldAsyncStack;
- RootedString oldAsyncCause;
+ const char* oldAsyncCause;
bool oldAsyncCallIsExplicit;
public:
@@ -4201,8 +4681,13 @@
// ambiguous whether that would clear any scheduled async stack and make the
// normal stack reappear in the new call, or just keep the async stack
// already scheduled for the new call, if any.
+ //
+ // asyncCause is owned by the caller and its lifetime must outlive the
+ // lifetime of the AutoSetAsyncStackForNewCalls object. It is strongly
+ // encouraged that asyncCause be a string constant or similar statically
+ // allocated string.
AutoSetAsyncStackForNewCalls(JSContext* cx, HandleObject stack,
- HandleString asyncCause,
+ const char* asyncCause,
AsyncCallKind kind = AsyncCallKind::IMPLICIT);
~AutoSetAsyncStackForNewCalls();
};
@@ -4227,9 +4712,21 @@
JS_NewStringCopyZ(JSContext* cx, const char* s);
extern JS_PUBLIC_API(JSString*)
+JS_NewStringCopyUTF8Z(JSContext* cx, const JS::ConstUTF8CharsZ s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars s);
+
+extern JS_PUBLIC_API(JSString*)
JS_AtomizeAndPinJSString(JSContext* cx, JS::HandleString str);
extern JS_PUBLIC_API(JSString*)
+JS_AtomizeStringN(JSContext* cx, const char* s, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeString(JSContext* cx, const char* s);
+
+extern JS_PUBLIC_API(JSString*)
JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length);
extern JS_PUBLIC_API(JSString*)
@@ -4245,6 +4742,12 @@
JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s);
extern JS_PUBLIC_API(JSString*)
+JS_AtomizeUCStringN(JSContext* cx, const char16_t* s, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeUCString(JSContext* cx, const char16_t* s);
+
+extern JS_PUBLIC_API(JSString*)
JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length);
extern JS_PUBLIC_API(JSString*)
@@ -4453,7 +4956,7 @@
}
~JSAutoByteString() {
- js_free(mBytes);
+ JS_free(nullptr, mBytes);
}
/* Take ownership of the given byte array. */
@@ -4498,7 +5001,7 @@
}
private:
- char* mBytes;
+ char* mBytes;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
/* Copy and assignment are not supported. */
@@ -4556,17 +5059,31 @@
GetSymbolDescription(HandleSymbol symbol);
/* Well-known symbols. */
+#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(macro) \
+ macro(isConcatSpreadable) \
+ macro(iterator) \
+ macro(match) \
+ macro(replace) \
+ macro(search) \
+ macro(species) \
+ macro(hasInstance) \
+ macro(split) \
+ macro(toPrimitive) \
+ macro(toStringTag) \
+ macro(unscopables)
+
enum class SymbolCode : uint32_t {
- iterator, // well-known symbols
- match,
- species,
- toPrimitive,
+ // There is one SymbolCode for each well-known symbol.
+#define JS_DEFINE_SYMBOL_ENUM(name) name,
+ JS_FOR_EACH_WELL_KNOWN_SYMBOL(JS_DEFINE_SYMBOL_ENUM) // SymbolCode::iterator, etc.
+#undef JS_DEFINE_SYMBOL_ENUM
+ Limit,
InSymbolRegistry = 0xfffffffe, // created by Symbol.for() or JS::GetSymbolFor()
UniqueSymbol = 0xffffffff // created by Symbol() or JS::NewSymbol()
};
/* For use in loops that iterate over the well-known symbols. */
-const size_t WellKnownSymbolLimit = 4;
+const size_t WellKnownSymbolLimit = size_t(SymbolCode::Limit);
/**
* Return the SymbolCode telling what sort of symbol `symbol` is.
@@ -4625,6 +5142,31 @@
JS_Stringify(JSContext* cx, JS::MutableHandleValue value, JS::HandleObject replacer,
JS::HandleValue space, JSONWriteCallback callback, void* data);
+namespace JS {
+
+/**
+ * An API akin to JS_Stringify but with the goal of not having observable
+ * side-effects when the stringification is performed. This means it does not
+ * allow a replacer or a custom space, and has the following constraints on its
+ * input:
+ *
+ * 1) The input must be a plain object or array, not an abitrary value.
+ * 2) Every value in the graph reached by the algorithm starting with this
+ * object must be one of the following: null, undefined, a string (NOT a
+ * string object!), a boolean, a finite number (i.e. no NaN or Infinity or
+ * -Infinity), a plain object with no accessor properties, or an Array with
+ * no holes.
+ *
+ * The actual behavior differs from JS_Stringify only in asserting the above and
+ * NOT attempting to get the "toJSON" property from things, since that could
+ * clearly have side-effects.
+ */
+JS_PUBLIC_API(bool)
+ToJSONMaybeSafely(JSContext* cx, JS::HandleObject input,
+ JSONWriteCallback callback, void* data);
+
+} /* namespace JS */
+
/**
* JSON.parse as specified by ES5.
*/
@@ -4652,13 +5194,19 @@
* The locale string remains owned by the caller.
*/
extern JS_PUBLIC_API(bool)
-JS_SetDefaultLocale(JSRuntime* rt, const char* locale);
+JS_SetDefaultLocale(JSContext* cx, const char* locale);
+
+/**
+ * Look up the default locale for the ECMAScript Internationalization API.
+ */
+extern JS_PUBLIC_API(JS::UniqueChars)
+JS_GetDefaultLocale(JSContext* cx);
/**
* Reset the default locale to OS defaults.
*/
extern JS_PUBLIC_API(void)
-JS_ResetDefaultLocale(JSRuntime* rt);
+JS_ResetDefaultLocale(JSContext* cx);
/**
* Locale specific string conversion and error message callbacks.
@@ -4672,17 +5220,17 @@
/**
* Establish locale callbacks. The pointer must persist as long as the
- * JSRuntime. Passing nullptr restores the default behaviour.
+ * JSContext. Passing nullptr restores the default behaviour.
*/
extern JS_PUBLIC_API(void)
-JS_SetLocaleCallbacks(JSRuntime* rt, const JSLocaleCallbacks* callbacks);
+JS_SetLocaleCallbacks(JSContext* cx, const JSLocaleCallbacks* callbacks);
/**
* Return the address of the current locale callbacks struct, which may
* be nullptr.
*/
extern JS_PUBLIC_API(const JSLocaleCallbacks*)
-JS_GetLocaleCallbacks(JSRuntime* rt);
+JS_GetLocaleCallbacks(JSContext* cx);
/************************************************************************/
@@ -4696,23 +5244,49 @@
/**
* Report an exception represented by the sprintf-like conversion of format
- * and its arguments. This exception message string is passed to a pre-set
- * JSErrorReporter function (set by JS_SetErrorReporter).
+ * and its arguments.
*/
extern JS_PUBLIC_API(void)
-JS_ReportError(JSContext* cx, const char* format, ...);
+JS_ReportErrorASCII(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorLatin1(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorUTF8(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
/*
* Use an errorNumber to retrieve the format string, args are char*
*/
extern JS_PUBLIC_API(void)
-JS_ReportErrorNumber(JSContext* cx, JSErrorCallback errorCallback,
- void* userRef, const unsigned errorNumber, ...);
+JS_ReportErrorNumberASCII(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberASCIIVA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberLatin1(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
#ifdef va_start
extern JS_PUBLIC_API(void)
-JS_ReportErrorNumberVA(JSContext* cx, JSErrorCallback errorCallback,
- void* userRef, const unsigned errorNumber, va_list ap);
+JS_ReportErrorNumberLatin1VA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
+#endif
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUTF8(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
+
+#ifdef va_start
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUTF8VA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
#endif
/*
@@ -4734,12 +5308,31 @@
* being set, false otherwise.
*/
extern JS_PUBLIC_API(bool)
-JS_ReportWarning(JSContext* cx, const char* format, ...);
+JS_ReportWarningASCII(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportWarningLatin1(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportWarningUTF8(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportErrorFlagsAndNumberASCII(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportErrorFlagsAndNumberLatin1(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
extern JS_PUBLIC_API(bool)
-JS_ReportErrorFlagsAndNumber(JSContext* cx, unsigned flags,
- JSErrorCallback errorCallback, void* userRef,
- const unsigned errorNumber, ...);
+JS_ReportErrorFlagsAndNumberUTF8(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
extern JS_PUBLIC_API(bool)
JS_ReportErrorFlagsAndNumberUC(JSContext* cx, unsigned flags,
@@ -4760,7 +5353,12 @@
class JSErrorReport
{
+ // The (default) error message.
+ // If ownsMessage_ is true, the it is freed in destructor.
+ JS::ConstUTF8CharsZ message_;
+
// Offending source line without final '\n'.
+ // If ownsLinebuf__ is true, the buffer is freed in destructor.
const char16_t* linebuf_;
// Number of chars in linebuf_. Does not include trailing '\0'.
@@ -4772,21 +5370,30 @@
public:
JSErrorReport()
: linebuf_(nullptr), linebufLength_(0), tokenOffset_(0),
- filename(nullptr), lineno(0), column(0), isMuted(false),
- flags(0), errorNumber(0), ucmessage(nullptr),
- messageArgs(nullptr), exnType(0)
+ filename(nullptr), lineno(0), column(0),
+ flags(0), errorNumber(0),
+ exnType(0), isMuted(false),
+ ownsLinebuf_(false), ownsMessage_(false)
{}
+ ~JSErrorReport() {
+ freeLinebuf();
+ freeMessage();
+ }
+
const char* filename; /* source file name, URL, etc., or null */
unsigned lineno; /* source line number */
unsigned column; /* zero-based column index in line */
- bool isMuted; /* See the comment in ReadOnlyCompileOptions. */
unsigned flags; /* error/warning, etc. */
unsigned errorNumber; /* the error number, e.g. see js.msg */
- const char16_t* ucmessage; /* the (default) error message */
- const char16_t** messageArgs; /* arguments for the error message */
int16_t exnType; /* One of the JSExnType constants */
+ bool isMuted : 1; /* See the comment in ReadOnlyCompileOptions. */
+ private:
+ bool ownsLinebuf_ : 1;
+ bool ownsMessage_ : 1;
+
+ public:
const char16_t* linebuf() const {
return linebuf_;
}
@@ -4796,7 +5403,29 @@
size_t tokenOffset() const {
return tokenOffset_;
}
- void initLinebuf(const char16_t* linebuf, size_t linebufLength, size_t tokenOffset);
+ void initOwnedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg) {
+ initBorrowedLinebuf(linebufArg, linebufLengthArg, tokenOffsetArg);
+ ownsLinebuf_ = true;
+ }
+ void initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg);
+ void freeLinebuf();
+
+ const JS::ConstUTF8CharsZ message() const {
+ return message_;
+ }
+
+ void initOwnedMessage(const char* messageArg) {
+ initBorrowedMessage(messageArg);
+ ownsMessage_ = true;
+ }
+ void initBorrowedMessage(const char* messageArg) {
+ MOZ_ASSERT(!message_);
+ message_ = JS::ConstUTF8CharsZ(messageArg, strlen(messageArg));
+ }
+
+ JSString* newMessageString(JSContext* cx);
+
+ void freeMessage();
};
/*
@@ -4807,14 +5436,7 @@
#define JSREPORT_EXCEPTION 0x2 /* exception was thrown */
#define JSREPORT_STRICT 0x4 /* error or warning due to strict option */
-/*
- * This condition is an error in strict mode code, a warning if
- * JS_HAS_STRICT_OPTION(cx), and otherwise should not be reported at
- * all. We check the strictness of the context's top frame's script;
- * where that isn't appropriate, the caller should do the right checks
- * itself instead of using this flag.
- */
-#define JSREPORT_STRICT_MODE_ERROR 0x8
+#define JSREPORT_USER_1 0x8 /* user-defined flag */
/*
* If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
@@ -4826,16 +5448,17 @@
#define JSREPORT_IS_WARNING(flags) (((flags) & JSREPORT_WARNING) != 0)
#define JSREPORT_IS_EXCEPTION(flags) (((flags) & JSREPORT_EXCEPTION) != 0)
#define JSREPORT_IS_STRICT(flags) (((flags) & JSREPORT_STRICT) != 0)
-#define JSREPORT_IS_STRICT_MODE_ERROR(flags) (((flags) & \
- JSREPORT_STRICT_MODE_ERROR) != 0)
-extern JS_PUBLIC_API(JSErrorReporter)
-JS_GetErrorReporter(JSRuntime* rt);
-
-extern JS_PUBLIC_API(JSErrorReporter)
-JS_SetErrorReporter(JSRuntime* rt, JSErrorReporter er);
namespace JS {
+using WarningReporter = void (*)(JSContext* cx, JSErrorReport* report);
+
+extern JS_PUBLIC_API(WarningReporter)
+SetWarningReporter(JSContext* cx, WarningReporter reporter);
+
+extern JS_PUBLIC_API(WarningReporter)
+GetWarningReporter(JSContext* cx);
+
extern JS_PUBLIC_API(bool)
CreateError(JSContext* cx, JSExnType type, HandleObject stack,
HandleString fileName, uint32_t lineNumber, uint32_t columnNumber,
@@ -4959,18 +5582,16 @@
#define JSREG_GLOB 0x02u /* global exec, creates array of matches */
#define JSREG_MULTILINE 0x04u /* treat ^ and $ as begin and end of line */
#define JSREG_STICKY 0x08u /* only match starting at lastIndex */
+#define JSREG_UNICODE 0x10u /* unicode */
extern JS_PUBLIC_API(JSObject*)
-JS_NewRegExpObject(JSContext* cx, JS::HandleObject obj, const char* bytes, size_t length,
- unsigned flags);
+JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags);
extern JS_PUBLIC_API(JSObject*)
-JS_NewUCRegExpObject(JSContext* cx, JS::HandleObject obj, const char16_t* chars, size_t length,
- unsigned flags);
+JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags);
extern JS_PUBLIC_API(bool)
-JS_SetRegExpInput(JSContext* cx, JS::HandleObject obj, JS::HandleString input,
- bool multiline);
+JS_SetRegExpInput(JSContext* cx, JS::HandleObject obj, JS::HandleString input);
extern JS_PUBLIC_API(bool)
JS_ClearRegExpStatics(JSContext* cx, JS::HandleObject obj);
@@ -4982,12 +5603,6 @@
/* RegExp interface for clients without a global object. */
-extern JS_PUBLIC_API(JSObject*)
-JS_NewRegExpObjectNoStatics(JSContext* cx, char* bytes, size_t length, unsigned flags);
-
-extern JS_PUBLIC_API(JSObject*)
-JS_NewUCRegExpObjectNoStatics(JSContext* cx, char16_t* chars, size_t length, unsigned flags);
-
extern JS_PUBLIC_API(bool)
JS_ExecuteRegExpNoStatics(JSContext* cx, JS::HandleObject reobj, char16_t* chars, size_t length,
size_t* indexp, bool test, JS::MutableHandleValue rval);
@@ -5022,9 +5637,6 @@
extern JS_PUBLIC_API(void)
JS_ClearPendingException(JSContext* cx);
-extern JS_PUBLIC_API(bool)
-JS_ReportPendingException(JSContext* cx);
-
namespace JS {
/**
@@ -5102,8 +5714,15 @@
extern JS_PUBLIC_API(JSErrorReport*)
JS_ErrorFromException(JSContext* cx, JS::HandleObject obj);
+/**
+ * If the given object is an exception object (or an unwrappable
+ * cross-compartment wrapper for one), return the stack for that exception, if
+ * any. Will return null if the given object is not an exception object
+ * (including if it's null or a security wrapper that can't be unwrapped) or if
+ * the exception has no stack.
+ */
extern JS_PUBLIC_API(JSObject*)
-ExceptionStackOrNull(JSContext* cx, JS::HandleObject obj);
+ExceptionStackOrNull(JS::HandleObject obj);
/*
* Throws a StopIteration exception on cx.
@@ -5112,23 +5731,20 @@
JS_ThrowStopIteration(JSContext* cx);
extern JS_PUBLIC_API(bool)
-JS_IsStopIteration(JS::Value v);
-
-extern JS_PUBLIC_API(intptr_t)
-JS_GetCurrentThread();
+JS_IsStopIteration(const JS::Value& v);
/**
- * A JS runtime always has an "owner thread". The owner thread is set when the
- * runtime is created (to the current thread) and practically all entry points
- * into the JS engine check that a runtime (or anything contained in the
- * runtime: context, compartment, object, etc) is only touched by its owner
+ * A JS context always has an "owner thread". The owner thread is set when the
+ * context is created (to the current thread) and practically all entry points
+ * into the JS engine check that a context (or anything contained in the
+ * context: runtime, compartment, object, etc) is only touched by its owner
* thread. Embeddings may check this invariant outside the JS engine by calling
* JS_AbortIfWrongThread (which will abort if not on the owner thread, even for
* non-debug builds).
*/
extern JS_PUBLIC_API(void)
-JS_AbortIfWrongThread(JSRuntime* rt);
+JS_AbortIfWrongThread(JSContext* cx);
/************************************************************************/
@@ -5146,7 +5762,7 @@
#define JS_DEFAULT_ZEAL_FREQ 100
extern JS_PUBLIC_API(void)
-JS_GetGCZeal(JSContext* cx, uint8_t* zeal, uint32_t* frequency, uint32_t* nextScheduled);
+JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled);
extern JS_PUBLIC_API(void)
JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency);
@@ -5156,10 +5772,10 @@
#endif
extern JS_PUBLIC_API(void)
-JS_SetParallelParsingEnabled(JSRuntime* rt, bool enabled);
+JS_SetParallelParsingEnabled(JSContext* cx, bool enabled);
extern JS_PUBLIC_API(void)
-JS_SetOffthreadIonCompilationEnabled(JSRuntime* rt, bool enabled);
+JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled);
#define JIT_COMPILER_OPTIONS(Register) \
Register(BASELINE_WARMUP_TRIGGER, "baseline.warmup.trigger") \
@@ -5167,9 +5783,14 @@
Register(ION_GVN_ENABLE, "ion.gvn.enable") \
Register(ION_FORCE_IC, "ion.forceinlineCaches") \
Register(ION_ENABLE, "ion.enable") \
+ Register(ION_INTERRUPT_WITHOUT_SIGNAL, "ion.interrupt-without-signals") \
+ Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis") \
Register(BASELINE_ENABLE, "baseline.enable") \
Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
- Register(SIGNALS_ENABLE, "signals.enable")
+ Register(JUMP_THRESHOLD, "jump-threshold") \
+ Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable") \
+ Register(WASM_TEST_MODE, "wasm.test-mode") \
+ Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets")
typedef enum JSJitCompilerOption {
#define JIT_COMPILER_DECLARE(key, str) \
@@ -5182,9 +5803,9 @@
} JSJitCompilerOption;
extern JS_PUBLIC_API(void)
-JS_SetGlobalJitCompilerOption(JSRuntime* rt, JSJitCompilerOption opt, uint32_t value);
-extern JS_PUBLIC_API(int)
-JS_GetGlobalJitCompilerOption(JSRuntime* rt, JSJitCompilerOption opt);
+JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t value);
+extern JS_PUBLIC_API(bool)
+JS_GetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t* valueOut);
/**
* Convert a uint32_t index into a jsid.
@@ -5214,26 +5835,38 @@
extern JS_PUBLIC_API(bool)
JS_IsIdentifier(const char16_t* chars, size_t length);
+namespace js {
+class ScriptSource;
+} // namespace js
+
namespace JS {
-/**
- * AutoFilename encapsulates a pointer to a C-string and keeps the C-string
- * alive for as long as the associated AutoFilename object is alive.
- */
-class MOZ_STACK_CLASS JS_PUBLIC_API(AutoFilename)
+class MOZ_RAII JS_PUBLIC_API(AutoFilename)
{
- void* scriptSource_;
+ private:
+ js::ScriptSource* ss_;
+ mozilla::Variant<const char*, UniqueChars> filename_;
AutoFilename(const AutoFilename&) = delete;
- void operator=(const AutoFilename&) = delete;
+ AutoFilename& operator=(const AutoFilename&) = delete;
public:
- AutoFilename() : scriptSource_(nullptr) {}
- ~AutoFilename() { reset(nullptr); }
+ AutoFilename()
+ : ss_(nullptr),
+ filename_(mozilla::AsVariant<const char*>(nullptr))
+ {}
- const char* get() const;
+ ~AutoFilename() {
+ reset();
+ }
- void reset(void* newScriptSource);
+ void reset();
+
+ void setOwned(UniqueChars&& filename);
+ void setUnowned(const char* filename);
+ void setScriptSource(js::ScriptSource* ss);
+
+ const char* get() const;
};
/**
@@ -5288,23 +5921,62 @@
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
-} /* namespace JS */
-
/*
* Encode/Decode interpreted scripts and functions to/from memory.
*/
-extern JS_PUBLIC_API(void*)
-JS_EncodeScript(JSContext* cx, JS::HandleScript script, uint32_t* lengthp);
+typedef mozilla::Vector<uint8_t> TranscodeBuffer;
-extern JS_PUBLIC_API(void*)
-JS_EncodeInterpretedFunction(JSContext* cx, JS::HandleObject funobj, uint32_t* lengthp);
+enum TranscodeResult
+{
+ // Successful encoding / decoding.
+ TranscodeResult_Ok = 0,
-extern JS_PUBLIC_API(JSScript*)
-JS_DecodeScript(JSContext* cx, const void* data, uint32_t length);
+ // A warning message, is set to the message out-param.
+ TranscodeResult_Failure = 0x100,
+ TranscodeResult_Failure_BadBuildId = TranscodeResult_Failure | 0x1,
+ TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
+ TranscodeResult_Failure_AsmJSNotSupported = TranscodeResult_Failure | 0x3,
+ TranscodeResult_Failure_UnknownClassKind = TranscodeResult_Failure | 0x4,
-extern JS_PUBLIC_API(JSObject*)
-JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length);
+ // A error, the JSContext has a pending exception.
+ TranscodeResult_Throw = 0x200
+};
+
+extern JS_PUBLIC_API(TranscodeResult)
+EncodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::HandleScript script);
+
+extern JS_PUBLIC_API(TranscodeResult)
+EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::HandleObject funobj);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp,
+ size_t cursorIndex = 0);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleFunction funp,
+ size_t cursorIndex = 0);
+
+} /* namespace JS */
+
+namespace js {
+
+enum class StackFormat { SpiderMonkey, V8, Default };
+
+/*
+ * Sets the format used for stringifying Error stacks.
+ *
+ * The default format is StackFormat::SpiderMonkey. Use StackFormat::V8
+ * in order to emulate V8's stack formatting. StackFormat::Default can't be
+ * used here.
+ */
+extern JS_PUBLIC_API(void)
+SetStackFormat(JSContext* cx, StackFormat format);
+
+extern JS_PUBLIC_API(StackFormat)
+GetStackFormat(JSContext* cx);
+
+}
namespace JS {
@@ -5326,8 +5998,8 @@
/** The list of reasons why an asm.js module may not be stored in the cache. */
enum AsmJSCacheResult
{
- AsmJSCache_MIN,
- AsmJSCache_Success = AsmJSCache_MIN,
+ AsmJSCache_Success,
+ AsmJSCache_MIN = AsmJSCache_Success,
AsmJSCache_ModuleTooSmall,
AsmJSCache_SynchronousScript,
AsmJSCache_QuotaExceeded,
@@ -5336,6 +6008,8 @@
AsmJSCache_Disabled_ShellFlags,
AsmJSCache_Disabled_JitInspector,
AsmJSCache_InternalError,
+ AsmJSCache_Disabled_PrivateBrowsing,
+ AsmJSCache_ESR52,
AsmJSCache_LIMIT
};
@@ -5361,7 +6035,16 @@
typedef void
(* CloseAsmJSCacheEntryForWriteOp)(size_t size, uint8_t* memory, intptr_t handle);
-typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
+struct AsmJSCacheOps
+{
+ OpenAsmJSCacheEntryForReadOp openEntryForRead;
+ CloseAsmJSCacheEntryForReadOp closeEntryForRead;
+ OpenAsmJSCacheEntryForWriteOp openEntryForWrite;
+ CloseAsmJSCacheEntryForWriteOp closeEntryForWrite;
+};
+
+extern JS_PUBLIC_API(void)
+SetAsmJSCacheOps(JSContext* cx, const AsmJSCacheOps* callbacks);
/**
* Return the buildId (represented as a sequence of characters) associated with
@@ -5370,20 +6053,64 @@
* engine, it is critical that the buildId shall change for each new build of
* the JS engine.
*/
+typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
+
typedef bool
(* BuildIdOp)(BuildIdCharVector* buildId);
-struct AsmJSCacheOps
+extern JS_PUBLIC_API(void)
+SetBuildIdOp(JSContext* cx, BuildIdOp buildIdOp);
+
+/**
+ * The WasmModule interface allows the embedding to hold a reference to the
+ * underying C++ implementation of a JS WebAssembly.Module object for purposes
+ * of (de)serialization off the object's JSRuntime's thread.
+ *
+ * - Serialization starts when WebAssembly.Module is passed to the
+ * structured-clone algorithm. JS::GetWasmModule is called on the JSRuntime
+ * thread that initiated the structured clone to get the JS::WasmModule.
+ * This interface is then taken to a background thread where serializedSize()
+ * and serialize() are called to write the object to two files: a bytecode file
+ * that always allows successful deserialization and a compiled-code file keyed
+ * on cpu- and build-id that may become invalid if either of these change between
+ * serialization and deserialization. After serialization, the reference is
+ * dropped from the background thread.
+ *
+ * - Deserialization starts when the structured clone algorithm encounters a
+ * serialized WebAssembly.Module. On a background thread, the compiled-code file
+ * is opened and CompiledWasmModuleAssumptionsMatch is called to see if it is
+ * still valid (as described above). DeserializeWasmModule is then called to
+ * construct a JS::WasmModule (also on the background thread), passing the
+ * bytecode file descriptor and, if valid, the compiled-code file descriptor.
+ * The JS::WasmObject is then transported to the JSRuntime thread (which
+ * originated the request) and the wrapping WebAssembly.Module object is created
+ * by calling createObject().
+ */
+
+struct WasmModule : mozilla::external::AtomicRefCounted<WasmModule>
{
- OpenAsmJSCacheEntryForReadOp openEntryForRead;
- CloseAsmJSCacheEntryForReadOp closeEntryForRead;
- OpenAsmJSCacheEntryForWriteOp openEntryForWrite;
- CloseAsmJSCacheEntryForWriteOp closeEntryForWrite;
- BuildIdOp buildId;
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(WasmModule)
+ virtual ~WasmModule() {}
+
+ virtual void serializedSize(size_t* maybeBytecodeSize, size_t* maybeCompiledSize) const = 0;
+ virtual void serialize(uint8_t* maybeBytecodeBegin, size_t maybeBytecodeSize,
+ uint8_t* maybeCompiledBegin, size_t maybeCompiledSize) const = 0;
+
+ virtual JSObject* createObject(JSContext* cx) = 0;
};
-extern JS_PUBLIC_API(void)
-SetAsmJSCacheOps(JSRuntime* rt, const AsmJSCacheOps* callbacks);
+extern JS_PUBLIC_API(bool)
+IsWasmModuleObject(HandleObject obj);
+
+extern JS_PUBLIC_API(RefPtr<WasmModule>)
+GetWasmModule(HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+CompiledWasmModuleAssumptionsMatch(PRFileDesc* compiled, BuildIdCharVector&& buildId);
+
+extern JS_PUBLIC_API(RefPtr<WasmModule>)
+DeserializeWasmModule(PRFileDesc* bytecode, PRFileDesc* maybeCompiled, BuildIdCharVector&& buildId,
+ JS::UniqueChars filename, unsigned line, unsigned column);
/**
* Convenience class for imitating a JS level for-of loop. Typical usage:
@@ -5475,7 +6202,7 @@
(* LargeAllocationFailureCallback)(void* data);
extern JS_PUBLIC_API(void)
-SetLargeAllocationFailureCallback(JSRuntime* rt, LargeAllocationFailureCallback afc, void* data);
+SetLargeAllocationFailureCallback(JSContext* cx, LargeAllocationFailureCallback afc, void* data);
/**
* Unlike the error reporter, which is only called if the exception for an OOM
@@ -5492,17 +6219,99 @@
(* OutOfMemoryCallback)(JSContext* cx, void* data);
extern JS_PUBLIC_API(void)
-SetOutOfMemoryCallback(JSRuntime* rt, OutOfMemoryCallback cb, void* data);
+SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data);
+
+/**
+ * Capture all frames.
+ */
+struct AllFrames { };
+
+/**
+ * Capture at most this many frames.
+ */
+struct MaxFrames
+{
+ uint32_t maxFrames;
+
+ explicit MaxFrames(uint32_t max)
+ : maxFrames(max)
+ {
+ MOZ_ASSERT(max > 0);
+ }
+};
+
+/**
+ * Capture the first frame with the given principals. By default, do not
+ * consider self-hosted frames with the given principals as satisfying the stack
+ * capture.
+ */
+struct JS_PUBLIC_API(FirstSubsumedFrame)
+{
+ JSContext* cx;
+ JSPrincipals* principals;
+ bool ignoreSelfHosted;
+
+ /**
+ * Use the cx's current compartment's principals.
+ */
+ explicit FirstSubsumedFrame(JSContext* cx, bool ignoreSelfHostedFrames = true);
+ explicit FirstSubsumedFrame(JSContext* ctx, JSPrincipals* p, bool ignoreSelfHostedFrames = true)
+ : cx(ctx)
+ , principals(p)
+ , ignoreSelfHosted(ignoreSelfHostedFrames)
+ {
+ if (principals)
+ JS_HoldPrincipals(principals);
+ }
+
+ // No copying because we want to avoid holding and dropping principals
+ // unnecessarily.
+ FirstSubsumedFrame(const FirstSubsumedFrame&) = delete;
+ FirstSubsumedFrame& operator=(const FirstSubsumedFrame&) = delete;
+
+ FirstSubsumedFrame(FirstSubsumedFrame&& rhs)
+ : principals(rhs.principals)
+ , ignoreSelfHosted(rhs.ignoreSelfHosted)
+ {
+ MOZ_ASSERT(this != &rhs, "self move disallowed");
+ rhs.principals = nullptr;
+ }
+
+ FirstSubsumedFrame& operator=(FirstSubsumedFrame&& rhs) {
+ new (this) FirstSubsumedFrame(mozilla::Move(rhs));
+ return *this;
+ }
+
+ ~FirstSubsumedFrame() {
+ if (principals)
+ JS_DropPrincipals(cx, principals);
+ }
+};
+
+using StackCapture = mozilla::Variant<AllFrames, MaxFrames, FirstSubsumedFrame>;
/**
* Capture the current call stack as a chain of SavedFrame JSObjects, and set
* |stackp| to the SavedFrame for the youngest stack frame, or nullptr if there
- * are no JS frames on the stack. If |maxFrameCount| is non-zero, capture at
- * most the youngest |maxFrameCount| frames.
+ * are no JS frames on the stack.
+ *
+ * The |capture| parameter describes the portion of the JS stack to capture:
+ *
+ * * |JS::AllFrames|: Capture all frames on the stack.
+ *
+ * * |JS::MaxFrames|: Capture no more than |JS::MaxFrames::maxFrames| from the
+ * stack.
+ *
+ * * |JS::FirstSubsumedFrame|: Capture the first frame whose principals are
+ * subsumed by |JS::FirstSubsumedFrame::principals|. By default, do not
+ * consider self-hosted frames; this can be controlled via the
+ * |JS::FirstSubsumedFrame::ignoreSelfHosted| flag. Do not capture any async
+ * stack.
*/
extern JS_PUBLIC_API(bool)
-CaptureCurrentStack(JSContext* cx, MutableHandleObject stackp, unsigned maxFrameCount = 0);
+CaptureCurrentStack(JSContext* cx, MutableHandleObject stackp,
+ StackCapture&& capture = StackCapture(AllFrames()));
/*
* This is a utility function for preparing an async stack to be used
@@ -5632,7 +6441,15 @@
* each line.
*/
extern JS_PUBLIC_API(bool)
-BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp, size_t indent = 0);
+BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp,
+ size_t indent = 0, js::StackFormat stackFormat = js::StackFormat::Default);
+
+/**
+ * Return true iff the given object is either a SavedFrame object or wrapper
+ * around a SavedFrame object, and it is not the SavedFrame.prototype object.
+ */
+extern JS_PUBLIC_API(bool)
+IsSavedFrame(JSObject* obj);
} /* namespace JS */
@@ -5649,7 +6466,7 @@
* provide a concrete implementation of this class, as well as the
* relevant callbacks (see below).
*/
-struct PerformanceGroup {
+struct JS_PUBLIC_API(PerformanceGroup) {
PerformanceGroup();
// The current iteration of the event loop.
@@ -5745,6 +6562,8 @@
uint64_t refCount_;
};
+using PerformanceGroupVector = mozilla::Vector<RefPtr<js::PerformanceGroup>, 0, SystemAllocPolicy>;
+
/**
* Commit any Performance Monitoring data.
*
@@ -5752,19 +6571,19 @@
* to the outside world and can cancelled with a call to `ResetMonitoring`.
*/
extern JS_PUBLIC_API(bool)
-FlushPerformanceMonitoring(JSRuntime*);
+FlushPerformanceMonitoring(JSContext*);
/**
* Cancel any measurement that hasn't been committed.
*/
extern JS_PUBLIC_API(void)
-ResetPerformanceMonitoring(JSRuntime*);
+ResetPerformanceMonitoring(JSContext*);
/**
* Cleanup any memory used by performance monitoring.
*/
extern JS_PUBLIC_API(void)
-DisposePerformanceMonitoring(JSRuntime*);
+DisposePerformanceMonitoring(JSContext*);
/**
* Turn on/off stopwatch-based CPU monitoring.
@@ -5774,20 +6593,17 @@
* happen if we are out of memory.
*/
extern JS_PUBLIC_API(bool)
-SetStopwatchIsMonitoringCPOW(JSRuntime*, bool);
+SetStopwatchIsMonitoringCPOW(JSContext*, bool);
extern JS_PUBLIC_API(bool)
-GetStopwatchIsMonitoringCPOW(JSRuntime*);
+GetStopwatchIsMonitoringCPOW(JSContext*);
extern JS_PUBLIC_API(bool)
-SetStopwatchIsMonitoringJank(JSRuntime*, bool);
-extern JS_PUBLIC_API(bool)
-GetStopwatchIsMonitoringJank(JSRuntime*);
-
+SetStopwatchIsMonitoringJank(JSContext*, bool);
extern JS_PUBLIC_API(bool)
-IsStopwatchActive(JSRuntime*);
+GetStopwatchIsMonitoringJank(JSContext*);
// Extract the CPU rescheduling data.
extern JS_PUBLIC_API(void)
-GetPerfMonitoringTestCpuRescheduling(JSRuntime*, uint64_t* stayed, uint64_t* moved);
+GetPerfMonitoringTestCpuRescheduling(JSContext*, uint64_t* stayed, uint64_t* moved);
/**
@@ -5795,22 +6611,22 @@
* since process start.
*/
extern JS_PUBLIC_API(void)
-AddCPOWPerformanceDelta(JSRuntime*, uint64_t delta);
+AddCPOWPerformanceDelta(JSContext*, uint64_t delta);
typedef bool
(*StopwatchStartCallback)(uint64_t, void*);
extern JS_PUBLIC_API(bool)
-SetStopwatchStartCallback(JSRuntime*, StopwatchStartCallback, void*);
+SetStopwatchStartCallback(JSContext*, StopwatchStartCallback, void*);
typedef bool
-(*StopwatchCommitCallback)(uint64_t, mozilla::Vector<RefPtr<PerformanceGroup>>&, void*);
+(*StopwatchCommitCallback)(uint64_t, PerformanceGroupVector&, void*);
extern JS_PUBLIC_API(bool)
-SetStopwatchCommitCallback(JSRuntime*, StopwatchCommitCallback, void*);
+SetStopwatchCommitCallback(JSContext*, StopwatchCommitCallback, void*);
typedef bool
-(*GetGroupsCallback)(JSContext*, mozilla::Vector<RefPtr<PerformanceGroup>>&, void*);
+(*GetGroupsCallback)(JSContext*, PerformanceGroupVector&, void*);
extern JS_PUBLIC_API(bool)
-SetGetPerformanceGroupsCallback(JSRuntime*, GetGroupsCallback, void*);
+SetGetPerformanceGroupsCallback(JSContext*, GetGroupsCallback, void*);
} /* namespace js */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jscpucfg.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jscpucfg.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jscpucfg.h
@@ -7,119 +7,7 @@
#ifndef jscpucfg_h
#define jscpucfg_h
-#define JS_HAVE_LONG_LONG
-
-#if defined(_WIN64)
-
-# if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# else /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
-# error "CPU type is unknown"
-# endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
-
-#elif defined(_WIN32)
-
-# ifdef __WATCOMC__
-# define HAVE_VA_LIST_AS_ARRAY 1
-# endif
-
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-
-#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
-
-#elif defined(JS_HAVE_ENDIAN_H)
-# include <endian.h>
-
-/*
- * Historically, OSes providing <endian.h> only defined
- * __BYTE_ORDER to either __LITTLE_ENDIAN or __BIG_ENDIAN.
- * The Austin group decided to standardise <endian.h> in
- * POSIX around 2011, expecting it to provide a BYTE_ORDER
- * #define set to either LITTLE_ENDIAN or BIG_ENDIAN. We
- * should try to cope with both possibilities here.
- */
-
-# if defined(__BYTE_ORDER) || defined(BYTE_ORDER)
-# if defined(__BYTE_ORDER)
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# elif __BYTE_ORDER == __BIG_ENDIAN
-# undef IS_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 1
-# endif
-# endif
-# if defined(BYTE_ORDER)
-# if BYTE_ORDER == LITTLE_ENDIAN
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# elif BYTE_ORDER == BIG_ENDIAN
-# undef IS_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 1
-# endif
-# endif
-# else /* !defined(__BYTE_ORDER) */
-# error "endian.h does not define __BYTE_ORDER nor BYTE_ORDER. Cannot determine endianness."
-# endif
-
-/* BSDs */
-#elif defined(JS_HAVE_MACHINE_ENDIAN_H)
-# include <sys/types.h>
-# include <machine/endian.h>
-
-# if defined(_BYTE_ORDER)
-# if _BYTE_ORDER == _LITTLE_ENDIAN
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# elif _BYTE_ORDER == _BIG_ENDIAN
-# undef IS_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 1
-# endif
-# else /* !defined(_BYTE_ORDER) */
-# error "machine/endian.h does not define _BYTE_ORDER. Cannot determine endianness."
-# endif
-
-#elif defined(JS_HAVE_SYS_ISA_DEFS_H)
-# include <sys/isa_defs.h>
-
-# if defined(_BIG_ENDIAN)
-# undef IS_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 1
-# elif defined(_LITTLE_ENDIAN)
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# else /* !defined(_LITTLE_ENDIAN) */
-# error "sys/isa_defs.h does not define _BIG_ENDIAN or _LITTLE_ENDIAN. Cannot determine endianness."
-# endif
-# if !defined(JS_STACK_GROWTH_DIRECTION)
-# 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(__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__) && ... */
-# error "Cannot determine endianness of your platform. Please add support to jscpucfg.h."
-#endif
+#include "mozilla/EndianUtils.h"
#ifndef JS_STACK_GROWTH_DIRECTION
# ifdef __hppa
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsfriendapi.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsfriendapi.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsfriendapi.h
@@ -9,6 +9,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/Casting.h"
+#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/UniquePtr.h"
@@ -19,6 +20,7 @@
#include "js/CallArgs.h"
#include "js/CallNonGenericMethod.h"
#include "js/Class.h"
+#include "js/Utility.h"
#if JS_STACK_GROWTH_DIRECTION > 0
# define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) < (limit)))
@@ -43,7 +45,7 @@
} /* namespace js */
extern JS_FRIEND_API(void)
-JS_SetGrayGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
+JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
extern JS_FRIEND_API(JSObject*)
JS_FindCompilationScope(JSContext* cx, JS::HandleObject obj);
@@ -72,9 +74,6 @@
extern JS_FRIEND_API(size_t)
JS_SetProtoCalled(JSContext* cx);
-extern JS_FRIEND_API(bool)
-JS_ImmutablePrototypesEnabled();
-
extern JS_FRIEND_API(size_t)
JS_GetCustomIteratorCount(JSContext* cx);
@@ -108,36 +107,46 @@
enum {
JS_TELEMETRY_GC_REASON,
- JS_TELEMETRY_GC_IS_COMPARTMENTAL,
+ JS_TELEMETRY_GC_IS_ZONE_GC,
JS_TELEMETRY_GC_MS,
JS_TELEMETRY_GC_BUDGET_MS,
JS_TELEMETRY_GC_ANIMATION_MS,
JS_TELEMETRY_GC_MAX_PAUSE_MS,
JS_TELEMETRY_GC_MARK_MS,
JS_TELEMETRY_GC_SWEEP_MS,
+ JS_TELEMETRY_GC_COMPACT_MS,
JS_TELEMETRY_GC_MARK_ROOTS_MS,
JS_TELEMETRY_GC_MARK_GRAY_MS,
JS_TELEMETRY_GC_SLICE_MS,
JS_TELEMETRY_GC_SLOW_PHASE,
JS_TELEMETRY_GC_MMU_50,
JS_TELEMETRY_GC_RESET,
+ JS_TELEMETRY_GC_RESET_REASON,
JS_TELEMETRY_GC_INCREMENTAL_DISABLED,
JS_TELEMETRY_GC_NON_INCREMENTAL,
+ JS_TELEMETRY_GC_NON_INCREMENTAL_REASON,
JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS,
JS_TELEMETRY_GC_MINOR_REASON,
JS_TELEMETRY_GC_MINOR_REASON_LONG,
JS_TELEMETRY_GC_MINOR_US,
+ JS_TELEMETRY_GC_NURSERY_BYTES,
+ JS_TELEMETRY_GC_PRETENURE_COUNT,
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT,
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS,
- JS_TELEMETRY_ADDON_EXCEPTIONS
+ JS_TELEMETRY_ADDON_EXCEPTIONS,
+ JS_TELEMETRY_AOT_USAGE,
+ JS_TELEMETRY_END
};
typedef void
(*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample, const char* key);
extern JS_FRIEND_API(void)
-JS_SetAccumulateTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback);
+JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback);
+
+extern JS_FRIEND_API(bool)
+JS_GetIsSecureContext(JSCompartment* compartment);
extern JS_FRIEND_API(JSPrincipals*)
JS_GetCompartmentPrincipals(JSCompartment* compartment);
@@ -178,7 +187,7 @@
namespace js {
JS_FRIEND_API(bool)
-GetBuiltinClass(JSContext* cx, JS::HandleObject obj, ESClassValue* classValue);
+GetBuiltinClass(JSContext* cx, JS::HandleObject obj, ESClass* cls);
JS_FRIEND_API(const char*)
ObjectClassName(JSContext* cx, JS::HandleObject obj);
@@ -198,41 +207,57 @@
#ifdef JS_DEBUG
/*
- * Routines to print out values during debugging. These are FRIEND_API to help
+ * Routines to print out values during debugging. These are FRIEND_API to help
* the debugger find them and to support temporarily hacking js::Dump* calls
- * into other code.
+ * into other code. Note that there are overloads that do not require the FILE*
+ * parameter, which will default to stderr.
*/
extern JS_FRIEND_API(void)
-DumpString(JSString* str);
+DumpString(JSString* str, FILE* fp);
extern JS_FRIEND_API(void)
-DumpAtom(JSAtom* atom);
+DumpAtom(JSAtom* atom, FILE* fp);
extern JS_FRIEND_API(void)
-DumpObject(JSObject* obj);
+DumpObject(JSObject* obj, FILE* fp);
extern JS_FRIEND_API(void)
-DumpChars(const char16_t* s, size_t n);
+DumpChars(const char16_t* s, size_t n, FILE* fp);
extern JS_FRIEND_API(void)
-DumpValue(const JS::Value& val);
+DumpValue(const JS::Value& val, FILE* fp);
extern JS_FRIEND_API(void)
-DumpId(jsid id);
+DumpId(jsid id, FILE* fp);
extern JS_FRIEND_API(void)
-DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start = nullptr);
+DumpInterpreterFrame(JSContext* cx, FILE* fp, InterpreterFrame* start = nullptr);
extern JS_FRIEND_API(bool)
-DumpPC(JSContext* cx);
+DumpPC(JSContext* cx, FILE* fp);
extern JS_FRIEND_API(bool)
-DumpScript(JSContext* cx, JSScript* scriptArg);
+DumpScript(JSContext* cx, JSScript* scriptArg, FILE* fp);
+
+// Versions for use directly in a debugger (default parameters are not handled
+// well in gdb; built-in handles like stderr are not handled well in lldb.)
+extern JS_FRIEND_API(void) DumpString(JSString* str);
+extern JS_FRIEND_API(void) DumpAtom(JSAtom* atom);
+extern JS_FRIEND_API(void) DumpObject(JSObject* obj);
+extern JS_FRIEND_API(void) DumpChars(const char16_t* s, size_t n);
+extern JS_FRIEND_API(void) DumpValue(const JS::Value& val);
+extern JS_FRIEND_API(void) DumpId(jsid id);
+extern JS_FRIEND_API(void) DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start = nullptr);
+extern JS_FRIEND_API(bool) DumpPC(JSContext* cx);
+extern JS_FRIEND_API(bool) DumpScript(JSContext* cx, JSScript* scriptArg);
#endif
extern JS_FRIEND_API(void)
+DumpBacktrace(JSContext* cx, FILE* fp);
+
+extern JS_FRIEND_API(void)
DumpBacktrace(JSContext* cx);
} // namespace js
@@ -243,6 +268,13 @@
extern JS_FRIEND_API(char*)
FormatStackDump(JSContext* cx, char* buf, bool showArgs, bool showLocals, bool showThisProps);
+/**
+ * Set all of the uninitialized lexicals on an object to undefined. Return
+ * true if any lexicals were initialized and false otherwise.
+ * */
+extern JS_FRIEND_API(bool)
+ForceLexicalInitialization(JSContext *cx, HandleObject obj);
+
} // namespace JS
/**
@@ -275,7 +307,7 @@
PropertyCopyBehavior copyBehavior = CopyNonConfigurableAsIs);
extern JS_FRIEND_API(bool)
-JS_WrapPropertyDescriptor(JSContext* cx, JS::MutableHandle<JSPropertyDescriptor> desc);
+JS_WrapPropertyDescriptor(JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);
struct JSFunctionSpecWithHelp {
const char* name;
@@ -300,61 +332,37 @@
namespace js {
+extern JS_FRIEND_DATA(const js::ClassOps) ProxyClassOps;
+extern JS_FRIEND_DATA(const js::ClassExtension) ProxyClassExtension;
+extern JS_FRIEND_DATA(const js::ObjectOps) ProxyObjectOps;
+
/*
* Helper Macros for creating JSClasses that function as proxies.
*
* NB: The macro invocation must be surrounded by braces, so as to
* allow for potential JSClass extensions.
*/
-#define PROXY_MAKE_EXT(isWrappedNative, objectMoved) \
+#define PROXY_MAKE_EXT(objectMoved) \
{ \
- isWrappedNative, \
js::proxy_WeakmapKeyDelegate, \
objectMoved \
}
-#define PROXY_CLASS_WITH_EXT(name, flags, ext) \
+#define PROXY_CLASS_WITH_EXT(name, flags, extPtr) \
{ \
name, \
js::Class::NON_NATIVE | \
JSCLASS_IS_PROXY | \
- JSCLASS_DELAY_METADATA_CALLBACK | \
+ JSCLASS_DELAY_METADATA_BUILDER | \
flags, \
- nullptr, /* addProperty */ \
- nullptr, /* delProperty */ \
- nullptr, /* getProperty */ \
- nullptr, /* setProperty */ \
- nullptr, /* enumerate */ \
- nullptr, /* resolve */ \
- nullptr, /* mayResolve */ \
- js::proxy_Finalize, /* finalize */ \
- nullptr, /* call */ \
- js::proxy_HasInstance, /* hasInstance */ \
- nullptr, /* construct */ \
- js::proxy_Trace, /* trace */ \
+ &js::ProxyClassOps, \
JS_NULL_CLASS_SPEC, \
- ext, \
- { \
- js::proxy_LookupProperty, \
- js::proxy_DefineProperty, \
- js::proxy_HasProperty, \
- js::proxy_GetProperty, \
- js::proxy_SetProperty, \
- js::proxy_GetOwnPropertyDescriptor, \
- js::proxy_DeleteProperty, \
- js::proxy_Watch, js::proxy_Unwatch, \
- js::proxy_GetElements, \
- nullptr, /* enumerate */ \
- js::proxy_FunToString, \
- } \
- }
-
-#define PROXY_CLASS_DEF(name, flags) \
- PROXY_CLASS_WITH_EXT(name, flags, \
- PROXY_MAKE_EXT( \
- false, /* isWrappedNative */ \
- js::proxy_ObjectMoved \
- ))
+ extPtr, \
+ &js::ProxyObjectOps \
+ }
+
+#define PROXY_CLASS_DEF(name, flags) \
+ PROXY_CLASS_WITH_EXT(name, flags, &js::ProxyClassExtension)
/*
* Proxy stubs, similar to JS_*Stub, for embedder proxy class definitions.
@@ -367,7 +375,7 @@
JS::MutableHandle<Shape*> propp);
extern JS_FRIEND_API(bool)
proxy_DefineProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::Handle<JSPropertyDescriptor> desc,
+ JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
extern JS_FRIEND_API(bool)
proxy_HasProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
@@ -379,7 +387,7 @@
JS::HandleValue receiver, JS::ObjectOpResult& result);
extern JS_FRIEND_API(bool)
proxy_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_FRIEND_API(bool)
proxy_DeleteProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::ObjectOpResult& result);
@@ -436,17 +444,17 @@
};
/**
- * Have |rt| use |hook| to retrieve lazily-retrieved source code. See the
- * comments for SourceHook. The runtime takes ownership of the hook, and
- * will delete it when the runtime itself is deleted, or when a new hook is
+ * Have |cx| use |hook| to retrieve lazily-retrieved source code. See the
+ * comments for SourceHook. The context takes ownership of the hook, and
+ * will delete it when the context itself is deleted, or when a new hook is
* set.
*/
extern JS_FRIEND_API(void)
-SetSourceHook(JSRuntime* rt, mozilla::UniquePtr<SourceHook> hook);
+SetSourceHook(JSContext* cx, mozilla::UniquePtr<SourceHook> hook);
-/** Remove |rt|'s source hook, and return it. The caller now owns the hook. */
+/** Remove |cx|'s source hook, and return it. The caller now owns the hook. */
extern JS_FRIEND_API(mozilla::UniquePtr<SourceHook>)
-ForgetSourceHook(JSRuntime* rt);
+ForgetSourceHook(JSContext* cx);
extern JS_FRIEND_API(JS::Zone*)
GetCompartmentZone(JSCompartment* comp);
@@ -464,7 +472,7 @@
* fp is the file for the dump output.
*/
extern JS_FRIEND_API(void)
-DumpHeap(JSRuntime* rt, FILE* fp, DumpHeapNurseryBehaviour nurseryBehaviour);
+DumpHeap(JSContext* cx, FILE* fp, DumpHeapNurseryBehaviour nurseryBehaviour);
#ifdef JS_OLD_GETTER_SETTER_METHODS
JS_FRIEND_API(bool) obj_defineGetter(JSContext* cx, unsigned argc, JS::Value* vp);
@@ -485,9 +493,9 @@
struct WeakMapTracer
{
- JSRuntime* runtime;
+ JSContext* context;
- explicit WeakMapTracer(JSRuntime* rt) : runtime(rt) {}
+ explicit WeakMapTracer(JSContext* cx) : context(cx) {}
// Weak map tracer callback, called once for every binding of every
// weak map that was live at the time of the last garbage collection.
@@ -502,7 +510,7 @@
TraceWeakMaps(WeakMapTracer* trc);
extern JS_FRIEND_API(bool)
-AreGCGrayBitsValid(JSRuntime* rt);
+AreGCGrayBitsValid(JSContext* cx);
extern JS_FRIEND_API(bool)
ZoneGlobalsAreAllGray(JS::Zone* zone);
@@ -516,15 +524,19 @@
extern JS_FRIEND_API(JSObject*)
GetWeakmapKeyDelegate(JSObject* key);
-JS_FRIEND_API(JS::TraceKind)
-GCThingTraceKind(void* thing);
-
/**
- * Invoke cellCallback on every gray JS_OBJECT in the given zone.
+ * Invoke cellCallback on every gray JSObject in the given zone.
*/
extern JS_FRIEND_API(void)
IterateGrayObjects(JS::Zone* zone, GCThingCallback cellCallback, void* data);
+/**
+ * Invoke cellCallback on every gray JSObject in the given zone while cycle
+ * collection is in progress.
+ */
+extern JS_FRIEND_API(void)
+IterateGrayObjectsUnderCC(JS::Zone* zone, GCThingCallback cellCallback, void* data);
+
#ifdef JS_HAS_CTYPES
extern JS_FRIEND_API(size_t)
SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj);
@@ -632,17 +644,6 @@
JS_FRIEND_API(const Class*)
ProtoKeyToClass(JSProtoKey key);
-// Returns true if the standard class identified by |key| inherits from
-// another standard class (in addition to Object) along its proto chain.
-//
-// In practice, this only returns true for Error subtypes.
-inline bool
-StandardClassIsDependent(JSProtoKey key)
-{
- const Class* clasp = ProtoKeyToClass(key);
- return clasp && clasp->spec.defined() && clasp->spec.dependent();
-}
-
// Returns the key for the class inherited by a given standard class (that
// is to say, the prototype of this standard class's prototype).
//
@@ -651,15 +652,15 @@
// cached proto key, except in cases where multiple JSProtoKeys share a
// JSClass.
inline JSProtoKey
-ParentKeyForStandardClass(JSProtoKey key)
+InheritanceProtoKeyForStandardClass(JSProtoKey key)
{
// [Object] has nothing to inherit from.
if (key == JSProto_Object)
return JSProto_Null;
- // If we're dependent, return the key of the class we depend on.
- if (StandardClassIsDependent(key))
- return ProtoKeyToClass(key)->spec.parentKey();
+ // If we're ClassSpec defined return the proto key from that
+ if (ProtoKeyToClass(key)->specDefined())
+ return ProtoKeyToClass(key)->specInheritanceProtoKey();
// Otherwise, we inherit [Object].
return JSProto_Object;
@@ -729,6 +730,9 @@
JS_FRIEND_API(bool)
GetObjectProto(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject proto);
+extern JS_FRIEND_API(JSObject*)
+GetStaticPrototype(JSObject* obj);
+
JS_FRIEND_API(bool)
GetOriginalEval(JSContext* cx, JS::HandleObject scope,
JS::MutableHandleObject eval);
@@ -884,28 +888,50 @@
return reinterpret_cast<JSLinearString*>(str);
}
+template<typename CharType>
+MOZ_ALWAYS_INLINE void
+CopyLinearStringChars(CharType* dest, JSLinearString* s, size_t len, size_t start = 0);
+
MOZ_ALWAYS_INLINE void
-CopyLinearStringChars(char16_t* dest, JSLinearString* s, size_t len)
+CopyLinearStringChars(char16_t* dest, JSLinearString* s, size_t len, size_t start = 0)
{
+ MOZ_ASSERT(start + len <= GetLinearStringLength(s));
JS::AutoCheckCannotGC nogc;
if (LinearStringHasLatin1Chars(s)) {
const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
for (size_t i = 0; i < len; i++)
- dest[i] = src[i];
+ dest[i] = src[start + i];
} else {
const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
- mozilla::PodCopy(dest, src, len);
+ mozilla::PodCopy(dest, src + start, len);
+ }
+}
+
+MOZ_ALWAYS_INLINE void
+CopyLinearStringChars(char* dest, JSLinearString* s, size_t len, size_t start = 0)
+{
+ MOZ_ASSERT(start + len <= GetLinearStringLength(s));
+ JS::AutoCheckCannotGC nogc;
+ if (LinearStringHasLatin1Chars(s)) {
+ const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
+ for (size_t i = 0; i < len; i++)
+ dest[i] = char(src[start + i]);
+ } else {
+ const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
+ for (size_t i = 0; i < len; i++)
+ dest[i] = char(src[start + i]);
}
}
+template<typename CharType>
inline bool
-CopyStringChars(JSContext* cx, char16_t* dest, JSString* s, size_t len)
+CopyStringChars(JSContext* cx, CharType* dest, JSString* s, size_t len, size_t start = 0)
{
JSLinearString* linear = StringToLinearString(cx, s);
if (!linear)
return false;
- CopyLinearStringChars(dest, linear, len);
+ CopyLinearStringChars(dest, linear, len, start);
return true;
}
@@ -946,15 +972,12 @@
StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
JS_FRIEND_API(void)
-SetPreserveWrapperCallback(JSRuntime* rt, PreserveWrapperCallback callback);
+SetPreserveWrapperCallback(JSContext* cx, PreserveWrapperCallback callback);
JS_FRIEND_API(bool)
IsObjectInContextCompartment(JSObject* obj, const JSContext* cx);
/*
- * NB: these flag bits are encoded into the bytecode stream in the immediate
- * operand of JSOP_ITER, so don't change them without advancing vm/Xdr.h's
- * XDR_BYTECODE_VERSION.
* NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
* The first three are omitted because they shouldn't be used in new code.
*/
@@ -972,9 +995,7 @@
inline uintptr_t
GetNativeStackLimit(JSContext* cx, StackKind kind, int extraAllowance = 0)
{
- PerThreadDataFriendFields* mainThread =
- PerThreadDataFriendFields::getMainThread(GetRuntime(cx));
- uintptr_t limit = mainThread->nativeStackLimit[kind];
+ uintptr_t limit = ContextFriendFields::get(cx)->nativeStackLimit[kind];
#if JS_STACK_GROWTH_DIRECTION > 0
limit += extraAllowance;
#else
@@ -1080,9 +1101,6 @@
JS_FRIEND_API(char*)
GetCodeCoverageSummary(JSContext* cx, size_t* length);
-JS_FRIEND_API(bool)
-ContextHasOutstandingRequests(const JSContext* cx);
-
typedef void
(* ActivityCallback)(void* arg, bool active);
@@ -1092,7 +1110,7 @@
* idle and a request begins.
*/
JS_FRIEND_API(void)
-SetActivityCallback(JSRuntime* rt, ActivityCallback cb, void* arg);
+SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg);
typedef bool
(* DOMInstanceClassHasProtoAtDepth)(const Class* instanceClass,
@@ -1103,10 +1121,10 @@
typedef struct JSDOMCallbacks DOMCallbacks;
extern JS_FRIEND_API(void)
-SetDOMCallbacks(JSRuntime* rt, const DOMCallbacks* callbacks);
+SetDOMCallbacks(JSContext* cx, const DOMCallbacks* callbacks);
extern JS_FRIEND_API(const DOMCallbacks*)
-GetDOMCallbacks(JSRuntime* rt);
+GetDOMCallbacks(JSContext* cx);
extern JS_FRIEND_API(JSObject*)
GetTestingFunctions(JSContext* cx);
@@ -1129,7 +1147,7 @@
* Returns nullptr for invalid arguments and JSEXN_INTERNALERR
*/
extern JS_FRIEND_API(JSFlatString*)
-GetErrorTypeName(JSRuntime* rt, int16_t exnType);
+GetErrorTypeName(JSContext* cx, int16_t exnType);
#ifdef JS_DEBUG
extern JS_FRIEND_API(unsigned)
@@ -1221,10 +1239,9 @@
generation(0)
{}
- void Unlink()
+ void OwnerUnlinked()
{
++generation;
- expando.setUndefined();
}
static size_t offsetOfExpando()
@@ -1306,29 +1323,35 @@
* JSString methods and often the code can be rewritten so that only indexes
* instead of char pointers are used in parts of the code that can GC.
*/
-class MOZ_STACK_CLASS AutoStableStringChars
+class MOZ_STACK_CLASS JS_FRIEND_API(AutoStableStringChars)
{
+ /*
+ * When copying string char, use this many bytes of inline storage. This is
+ * chosen to allow the inline string types to be copied without allocating.
+ * This is asserted in AutoStableStringChars::allocOwnChars.
+ */
+ static const size_t InlineCapacity = 24;
+
/* Ensure the string is kept alive while we're using its chars. */
JS::RootedString s_;
union {
const char16_t* twoByteChars_;
const JS::Latin1Char* latin1Chars_;
};
+ mozilla::Maybe<Vector<uint8_t, InlineCapacity>> ownChars_;
enum State { Uninitialized, Latin1, TwoByte };
State state_;
- bool ownsChars_;
public:
explicit AutoStableStringChars(JSContext* cx)
- : s_(cx), state_(Uninitialized), ownsChars_(false)
+ : s_(cx), state_(Uninitialized)
{}
- ~AutoStableStringChars();
- MOZ_WARN_UNUSED_RESULT
+ MOZ_MUST_USE
bool init(JSContext* cx, JSString* s);
/* Like init(), but Latin1 chars are inflated to TwoByte. */
- MOZ_WARN_UNUSED_RESULT
+ MOZ_MUST_USE
bool initTwoByte(JSContext* cx, JSString* s);
bool isLatin1() const { return state_ == Latin1; }
@@ -1348,46 +1371,79 @@
mozilla::Range<const char16_t> twoByteRange() const {
MOZ_ASSERT(state_ == TwoByte);
return mozilla::Range<const char16_t>(twoByteChars_,
- GetStringLength(s_));
+ GetStringLength(s_));
}
/* If we own the chars, transfer ownership to the caller. */
bool maybeGiveOwnershipToCaller() {
MOZ_ASSERT(state_ != Uninitialized);
- if (!ownsChars_)
+ if (!ownChars_.isSome() || !ownChars_->extractRawBuffer())
return false;
state_ = Uninitialized;
- ownsChars_ = false;
+ ownChars_.reset();
return true;
}
private:
AutoStableStringChars(const AutoStableStringChars& other) = delete;
void operator=(const AutoStableStringChars& other) = delete;
-};
-/**
- * Creates a string of the form |ErrorType: ErrorMessage| for a JSErrorReport,
- * which generally matches the toString() behavior of an ErrorObject.
- */
-extern JS_FRIEND_API(JSString*)
-ErrorReportToString(JSContext* cx, JSErrorReport* reportp);
+ bool baseIsInline(JS::Handle<JSLinearString*> linearString);
+ template <typename T> T* allocOwnChars(JSContext* cx, size_t count);
+ bool copyLatin1Chars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
+ bool copyTwoByteChars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
+ bool copyAndInflateLatin1Chars(JSContext*, JS::Handle<JSLinearString*> linearString);
+};
struct MOZ_STACK_CLASS JS_FRIEND_API(ErrorReport)
{
explicit ErrorReport(JSContext* cx);
~ErrorReport();
- bool init(JSContext* cx, JS::HandleValue exn);
+ enum SniffingBehavior {
+ WithSideEffects,
+ NoSideEffects
+ };
+
+ /**
+ * Generate a JSErrorReport from the provided thrown value.
+ *
+ * If the value is a (possibly wrapped) Error object, the JSErrorReport will
+ * be exactly initialized from the Error object's information, without
+ * observable side effects. (The Error object's JSErrorReport is reused, if
+ * it has one.)
+ *
+ * Otherwise various attempts are made to derive JSErrorReport information
+ * from |exn| and from the current execution state. This process is
+ * *definitely* inconsistent with any standard, and particulars of the
+ * behavior implemented here generally shouldn't be relied upon.
+ *
+ * If the value of |sniffingBehavior| is |WithSideEffects|, some of these
+ * attempts *may* invoke user-configurable behavior when |exn| is an object:
+ * converting |exn| to a string, detecting and getting properties on |exn|,
+ * accessing |exn|'s prototype chain, and others are possible. Users *must*
+ * tolerate |ErrorReport::init| potentially having arbitrary effects. Any
+ * exceptions thrown by these operations will be caught and silently
+ * ignored, and "default" values will be substituted into the JSErrorReport.
+ *
+ * But if the value of |sniffingBehavior| is |NoSideEffects|, these attempts
+ * *will not* invoke any observable side effects. The JSErrorReport will
+ * simply contain fewer, less precise details.
+ *
+ * Unlike some functions involved in error handling, this function adheres
+ * to the usual JSAPI return value error behavior.
+ */
+ bool init(JSContext* cx, JS::HandleValue exn,
+ SniffingBehavior sniffingBehavior);
JSErrorReport* report()
{
return reportp;
}
- const char* message()
+ const JS::ConstUTF8CharsZ toStringResult()
{
- return message_;
+ return toStringResult_;
}
private:
@@ -1397,8 +1453,8 @@
//
// Returns false if we fail to actually populate the ErrorReport
// for some reason (probably out of memory).
- bool populateUncaughtExceptionReport(JSContext* cx, ...);
- bool populateUncaughtExceptionReportVA(JSContext* cx, va_list ap);
+ bool populateUncaughtExceptionReportUTF8(JSContext* cx, ...);
+ bool populateUncaughtExceptionReportUTF8VA(JSContext* cx, va_list ap);
// Reports exceptions from add-on scopes to telementry.
void ReportAddonExceptionToTelementry(JSContext* cx);
@@ -1406,16 +1462,9 @@
// We may have a provided JSErrorReport, so need a way to represent that.
JSErrorReport* reportp;
- // And we may have a message.
- const char* message_;
-
// Or we may need to synthesize a JSErrorReport one of our own.
JSErrorReport ownedReport;
- // Or a message of our own. If this is non-null, we need to clean up both
- // it and ownedReport.
- char* ownedMessage;
-
// And we have a string to maybe keep alive that has pointers into
// it from ownedReport.
JS::RootedString str;
@@ -1426,14 +1475,14 @@
// And we need to root our exception value.
JS::RootedObject exnObject;
- // And possibly some byte storage for our message_.
- JSAutoByteString bytesStorage;
-
// And for our filename.
JSAutoByteString filename;
- // True if we need to free message_ and the stuff in ownedReport
- bool ownsMessageAndReport;
+ // We may have a result of error.toString().
+ // FIXME: We should not call error.toString(), since it could have side
+ // effect (see bug 633623).
+ JS::ConstUTF8CharsZ toStringResult_;
+ JSAutoByteString toStringResultBytesStorage;
};
/* Implemented in vm/StructuredClone.cpp. */
@@ -1465,11 +1514,14 @@
Uint8Clamped,
/**
- * SIMD types don't have their own TypedArray equivalent, for now.
+ * Types that don't have their own TypedArray equivalent, for now.
*/
MaxTypedArrayViewType,
+ Int64,
Float32x4,
+ Int8x16,
+ Int16x8,
Int32x4
};
@@ -1488,8 +1540,11 @@
case Uint32:
case Float32:
return 4;
+ case Int64:
case Float64:
return 8;
+ case Int8x16:
+ case Int16x8:
case Int32x4:
case Float32x4:
return 16;
@@ -1504,6 +1559,9 @@
case Int8:
case Int16:
case Int32:
+ case Int64:
+ case Int8x16:
+ case Int16x8:
case Int32x4:
return true;
case Uint8:
@@ -1529,9 +1587,12 @@
case Uint16:
case Int32:
case Uint32:
+ case Int64:
case Float32:
case Float64:
return false;
+ case Int8x16:
+ case Int16x8:
case Int32x4:
case Float32x4:
return true;
@@ -1544,6 +1605,10 @@
static inline size_t
scalarByteSize(Type atype) {
switch (atype) {
+ case Int8x16:
+ return 1;
+ case Int16x8:
+ return 2;
case Int32x4:
case Float32x4:
return 4;
@@ -1554,6 +1619,7 @@
case Uint16:
case Int32:
case Uint32:
+ case Int64:
case Float32:
case Float64:
case MaxTypedArrayViewType:
@@ -1653,7 +1719,10 @@
uint32_t byteOffset, int32_t length);
/**
- * Create a new SharedArrayBuffer with the given byte length.
+ * Create a new SharedArrayBuffer with the given byte length. This
+ * may only be called if
+ * JS::CompartmentCreationOptionsRef(cx).getSharedMemoryAndAtomicsEnabled() is
+ * true.
*/
extern JS_FRIEND_API(JSObject*)
JS_NewSharedArrayBuffer(JSContext* cx, uint32_t nbytes);
@@ -1889,7 +1958,7 @@
/**
* Return true if the arrayBuffer contains any data. This will return false for
- * ArrayBuffer.prototype and neutered ArrayBuffers.
+ * ArrayBuffer.prototype and detached ArrayBuffers.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
@@ -2010,39 +2079,29 @@
JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
/**
- * Return the ArrayBuffer or SharedArrayBuffer underlying an
- * ArrayBufferView. If the buffer has been neutered, this will still
- * return the neutered buffer. |obj| must be an object that would
+ * Return the ArrayBuffer or SharedArrayBuffer underlying an ArrayBufferView.
+ * This may return a detached buffer. |obj| must be an object that would
* return true for JS_IsArrayBufferViewObject().
*/
extern JS_FRIEND_API(JSObject*)
JS_GetArrayBufferViewBuffer(JSContext* cx, JS::HandleObject obj, bool* isSharedMemory);
-typedef enum {
- ChangeData,
- KeepData
-} NeuterDataDisposition;
-
/**
- * Set an ArrayBuffer's length to 0 and neuter all of its views.
+ * Detach an ArrayBuffer, causing all associated views to no longer refer to
+ * the ArrayBuffer's original attached memory.
*
- * The |changeData| argument is a hint to inform internal behavior with respect
- * to the internal pointer to the ArrayBuffer's data after being neutered.
- * There is no guarantee it will be respected. But if it is respected, the
- * ArrayBuffer's internal data pointer will, or will not, have changed
- * accordingly.
+ * The |changeData| argument is obsolete and ignored.
*/
extern JS_FRIEND_API(bool)
-JS_NeuterArrayBuffer(JSContext* cx, JS::HandleObject obj,
- NeuterDataDisposition changeData);
+JS_DetachArrayBuffer(JSContext* cx, JS::HandleObject obj);
/**
- * Check whether the obj is ArrayBufferObject and neutered. Note that this
- * may return false if a security wrapper is encountered that denies the
+ * Check whether the obj is a detached ArrayBufferObject. Note that this may
+ * return false if a security wrapper is encountered that denies the
* unwrapping.
*/
extern JS_FRIEND_API(bool)
-JS_IsNeuteredArrayBufferObject(JSObject* obj);
+JS_IsDetachedArrayBufferObject(JSObject* obj);
/**
* Check whether obj supports JS_GetDataView* APIs.
@@ -2336,7 +2395,12 @@
js::jit::InlinableNative inlinableNative;
};
- uint16_t depth;
+ union {
+ uint16_t depth;
+
+ // Additional opcode for some InlinableNative functions.
+ uint16_t nativeOp;
+ };
// These fields are carefully packed to take up 4 bytes. If you need more
// bits for whatever reason, please see if you can steal bits from existing
@@ -2602,22 +2666,7 @@
ScriptEnvironmentPreparer::Closure& closure);
JS_FRIEND_API(void)
-SetScriptEnvironmentPreparer(JSRuntime* rt, ScriptEnvironmentPreparer*
-preparer);
-
-/**
- * To help embedders enforce their invariants, we allow them to specify in
- * advance which JSContext should be passed to JSAPI calls. If this is set
- * to a non-null value, the assertSameCompartment machinery does double-
- * duty (in debug builds) to verify that it matches the cx being used.
- */
-#ifdef DEBUG
-JS_FRIEND_API(void)
-Debug_SetActiveJSContext(JSRuntime* rt, JSContext* cx);
-#else
-inline void
-Debug_SetActiveJSContext(JSRuntime* rt, JSContext* cx) {}
-#endif
+SetScriptEnvironmentPreparer(JSContext* cx, ScriptEnvironmentPreparer* preparer);
enum CTypesActivityType {
CTYPES_CALL_BEGIN,
@@ -2634,7 +2683,7 @@
* calling into C.
*/
JS_FRIEND_API(void)
-SetCTypesActivityCallback(JSRuntime* rt, CTypesActivityCallback cb);
+SetCTypesActivityCallback(JSContext* cx, CTypesActivityCallback cb);
class MOZ_RAII JS_FRIEND_API(AutoCTypesActivityCallback) {
private:
@@ -2658,8 +2707,23 @@
}
};
-typedef JSObject*
-(* ObjectMetadataCallback)(JSContext* cx, JSObject* obj);
+// Abstract base class for objects that build allocation metadata for JavaScript
+// values.
+struct AllocationMetadataBuilder {
+ AllocationMetadataBuilder() { }
+
+ // Return a metadata object for the newly constructed object |obj|, or
+ // nullptr if there's no metadata to attach.
+ //
+ // Implementations should treat all errors as fatal; there is no way to
+ // report errors from this callback. In particular, the caller provides an
+ // oomUnsafe for overriding implementations to use.
+ virtual JSObject* build(JSContext* cx, JS::HandleObject obj,
+ AutoEnterOOMUnsafeRegion& oomUnsafe) const
+ {
+ return nullptr;
+ }
+};
/**
* Specify a callback to invoke when creating each JS object in the current
@@ -2667,11 +2731,11 @@
* object.
*/
JS_FRIEND_API(void)
-SetObjectMetadataCallback(JSContext* cx, ObjectMetadataCallback callback);
+SetAllocationMetadataBuilder(JSContext* cx, const AllocationMetadataBuilder *callback);
/** Get the metadata associated with an object. */
JS_FRIEND_API(JSObject*)
-GetObjectMetadata(JSObject* obj);
+GetAllocationMetadata(JSObject* obj);
JS_FRIEND_API(bool)
GetElementsWithAdder(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver,
@@ -2703,11 +2767,11 @@
JS_FRIEND_API(bool)
SetPropertyIgnoringNamedGetter(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::HandleValue v, JS::HandleValue receiver,
- JS::Handle<JSPropertyDescriptor> ownDesc,
+ JS::Handle<JS::PropertyDescriptor> ownDesc,
JS::ObjectOpResult& result);
JS_FRIEND_API(void)
-ReportErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
+ReportASCIIErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
// This function is for one specific use case, please don't use this for anything else!
extern JS_FRIEND_API(bool)
@@ -2745,12 +2809,12 @@
#endif
/**
- * Get the nearest enclosing with scope object for a given function. If the
- * function is not scripted or is not enclosed by a with scope, returns the
- * global.
+ * Get the nearest enclosing with environment object for a given function. If
+ * the function is not scripted or is not enclosed by a with scope, returns
+ * the global.
*/
extern JS_FRIEND_API(JSObject*)
-GetNearestEnclosingWithScopeObjectForFunction(JSFunction* fun);
+GetNearestEnclosingWithEnvironmentObjectForFunction(JSFunction* fun);
/**
* Get the first SavedFrame object in this SavedFrame stack whose principals are
@@ -2776,7 +2840,7 @@
* invariant that actual Window objects (the global objects of web pages) are
* never directly exposed to script. Instead we often substitute a WindowProxy.
*
- * The scope chain, on the other hand, contains the Window and never its
+ * The environment chain, on the other hand, contains the Window and never its
* WindowProxy.
*
* As a result, we have calls to these "substitute-this-object-for-that-object"
@@ -2790,7 +2854,7 @@
* functions below.
*/
extern JS_FRIEND_API(void)
-SetWindowProxyClass(JSRuntime* rt, const Class* clasp);
+SetWindowProxyClass(JSContext* cx, const Class* clasp);
/**
* Associates a WindowProxy with a Window (global object). `windowProxy` must
@@ -2842,26 +2906,6 @@
} /* namespace js */
-extern JS_FRIEND_API(void)
-JS_StoreObjectPostBarrierCallback(JSContext* cx,
- void (*callback)(JSTracer* trc, JSObject* key, void* data),
- JSObject* key, void* data);
-
-extern JS_FRIEND_API(void)
-JS_StoreStringPostBarrierCallback(JSContext* cx,
- void (*callback)(JSTracer* trc, JSString* key, void* data),
- JSString* key, void* data);
-
-/**
- * Forcibly clear postbarrier callbacks queued by the previous two methods.
- * This should be used when the object owning the postbarriered pointers is
- * being destroyed outside of a garbage collection.
- *
- * This currently works by performing a minor GC.
- */
-extern JS_FRIEND_API(void)
-JS_ClearAllPostBarrierCallbacks(JSRuntime *rt);
-
class NativeProfiler
{
public:
@@ -2888,7 +2932,7 @@
class MemProfiler
{
static mozilla::Atomic<uint32_t, mozilla::Relaxed> sActiveProfilerCount;
- static NativeProfiler* sNativeProfiler;
+ static JS_FRIEND_DATA(NativeProfiler*) sNativeProfiler;
static GCHeapProfiler* GetGCHeapProfiler(void* addr);
static GCHeapProfiler* GetGCHeapProfiler(JSRuntime* runtime);
@@ -2903,8 +2947,8 @@
public:
explicit MemProfiler(JSRuntime* aRuntime) : mGCHeapProfiler(nullptr), mRuntime(aRuntime) {}
- void start(GCHeapProfiler* aGCHeapProfiler);
- void stop();
+ JS_FRIEND_API(void) start(GCHeapProfiler* aGCHeapProfiler);
+ JS_FRIEND_API(void) stop();
GCHeapProfiler* getGCHeapProfiler() const {
return mGCHeapProfiler;
@@ -2914,7 +2958,7 @@
return sActiveProfilerCount > 0;
}
- static MemProfiler* GetMemProfiler(JSRuntime* runtime);
+ static JS_FRIEND_API(MemProfiler*) GetMemProfiler(JSContext* context);
static void SetNativeProfiler(NativeProfiler* aProfiler) {
sNativeProfiler = aProfiler;
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsperf.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsperf.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsperf.h
@@ -126,7 +126,7 @@
* Value is not an instance of the wrapper.
*/
extern JS_FRIEND_API(PerfMeasurement*)
- ExtractPerfMeasurement(Value wrapper);
+ ExtractPerfMeasurement(const Value& wrapper);
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsprf.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsprf.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsprf.h
@@ -14,34 +14,33 @@
** %x - unsigned hex
** %X - unsigned uppercase hex
** %o - unsigned octal
-** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
-** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
-** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
-** %s - ascii string
-** %hs - ucs2 string
+** %hd, %hu, %hx, %hX, %ho - "short" versions of above
+** %ld, %lu, %lx, %lX, %lo - "long" versions of above
+** %lld, %llu, %llx, %llX, %llo - "long long" versions of above
+** %zd, %zo, %zu, %zx, %zX - size_t versions of above
+** %Id, %Io, %Iu, %Ix, %IX - size_t versions of above (for Windows compat)
+** You should use PRI*SIZE macros instead
+** %s - string
** %c - character
** %p - pointer (deals with machine dependent pointer size)
** %f - float
** %g - float
*/
+#include "mozilla/IntegerPrintfMacros.h"
+#include "mozilla/SizePrintfMacros.h"
+
#include <stdarg.h>
#include "jstypes.h"
/*
-** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
-** of the buffer. Returns the length of the written output, NOT including
-** the NUL, or (uint32_t)-1 if an error occurs.
-*/
-extern JS_PUBLIC_API(uint32_t) JS_snprintf(char* out, uint32_t outlen, const char* fmt, ...);
-
-/*
** sprintf into a malloc'd buffer. Return a pointer to the malloc'd
** buffer on success, nullptr on failure. Call "JS_smprintf_free" to release
** the memory returned.
*/
-extern JS_PUBLIC_API(char*) JS_smprintf(const char* fmt, ...);
+extern JS_PUBLIC_API(char*) JS_smprintf(const char* fmt, ...)
+ MOZ_FORMAT_PRINTF(1, 2);
/*
** Free the memory allocated, for the caller, by JS_smprintf
@@ -55,12 +54,12 @@
** will allocate the initial string. The return value is the new value of
** last for subsequent calls, or nullptr if there is a malloc failure.
*/
-extern JS_PUBLIC_API(char*) JS_sprintf_append(char* last, const char* fmt, ...);
+extern JS_PUBLIC_API(char*) JS_sprintf_append(char* last, const char* fmt, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
/*
** va_list forms of the above.
*/
-extern JS_PUBLIC_API(uint32_t) JS_vsnprintf(char* out, uint32_t outlen, const char* fmt, va_list ap);
extern JS_PUBLIC_API(char*) JS_vsmprintf(const char* fmt, va_list ap);
extern JS_PUBLIC_API(char*) JS_vsprintf_append(char* last, const char* fmt, va_list ap);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsprototypes.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsprototypes.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsprototypes.h
@@ -49,12 +49,24 @@
#define IF_BDATA(real,imaginary) imaginary
#endif
+#ifdef ENABLE_SIMD
+# define IF_SIMD(real,imaginary) real
+#else
+# define IF_SIMD(real,imaginary) imaginary
+#endif
+
#ifdef ENABLE_SHARED_ARRAY_BUFFER
#define IF_SAB(real,imaginary) real
#else
#define IF_SAB(real,imaginary) imaginary
#endif
+#ifdef SPIDERMONKEY_PROMISE
+#define IF_PROMISE(real,imaginary) real
+#else
+#define IF_PROMISE(real,imaginary) imaginary
+#endif
+
#define JS_FOR_PROTOTYPES(real,imaginary) \
imaginary(Null, 0, InitNullClass, dummy) \
real(Object, 1, InitViaClassSpec, OCLASP(Plain)) \
@@ -75,33 +87,42 @@
real(SyntaxError, 16, InitViaClassSpec, ERROR_CLASP(JSEXN_SYNTAXERR)) \
real(TypeError, 17, InitViaClassSpec, ERROR_CLASP(JSEXN_TYPEERR)) \
real(URIError, 18, InitViaClassSpec, ERROR_CLASP(JSEXN_URIERR)) \
- real(Iterator, 19, InitLegacyIteratorClass,OCLASP(PropertyIterator)) \
- real(StopIteration, 20, InitStopIterationClass, OCLASP(StopIteration)) \
- real(ArrayBuffer, 21, InitArrayBufferClass, &js::ArrayBufferObject::protoClass) \
- real(Int8Array, 22, InitViaClassSpec, TYPED_ARRAY_CLASP(Int8)) \
- real(Uint8Array, 23, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8)) \
- real(Int16Array, 24, InitViaClassSpec, TYPED_ARRAY_CLASP(Int16)) \
- real(Uint16Array, 25, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint16)) \
- real(Int32Array, 26, InitViaClassSpec, TYPED_ARRAY_CLASP(Int32)) \
- real(Uint32Array, 27, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint32)) \
- real(Float32Array, 28, InitViaClassSpec, TYPED_ARRAY_CLASP(Float32)) \
- real(Float64Array, 29, InitViaClassSpec, TYPED_ARRAY_CLASP(Float64)) \
- real(Uint8ClampedArray, 30, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8Clamped)) \
- real(Proxy, 31, InitProxyClass, js::ProxyClassPtr) \
- real(WeakMap, 32, InitWeakMapClass, OCLASP(WeakMap)) \
- real(Map, 33, InitMapClass, OCLASP(Map)) \
- real(Set, 34, InitSetClass, OCLASP(Set)) \
- real(DataView, 35, InitDataViewClass, OCLASP(DataView)) \
- real(Symbol, 36, InitSymbolClass, OCLASP(Symbol)) \
-IF_SAB(real,imaginary)(SharedArrayBuffer, 37, InitSharedArrayBufferClass, &js::SharedArrayBufferObject::protoClass) \
-IF_INTL(real,imaginary) (Intl, 38, InitIntlClass, CLASP(Intl)) \
-IF_BDATA(real,imaginary)(TypedObject, 39, InitTypedObjectModuleObject, OCLASP(TypedObjectModule)) \
- real(Reflect, 40, InitReflect, nullptr) \
-IF_BDATA(real,imaginary)(SIMD, 41, InitSIMDClass, OCLASP(SIMD)) \
- real(WeakSet, 42, InitWeakSetClass, OCLASP(WeakSet)) \
- real(TypedArray, 43, InitViaClassSpec, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
-IF_SAB(real,imaginary)(Atomics, 44, InitAtomicsClass, OCLASP(Atomics)) \
- real(SavedFrame, 45, InitViaClassSpec, &js::SavedFrame::class_) \
+ real(DebuggeeWouldRun, 19, InitViaClassSpec, ERROR_CLASP(JSEXN_DEBUGGEEWOULDRUN)) \
+ real(CompileError, 20, InitViaClassSpec, ERROR_CLASP(JSEXN_WASMCOMPILEERROR)) \
+ real(RuntimeError, 21, InitViaClassSpec, ERROR_CLASP(JSEXN_WASMRUNTIMEERROR)) \
+ real(Iterator, 22, InitLegacyIteratorClass,OCLASP(PropertyIterator)) \
+ real(StopIteration, 23, InitStopIterationClass, OCLASP(StopIteration)) \
+ real(ArrayBuffer, 24, InitViaClassSpec, OCLASP(ArrayBuffer)) \
+ real(Int8Array, 25, InitViaClassSpec, TYPED_ARRAY_CLASP(Int8)) \
+ real(Uint8Array, 26, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8)) \
+ real(Int16Array, 27, InitViaClassSpec, TYPED_ARRAY_CLASP(Int16)) \
+ real(Uint16Array, 28, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint16)) \
+ real(Int32Array, 29, InitViaClassSpec, TYPED_ARRAY_CLASP(Int32)) \
+ real(Uint32Array, 30, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint32)) \
+ real(Float32Array, 31, InitViaClassSpec, TYPED_ARRAY_CLASP(Float32)) \
+ real(Float64Array, 32, InitViaClassSpec, TYPED_ARRAY_CLASP(Float64)) \
+ real(Uint8ClampedArray, 33, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8Clamped)) \
+ real(Proxy, 34, InitProxyClass, js::ProxyClassPtr) \
+ real(WeakMap, 35, InitWeakMapClass, OCLASP(WeakMap)) \
+ real(Map, 36, InitMapClass, OCLASP(Map)) \
+ real(Set, 37, InitSetClass, OCLASP(Set)) \
+ real(DataView, 38, InitDataViewClass, OCLASP(DataView)) \
+ real(Symbol, 39, InitSymbolClass, OCLASP(Symbol)) \
+IF_SAB(real,imaginary)(SharedArrayBuffer, 40, InitViaClassSpec, OCLASP(SharedArrayBuffer)) \
+IF_INTL(real,imaginary) (Intl, 41, InitIntlClass, CLASP(Intl)) \
+IF_BDATA(real,imaginary)(TypedObject, 42, InitTypedObjectModuleObject, OCLASP(TypedObjectModule)) \
+ real(Reflect, 43, InitReflect, nullptr) \
+IF_SIMD(real,imaginary)(SIMD, 44, InitSimdClass, OCLASP(Simd)) \
+ real(WeakSet, 45, InitWeakSetClass, OCLASP(WeakSet)) \
+ real(TypedArray, 46, InitViaClassSpec, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
+IF_SAB(real,imaginary)(Atomics, 47, InitAtomicsClass, OCLASP(Atomics)) \
+ real(SavedFrame, 48, InitViaClassSpec, &js::SavedFrame::class_) \
+ real(WebAssembly, 49, InitWebAssemblyClass, CLASP(WebAssembly)) \
+ imaginary(WasmModule, 50, dummy, dummy) \
+ imaginary(WasmInstance, 51, dummy, dummy) \
+ imaginary(WasmMemory, 52, dummy, dummy) \
+ imaginary(WasmTable, 53, dummy, dummy) \
+IF_PROMISE(real,imaginary)(Promise, 54, InitViaClassSpec, OCLASP(Promise)) \
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jspubtd.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jspubtd.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jspubtd.h
@@ -12,12 +12,14 @@
*/
#include "mozilla/Assertions.h"
+#include "mozilla/EnumeratedArray.h"
#include "mozilla/LinkedList.h"
#include "mozilla/PodOperations.h"
#include "jsprototypes.h"
#include "jstypes.h"
+#include "js/TraceKind.h"
#include "js/TypeDecls.h"
#if defined(JS_GC_ZEAL) || defined(DEBUG)
@@ -26,9 +28,7 @@
namespace JS {
-template <typename T>
-class AutoVectorRooter;
-typedef AutoVectorRooter<jsid> AutoIdVector;
+class AutoIdVector;
class CallArgs;
template <typename T>
@@ -40,13 +40,17 @@
class JS_FRIEND_API(TransitiveCompileOptions);
class JS_PUBLIC_API(CompartmentOptions);
+struct RootingContext;
class Value;
struct Zone;
-} /* namespace JS */
+namespace shadow {
+struct Runtime;
+} // namespace shadow
+
+} // namespace JS
namespace js {
-struct ContextFriendFields;
class RootLists;
} // namespace js
@@ -97,7 +101,6 @@
struct JSLocaleCallbacks;
struct JSObjectMap;
struct JSPrincipals;
-struct JSPropertyDescriptor;
struct JSPropertyName;
struct JSPropertySpec;
struct JSRuntime;
@@ -109,7 +112,6 @@
class JSFlatString;
-typedef struct PRCallOnceType JSCallOnceType;
typedef bool (*JSInitCallback)(void);
template<typename T> struct JSConstScalarSpec;
@@ -117,60 +119,105 @@
typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
/*
- * Generic trace operation that calls JS_CallTracer on each traceable thing
- * stored in data.
+ * Generic trace operation that calls JS::TraceEdge on each traceable thing's
+ * location reachable from data.
*/
typedef void
(* JSTraceDataOp)(JSTracer* trc, void* data);
namespace js {
-
-void FinishGC(JSRuntime* rt);
-
namespace gc {
class AutoTraceSession;
class StoreBuffer;
-void MarkPersistentRootedChains(JSTracer*);
-void MarkPersistentRootedChainsInLists(js::RootLists&, JSTracer*);
-void FinishPersistentRootedChains(js::RootLists&);
} // namespace gc
+
+// Whether the current thread is permitted access to any part of the specified
+// runtime or zone.
+JS_FRIEND_API(bool)
+CurrentThreadCanAccessRuntime(const JSRuntime* rt);
+
+#ifdef DEBUG
+JS_FRIEND_API(bool)
+CurrentThreadIsPerformingGC();
+#endif
+
} // namespace js
namespace JS {
+class JS_PUBLIC_API(AutoEnterCycleCollection);
+class JS_PUBLIC_API(AutoAssertOnBarrier);
+struct JS_PUBLIC_API(PropertyDescriptor);
+
typedef void (*OffThreadCompileCallback)(void* token, void* callbackData);
enum class HeapState {
Idle, // doing nothing with the GC heap
Tracing, // tracing the GC heap without collecting, e.g. IterateCompartments()
MajorCollecting, // doing a GC of the major heap
- MinorCollecting // doing a GC of the minor heap (nursery)
+ MinorCollecting, // doing a GC of the minor heap (nursery)
+ CycleCollecting // in the "Unlink" phase of cycle collection
};
namespace shadow {
struct Runtime
{
- protected:
- // Allow inlining of heapState checks.
- friend class js::gc::AutoTraceSession;
+ private:
JS::HeapState heapState_;
+ protected:
+ void setHeapState(JS::HeapState newState) {
+ MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(asRuntime()));
+ MOZ_ASSERT(heapState_ != newState);
+ heapState_ = newState;
+ }
+
+ JS::HeapState heapState() const {
+ MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(asRuntime()) ||
+ js::CurrentThreadIsPerformingGC());
+ return heapState_;
+ }
+
+ // In some cases, invoking GC barriers (incremental or otherwise) will break
+ // things. These barriers assert if this flag is set.
+ bool allowGCBarriers_;
+ friend class JS::AutoAssertOnBarrier;
+
js::gc::StoreBuffer* gcStoreBufferPtr_;
+ // The gray bits can become invalid if UnmarkGray overflows the stack. A
+ // full GC will reset this bit, since it fills in all the gray bits.
+ bool gcGrayBitsValid_;
+
public:
Runtime()
: heapState_(JS::HeapState::Idle)
+ , allowGCBarriers_(true)
, gcStoreBufferPtr_(nullptr)
+ , gcGrayBitsValid_(false)
{}
- bool isHeapBusy() const { return heapState_ != JS::HeapState::Idle; }
- bool isHeapMajorCollecting() const { return heapState_ == JS::HeapState::MajorCollecting; }
- bool isHeapMinorCollecting() const { return heapState_ == JS::HeapState::MinorCollecting; }
+ bool isHeapBusy() const { return heapState() != JS::HeapState::Idle; }
+ bool isHeapTracing() const { return heapState() == JS::HeapState::Tracing; }
+ bool isHeapMajorCollecting() const { return heapState() == JS::HeapState::MajorCollecting; }
+ bool isHeapMinorCollecting() const { return heapState() == JS::HeapState::MinorCollecting; }
bool isHeapCollecting() const { return isHeapMinorCollecting() || isHeapMajorCollecting(); }
+ bool isCycleCollecting() const {
+ return heapState() == JS::HeapState::CycleCollecting;
+ }
+
+ bool allowGCBarriers() const { return allowGCBarriers_; }
js::gc::StoreBuffer* gcStoreBufferPtr() { return gcStoreBufferPtr_; }
+ bool areGCGrayBitsValid() const { return gcGrayBitsValid_; }
+ void setGCGrayBitsValid(bool valid) { gcGrayBitsValid_ = valid; }
+
+ const JSRuntime* asRuntime() const {
+ return reinterpret_cast<const JSRuntime*>(this);
+ }
+
static JS::shadow::Runtime* asShadowRuntime(JSRuntime* rt) {
return reinterpret_cast<JS::shadow::Runtime*>(rt);
}
@@ -183,11 +230,28 @@
} /* namespace shadow */
+// Decorates the Unlinking phase of CycleCollection so that accidental use
+// of barriered accessors results in assertions instead of leaks.
+class MOZ_STACK_CLASS JS_PUBLIC_API(AutoEnterCycleCollection)
+{
+#ifdef DEBUG
+ JSRuntime* runtime;
+
+ public:
+ explicit AutoEnterCycleCollection(JSContext* cx);
+ ~AutoEnterCycleCollection();
+#else
+ public:
+ explicit AutoEnterCycleCollection(JSContext* cx) {}
+ ~AutoEnterCycleCollection() {}
+#endif
+};
+
class JS_PUBLIC_API(AutoGCRooter)
{
public:
AutoGCRooter(JSContext* cx, ptrdiff_t tag);
- AutoGCRooter(js::ContextFriendFields* cx, ptrdiff_t tag);
+ AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag);
~AutoGCRooter() {
MOZ_ASSERT(this == *stackTop);
@@ -199,13 +263,6 @@
static void traceAll(JSTracer* trc);
static void traceAllWrappers(JSTracer* trc);
- /* T must be a context type */
- template<typename T>
- static void traceAllInContext(T* cx, JSTracer* trc) {
- for (AutoGCRooter* gcr = cx->roots.autoGCRooters_; gcr; gcr = gcr->down)
- gcr->trace(trc);
- }
-
protected:
AutoGCRooter * const down;
@@ -242,6 +299,13 @@
void operator=(AutoGCRooter& ida) = delete;
};
+// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
+// instantiation of MapTypeToRootKind.
+template <>
+struct MapTypeToRootKind<void*> {
+ static const RootKind kind = RootKind::Traceable;
+};
+
} /* namespace JS */
namespace js {
@@ -261,132 +325,98 @@
StackKindCount
};
-enum ThingRootKind
-{
- THING_ROOT_OBJECT,
- THING_ROOT_SHAPE,
- THING_ROOT_BASE_SHAPE,
- THING_ROOT_OBJECT_GROUP,
- THING_ROOT_STRING,
- THING_ROOT_SYMBOL,
- THING_ROOT_JIT_CODE,
- THING_ROOT_SCRIPT,
- THING_ROOT_LAZY_SCRIPT,
- THING_ROOT_ID,
- THING_ROOT_VALUE,
- THING_ROOT_TRACEABLE,
- THING_ROOT_LIMIT
-};
-
-template <typename T>
-struct RootKind;
-
-/*
- * Specifically mark the ThingRootKind of externally visible types, so that
- * JSAPI users may use JSRooted... types without having the class definition
- * available.
- */
-template<typename T, ThingRootKind Kind>
-struct SpecificRootKind
-{
- static ThingRootKind rootKind() { return Kind; }
-};
-
-template <> struct RootKind<JSObject*> : SpecificRootKind<JSObject*, THING_ROOT_OBJECT> {};
-template <> struct RootKind<JSFlatString*> : SpecificRootKind<JSFlatString*, THING_ROOT_STRING> {};
-template <> struct RootKind<JSFunction*> : SpecificRootKind<JSFunction*, THING_ROOT_OBJECT> {};
-template <> struct RootKind<JSString*> : SpecificRootKind<JSString*, THING_ROOT_STRING> {};
-template <> struct RootKind<JS::Symbol*> : SpecificRootKind<JS::Symbol*, THING_ROOT_SYMBOL> {};
-template <> struct RootKind<JSScript*> : SpecificRootKind<JSScript*, THING_ROOT_SCRIPT> {};
-template <> struct RootKind<jsid> : SpecificRootKind<jsid, THING_ROOT_ID> {};
-template <> struct RootKind<JS::Value> : SpecificRootKind<JS::Value, THING_ROOT_VALUE> {};
+using RootedListHeads = mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
+ JS::Rooted<void*>*>;
// Abstracts JS rooting mechanisms so they can be shared between the JSContext
// and JSRuntime.
class RootLists
{
- // Stack GC roots for stack-allocated GC heap pointers.
- JS::Rooted<void*>* stackRoots_[THING_ROOT_LIMIT];
+ // Stack GC roots for Rooted GC heap pointers.
+ RootedListHeads stackRoots_;
template <typename T> friend class JS::Rooted;
- // Stack GC roots for stack-allocated AutoFooRooter classes.
+ // Stack GC roots for AutoFooRooter classes.
JS::AutoGCRooter* autoGCRooters_;
friend class JS::AutoGCRooter;
+ // Heap GC roots for PersistentRooted pointers.
+ mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
+ mozilla::LinkedList<JS::PersistentRooted<void*>>> heapRoots_;
+ template <typename T> friend class JS::PersistentRooted;
+
public:
RootLists() : autoGCRooters_(nullptr) {
- mozilla::PodArrayZero(stackRoots_);
+ for (auto& stackRootPtr : stackRoots_)
+ stackRootPtr = nullptr;
}
- template <class T>
- inline JS::Rooted<T>* gcRooters() {
- js::ThingRootKind kind = RootKind<T>::rootKind();
- return reinterpret_cast<JS::Rooted<T>*>(stackRoots_[kind]);
+ ~RootLists() {
+ // The semantics of PersistentRooted containing pointers and tagged
+ // pointers are somewhat different from those of PersistentRooted
+ // containing a structure with a trace method. PersistentRooted
+ // containing pointers are allowed to outlive the owning RootLists,
+ // whereas those containing a traceable structure are not.
+ //
+ // The purpose of this feature is to support lazy initialization of
+ // global references for the several places in Gecko that do not have
+ // access to a tighter context, but that still need to refer to GC
+ // pointers. For such pointers, FinishPersistentRootedChains ensures
+ // that the contained references are nulled out when the owning
+ // RootLists dies to prevent UAF errors.
+ //
+ // However, for RootKind::Traceable, we do not know the concrete type
+ // of the held thing, so we simply cannot do this without accruing
+ // extra overhead and complexity for all users for a case that is
+ // unlikely to ever be used in practice. For this reason, the following
+ // assertion disallows usage of PersistentRooted<Traceable> that
+ // outlives the RootLists.
+ MOZ_ASSERT(heapRoots_[JS::RootKind::Traceable].isEmpty());
}
+ void traceStackRoots(JSTracer* trc);
void checkNoGCRooters();
- /* Allow inlining of PersistentRooted constructors and destructors. */
- private:
- template <typename Referent> friend class JS::PersistentRooted;
- friend void js::gc::MarkPersistentRootedChains(JSTracer*);
- friend void js::gc::MarkPersistentRootedChainsInLists(RootLists&, JSTracer*);
- friend void js::gc::FinishPersistentRootedChains(RootLists&);
-
- mozilla::LinkedList<JS::PersistentRooted<void*>> heapRoots_[THING_ROOT_LIMIT];
-
- /* Specializations of this return references to the appropriate list. */
- template<typename Referent>
- inline mozilla::LinkedList<JS::PersistentRooted<Referent>>& getPersistentRootedList();
-};
-
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedFunction>&
-RootLists::getPersistentRootedList<JSFunction*>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSFunction*>>&>(
- heapRoots_[THING_ROOT_OBJECT]);
-}
+ void tracePersistentRoots(JSTracer* trc);
+ void finishPersistentRoots();
+};
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedObject>&
-RootLists::getPersistentRootedList<JSObject*>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSObject*>>&>(
- heapRoots_[THING_ROOT_OBJECT]);
-}
+} // namespace js
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedId>&
-RootLists::getPersistentRootedList<jsid>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<jsid>>&>(
- heapRoots_[THING_ROOT_ID]);
-}
+namespace JS {
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedScript>&
-RootLists::getPersistentRootedList<JSScript*>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSScript*>>&>(
- heapRoots_[THING_ROOT_SCRIPT]);
-}
+/*
+ * JS::RootingContext is a base class of ContextFriendFields and JSContext.
+ * This class can be used to let code construct a Rooted<> or PersistentRooted<>
+ * instance, without giving it full access to the JSContext.
+ */
+struct RootingContext
+{
+ js::RootLists roots;
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedString>&
-RootLists::getPersistentRootedList<JSString*>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSString*>>&>(
- heapRoots_[THING_ROOT_STRING]);
-}
+#ifdef DEBUG
+ // Whether the derived class is a JSContext or an ExclusiveContext.
+ bool isJSContext;
+#endif
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedValue>&
-RootLists::getPersistentRootedList<JS::Value>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JS::Value>>&>(
- heapRoots_[THING_ROOT_VALUE]);
-}
+ explicit RootingContext(bool isJSContextArg)
+#ifdef DEBUG
+ : isJSContext(isJSContextArg)
+#endif
+ {}
-struct ContextFriendFields
+ static RootingContext* get(JSContext* cx) {
+ return reinterpret_cast<RootingContext*>(cx);
+ }
+};
+
+} // namespace JS
+
+namespace js {
+
+struct ContextFriendFields : public JS::RootingContext
{
protected:
- JSRuntime* const runtime_;
-
/* The current compartment. */
JSCompartment* compartment_;
@@ -394,12 +424,10 @@
JS::Zone* zone_;
public:
- /* Rooting structures. */
- RootLists roots;
+ /* Limit pointer for checking native stack consumption. */
+ uintptr_t nativeStackLimit[js::StackKindCount];
- explicit ContextFriendFields(JSRuntime* rt)
- : runtime_(rt), compartment_(nullptr), zone_(nullptr)
- {}
+ explicit ContextFriendFields(bool isJSContext);
static const ContextFriendFields* get(const JSContext* cx) {
return reinterpret_cast<const ContextFriendFields*>(cx);
@@ -409,7 +437,6 @@
return reinterpret_cast<ContextFriendFields*>(cx);
}
- friend JSRuntime* GetRuntime(const JSContext* cx);
friend JSCompartment* GetContextCompartment(const JSContext* cx);
friend JS::Zone* GetContextZone(const JSContext* cx);
template <typename T> friend class JS::Rooted;
@@ -425,12 +452,6 @@
* usable without resorting to jsfriendapi.h, and when JSContext is an
* incomplete type.
*/
-inline JSRuntime*
-GetRuntime(const JSContext* cx)
-{
- return ContextFriendFields::get(cx)->runtime_;
-}
-
inline JSCompartment*
GetContextCompartment(const JSContext* cx)
{
@@ -443,57 +464,13 @@
return ContextFriendFields::get(cx)->zone_;
}
-class PerThreadData;
-
-struct PerThreadDataFriendFields
-{
- private:
- // Note: this type only exists to permit us to derive the offset of
- // the perThread data within the real JSRuntime* type in a portable
- // way.
- struct RuntimeDummy : JS::shadow::Runtime
- {
- struct PerThreadDummy {
- void* field1;
- uintptr_t field2;
-#ifdef JS_DEBUG
- uint64_t field3;
-#endif
- } mainThread;
- };
-
- public:
- /* Rooting structures. */
- RootLists roots;
-
- PerThreadDataFriendFields();
-
- /* Limit pointer for checking native stack consumption. */
- uintptr_t nativeStackLimit[js::StackKindCount];
-
- static const size_t RuntimeMainThreadOffset = offsetof(RuntimeDummy, mainThread);
-
- static inline PerThreadDataFriendFields* get(js::PerThreadData* pt) {
- return reinterpret_cast<PerThreadDataFriendFields*>(pt);
- }
-
- static inline PerThreadDataFriendFields* getMainThread(JSRuntime* rt) {
- // mainThread must always appear directly after |JS::shadow::Runtime|.
- // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
- return reinterpret_cast<PerThreadDataFriendFields*>(
- reinterpret_cast<char*>(rt) + RuntimeMainThreadOffset);
- }
+} /* namespace js */
- static inline const PerThreadDataFriendFields* getMainThread(const JSRuntime* rt) {
- // mainThread must always appear directly after |JS::shadow::Runtime|.
- // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
- return reinterpret_cast<const PerThreadDataFriendFields*>(
- reinterpret_cast<const char*>(rt) + RuntimeMainThreadOffset);
- }
+MOZ_BEGIN_EXTERN_C
- template <typename T> friend class JS::Rooted;
-};
+// Defined in NSPR prio.h.
+typedef struct PRFileDesc PRFileDesc;
-} /* namespace js */
+MOZ_END_EXTERN_C
#endif /* jspubtd_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jstypes.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jstypes.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jstypes.h
@@ -70,18 +70,16 @@
#if defined(STATIC_JS_API)
# define JS_PUBLIC_API(t) t
# define JS_PUBLIC_DATA(t) t
+# define JS_FRIEND_API(t) t
+# define JS_FRIEND_DATA(t) t
#elif defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
# define JS_PUBLIC_API(t) MOZ_EXPORT t
# define JS_PUBLIC_DATA(t) MOZ_EXPORT t
-#else
-# define JS_PUBLIC_API(t) MOZ_IMPORT_API t
-# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA t
-#endif
-
-#if defined(STATIC_JS_API) || defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
# define JS_FRIEND_API(t) MOZ_EXPORT t
# define JS_FRIEND_DATA(t) MOZ_EXPORT t
#else
+# define JS_PUBLIC_API(t) MOZ_IMPORT_API t
+# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA t
# define JS_FRIEND_API(t) MOZ_IMPORT_API t
# define JS_FRIEND_DATA(t) MOZ_IMPORT_DATA t
#endif
@@ -95,6 +93,14 @@
#define JS_NO_FASTCALL
#endif
+// gcc is buggy and warns on our attempts to JS_PUBLIC_API our
+// forward-declarations or explicit template instantiations. See
+// <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50044>. Add a way to detect
+// that so we can locally disable that warning.
+#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ < 6 || (__GNUC__ == 6 && __GNUC_MINOR__ <= 4))
+#define JS_BROKEN_GCC_ATTRIBUTE_WARNING
+#endif
+
/***********************************************************************
** MACROS: JS_BEGIN_MACRO
** JS_END_MACRO
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsversion.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsversion.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jsversion.h
@@ -22,7 +22,7 @@
#define JS_HAS_GENERATORS 1 /* (no longer used) */
#define JS_HAS_BLOCK_SCOPE 1 /* (no longer used) */
#define JS_HAS_DESTRUCTURING 2 /* (no longer used) */
-#define JS_HAS_GENERATOR_EXPRS 1 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_GENERATOR_EXPRS 1 /* (no longer used) */
#define JS_HAS_EXPR_CLOSURES 1 /* has function (formals) listexpr */
/* (no longer used) */
@@ -37,11 +37,4 @@
*/
#define JS_OLD_GETTER_SETTER_METHODS 1
-#ifdef NIGHTLY_BUILD
-
-/* Support for ES7 Exponentiation proposal. */
-#define JS_HAS_EXPONENTIATION 1
-
-#endif // NIGHTLY_BUILD
-
#endif /* jsversion_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/jswrapper.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/jswrapper.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/jswrapper.h
@@ -44,19 +44,88 @@
/*
* A wrapper is a proxy with a target object to which it generally forwards
- * operations, but may restrict access to certain operations or instrument the
- * methods in various ways. A wrapper is distinct from a Direct Proxy Handler
- * in the sense that it can be "unwrapped" in C++, exposing the underlying
- * object (Direct Proxy Handlers have an underlying target object, but don't
- * expect to expose this object via any kind of unwrapping operation). Callers
- * should be careful to avoid unwrapping security wrappers in the wrong
+ * operations, but may restrict access to certain operations or augment those
+ * operations in various ways.
+ *
+ * A wrapper can be "unwrapped" in C++, exposing the underlying object.
+ * Callers should be careful to avoid unwrapping security wrappers in the wrong
* context.
+ *
+ * Important: If you add a method implementation here, you probably also need
+ * to add an override in CrossCompartmentWrapper. If you don't, you risk
+ * compartment mismatches. See bug 945826 comment 0.
*/
-class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
+class JS_FRIEND_API(Wrapper) : public BaseProxyHandler
{
unsigned mFlags;
public:
+ explicit constexpr Wrapper(unsigned aFlags, bool aHasPrototype = false,
+ bool aHasSecurityPolicy = false)
+ : BaseProxyHandler(&family, aHasPrototype, aHasSecurityPolicy),
+ mFlags(aFlags)
+ { }
+
+ virtual bool finalizeInBackground(const Value& priv) const override;
+
+ /* Standard internal methods. */
+ virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
+ MutableHandle<PropertyDescriptor> desc) const override;
+ virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
+ Handle<PropertyDescriptor> desc,
+ ObjectOpResult& result) const override;
+ virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
+ AutoIdVector& props) const override;
+ virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
+ ObjectOpResult& result) const override;
+ virtual bool enumerate(JSContext* cx, HandleObject proxy,
+ MutableHandleObject objp) const override;
+ virtual bool getPrototype(JSContext* cx, HandleObject proxy,
+ MutableHandleObject protop) const override;
+ virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
+ ObjectOpResult& result) const override;
+ virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
+ MutableHandleObject protop) const override;
+ virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
+ bool* succeeded) const override;
+ virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
+ ObjectOpResult& result) const override;
+ virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
+ virtual bool has(JSContext* cx, HandleObject proxy, HandleId id,
+ bool* bp) const override;
+ virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
+ HandleId id, MutableHandleValue vp) const override;
+ virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
+ HandleValue receiver, ObjectOpResult& result) const override;
+ virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
+ virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
+
+ /* SpiderMonkey extensions. */
+ virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
+ MutableHandle<PropertyDescriptor> desc) const override;
+ virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id,
+ bool* bp) const override;
+ virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
+ AutoIdVector& props) const override;
+ virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
+ const CallArgs& args) const override;
+ virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
+ bool* bp) const override;
+ virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls) const override;
+ virtual bool isArray(JSContext* cx, HandleObject proxy,
+ JS::IsArrayAnswer* answer) const override;
+ virtual const char* className(JSContext* cx, HandleObject proxy) const override;
+ virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
+ unsigned indent) const override;
+ virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
+ RegExpGuard* g) const override;
+ virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy,
+ MutableHandleValue vp) const override;
+ virtual bool isCallable(JSObject* obj) const override;
+ virtual bool isConstructor(JSObject* obj) const override;
+ virtual JSObject* weakmapKeyDelegate(JSObject* proxy) const override;
+
+ public:
using BaseProxyHandler::Action;
enum Flags {
@@ -77,15 +146,6 @@
return mFlags;
}
- explicit MOZ_CONSTEXPR Wrapper(unsigned aFlags, bool aHasPrototype = false,
- bool aHasSecurityPolicy = false)
- : DirectProxyHandler(&family, aHasPrototype, aHasSecurityPolicy),
- mFlags(aFlags)
- { }
-
- virtual bool finalizeInBackground(Value priv) const override;
- virtual bool isConstructor(JSObject* obj) const override;
-
static const char family;
static const Wrapper singleton;
static const Wrapper singletonWithPrototype;
@@ -103,16 +163,16 @@
class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
{
public:
- explicit MOZ_CONSTEXPR CrossCompartmentWrapper(unsigned aFlags, bool aHasPrototype = false,
+ explicit constexpr CrossCompartmentWrapper(unsigned aFlags, bool aHasPrototype = false,
bool aHasSecurityPolicy = false)
: Wrapper(CROSS_COMPARTMENT | aFlags, aHasPrototype, aHasSecurityPolicy)
{ }
/* Standard internal methods. */
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
+ MutableHandle<PropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<JSPropertyDescriptor> desc,
+ Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const override;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
@@ -124,6 +184,8 @@
virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
ObjectOpResult& result) const override;
+ virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
+ MutableHandleObject protop) const override;
virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
bool* succeeded) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
@@ -139,7 +201,7 @@
/* SpiderMonkey extensions. */
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
+ MutableHandle<PropertyDescriptor> desc) const override;
virtual bool hasOwn(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
@@ -153,6 +215,9 @@
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
+ // Allocate CrossCompartmentWrappers in the nursery.
+ virtual bool canNurseryAllocate() const override { return true; }
+
static const CrossCompartmentWrapper singleton;
static const CrossCompartmentWrapper singletonWithPrototype;
};
@@ -160,14 +225,14 @@
class JS_FRIEND_API(OpaqueCrossCompartmentWrapper) : public CrossCompartmentWrapper
{
public:
- explicit MOZ_CONSTEXPR OpaqueCrossCompartmentWrapper() : CrossCompartmentWrapper(0)
+ explicit constexpr OpaqueCrossCompartmentWrapper() : CrossCompartmentWrapper(0)
{ }
/* Standard internal methods. */
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
+ MutableHandle<PropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<JSPropertyDescriptor> desc,
+ Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const override;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
@@ -179,6 +244,8 @@
MutableHandleObject protop) const override;
virtual bool setPrototype(JSContext* cx, HandleObject wrapper, HandleObject proto,
ObjectOpResult& result) const override;
+ virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject wrapper, bool* isOrdinary,
+ MutableHandleObject protop) const override;
virtual bool setImmutablePrototype(JSContext* cx, HandleObject wrapper,
bool* succeeded) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
@@ -195,13 +262,12 @@
/* SpiderMonkey extensions. */
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
+ MutableHandle<PropertyDescriptor> desc) const override;
virtual bool hasOwn(JSContext* cx, HandleObject wrapper, HandleId id,
bool* bp) const override;
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper,
- ESClassValue* classValue) const override;
+ virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper, ESClass* cls) const override;
virtual bool isArray(JSContext* cx, HandleObject obj,
JS::IsArrayAnswer* answer) const override;
virtual const char* className(JSContext* cx, HandleObject wrapper) const override;
@@ -223,7 +289,7 @@
class JS_FRIEND_API(SecurityWrapper) : public Base
{
public:
- explicit MOZ_CONSTEXPR SecurityWrapper(unsigned flags, bool hasPrototype = false)
+ explicit constexpr SecurityWrapper(unsigned flags, bool hasPrototype = false)
: Base(flags, hasPrototype, /* hasSecurityPolicy = */ true)
{ }
@@ -231,7 +297,7 @@
bool* bp) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<JSPropertyDescriptor> desc,
+ Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const override;
virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
@@ -242,8 +308,7 @@
virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
const CallArgs& args) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper,
- ESClassValue* classValue) const override;
+ virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper, ESClass* cls) const override;
virtual bool isArray(JSContext* cx, HandleObject wrapper, JS::IsArrayAnswer* answer) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
@@ -263,7 +328,6 @@
typedef SecurityWrapper<Base> Restrictive;
};
-typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
extern JSObject*
@@ -297,10 +361,10 @@
JS_FRIEND_API(bool)
IsCrossCompartmentWrapper(JSObject* obj);
-void
+JS_FRIEND_API(void)
NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper);
-bool
+void
RemapWrapper(JSContext* cx, JSObject* wobj, JSObject* newTarget);
JS_FRIEND_API(bool)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Alignment.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Alignment.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Alignment.h
@@ -120,6 +120,13 @@
const void* addr() const { return u.mBytes; }
void* addr() { return u.mBytes; }
+
+ AlignedStorage() = default;
+
+ // AlignedStorage is non-copyable: the default copy constructor violates
+ // strict aliasing rules, per bug 1269319.
+ AlignedStorage(const AlignedStorage&) = delete;
+ void operator=(const AlignedStorage&) = delete;
};
template<typename T>
@@ -133,6 +140,13 @@
const T* addr() const { return reinterpret_cast<const T*>(u.mBytes); }
T* addr() { return static_cast<T*>(static_cast<void*>(u.mBytes)); }
+
+ AlignedStorage2() = default;
+
+ // AlignedStorage2 is non-copyable: the default copy constructor violates
+ // strict aliasing rules, per bug 1269319.
+ AlignedStorage2(const AlignedStorage2&) = delete;
+ void operator=(const AlignedStorage2&) = delete;
};
} /* namespace mozilla */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/AllocPolicy.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/AllocPolicy.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/AllocPolicy.h
@@ -12,6 +12,7 @@
#ifndef mozilla_AllocPolicy_h
#define mozilla_AllocPolicy_h
+#include "mozilla/Attributes.h"
#include "mozilla/TemplateLib.h"
#include <stddef.h>
@@ -121,7 +122,7 @@
{
}
- bool checkSimulatedOOM() const
+ MOZ_MUST_USE bool checkSimulatedOOM() const
{
return true;
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/AlreadyAddRefed.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/AlreadyAddRefed.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/AlreadyAddRefed.h
@@ -29,7 +29,7 @@
* because of the sheer number of usages of already_AddRefed.
*/
template<class T>
-struct MOZ_MUST_USE MOZ_NON_AUTOABLE already_AddRefed
+struct MOZ_MUST_USE_TYPE MOZ_NON_AUTOABLE already_AddRefed
{
/*
* We want to allow returning nullptr from functions returning
@@ -111,7 +111,7 @@
aUnused << mutableAlreadyAddRefed->take();
}
- MOZ_WARN_UNUSED_RESULT T* take()
+ MOZ_MUST_USE T* take()
{
T* rawPtr = mRawPtr;
mRawPtr = nullptr;
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Array.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Array.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Array.h
@@ -11,6 +11,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
+#include "mozilla/Move.h"
#include "mozilla/ReverseIterator.h"
#include <stddef.h>
@@ -23,6 +24,16 @@
T mArr[Length];
public:
+ Array() {}
+
+ template <typename... Args>
+ MOZ_IMPLICIT Array(Args&&... aArgs)
+ : mArr{mozilla::Forward<Args>(aArgs)...}
+ {
+ static_assert(sizeof...(aArgs) == Length,
+ "The number of arguments should be equal to the template parameter Length");
+ }
+
T& operator[](size_t aIndex)
{
MOZ_ASSERT(aIndex < Length);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ArrayUtils.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ArrayUtils.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ArrayUtils.h
@@ -52,21 +52,21 @@
* Beware of the implicit trailing '\0' when using this with string constants.
*/
template<typename T, size_t N>
-MOZ_CONSTEXPR size_t
+constexpr size_t
ArrayLength(T (&aArr)[N])
{
return N;
}
template<typename T, size_t N>
-MOZ_CONSTEXPR size_t
+constexpr size_t
ArrayLength(const Array<T, N>& aArr)
{
return N;
}
template<typename E, E N, typename T>
-MOZ_CONSTEXPR size_t
+constexpr size_t
ArrayLength(const EnumeratedArray<E, N, T>& aArr)
{
return size_t(N);
@@ -78,21 +78,21 @@
* Beware of the implicit trailing '\0' when using this with string constants.
*/
template<typename T, size_t N>
-MOZ_CONSTEXPR T*
+constexpr T*
ArrayEnd(T (&aArr)[N])
{
return aArr + ArrayLength(aArr);
}
template<typename T, size_t N>
-MOZ_CONSTEXPR T*
+constexpr T*
ArrayEnd(Array<T, N>& aArr)
{
return &aArr[0] + ArrayLength(aArr);
}
template<typename T, size_t N>
-MOZ_CONSTEXPR const T*
+constexpr const T*
ArrayEnd(const Array<T, N>& aArr)
{
return &aArr[0] + ArrayLength(aArr);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Assertions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Assertions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Assertions.h
@@ -17,23 +17,29 @@
#include "mozilla/Compiler.h"
#include "mozilla/Likely.h"
#include "mozilla/MacroArgs.h"
+#include "mozilla/StaticAnalysisFunctions.h"
+#include "mozilla/Types.h"
#ifdef MOZ_DUMP_ASSERTION_STACK
#include "nsTraceRefcnt.h"
#endif
-#if defined(MOZ_CRASHREPORTER) && defined(MOZILLA_INTERNAL_API) && \
- !defined(MOZILLA_EXTERNAL_LINKAGE) && defined(__cplusplus)
-namespace CrashReporter {
-// This declaration is present here as well as in nsExceptionHandler.h
-// nsExceptionHandler.h is not directly included in this file as it includes
-// windows.h, which can cause problems when it is imported into some files due
-// to the number of macros defined.
-// XXX If you change this definition - also change the definition in
-// nsExceptionHandler.h
-void AnnotateMozCrashReason(const char* aReason);
-} // namespace CrashReporter
+#if defined(MOZ_HAS_MOZGLUE) || defined(MOZILLA_INTERNAL_API)
+/*
+ * The crash reason set by MOZ_CRASH_ANNOTATE is consumed by the crash reporter
+ * if present. It is declared here (and defined in Assertions.cpp) to make it
+ * available to all code, even libraries that don't link with the crash reporter
+ * directly.
+ */
+MOZ_BEGIN_EXTERN_C
+extern MFBT_DATA const char* gMozCrashReason;
+MOZ_END_EXTERN_C
-# define MOZ_CRASH_ANNOTATE(...) CrashReporter::AnnotateMozCrashReason("" __VA_ARGS__)
+static inline void
+AnnotateMozCrashReason(const char* reason)
+{
+ gMozCrashReason = reason;
+}
+# define MOZ_CRASH_ANNOTATE(...) AnnotateMozCrashReason(__VA_ARGS__)
#else
# define MOZ_CRASH_ANNOTATE(...) do { /* nothing */ } while (0)
#endif
@@ -158,7 +164,7 @@
aStr, aFilename, aLine);
#else
fprintf(stderr, "Assertion failure: %s, at %s:%d\n", aStr, aFilename, aLine);
-#if defined (MOZ_DUMP_ASSERTION_STACK) && !defined(MOZILLA_XPCOMRT_API)
+#if defined (MOZ_DUMP_ASSERTION_STACK)
nsTraceRefcnt::WalkTheStack(stderr);
#endif
fflush(stderr);
@@ -174,7 +180,7 @@
"Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
#else
fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
-#if defined(MOZ_DUMP_ASSERTION_STACK) && !defined(MOZILLA_XPCOMRT_API)
+#if defined(MOZ_DUMP_ASSERTION_STACK)
nsTraceRefcnt::WalkTheStack(stderr);
#endif
fflush(stderr);
@@ -212,33 +218,33 @@
__declspec(noreturn) __inline void MOZ_NoReturn() {}
# ifdef __cplusplus
-# define MOZ_REALLY_CRASH() \
+# define MOZ_REALLY_CRASH(line) \
do { \
::__debugbreak(); \
- *((volatile int*) NULL) = __LINE__; \
+ *((volatile int*) NULL) = line; \
::TerminateProcess(::GetCurrentProcess(), 3); \
::MOZ_NoReturn(); \
} while (0)
# else
-# define MOZ_REALLY_CRASH() \
+# define MOZ_REALLY_CRASH(line) \
do { \
__debugbreak(); \
- *((volatile int*) NULL) = __LINE__; \
+ *((volatile int*) NULL) = line; \
TerminateProcess(GetCurrentProcess(), 3); \
MOZ_NoReturn(); \
} while (0)
# endif
#else
# ifdef __cplusplus
-# define MOZ_REALLY_CRASH() \
+# define MOZ_REALLY_CRASH(line) \
do { \
- *((volatile int*) NULL) = __LINE__; \
+ *((volatile int*) NULL) = line; \
::abort(); \
} while (0)
# else
-# define MOZ_REALLY_CRASH() \
+# define MOZ_REALLY_CRASH(line) \
do { \
- *((volatile int*) NULL) = __LINE__; \
+ *((volatile int*) NULL) = line; \
abort(); \
} while (0)
# endif
@@ -269,17 +275,69 @@
# define MOZ_CRASH(...) \
do { \
MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
- MOZ_REALLY_CRASH(); \
+ MOZ_REALLY_CRASH(__LINE__); \
} while (0)
#else
# define MOZ_CRASH(...) \
do { \
MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
- MOZ_REALLY_CRASH(); \
+ MOZ_REALLY_CRASH(__LINE__); \
} while (0)
#endif
+/*
+ * MOZ_CRASH_UNSAFE_OOL(explanation-string) can be used if the explanation
+ * string cannot be a string literal (but no other processing needs to be done
+ * on it). A regular MOZ_CRASH() is preferred wherever possible, as passing
+ * arbitrary strings from a potentially compromised process is not without risk.
+ * If the string being passed is the result of a printf-style function,
+ * consider using MOZ_CRASH_UNSAFE_PRINTF instead.
+ */
+#ifndef DEBUG
+MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
+MOZ_CrashOOL(int aLine, const char* aReason);
+# define MOZ_CRASH_UNSAFE_OOL(reason) MOZ_CrashOOL(__LINE__, reason)
+#else
+MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
+MOZ_CrashOOL(const char* aFilename, int aLine, const char* aReason);
+# define MOZ_CRASH_UNSAFE_OOL(reason) MOZ_CrashOOL(__FILE__, __LINE__, reason)
+#endif
+
+static const size_t sPrintfMaxArgs = 4;
+static const size_t sPrintfCrashReasonSize = 1024;
+
+#ifndef DEBUG
+MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(2, 3) void
+MOZ_CrashPrintf(int aLine, const char* aFormat, ...);
+# define MOZ_CALL_CRASH_PRINTF(format, ...) \
+ MOZ_CrashPrintf(__LINE__, format, __VA_ARGS__)
+#else
+MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(3, 4) void
+MOZ_CrashPrintf(const char* aFilename, int aLine, const char* aFormat, ...);
+# define MOZ_CALL_CRASH_PRINTF(format, ...) \
+ MOZ_CrashPrintf(__FILE__, __LINE__, format, __VA_ARGS__)
+#endif
+
+/*
+ * MOZ_CRASH_UNSAFE_PRINTF(format, arg1 [, args]) can be used when more
+ * information is desired than a string literal can supply. The caller provides
+ * a printf-style format string, which must be a string literal and between
+ * 1 and 4 additional arguments. A regular MOZ_CRASH() is preferred wherever
+ * possible, as passing arbitrary strings to printf from a potentially
+ * compromised process is not without risk.
+ */
+#define MOZ_CRASH_UNSAFE_PRINTF(format, ...) \
+ do { \
+ MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
+ static_assert( \
+ MOZ_PASTE_PREFIX_AND_ARG_COUNT(, __VA_ARGS__) <= sPrintfMaxArgs, \
+ "Only up to 4 additional arguments are allowed!"); \
+ static_assert(sizeof(format) <= sPrintfCrashReasonSize, \
+ "The supplied format string is too long!"); \
+ MOZ_CALL_CRASH_PRINTF("" format, __VA_ARGS__); \
+ } while (0)
+
#ifdef __cplusplus
} /* extern "C" */
#endif
@@ -368,20 +426,20 @@
#define MOZ_ASSERT_HELPER1(expr) \
do { \
MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
- if (MOZ_UNLIKELY(!(expr))) { \
+ if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ")"); \
- MOZ_REALLY_CRASH(); \
+ MOZ_REALLY_CRASH(__LINE__); \
} \
} while (0)
/* Now the two-argument form. */
#define MOZ_ASSERT_HELPER2(expr, explain) \
do { \
MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
- if (MOZ_UNLIKELY(!(expr))) { \
+ if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ") (" explain ")"); \
- MOZ_REALLY_CRASH(); \
+ MOZ_REALLY_CRASH(__LINE__); \
} \
} while (0)
@@ -397,7 +455,7 @@
# define MOZ_ASSERT(...) do { } while (0)
#endif /* DEBUG */
-#ifdef RELEASE_BUILD
+#ifdef RELEASE_OR_BETA
# define MOZ_DIAGNOSTIC_ASSERT MOZ_ASSERT
#else
# define MOZ_DIAGNOSTIC_ASSERT MOZ_RELEASE_ASSERT
@@ -496,6 +554,45 @@
MOZ_ASSUME_UNREACHABLE_MARKER(); \
} while (0)
+/**
+ * MOZ_FALLTHROUGH_ASSERT is an annotation to suppress compiler warnings about
+ * switch cases that MOZ_ASSERT(false) (or its alias MOZ_ASSERT_UNREACHABLE) in
+ * debug builds, but intentionally fall through in release builds to handle
+ * unexpected values.
+ *
+ * Why do we need MOZ_FALLTHROUGH_ASSERT in addition to MOZ_FALLTHROUGH? In
+ * release builds, the MOZ_ASSERT(false) will expand to `do { } while (0)`,
+ * requiring a MOZ_FALLTHROUGH annotation to suppress a -Wimplicit-fallthrough
+ * warning. In debug builds, the MOZ_ASSERT(false) will expand to something like
+ * `if (true) { MOZ_CRASH(); }` and the MOZ_FALLTHROUGH annotation will cause
+ * a -Wunreachable-code warning. The MOZ_FALLTHROUGH_ASSERT macro breaks this
+ * warning stalemate.
+ *
+ * // Example before MOZ_FALLTHROUGH_ASSERT:
+ * switch (foo) {
+ * default:
+ * // This case wants to assert in debug builds, fall through in release.
+ * MOZ_ASSERT(false); // -Wimplicit-fallthrough warning in release builds!
+ * MOZ_FALLTHROUGH; // but -Wunreachable-code warning in debug builds!
+ * case 5:
+ * return 5;
+ * }
+ *
+ * // Example with MOZ_FALLTHROUGH_ASSERT:
+ * switch (foo) {
+ * default:
+ * // This case asserts in debug builds, falls through in release.
+ * MOZ_FALLTHROUGH_ASSERT("Unexpected foo value?!");
+ * case 5:
+ * return 5;
+ * }
+ */
+#ifdef DEBUG
+# define MOZ_FALLTHROUGH_ASSERT(reason) MOZ_CRASH("MOZ_FALLTHROUGH_ASSERT: " reason)
+#else
+# define MOZ_FALLTHROUGH_ASSERT(...) MOZ_FALLTHROUGH
+#endif
+
/*
* MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
* expression, in debug builds and in release builds both. Then, in debug
@@ -503,21 +600,35 @@
* using MOZ_ASSERT.
*/
#ifdef DEBUG
-# define MOZ_ALWAYS_TRUE(expr) MOZ_ASSERT((expr))
-# define MOZ_ALWAYS_FALSE(expr) MOZ_ASSERT(!(expr))
+# define MOZ_ALWAYS_TRUE(expr) \
+ do { \
+ if ((expr)) { \
+ /* Do nothing. */ \
+ } else { \
+ MOZ_ASSERT(false, #expr); \
+ } \
+ } while (0)
+# define MOZ_ALWAYS_FALSE(expr) \
+ do { \
+ if ((expr)) { \
+ MOZ_ASSERT(false, #expr); \
+ } else { \
+ /* Do nothing. */ \
+ } \
+ } while (0)
#else
# define MOZ_ALWAYS_TRUE(expr) \
- do { \
- if ( ( expr ) ) { \
- /* Silence MOZ_WARN_UNUSED_RESULT. */ \
- } \
- } while (0)
+ do { \
+ if ((expr)) { \
+ /* Silence MOZ_MUST_USE. */ \
+ } \
+ } while (0)
# define MOZ_ALWAYS_FALSE(expr) \
- do { \
- if ( ( expr ) ) { \
- /* Silence MOZ_WARN_UNUSED_RESULT. */ \
- } \
- } while (0)
+ do { \
+ if ((expr)) { \
+ /* Silence MOZ_MUST_USE. */ \
+ } \
+ } while (0)
#endif
#undef MOZ_DUMP_ASSERTION_STACK
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Atomics.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Atomics.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Atomics.h
@@ -323,7 +323,7 @@
template<typename T>
struct ToStorageTypeArgument
{
- static T convert (T aT) { return aT; }
+ static constexpr T convert (T aT) { return aT; }
};
} // namespace detail
@@ -514,13 +514,13 @@
{
typedef typename AtomicStorageType<T>::Type ResultType;
- static ResultType convert (T aT) { return ResultType(aT); }
+ static constexpr ResultType convert (T aT) { return ResultType(aT); }
};
template<typename T>
struct ToStorageTypeArgument<T, false>
{
- static T convert (T aT) { return aT; }
+ static constexpr T convert (T aT) { return aT; }
};
} // namespace detail
@@ -546,8 +546,8 @@
ValueType mValue;
public:
- MOZ_CONSTEXPR AtomicBase() : mValue() {}
- explicit MOZ_CONSTEXPR AtomicBase(T aInit)
+ constexpr AtomicBase() : mValue() {}
+ explicit constexpr AtomicBase(T aInit)
: mValue(ToStorageTypeArgument<T>::convert(aInit))
{}
@@ -598,8 +598,8 @@
typedef typename detail::AtomicBase<T, Order> Base;
public:
- MOZ_CONSTEXPR AtomicBaseIncDec() : Base() {}
- explicit MOZ_CONSTEXPR AtomicBaseIncDec(T aInit) : Base(aInit) {}
+ constexpr AtomicBaseIncDec() : Base() {}
+ explicit constexpr AtomicBaseIncDec(T aInit) : Base(aInit) {}
using Base::operator=;
@@ -654,8 +654,8 @@
typedef typename detail::AtomicBaseIncDec<T, Order> Base;
public:
- MOZ_CONSTEXPR Atomic() : Base() {}
- explicit MOZ_CONSTEXPR Atomic(T aInit) : Base(aInit) {}
+ constexpr Atomic() : Base() {}
+ explicit constexpr Atomic(T aInit) : Base(aInit) {}
using Base::operator=;
@@ -702,8 +702,8 @@
typedef typename detail::AtomicBaseIncDec<T*, Order> Base;
public:
- MOZ_CONSTEXPR Atomic() : Base() {}
- explicit MOZ_CONSTEXPR Atomic(T* aInit) : Base(aInit) {}
+ constexpr Atomic() : Base() {}
+ explicit constexpr Atomic(T* aInit) : Base(aInit) {}
using Base::operator=;
@@ -733,8 +733,8 @@
typedef typename detail::AtomicBase<T, Order> Base;
public:
- MOZ_CONSTEXPR Atomic() : Base() {}
- explicit MOZ_CONSTEXPR Atomic(T aInit) : Base(aInit) {}
+ constexpr Atomic() : Base() {}
+ explicit constexpr Atomic(T aInit) : Base(aInit) {}
operator T() const { return T(Base::Intrinsics::load(Base::mValue)); }
@@ -767,8 +767,8 @@
typedef typename detail::AtomicBase<uint32_t, Order> Base;
public:
- MOZ_CONSTEXPR Atomic() : Base() {}
- explicit MOZ_CONSTEXPR Atomic(bool aInit) : Base(aInit) {}
+ constexpr Atomic() : Base() {}
+ explicit constexpr Atomic(bool aInit) : Base(aInit) {}
// We provide boolean wrappers for the underlying AtomicBase methods.
MOZ_IMPLICIT operator bool() const
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Attributes.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Attributes.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Attributes.h
@@ -45,27 +45,9 @@
* standardly, by checking whether __cplusplus has a C++11 or greater value.
* Current versions of g++ do not correctly set __cplusplus, so we check both
* for forward compatibility.
- *
- * Even though some versions of MSVC support explicit conversion operators, we
- * don't indicate support for them here, due to
- * http://stackoverflow.com/questions/20498142/visual-studio-2013-explicit-keyword-bug
*/
# define MOZ_HAVE_NEVER_INLINE __declspec(noinline)
# define MOZ_HAVE_NORETURN __declspec(noreturn)
-# if _MSC_VER >= 1900
-# define MOZ_HAVE_CXX11_CONSTEXPR
-# define MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
-# define MOZ_HAVE_EXPLICIT_CONVERSION
-# endif
-# ifdef __clang__
- /* clang-cl probably supports constexpr and explicit conversions. */
-# if __has_extension(cxx_constexpr)
-# define MOZ_HAVE_CXX11_CONSTEXPR
-# endif
-# if __has_extension(cxx_explicit_conversions)
-# define MOZ_HAVE_EXPLICIT_CONVERSION
-# endif
-# endif
#elif defined(__clang__)
/*
* Per Clang documentation, "Note that marketing version numbers should not
@@ -75,12 +57,6 @@
# ifndef __has_extension
# define __has_extension __has_feature /* compatibility, for older versions of clang */
# endif
-# if __has_extension(cxx_constexpr)
-# define MOZ_HAVE_CXX11_CONSTEXPR
-# endif
-# if __has_extension(cxx_explicit_conversions)
-# define MOZ_HAVE_EXPLICIT_CONVERSION
-# endif
# if __has_attribute(noinline)
# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
# endif
@@ -88,13 +64,6 @@
# define MOZ_HAVE_NORETURN __attribute__((noreturn))
# endif
#elif defined(__GNUC__)
-# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
-# define MOZ_HAVE_CXX11_CONSTEXPR
-# if MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
-# define MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
-# endif
-# define MOZ_HAVE_EXPLICIT_CONVERSION
-# endif
# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
# define MOZ_HAVE_NORETURN __attribute__((noreturn))
#endif
@@ -110,55 +79,6 @@
#endif
/*
- * The MOZ_CONSTEXPR specifier declares that a C++11 compiler can evaluate a
- * function at compile time. A constexpr function cannot examine any values
- * except its arguments and can have no side effects except its return value.
- * The MOZ_CONSTEXPR_VAR specifier tells a C++11 compiler that a variable's
- * value may be computed at compile time. It should be prefered to just
- * marking variables as MOZ_CONSTEXPR because if the compiler does not support
- * constexpr it will fall back to making the variable const, and some compilers
- * do not accept variables being marked both const and constexpr.
- */
-#ifdef MOZ_HAVE_CXX11_CONSTEXPR
-# define MOZ_CONSTEXPR constexpr
-# define MOZ_CONSTEXPR_VAR constexpr
-# ifdef MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
-# define MOZ_CONSTEXPR_TMPL constexpr
-# else
-# define MOZ_CONSTEXPR_TMPL
-# endif
-#else
-# define MOZ_CONSTEXPR /* no support */
-# define MOZ_CONSTEXPR_VAR const
-# define MOZ_CONSTEXPR_TMPL
-#endif
-
-/*
- * MOZ_EXPLICIT_CONVERSION is a specifier on a type conversion
- * overloaded operator that declares that a C++11 compiler should restrict
- * this operator to allow only explicit type conversions, disallowing
- * implicit conversions.
- *
- * Example:
- *
- * template<typename T>
- * class Ptr
- * {
- * T* mPtr;
- * MOZ_EXPLICIT_CONVERSION operator bool() const
- * {
- * return mPtr != nullptr;
- * }
- * };
- *
- */
-#ifdef MOZ_HAVE_EXPLICIT_CONVERSION
-# define MOZ_EXPLICIT_CONVERSION explicit
-#else
-# define MOZ_EXPLICIT_CONVERSION /* no support */
-#endif
-
-/*
* MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
* method decorated with it must never be inlined, even if the compiler would
* otherwise choose to inline the method. Compilers aren't absolutely
@@ -318,37 +238,48 @@
#endif
/**
- * MOZ_WARN_UNUSED_RESULT tells the compiler to emit a warning if a function's
+ * MOZ_MUST_USE tells the compiler to emit a warning if a function's
* return value is not used by the caller.
*
- * Place this attribute at the very beginning of a function definition. For
+ * Place this attribute at the very beginning of a function declaration. For
* example, write
*
- * MOZ_WARN_UNUSED_RESULT int foo();
+ * MOZ_MUST_USE int foo();
*
* or
*
- * MOZ_WARN_UNUSED_RESULT int foo() { return 42; }
+ * MOZ_MUST_USE int foo() { return 42; }
*/
#if defined(__GNUC__) || defined(__clang__)
-# define MOZ_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+# define MOZ_MUST_USE __attribute__ ((warn_unused_result))
#else
-# define MOZ_WARN_UNUSED_RESULT
+# define MOZ_MUST_USE
#endif
/**
* MOZ_FALLTHROUGH is an annotation to suppress compiler warnings about switch
* cases that fall through without a break or return statement. MOZ_FALLTHROUGH
- * is only needed on cases that have code:
+ * is only needed on cases that have code.
+ *
+ * MOZ_FALLTHROUGH_ASSERT is an annotation to suppress compiler warnings about
+ * switch cases that MOZ_ASSERT(false) (or its alias MOZ_ASSERT_UNREACHABLE) in
+ * debug builds, but intentionally fall through in release builds. See comment
+ * in Assertions.h for more details.
*
* switch (foo) {
* case 1: // These cases have no code. No fallthrough annotations are needed.
* case 2:
- * case 3:
- * foo = 4; // This case has code, so a fallthrough annotation is needed:
+ * case 3: // This case has code, so a fallthrough annotation is needed!
+ * foo++;
* MOZ_FALLTHROUGH;
- * default:
+ * case 4:
* return foo;
+ *
+ * default:
+ * // This case asserts in debug builds, falls through in release.
+ * MOZ_FALLTHROUGH_ASSERT("Unexpected foo value?!");
+ * case 5:
+ * return 5;
* }
*/
#if defined(__clang__) && __cplusplus >= 201103L
@@ -451,10 +382,12 @@
* intended to prevent introducing static initializers. This attribute
* currently makes it a compile-time error to instantiate these classes
* anywhere other than at the global scope, or as a static member of a class.
+ * In non-debug mode, it also prohibits non-trivial constructors and
+ * destructors.
* MOZ_TRIVIAL_CTOR_DTOR: Applies to all classes that must have both a trivial
- * constructor and a trivial destructor. Setting this attribute on a class
- * makes it a compile-time error for that class to get a non-trivial
- * constructor or destructor for any reason.
+ * or constexpr constructor and a trivial destructor. Setting this attribute
+ * on a class makes it a compile-time error for that class to get a
+ * non-trivial constructor or destructor for any reason.
* MOZ_HEAP_ALLOCATOR: Applies to any function. This indicates that the return
* value is allocated on the heap, and will as a result check such allocations
* during MOZ_STACK_CLASS and MOZ_NONHEAP_CLASS annotation checking.
@@ -500,9 +433,9 @@
* function. This is intended to be used with operator->() of our smart
* pointer classes to ensure that the refcount of an object wrapped in a
* smart pointer is not manipulated directly.
- * MOZ_MUST_USE: Applies to type declarations. Makes it a compile time error to not
- * use the return value of a function which has this type. This is intended to be
- * used with types which it is an error to not use.
+ * MOZ_MUST_USE_TYPE: Applies to type declarations. Makes it a compile time
+ * error to not use the return value of a function which has this type. This
+ * is intended to be used with types which it is an error to not use.
* MOZ_NEEDS_NO_VTABLE_TYPE: Applies to template class declarations. Makes it
* a compile time error to instantiate this template with a type parameter which
* has a VTable.
@@ -512,14 +445,35 @@
* template arguments are required to be safe to move in memory using
* memmove(). Passing MOZ_NON_MEMMOVABLE types to these templates is a
* compile time error.
+ * MOZ_NEEDS_MEMMOVABLE_MEMBERS: Applies to class declarations where each member
+ * must be safe to move in memory using memmove(). MOZ_NON_MEMMOVABLE types
+ * used in members of these classes are compile time errors.
* MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS: Applies to template class
* declarations where an instance of the template should be considered, for
* static analysis purposes, to inherit any type annotations (such as
- * MOZ_MUST_USE and MOZ_STACK_CLASS) from its template arguments.
+ * MOZ_MUST_USE_TYPE and MOZ_STACK_CLASS) from its template arguments.
+ * MOZ_INIT_OUTSIDE_CTOR: Applies to class member declarations. Occasionally
+ * there are class members that are not initialized in the constructor,
+ * but logic elsewhere in the class ensures they are initialized prior to use.
+ * Using this attribute on a member disables the check that this member must be
+ * initialized in constructors via list-initialization, in the constructor body,
+ * or via functions called from the constructor body.
+ * MOZ_IS_CLASS_INIT: Applies to class method declarations. Occasionally the
+ * constructor doesn't initialize all of the member variables and another function
+ * is used to initialize the rest. This marker is used to make the static analysis
+ * tool aware that the marked function is part of the initialization process
+ * and to include the marked function in the scan mechanism that determines witch
+ * member variables still remain uninitialized.
+ * MOZ_NON_PARAM: Applies to types. Makes it compile time error to use the type
+ * in parameter without pointer or reference.
* MOZ_NON_AUTOABLE: Applies to class declarations. Makes it a compile time error to
* use `auto` in place of this type in variable declarations. This is intended to
* be used with types which are intended to be implicitly constructed into other
* other types before being assigned to variables.
+ * MOZ_REQUIRED_BASE_METHOD: Applies to virtual class method declarations.
+ * Sometimes derived classes override methods that need to be called by their
+ * overridden counterparts. This marker indicates that the marked method must
+ * be called by the method that it overrides.
*/
#ifdef MOZ_CLANG_PLUGIN
# define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
@@ -541,13 +495,22 @@
# define MOZ_NON_OWNING_REF __attribute__((annotate("moz_weak_ref")))
# define MOZ_UNSAFE_REF(reason) __attribute__((annotate("moz_weak_ref")))
# define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return")))
-# define MOZ_MUST_USE __attribute__((annotate("moz_must_use")))
+# define MOZ_MUST_USE_TYPE __attribute__((annotate("moz_must_use_type")))
# define MOZ_NEEDS_NO_VTABLE_TYPE __attribute__((annotate("moz_needs_no_vtable_type")))
# define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
# define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
+# define MOZ_NEEDS_MEMMOVABLE_MEMBERS __attribute__((annotate("moz_needs_memmovable_members")))
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS \
__attribute__((annotate("moz_inherit_type_annotations_from_template_args")))
# define MOZ_NON_AUTOABLE __attribute__((annotate("moz_non_autoable")))
+# define MOZ_INIT_OUTSIDE_CTOR \
+ __attribute__((annotate("moz_ignore_ctor_initialization")))
+# define MOZ_IS_CLASS_INIT \
+ __attribute__((annotate("moz_is_class_init")))
+# define MOZ_NON_PARAM \
+ __attribute__((annotate("moz_non_param")))
+# define MOZ_REQUIRED_BASE_METHOD \
+ __attribute__((annotate("moz_required_base_method")))
/*
* It turns out that clang doesn't like void func() __attribute__ {} without a
* warning, so use pragmas to disable the warning. This code won't work on GCC
@@ -573,12 +536,17 @@
# define MOZ_NON_OWNING_REF /* nothing */
# define MOZ_UNSAFE_REF(reason) /* nothing */
# define MOZ_NO_ADDREF_RELEASE_ON_RETURN /* nothing */
-# define MOZ_MUST_USE /* nothing */
+# define MOZ_MUST_USE_TYPE /* nothing */
# define MOZ_NEEDS_NO_VTABLE_TYPE /* nothing */
# define MOZ_NON_MEMMOVABLE /* nothing */
# define MOZ_NEEDS_MEMMOVABLE_TYPE /* nothing */
+# define MOZ_NEEDS_MEMMOVABLE_MEMBERS /* nothing */
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS /* nothing */
+# define MOZ_INIT_OUTSIDE_CTOR /* nothing */
+# define MOZ_IS_CLASS_INIT /* nothing */
+# define MOZ_NON_PARAM /* nothing */
# define MOZ_NON_AUTOABLE /* nothing */
+# define MOZ_REQUIRED_BASE_METHOD /* nothing */
#endif /* MOZ_CLANG_PLUGIN */
#define MOZ_RAII MOZ_NON_TEMPORARY_CLASS MOZ_STACK_CLASS
@@ -601,4 +569,36 @@
#endif /* __cplusplus */
+/**
+ * Printf style formats. MOZ_FORMAT_PRINTF can be used to annotate a
+ * function or method that is "printf-like"; this will let (some)
+ * compilers check that the arguments match the template string.
+ *
+ * This macro takes two arguments. The first argument is the argument
+ * number of the template string. The second argument is the argument
+ * number of the '...' argument holding the arguments.
+ *
+ * Argument numbers start at 1. Note that the implicit "this"
+ * argument of a non-static member function counts as an argument.
+ *
+ * So, for a simple case like:
+ * void print_something (int whatever, const char *fmt, ...);
+ * The corresponding annotation would be
+ * MOZ_FORMAT_PRINTF(2, 3)
+ * However, if "print_something" were a non-static member function,
+ * then the annotation would be:
+ * MOZ_FORMAT_PRINTF(3, 4)
+ *
+ * Note that the checking is limited to standards-conforming
+ * printf-likes, and in particular this should not be used for
+ * PR_snprintf and friends, which are "printf-like" but which assign
+ * different meanings to the various formats.
+ */
+#ifdef __GNUC__
+#define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck) \
+ __attribute__ ((format (printf, stringIndex, firstToCheck)))
+#else
+#define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck)
+#endif
+
#endif /* mozilla_Attributes_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/BinarySearch.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/BinarySearch.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/BinarySearch.h
@@ -31,7 +31,7 @@
* printf("found 13 at %lu\n", match);
* }
*
- * The BinarySearchIf() version behaves similar, but takes |aComparator|, a
+ * The BinarySearchIf() version behaves similarly, but takes |aComparator|, a
* functor to compare the values with, instead of a value to find.
* That functor should take one argument - the value to compare - and return an
* |int| with the comparison result:
@@ -45,13 +45,13 @@
* Example:
*
* struct Comparator {
- * int operator()(int val) const {
- * if (mTarget < val) return -1;
- * if (mValue > val) return 1;
+ * int operator()(int aVal) const {
+ * if (mTarget < aVal) { return -1; }
+ * if (mTarget > aVal) { return 1; }
* return 0;
* }
- * Comparator(int target) : mTarget(target) {}
- const int mTarget;
+ * explicit Comparator(int aTarget) : mTarget(aTarget) {}
+ * const int mTarget;
* };
*
* Vector<int> sortedInts = ...
@@ -106,12 +106,12 @@
{}
template <class U>
- int operator()(const U& val) const {
- if (mTarget == val) {
+ int operator()(const U& aVal) const {
+ if (mTarget == aVal) {
return 0;
}
- if (mTarget < val) {
+ if (mTarget < aVal) {
return -1;
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/BufferList.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/BufferList.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/BufferList.h
@@ -0,0 +1,568 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_BufferList_h
+#define mozilla_BufferList_h
+
+#include <algorithm>
+#include "mozilla/AllocPolicy.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Move.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/Types.h"
+#include "mozilla/TypeTraits.h"
+#include "mozilla/Vector.h"
+#include <string.h>
+
+// Undo potential #include <windows.h> damage to be able to use std::min.
+#undef min
+
+// BufferList represents a sequence of buffers of data. A BufferList can choose
+// to own its buffers or not. The class handles writing to the buffers,
+// iterating over them, and reading data out. Unlike SegmentedVector, the
+// buffers may be of unequal size. Like SegmentedVector, BufferList is a nice
+// way to avoid large contiguous allocations (which can trigger OOMs).
+
+namespace mozilla {
+
+template<typename AllocPolicy>
+class BufferList : private AllocPolicy
+{
+ // Each buffer in a BufferList has a size and a capacity. The first mSize
+ // bytes are initialized and the remaining |mCapacity - mSize| bytes are free.
+ struct Segment
+ {
+ char* mData;
+ size_t mSize;
+ size_t mCapacity;
+
+ Segment(char* aData, size_t aSize, size_t aCapacity)
+ : mData(aData),
+ mSize(aSize),
+ mCapacity(aCapacity)
+ {
+ }
+
+ Segment(const Segment&) = delete;
+ Segment& operator=(const Segment&) = delete;
+
+ Segment(Segment&&) = default;
+ Segment& operator=(Segment&&) = default;
+
+ char* Start() const { return mData; }
+ char* End() const { return mData + mSize; }
+ };
+
+ template<typename OtherAllocPolicy>
+ friend class BufferList;
+
+ public:
+ // For the convenience of callers, all segments are required to be a multiple
+ // of 8 bytes in capacity. Also, every buffer except the last one is required
+ // to be full (i.e., size == capacity). Therefore, a byte at offset N within
+ // the BufferList and stored in memory at an address A will satisfy
+ // (N % Align == A % Align) if Align == 2, 4, or 8.
+ static const size_t kSegmentAlignment = 8;
+
+ // Allocate a BufferList. The BufferList will free all its buffers when it is
+ // destroyed. An initial buffer of size aInitialSize and capacity
+ // aInitialCapacity is allocated automatically. This data will be contiguous
+ // an can be accessed via |Start()|. Subsequent buffers will be allocated with
+ // capacity aStandardCapacity.
+ BufferList(size_t aInitialSize,
+ size_t aInitialCapacity,
+ size_t aStandardCapacity,
+ AllocPolicy aAP = AllocPolicy())
+ : AllocPolicy(aAP),
+ mOwning(true),
+ mSegments(aAP),
+ mSize(0),
+ mStandardCapacity(aStandardCapacity)
+ {
+ MOZ_ASSERT(aInitialCapacity % kSegmentAlignment == 0);
+ MOZ_ASSERT(aStandardCapacity % kSegmentAlignment == 0);
+
+ if (aInitialCapacity) {
+ AllocateSegment(aInitialSize, aInitialCapacity);
+ }
+ }
+
+ BufferList(const BufferList& aOther) = delete;
+
+ BufferList(BufferList&& aOther)
+ : mOwning(aOther.mOwning),
+ mSegments(Move(aOther.mSegments)),
+ mSize(aOther.mSize),
+ mStandardCapacity(aOther.mStandardCapacity)
+ {
+ aOther.mSegments.clear();
+ aOther.mSize = 0;
+ }
+
+ BufferList& operator=(const BufferList& aOther) = delete;
+
+ BufferList& operator=(BufferList&& aOther)
+ {
+ Clear();
+
+ mOwning = aOther.mOwning;
+ mSegments = Move(aOther.mSegments);
+ mSize = aOther.mSize;
+ aOther.mSegments.clear();
+ aOther.mSize = 0;
+ return *this;
+ }
+
+ ~BufferList() { Clear(); }
+
+ // Returns the sum of the sizes of all the buffers.
+ size_t Size() const { return mSize; }
+
+ void Clear()
+ {
+ if (mOwning) {
+ for (Segment& segment : mSegments) {
+ this->free_(segment.mData);
+ }
+ }
+ mSegments.clear();
+
+ mSize = 0;
+ }
+
+ // Iterates over bytes in the segments. You can advance it by as many bytes as
+ // you choose.
+ class IterImpl
+ {
+ // Invariants:
+ // (0) mSegment <= bufferList.mSegments.size()
+ // (1) mData <= mDataEnd
+ // (2) If mSegment is not the last segment, mData < mDataEnd
+ uintptr_t mSegment;
+ char* mData;
+ char* mDataEnd;
+
+ friend class BufferList;
+
+ public:
+ explicit IterImpl(const BufferList& aBuffers)
+ : mSegment(0),
+ mData(nullptr),
+ mDataEnd(nullptr)
+ {
+ if (!aBuffers.mSegments.empty()) {
+ mData = aBuffers.mSegments[0].Start();
+ mDataEnd = aBuffers.mSegments[0].End();
+ }
+ }
+
+ // Returns a pointer to the raw data. It is valid to access up to
+ // RemainingInSegment bytes of this buffer.
+ char* Data() const
+ {
+ MOZ_RELEASE_ASSERT(!Done());
+ return mData;
+ }
+
+ // Returns true if the memory in the range [Data(), Data() + aBytes) is all
+ // part of one contiguous buffer.
+ bool HasRoomFor(size_t aBytes) const
+ {
+ MOZ_RELEASE_ASSERT(mData <= mDataEnd);
+ return size_t(mDataEnd - mData) >= aBytes;
+ }
+
+ // Returns the maximum value aBytes for which HasRoomFor(aBytes) will be
+ // true.
+ size_t RemainingInSegment() const
+ {
+ MOZ_RELEASE_ASSERT(mData <= mDataEnd);
+ return mDataEnd - mData;
+ }
+
+ // Advances the iterator by aBytes bytes. aBytes must be less than
+ // RemainingInSegment(). If advancing by aBytes takes the iterator to the
+ // end of a buffer, it will be moved to the beginning of the next buffer
+ // unless it is the last buffer.
+ void Advance(const BufferList& aBuffers, size_t aBytes)
+ {
+ const Segment& segment = aBuffers.mSegments[mSegment];
+ MOZ_RELEASE_ASSERT(segment.Start() <= mData);
+ MOZ_RELEASE_ASSERT(mData <= mDataEnd);
+ MOZ_RELEASE_ASSERT(mDataEnd == segment.End());
+
+ MOZ_RELEASE_ASSERT(HasRoomFor(aBytes));
+ mData += aBytes;
+
+ if (mData == mDataEnd && mSegment + 1 < aBuffers.mSegments.length()) {
+ mSegment++;
+ const Segment& nextSegment = aBuffers.mSegments[mSegment];
+ mData = nextSegment.Start();
+ mDataEnd = nextSegment.End();
+ MOZ_RELEASE_ASSERT(mData < mDataEnd);
+ }
+ }
+
+ // Advance the iterator by aBytes, possibly crossing segments. This function
+ // returns false if it runs out of buffers to advance through. Otherwise it
+ // returns true.
+ bool AdvanceAcrossSegments(const BufferList& aBuffers, size_t aBytes)
+ {
+ size_t bytes = aBytes;
+ while (bytes) {
+ size_t toAdvance = std::min(bytes, RemainingInSegment());
+ if (!toAdvance) {
+ return false;
+ }
+ Advance(aBuffers, toAdvance);
+ bytes -= toAdvance;
+ }
+ return true;
+ }
+
+ // Returns true when the iterator reaches the end of the BufferList.
+ bool Done() const
+ {
+ return mData == mDataEnd;
+ }
+
+ private:
+
+ // Count the bytes we would need to advance in order to reach aTarget.
+ size_t BytesUntil(const BufferList& aBuffers, const IterImpl& aTarget) const {
+ size_t offset = 0;
+
+ MOZ_ASSERT(aTarget.IsIn(aBuffers));
+
+ char* data = mData;
+ for (uintptr_t segment = mSegment; segment < aTarget.mSegment; segment++) {
+ offset += aBuffers.mSegments[segment].End() - data;
+ data = aBuffers.mSegments[segment].mData;
+ }
+
+ MOZ_RELEASE_ASSERT(IsIn(aBuffers));
+ MOZ_RELEASE_ASSERT(aTarget.mData >= data);
+
+ offset += aTarget.mData - data;
+ return offset;
+ }
+
+ bool IsIn(const BufferList& aBuffers) const {
+ return mSegment < aBuffers.mSegments.length() &&
+ mData >= aBuffers.mSegments[mSegment].mData &&
+ mData < aBuffers.mSegments[mSegment].End();
+ }
+ };
+
+ // Special convenience method that returns Iter().Data().
+ char* Start() { return mSegments[0].mData; }
+ const char* Start() const { return mSegments[0].mData; }
+
+ IterImpl Iter() const { return IterImpl(*this); }
+
+ // Copies aSize bytes from aData into the BufferList. The storage for these
+ // bytes may be split across multiple buffers. Size() is increased by aSize.
+ inline bool WriteBytes(const char* aData, size_t aSize);
+
+ // Copies possibly non-contiguous byte range starting at aIter into
+ // aData. aIter is advanced by aSize bytes. Returns false if it runs out of
+ // data before aSize.
+ inline bool ReadBytes(IterImpl& aIter, char* aData, size_t aSize) const;
+
+ // Return a new BufferList that shares storage with this BufferList. The new
+ // BufferList is read-only. It allows iteration over aSize bytes starting at
+ // aIter. Borrow can fail, in which case *aSuccess will be false upon
+ // return. The borrowed BufferList can use a different AllocPolicy than the
+ // original one. However, it is not responsible for freeing buffers, so the
+ // AllocPolicy is only used for the buffer vector.
+ template<typename BorrowingAllocPolicy>
+ BufferList<BorrowingAllocPolicy> Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
+ BorrowingAllocPolicy aAP = BorrowingAllocPolicy()) const;
+
+ // Return a new BufferList and move storage from this BufferList to it. The
+ // new BufferList owns the buffers. Move can fail, in which case *aSuccess
+ // will be false upon return. The new BufferList can use a different
+ // AllocPolicy than the original one. The new OtherAllocPolicy is responsible
+ // for freeing buffers, so the OtherAllocPolicy must use freeing method
+ // compatible to the original one.
+ template<typename OtherAllocPolicy>
+ BufferList<OtherAllocPolicy> MoveFallible(bool* aSuccess, OtherAllocPolicy aAP = OtherAllocPolicy());
+
+ // Return a new BufferList that adopts the byte range starting at Iter so that
+ // range [aIter, aIter + aSize) is transplanted to the returned BufferList.
+ // Contents of the buffer before aIter + aSize is left undefined.
+ // Extract can fail, in which case *aSuccess will be false upon return. The
+ // moved buffers are erased from the original BufferList. In case of extract
+ // fails, the original BufferList is intact. All other iterators except aIter
+ // are invalidated.
+ // This method requires aIter and aSize to be 8-byte aligned.
+ BufferList Extract(IterImpl& aIter, size_t aSize, bool* aSuccess);
+
+ // Return the number of bytes from 'start' to 'end', two iterators within
+ // this BufferList.
+ size_t RangeLength(const IterImpl& start, const IterImpl& end) const {
+ MOZ_ASSERT(start.IsIn(*this) && end.IsIn(*this));
+ return start.BytesUntil(*this, end);
+ }
+
+private:
+ explicit BufferList(AllocPolicy aAP)
+ : AllocPolicy(aAP),
+ mOwning(false),
+ mSize(0),
+ mStandardCapacity(0)
+ {
+ }
+
+ void* AllocateSegment(size_t aSize, size_t aCapacity)
+ {
+ MOZ_RELEASE_ASSERT(mOwning);
+
+ char* data = this->template pod_malloc<char>(aCapacity);
+ if (!data) {
+ return nullptr;
+ }
+ if (!mSegments.append(Segment(data, aSize, aCapacity))) {
+ this->free_(data);
+ return nullptr;
+ }
+ mSize += aSize;
+ return data;
+ }
+
+ bool mOwning;
+ Vector<Segment, 1, AllocPolicy> mSegments;
+ size_t mSize;
+ size_t mStandardCapacity;
+};
+
+template<typename AllocPolicy>
+bool
+BufferList<AllocPolicy>::WriteBytes(const char* aData, size_t aSize)
+{
+ MOZ_RELEASE_ASSERT(mOwning);
+ MOZ_RELEASE_ASSERT(mStandardCapacity);
+
+ size_t copied = 0;
+ size_t remaining = aSize;
+
+ if (!mSegments.empty()) {
+ Segment& lastSegment = mSegments.back();
+
+ size_t toCopy = std::min(aSize, lastSegment.mCapacity - lastSegment.mSize);
+ memcpy(lastSegment.mData + lastSegment.mSize, aData, toCopy);
+ lastSegment.mSize += toCopy;
+ mSize += toCopy;
+
+ copied += toCopy;
+ remaining -= toCopy;
+ }
+
+ while (remaining) {
+ size_t toCopy = std::min(remaining, mStandardCapacity);
+
+ void* data = AllocateSegment(toCopy, mStandardCapacity);
+ if (!data) {
+ return false;
+ }
+ memcpy(data, aData + copied, toCopy);
+
+ copied += toCopy;
+ remaining -= toCopy;
+ }
+
+ return true;
+}
+
+template<typename AllocPolicy>
+bool
+BufferList<AllocPolicy>::ReadBytes(IterImpl& aIter, char* aData, size_t aSize) const
+{
+ size_t copied = 0;
+ size_t remaining = aSize;
+ while (remaining) {
+ size_t toCopy = std::min(aIter.RemainingInSegment(), remaining);
+ if (!toCopy) {
+ // We've run out of data in the last segment.
+ return false;
+ }
+ memcpy(aData + copied, aIter.Data(), toCopy);
+ copied += toCopy;
+ remaining -= toCopy;
+
+ aIter.Advance(*this, toCopy);
+ }
+
+ return true;
+}
+
+template<typename AllocPolicy> template<typename BorrowingAllocPolicy>
+BufferList<BorrowingAllocPolicy>
+BufferList<AllocPolicy>::Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
+ BorrowingAllocPolicy aAP) const
+{
+ BufferList<BorrowingAllocPolicy> result(aAP);
+
+ size_t size = aSize;
+ while (size) {
+ size_t toAdvance = std::min(size, aIter.RemainingInSegment());
+
+ if (!toAdvance || !result.mSegments.append(typename BufferList<BorrowingAllocPolicy>::Segment(aIter.mData, toAdvance, toAdvance))) {
+ *aSuccess = false;
+ return result;
+ }
+ aIter.Advance(*this, toAdvance);
+ size -= toAdvance;
+ }
+
+ result.mSize = aSize;
+ *aSuccess = true;
+ return result;
+}
+
+template<typename AllocPolicy> template<typename OtherAllocPolicy>
+BufferList<OtherAllocPolicy>
+BufferList<AllocPolicy>::MoveFallible(bool* aSuccess, OtherAllocPolicy aAP)
+{
+ BufferList<OtherAllocPolicy> result(0, 0, mStandardCapacity, aAP);
+
+ IterImpl iter = Iter();
+ while (!iter.Done()) {
+ size_t toAdvance = iter.RemainingInSegment();
+
+ if (!toAdvance || !result.mSegments.append(typename BufferList<OtherAllocPolicy>::Segment(iter.mData, toAdvance, toAdvance))) {
+ *aSuccess = false;
+ result.mSegments.clear();
+ return result;
+ }
+ iter.Advance(*this, toAdvance);
+ }
+
+ result.mSize = mSize;
+ mSegments.clear();
+ mSize = 0;
+ *aSuccess = true;
+ return result;
+}
+
+template<typename AllocPolicy>
+BufferList<AllocPolicy>
+BufferList<AllocPolicy>::Extract(IterImpl& aIter, size_t aSize, bool* aSuccess)
+{
+ MOZ_RELEASE_ASSERT(aSize);
+ MOZ_RELEASE_ASSERT(mOwning);
+ MOZ_ASSERT(aSize % kSegmentAlignment == 0);
+ MOZ_ASSERT(intptr_t(aIter.mData) % kSegmentAlignment == 0);
+
+ auto failure = [this, aSuccess]() {
+ *aSuccess = false;
+ return BufferList(0, 0, mStandardCapacity);
+ };
+
+ // Number of segments we'll need to copy data from to satisfy the request.
+ size_t segmentsNeeded = 0;
+ // If this is None then the last segment is a full segment, otherwise we need
+ // to copy this many bytes.
+ Maybe<size_t> lastSegmentSize;
+ {
+ // Copy of the iterator to walk the BufferList and see how many segments we
+ // need to copy.
+ IterImpl iter = aIter;
+ size_t remaining = aSize;
+ while (!iter.Done() && remaining &&
+ remaining >= iter.RemainingInSegment()) {
+ remaining -= iter.RemainingInSegment();
+ iter.Advance(*this, iter.RemainingInSegment());
+ segmentsNeeded++;
+ }
+
+ if (remaining) {
+ if (iter.Done()) {
+ // We reached the end of the BufferList and there wasn't enough data to
+ // satisfy the request.
+ return failure();
+ }
+ lastSegmentSize.emplace(remaining);
+ // The last block also counts as a segment. This makes the conditionals
+ // on segmentsNeeded work in the rest of the function.
+ segmentsNeeded++;
+ }
+ }
+
+ BufferList result(0, 0, mStandardCapacity);
+ if (!result.mSegments.reserve(segmentsNeeded + lastSegmentSize.isSome())) {
+ return failure();
+ }
+
+ // Copy the first segment, it's special because we can't just steal the
+ // entire Segment struct from this->mSegments.
+ size_t firstSegmentSize = std::min(aSize, aIter.RemainingInSegment());
+ if (!result.WriteBytes(aIter.Data(), firstSegmentSize)) {
+ return failure();
+ }
+ aIter.Advance(*this, firstSegmentSize);
+ segmentsNeeded--;
+
+ // The entirety of the request wasn't in the first segment, now copy the
+ // rest.
+ if (segmentsNeeded) {
+ char* finalSegment = nullptr;
+ // Pre-allocate the final segment so that if this fails, we return before
+ // we delete the elements from |this->mSegments|.
+ if (lastSegmentSize.isSome()) {
+ MOZ_RELEASE_ASSERT(mStandardCapacity >= *lastSegmentSize);
+ finalSegment = this->template pod_malloc<char>(mStandardCapacity);
+ if (!finalSegment) {
+ return failure();
+ }
+ }
+
+ size_t copyStart = aIter.mSegment;
+ // Copy segments from this over to the result and remove them from our
+ // storage. Not needed if the only segment we need to copy is the last
+ // partial one.
+ size_t segmentsToCopy = segmentsNeeded - lastSegmentSize.isSome();
+ for (size_t i = 0; i < segmentsToCopy; ++i) {
+ result.mSegments.infallibleAppend(
+ Segment(mSegments[aIter.mSegment].mData,
+ mSegments[aIter.mSegment].mSize,
+ mSegments[aIter.mSegment].mCapacity));
+ aIter.Advance(*this, aIter.RemainingInSegment());
+ }
+ // Due to the way IterImpl works, there are two cases here: (1) if we've
+ // consumed the entirety of the BufferList, then the iterator is pointed at
+ // the end of the final segment, (2) otherwise it is pointed at the start
+ // of the next segment. We want to verify that we really consumed all
+ // |segmentsToCopy| segments.
+ MOZ_RELEASE_ASSERT(
+ (aIter.mSegment == copyStart + segmentsToCopy) ||
+ (aIter.Done() && aIter.mSegment == copyStart + segmentsToCopy - 1));
+ mSegments.erase(mSegments.begin() + copyStart,
+ mSegments.begin() + copyStart + segmentsToCopy);
+
+ // Reset the iter's position for what we just deleted.
+ aIter.mSegment -= segmentsToCopy;
+
+ if (lastSegmentSize.isSome()) {
+ // We called reserve() on result.mSegments so infallibleAppend is safe.
+ result.mSegments.infallibleAppend(
+ Segment(finalSegment, 0, mStandardCapacity));
+ bool r = result.WriteBytes(aIter.Data(), *lastSegmentSize);
+ MOZ_RELEASE_ASSERT(r);
+ aIter.Advance(*this, *lastSegmentSize);
+ }
+ }
+
+ mSize -= aSize;
+ result.mSize = aSize;
+
+ *aSuccess = true;
+ return result;
+}
+
+} // namespace mozilla
+
+#endif /* mozilla_BufferList_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Casting.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Casting.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Casting.h
@@ -17,16 +17,29 @@
namespace mozilla {
/**
- * Return a value of type |To|, containing the underlying bit pattern of
+ * Sets the outparam value of type |To| with the same underlying bit pattern of
* |aFrom|.
*
* |To| and |From| must be types of the same size; be careful of cross-platform
* size differences, or this might fail to compile on some but not all
* platforms.
+ *
+ * There is also a variant that returns the value directly. In most cases, the
+ * two variants should be identical. However, in the specific case of x86
+ * chips, the behavior differs: returning floating-point values directly is done
+ * through the x87 stack, and x87 loads and stores turn signaling NaNs into
+ * quiet NaNs... silently. Returning floating-point values via outparam,
+ * however, is done entirely within the SSE registers when SSE2 floating-point
+ * is enabled in the compiler, which has semantics-preserving behavior you would
+ * expect.
+ *
+ * If preserving the distinction between signaling NaNs and quiet NaNs is
+ * important to you, you should use the outparam version. In all other cases,
+ * you should use the direct return version.
*/
template<typename To, typename From>
-inline To
-BitwiseCast(const From aFrom)
+inline void
+BitwiseCast(const From aFrom, To* aResult)
{
static_assert(sizeof(From) == sizeof(To),
"To and From must have the same size");
@@ -36,7 +49,16 @@
To mTo;
} u;
u.mFrom = aFrom;
- return u.mTo;
+ *aResult = u.mTo;
+}
+
+template<typename To, typename From>
+inline To
+BitwiseCast(const From aFrom)
+{
+ To temp;
+ BitwiseCast<To, From>(aFrom, &temp);
+ return temp;
}
namespace detail {
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ChaosMode.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ChaosMode.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ChaosMode.h
@@ -27,6 +27,8 @@
IOAmounts = 0x8,
// Iterate over hash tables in random order.
HashTableIteration = 0x10,
+ // Randomly refuse to use cached version of image (when allowed by spec).
+ ImageCache = 0x20,
Any = 0xffffffff,
};
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Char16.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Char16.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Char16.h
@@ -17,38 +17,8 @@
* is a 16-bit code unit of a Unicode code point, not a "character".
*/
-#if defined(_MSC_VER) && _MSC_VER < 1900
- /*
- * C++11 says char16_t is a distinct builtin type, but Windows's yvals.h
- * typedefs char16_t as an unsigned short prior to MSVC 2015, which
- * implemented C++11's distinct char16_t type. We would like to alias
- * char16_t to Windows's 16-bit wchar_t so we can declare UTF-16 literals as
- * constant expressions (and pass char16_t pointers to Windows APIs). We
- * #define _CHAR16T here in order to prevent yvals.h from overriding our
- * char16_t typedefs, which we set to wchar_t for C++ code.
- *
- * In addition, #defining _CHAR16T will prevent yvals.h from defining a
- * char32_t type, so we have to undo that damage here and provide our own,
- * which is identical to the yvals.h type.
- */
-# define MOZ_UTF16_HELPER(s) L##s
-# define _CHAR16T
-typedef wchar_t char16_t;
-typedef unsigned int char32_t;
-#else
- /* C++11 has a builtin char16_t type. */
-# define MOZ_UTF16_HELPER(s) u##s
- /**
- * This macro is used to distinguish when char16_t would be a distinct
- * typedef from wchar_t.
- */
-# define MOZ_CHAR16_IS_NOT_WCHAR
-# ifdef WIN32
-# define MOZ_USE_CHAR16_WRAPPER
-# endif
-#endif
-
-#ifdef MOZ_USE_CHAR16_WRAPPER
+#ifdef WIN32
+# define MOZ_USE_CHAR16_WRAPPER
# include <cstdint>
/**
* Win32 API extensively uses wchar_t, which is represented by a separated
@@ -214,20 +184,10 @@
#endif
-/*
- * Macro arguments used in concatenation or stringification won't be expanded.
- * Therefore, in order for |MOZ_UTF16(FOO)| to work as expected (which is to
- * expand |FOO| before doing whatever |MOZ_UTF16| needs to do to it) a helper
- * macro, |MOZ_UTF16_HELPER| needs to be inserted in between to allow the macro
- * argument to expand. See "3.10.6 Separate Expansion of Macro Arguments" of the
- * CPP manual for a more accurate and precise explanation.
- */
-#define MOZ_UTF16(s) MOZ_UTF16_HELPER(s)
-
static_assert(sizeof(char16_t) == 2, "Is char16_t type 16 bits?");
static_assert(char16_t(-1) > char16_t(0), "Is char16_t type unsigned?");
-static_assert(sizeof(MOZ_UTF16('A')) == 2, "Is char literal 16 bits?");
-static_assert(sizeof(MOZ_UTF16("")[0]) == 2, "Is string char 16 bits?");
+static_assert(sizeof(u'A') == 2, "Is unicode char literal 16 bits?");
+static_assert(sizeof(u""[0]) == 2, "Is unicode string char 16 bits?");
#endif
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Compiler.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Compiler.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Compiler.h
@@ -10,21 +10,24 @@
#define mozilla_Compiler_h
#define MOZ_IS_GCC 0
-#define MOS_IS_MSVC 0
+#define MOZ_IS_MSVC 0
#if !defined(__clang__) && defined(__GNUC__)
# undef MOZ_IS_GCC
# define MOZ_IS_GCC 1
/*
- * This macro should simplify gcc version checking. For example, to check
+ * These macros should simplify gcc version checking. For example, to check
* for gcc 4.7.1 or later, check `#if MOZ_GCC_VERSION_AT_LEAST(4, 7, 1)`.
*/
# define MOZ_GCC_VERSION_AT_LEAST(major, minor, patchlevel) \
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
>= ((major) * 10000 + (minor) * 100 + (patchlevel)))
-# if !MOZ_GCC_VERSION_AT_LEAST(4, 7, 0)
-# error "mfbt (and Gecko) require at least gcc 4.7 to build."
+# define MOZ_GCC_VERSION_AT_MOST(major, minor, patchlevel) \
+ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
+ <= ((major) * 10000 + (minor) * 100 + (patchlevel)))
+# if !MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
+# error "mfbt (and Gecko) require at least gcc 4.8 to build."
# endif
#elif defined(_MSC_VER)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Compression.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Compression.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Compression.h
@@ -61,8 +61,7 @@
/**
* If the source stream is malformed, the function will stop decoding
- * and return a negative result, indicating the byte position of the
- * faulty instruction
+ * and return false.
*
* This function never writes outside of provided buffers, and never
* modifies input buffer.
@@ -71,9 +70,9 @@
* minimum of |aOutputSize| bytes.
*
* @param aOutputSize is the output size, therefore the original size
- * @return the number of bytes read in the source buffer
+ * @return true on success, false on failure
*/
- static MFBT_API bool
+ static MFBT_API MOZ_MUST_USE bool
decompress(const char* aSource, char* aDest, size_t aOutputSize);
/**
@@ -91,8 +90,9 @@
* already allocated)
* @param aOutputSize the actual number of bytes decoded in the destination
* buffer (necessarily <= aMaxOutputSize)
+ * @return true on success, false on failure
*/
- static MFBT_API bool
+ static MFBT_API MOZ_MUST_USE bool
decompress(const char* aSource, size_t aInputSize, char* aDest,
size_t aMaxOutputSize, size_t* aOutputSize);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/DebugOnly.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/DebugOnly.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/DebugOnly.h
@@ -24,17 +24,19 @@
* DebugOnly<bool> check = func();
* MOZ_ASSERT(check);
*
- * more concisely than declaring |check| conditional on #ifdef DEBUG, but also
- * without allocating storage space for |check| in release builds.
+ * more concisely than declaring |check| conditional on #ifdef DEBUG.
*
* DebugOnly instances can only be coerced to T in debug builds. In release
* builds they don't have a value, so type coercion is not well defined.
*
- * Note that DebugOnly instances still take up one byte of space, plus padding,
- * when used as members of structs.
+ * NOTE: DebugOnly instances still take up one byte of space, plus padding, even
+ * in optimized, non-DEBUG builds (see bug 1253094 comment 37 for more info).
+ * For this reason the class is MOZ_STACK_CLASS to prevent consumers using
+ * DebugOnly for struct/class members and unwittingly inflating the size of
+ * their objects in release builds.
*/
template<typename T>
-class DebugOnly
+class MOZ_STACK_CLASS DebugOnly
{
public:
#ifdef DEBUG
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Decimal.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Decimal.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Decimal.h
@@ -30,8 +30,8 @@
/**
* Imported from:
- * http://src.chromium.org/viewvc/blink/trunk/Source/core/platform/Decimal.h
- * Check hg log for the svn rev of the last update from Blink core.
+ * https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/platform/Decimal.h
+ * Check UPSTREAM-GIT-SHA for the commit ID of the last update from Blink core.
*/
#ifndef Decimal_h
@@ -48,25 +48,33 @@
#define ASSERT MOZ_ASSERT
#endif
-// To use WTF_MAKE_FAST_ALLOCATED we'd need:
-// http://src.chromium.org/viewvc/blink/trunk/Source/wtf/FastMalloc.h
+#define PLATFORM_EXPORT
+
+// To use USING_FAST_MALLOC we'd need:
+// https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/wtf/Allocator.h
// Since we don't allocate Decimal objects, no need.
-#define WTF_MAKE_FAST_ALLOCATED \
+#define USING_FAST_MALLOC(type) \
void ignore_this_dummy_method() = delete
-namespace WebCore {
+#define DISALLOW_NEW() \
+ private: \
+ void* operator new(size_t) = delete; \
+ void* operator new(size_t, void*) = delete; \
+ public:
+
+namespace blink {
namespace DecimalPrivate {
class SpecialValueHandler;
-} // namespace DecimalPrivate
+}
// This class represents decimal base floating point number.
//
// FIXME: Once all C++ compiler support decimal type, we should replace this
// class to compiler supported one. See below URI for current status of decimal
// type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
-class Decimal {
- WTF_MAKE_FAST_ALLOCATED;
+class PLATFORM_EXPORT Decimal {
+ USING_FAST_MALLOC(Decimal);
public:
enum Sign {
Positive,
@@ -75,6 +83,7 @@
// You should not use EncodedData other than unit testing.
class EncodedData {
+ DISALLOW_NEW();
// For accessing FormatClass.
friend class Decimal;
friend class DecimalPrivate::SpecialValueHandler;
@@ -93,7 +102,7 @@
bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; }
bool isZero() const { return m_formatClass == ClassZero; }
Sign sign() const { return m_sign; }
- void setSign(Sign aSign) { m_sign = aSign; }
+ void setSign(Sign sign) { m_sign = sign; }
private:
enum FormatClass {
@@ -151,7 +160,7 @@
bool isZero() const { return m_data.isZero(); }
MFBT_API Decimal abs() const;
- MFBT_API Decimal ceiling() const;
+ MFBT_API Decimal ceil() const;
MFBT_API Decimal floor() const;
MFBT_API Decimal remainder(const Decimal&) const;
MFBT_API Decimal round() const;
@@ -196,13 +205,13 @@
EncodedData m_data;
};
-} // namespace WebCore
+} // namespace blink
namespace mozilla {
- typedef WebCore::Decimal Decimal;
+typedef blink::Decimal Decimal;
} // namespace mozilla
-#undef WTF_MAKE_FAST_ALLOCATED
+#undef USING_FAST_MALLOC
#ifdef DEFINED_ASSERT_FOR_DECIMAL_H
#undef DEFINED_ASSERT_FOR_DECIMAL_H
@@ -210,4 +219,3 @@
#endif
#endif // Decimal_h
-
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Endian.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Endian.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Endian.h
@@ -1,697 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/* Functions for reading and writing integers in various endiannesses. */
-
-/*
- * The classes LittleEndian and BigEndian expose static methods for
- * reading and writing 16-, 32-, and 64-bit signed and unsigned integers
- * in their respective endianness. The naming scheme is:
- *
- * {Little,Big}Endian::{read,write}{Uint,Int}<bitsize>
- *
- * For instance, LittleEndian::readInt32 will read a 32-bit signed
- * integer from memory in little endian format. Similarly,
- * BigEndian::writeUint16 will write a 16-bit unsigned integer to memory
- * in big-endian format.
- *
- * The class NativeEndian exposes methods for conversion of existing
- * data to and from the native endianness. These methods are intended
- * for cases where data needs to be transferred, serialized, etc.
- * swap{To,From}{Little,Big}Endian byteswap a single value if necessary.
- * Bulk conversion functions are also provided which optimize the
- * no-conversion-needed case:
- *
- * - copyAndSwap{To,From}{Little,Big}Endian;
- * - swap{To,From}{Little,Big}EndianInPlace.
- *
- * The *From* variants are intended to be used for reading data and the
- * *To* variants for writing data.
- *
- * Methods on NativeEndian work with integer data of any type.
- * Floating-point data is not supported.
- *
- * For clarity in networking code, "Network" may be used as a synonym
- * for "Big" in any of the above methods or class names.
- *
- * As an example, reading a file format header whose fields are stored
- * in big-endian format might look like:
- *
- * class ExampleHeader
- * {
- * private:
- * uint32_t mMagic;
- * uint32_t mLength;
- * uint32_t mTotalRecords;
- * uint64_t mChecksum;
- *
- * public:
- * ExampleHeader(const void* data)
- * {
- * const uint8_t* ptr = static_cast<const uint8_t*>(data);
- * mMagic = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
- * mLength = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
- * mTotalRecords = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
- * mChecksum = BigEndian::readUint64(ptr);
- * }
- * ...
- * };
- */
-
-#ifndef mozilla_Endian_h
-#define mozilla_Endian_h
-
-#include "mozilla/Assertions.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/Compiler.h"
-#include "mozilla/DebugOnly.h"
-#include "mozilla/TypeTraits.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#if defined(_MSC_VER)
-# include <stdlib.h>
-# pragma intrinsic(_byteswap_ushort)
-# pragma intrinsic(_byteswap_ulong)
-# pragma intrinsic(_byteswap_uint64)
-#endif
-
-#if defined(_WIN64)
-# if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
-# define MOZ_LITTLE_ENDIAN 1
-# else
-# error "CPU type is unknown"
-# endif
-#elif defined(_WIN32)
-# if defined(_M_IX86)
-# define MOZ_LITTLE_ENDIAN 1
-# elif defined(_M_ARM)
-# define MOZ_LITTLE_ENDIAN 1
-# else
-# error "CPU type is unknown"
-# endif
-#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__) && \
- defined(__ORDER_BIG_ENDIAN__)
- /*
- * Some versions of GCC provide architecture-independent macros for
- * this. Yes, there are more than two values for __BYTE_ORDER__.
- */
-# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-# define MOZ_LITTLE_ENDIAN 1
-# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-# define MOZ_BIG_ENDIAN 1
-# else
-# error "Can't handle mixed-endian architectures"
-# 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(__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__) || \
- defined(__alpha__) || defined(__AARCH64EL__) || \
- (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
- (defined(__ia64) && !defined(__BIG_ENDIAN__))
-# define MOZ_LITTLE_ENDIAN 1
-#endif
-
-#if MOZ_BIG_ENDIAN
-# define MOZ_LITTLE_ENDIAN 0
-#elif MOZ_LITTLE_ENDIAN
-# define MOZ_BIG_ENDIAN 0
-#else
-# error "Cannot determine endianness"
-#endif
-
-#if defined(__clang__)
-# if __has_builtin(__builtin_bswap16)
-# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
-# endif
-#elif defined(__GNUC__)
-# if MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
-# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
-# endif
-#elif defined(_MSC_VER)
-# define MOZ_HAVE_BUILTIN_BYTESWAP16 _byteswap_ushort
-#endif
-
-namespace mozilla {
-
-namespace detail {
-
-/*
- * We need wrappers here because free functions with default template
- * arguments and/or partial specialization of function templates are not
- * supported by all the compilers we use.
- */
-template<typename T, size_t Size = sizeof(T)>
-struct Swapper;
-
-template<typename T>
-struct Swapper<T, 2>
-{
- static T swap(T aValue)
- {
-#if defined(MOZ_HAVE_BUILTIN_BYTESWAP16)
- return MOZ_HAVE_BUILTIN_BYTESWAP16(aValue);
-#else
- return T(((aValue & 0x00ff) << 8) | ((aValue & 0xff00) >> 8));
-#endif
- }
-};
-
-template<typename T>
-struct Swapper<T, 4>
-{
- static T swap(T aValue)
- {
-#if defined(__clang__) || defined(__GNUC__)
- return T(__builtin_bswap32(aValue));
-#elif defined(_MSC_VER)
- return T(_byteswap_ulong(aValue));
-#else
- return T(((aValue & 0x000000ffU) << 24) |
- ((aValue & 0x0000ff00U) << 8) |
- ((aValue & 0x00ff0000U) >> 8) |
- ((aValue & 0xff000000U) >> 24));
-#endif
- }
-};
-
-template<typename T>
-struct Swapper<T, 8>
-{
- static inline T swap(T aValue)
- {
-#if defined(__clang__) || defined(__GNUC__)
- return T(__builtin_bswap64(aValue));
-#elif defined(_MSC_VER)
- return T(_byteswap_uint64(aValue));
-#else
- return T(((aValue & 0x00000000000000ffULL) << 56) |
- ((aValue & 0x000000000000ff00ULL) << 40) |
- ((aValue & 0x0000000000ff0000ULL) << 24) |
- ((aValue & 0x00000000ff000000ULL) << 8) |
- ((aValue & 0x000000ff00000000ULL) >> 8) |
- ((aValue & 0x0000ff0000000000ULL) >> 24) |
- ((aValue & 0x00ff000000000000ULL) >> 40) |
- ((aValue & 0xff00000000000000ULL) >> 56));
-#endif
- }
-};
-
-enum Endianness { Little, Big };
-
-#if MOZ_BIG_ENDIAN
-# define MOZ_NATIVE_ENDIANNESS detail::Big
-#else
-# define MOZ_NATIVE_ENDIANNESS detail::Little
-#endif
-
-class EndianUtils
-{
- /**
- * Assert that the memory regions [aDest, aDest+aCount) and
- * [aSrc, aSrc+aCount] do not overlap. aCount is given in bytes.
- */
- static void assertNoOverlap(const void* aDest, const void* aSrc,
- size_t aCount)
- {
- DebugOnly<const uint8_t*> byteDestPtr = static_cast<const uint8_t*>(aDest);
- DebugOnly<const uint8_t*> byteSrcPtr = static_cast<const uint8_t*>(aSrc);
- MOZ_ASSERT((byteDestPtr <= byteSrcPtr &&
- byteDestPtr + aCount <= byteSrcPtr) ||
- (byteSrcPtr <= byteDestPtr &&
- byteSrcPtr + aCount <= byteDestPtr));
- }
-
- template<typename T>
- static void assertAligned(T* aPtr)
- {
- MOZ_ASSERT((uintptr_t(aPtr) % sizeof(T)) == 0, "Unaligned pointer!");
- }
-
-protected:
- /**
- * Return |aValue| converted from SourceEndian encoding to DestEndian
- * encoding.
- */
- template<Endianness SourceEndian, Endianness DestEndian, typename T>
- static inline T maybeSwap(T aValue)
- {
- if (SourceEndian == DestEndian) {
- return aValue;
- }
- return Swapper<T>::swap(aValue);
- }
-
- /**
- * Convert |aCount| elements at |aPtr| from SourceEndian encoding to
- * DestEndian encoding.
- */
- template<Endianness SourceEndian, Endianness DestEndian, typename T>
- static inline void maybeSwapInPlace(T* aPtr, size_t aCount)
- {
- assertAligned(aPtr);
-
- if (SourceEndian == DestEndian) {
- return;
- }
- for (size_t i = 0; i < aCount; i++) {
- aPtr[i] = Swapper<T>::swap(aPtr[i]);
- }
- }
-
- /**
- * Write |aCount| elements to the unaligned address |aDest| in DestEndian
- * format, using elements found at |aSrc| in SourceEndian format.
- */
- template<Endianness SourceEndian, Endianness DestEndian, typename T>
- static void copyAndSwapTo(void* aDest, const T* aSrc, size_t aCount)
- {
- assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
- assertAligned(aSrc);
-
- if (SourceEndian == DestEndian) {
- memcpy(aDest, aSrc, aCount * sizeof(T));
- return;
- }
-
- uint8_t* byteDestPtr = static_cast<uint8_t*>(aDest);
- for (size_t i = 0; i < aCount; ++i) {
- union
- {
- T mVal;
- uint8_t mBuffer[sizeof(T)];
- } u;
- u.mVal = maybeSwap<SourceEndian, DestEndian>(aSrc[i]);
- memcpy(byteDestPtr, u.mBuffer, sizeof(T));
- byteDestPtr += sizeof(T);
- }
- }
-
- /**
- * Write |aCount| elements to |aDest| in DestEndian format, using elements
- * found at the unaligned address |aSrc| in SourceEndian format.
- */
- template<Endianness SourceEndian, Endianness DestEndian, typename T>
- static void copyAndSwapFrom(T* aDest, const void* aSrc, size_t aCount)
- {
- assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
- assertAligned(aDest);
-
- if (SourceEndian == DestEndian) {
- memcpy(aDest, aSrc, aCount * sizeof(T));
- return;
- }
-
- const uint8_t* byteSrcPtr = static_cast<const uint8_t*>(aSrc);
- for (size_t i = 0; i < aCount; ++i) {
- union
- {
- T mVal;
- uint8_t mBuffer[sizeof(T)];
- } u;
- memcpy(u.mBuffer, byteSrcPtr, sizeof(T));
- aDest[i] = maybeSwap<SourceEndian, DestEndian>(u.mVal);
- byteSrcPtr += sizeof(T);
- }
- }
-};
-
-template<Endianness ThisEndian>
-class Endian : private EndianUtils
-{
-protected:
- /** Read a uint16_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT uint16_t readUint16(const void* aPtr)
- {
- return read<uint16_t>(aPtr);
- }
-
- /** Read a uint32_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT uint32_t readUint32(const void* aPtr)
- {
- return read<uint32_t>(aPtr);
- }
-
- /** Read a uint64_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT uint64_t readUint64(const void* aPtr)
- {
- return read<uint64_t>(aPtr);
- }
-
- /** Read an int16_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT int16_t readInt16(const void* aPtr)
- {
- return read<int16_t>(aPtr);
- }
-
- /** Read an int32_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT int32_t readInt32(const void* aPtr)
- {
- return read<uint32_t>(aPtr);
- }
-
- /** Read an int64_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT int64_t readInt64(const void* aPtr)
- {
- return read<int64_t>(aPtr);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeUint16(void* aPtr, uint16_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeUint32(void* aPtr, uint32_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeUint64(void* aPtr, uint64_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeInt16(void* aPtr, int16_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeInt32(void* aPtr, int32_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeInt64(void* aPtr, int64_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /*
- * Converts a value of type T to little-endian format.
- *
- * This function is intended for cases where you have data in your
- * native-endian format and you need it to appear in little-endian
- * format for transmission.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapToLittleEndian(T aValue)
- {
- return maybeSwap<ThisEndian, Little>(aValue);
- }
-
- /*
- * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
- * them to little-endian format if ThisEndian is Big.
- * As with memcpy, |aDest| and |aSrc| must not overlap.
- */
- template<typename T>
- static void copyAndSwapToLittleEndian(void* aDest, const T* aSrc,
- size_t aCount)
- {
- copyAndSwapTo<ThisEndian, Little>(aDest, aSrc, aCount);
- }
-
- /*
- * Likewise, but converts values in place.
- */
- template<typename T>
- static void swapToLittleEndianInPlace(T* aPtr, size_t aCount)
- {
- maybeSwapInPlace<ThisEndian, Little>(aPtr, aCount);
- }
-
- /*
- * Converts a value of type T to big-endian format.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapToBigEndian(T aValue)
- {
- return maybeSwap<ThisEndian, Big>(aValue);
- }
-
- /*
- * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
- * them to big-endian format if ThisEndian is Little.
- * As with memcpy, |aDest| and |aSrc| must not overlap.
- */
- template<typename T>
- static void copyAndSwapToBigEndian(void* aDest, const T* aSrc,
- size_t aCount)
- {
- copyAndSwapTo<ThisEndian, Big>(aDest, aSrc, aCount);
- }
-
- /*
- * Likewise, but converts values in place.
- */
- template<typename T>
- static void swapToBigEndianInPlace(T* aPtr, size_t aCount)
- {
- maybeSwapInPlace<ThisEndian, Big>(aPtr, aCount);
- }
-
- /*
- * Synonyms for the big-endian functions, for better readability
- * in network code.
- */
-
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapToNetworkOrder(T aValue)
- {
- return swapToBigEndian(aValue);
- }
-
- template<typename T>
- static void
- copyAndSwapToNetworkOrder(void* aDest, const T* aSrc, size_t aCount)
- {
- copyAndSwapToBigEndian(aDest, aSrc, aCount);
- }
-
- template<typename T>
- static void
- swapToNetworkOrderInPlace(T* aPtr, size_t aCount)
- {
- swapToBigEndianInPlace(aPtr, aCount);
- }
-
- /*
- * Converts a value of type T from little-endian format.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapFromLittleEndian(T aValue)
- {
- return maybeSwap<Little, ThisEndian>(aValue);
- }
-
- /*
- * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
- * them to little-endian format if ThisEndian is Big.
- * As with memcpy, |aDest| and |aSrc| must not overlap.
- */
- template<typename T>
- static void copyAndSwapFromLittleEndian(T* aDest, const void* aSrc,
- size_t aCount)
- {
- copyAndSwapFrom<Little, ThisEndian>(aDest, aSrc, aCount);
- }
-
- /*
- * Likewise, but converts values in place.
- */
- template<typename T>
- static void swapFromLittleEndianInPlace(T* aPtr, size_t aCount)
- {
- maybeSwapInPlace<Little, ThisEndian>(aPtr, aCount);
- }
-
- /*
- * Converts a value of type T from big-endian format.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapFromBigEndian(T aValue)
- {
- return maybeSwap<Big, ThisEndian>(aValue);
- }
-
- /*
- * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
- * them to big-endian format if ThisEndian is Little.
- * As with memcpy, |aDest| and |aSrc| must not overlap.
- */
- template<typename T>
- static void copyAndSwapFromBigEndian(T* aDest, const void* aSrc,
- size_t aCount)
- {
- copyAndSwapFrom<Big, ThisEndian>(aDest, aSrc, aCount);
- }
-
- /*
- * Likewise, but converts values in place.
- */
- template<typename T>
- static void swapFromBigEndianInPlace(T* aPtr, size_t aCount)
- {
- maybeSwapInPlace<Big, ThisEndian>(aPtr, aCount);
- }
-
- /*
- * Synonyms for the big-endian functions, for better readability
- * in network code.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapFromNetworkOrder(T aValue)
- {
- return swapFromBigEndian(aValue);
- }
-
- template<typename T>
- static void copyAndSwapFromNetworkOrder(T* aDest, const void* aSrc,
- size_t aCount)
- {
- copyAndSwapFromBigEndian(aDest, aSrc, aCount);
- }
-
- template<typename T>
- static void swapFromNetworkOrderInPlace(T* aPtr, size_t aCount)
- {
- swapFromBigEndianInPlace(aPtr, aCount);
- }
-
-private:
- /**
- * Read a value of type T, encoded in endianness ThisEndian from |aPtr|.
- * Return that value encoded in native endianness.
- */
- template<typename T>
- static T read(const void* aPtr)
- {
- union
- {
- T mVal;
- uint8_t mBuffer[sizeof(T)];
- } u;
- memcpy(u.mBuffer, aPtr, sizeof(T));
- return maybeSwap<ThisEndian, MOZ_NATIVE_ENDIANNESS>(u.mVal);
- }
-
- /**
- * Write a value of type T, in native endianness, to |aPtr|, in ThisEndian
- * endianness.
- */
- template<typename T>
- static void write(void* aPtr, T aValue)
- {
- T tmp = maybeSwap<MOZ_NATIVE_ENDIANNESS, ThisEndian>(aValue);
- memcpy(aPtr, &tmp, sizeof(T));
- }
-
- Endian() = delete;
- Endian(const Endian& aTther) = delete;
- void operator=(const Endian& aOther) = delete;
-};
-
-template<Endianness ThisEndian>
-class EndianReadWrite : public Endian<ThisEndian>
-{
-private:
- typedef Endian<ThisEndian> super;
-
-public:
- using super::readUint16;
- using super::readUint32;
- using super::readUint64;
- using super::readInt16;
- using super::readInt32;
- using super::readInt64;
- using super::writeUint16;
- using super::writeUint32;
- using super::writeUint64;
- using super::writeInt16;
- using super::writeInt32;
- using super::writeInt64;
-};
-
-} /* namespace detail */
-
-class LittleEndian final : public detail::EndianReadWrite<detail::Little>
-{};
-
-class BigEndian final : public detail::EndianReadWrite<detail::Big>
-{};
-
-typedef BigEndian NetworkEndian;
-
-class NativeEndian final : public detail::Endian<MOZ_NATIVE_ENDIANNESS>
-{
-private:
- typedef detail::Endian<MOZ_NATIVE_ENDIANNESS> super;
-
-public:
- /*
- * These functions are intended for cases where you have data in your
- * native-endian format and you need the data to appear in the appropriate
- * endianness for transmission, serialization, etc.
- */
- using super::swapToLittleEndian;
- using super::copyAndSwapToLittleEndian;
- using super::swapToLittleEndianInPlace;
- using super::swapToBigEndian;
- using super::copyAndSwapToBigEndian;
- using super::swapToBigEndianInPlace;
- using super::swapToNetworkOrder;
- using super::copyAndSwapToNetworkOrder;
- using super::swapToNetworkOrderInPlace;
-
- /*
- * These functions are intended for cases where you have data in the
- * given endianness (e.g. reading from disk or a file-format) and you
- * need the data to appear in native-endian format for processing.
- */
- using super::swapFromLittleEndian;
- using super::copyAndSwapFromLittleEndian;
- using super::swapFromLittleEndianInPlace;
- using super::swapFromBigEndian;
- using super::copyAndSwapFromBigEndian;
- using super::swapFromBigEndianInPlace;
- using super::swapFromNetworkOrder;
- using super::copyAndSwapFromNetworkOrder;
- using super::swapFromNetworkOrderInPlace;
-};
-
-#undef MOZ_NATIVE_ENDIANNESS
-
-} /* namespace mozilla */
-
-#endif /* mozilla_Endian_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EndianUtils.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EndianUtils.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EndianUtils.h
@@ -0,0 +1,695 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Functions for reading and writing integers in various endiannesses. */
+
+/*
+ * The classes LittleEndian and BigEndian expose static methods for
+ * reading and writing 16-, 32-, and 64-bit signed and unsigned integers
+ * in their respective endianness. The naming scheme is:
+ *
+ * {Little,Big}Endian::{read,write}{Uint,Int}<bitsize>
+ *
+ * For instance, LittleEndian::readInt32 will read a 32-bit signed
+ * integer from memory in little endian format. Similarly,
+ * BigEndian::writeUint16 will write a 16-bit unsigned integer to memory
+ * in big-endian format.
+ *
+ * The class NativeEndian exposes methods for conversion of existing
+ * data to and from the native endianness. These methods are intended
+ * for cases where data needs to be transferred, serialized, etc.
+ * swap{To,From}{Little,Big}Endian byteswap a single value if necessary.
+ * Bulk conversion functions are also provided which optimize the
+ * no-conversion-needed case:
+ *
+ * - copyAndSwap{To,From}{Little,Big}Endian;
+ * - swap{To,From}{Little,Big}EndianInPlace.
+ *
+ * The *From* variants are intended to be used for reading data and the
+ * *To* variants for writing data.
+ *
+ * Methods on NativeEndian work with integer data of any type.
+ * Floating-point data is not supported.
+ *
+ * For clarity in networking code, "Network" may be used as a synonym
+ * for "Big" in any of the above methods or class names.
+ *
+ * As an example, reading a file format header whose fields are stored
+ * in big-endian format might look like:
+ *
+ * class ExampleHeader
+ * {
+ * private:
+ * uint32_t mMagic;
+ * uint32_t mLength;
+ * uint32_t mTotalRecords;
+ * uint64_t mChecksum;
+ *
+ * public:
+ * ExampleHeader(const void* data)
+ * {
+ * const uint8_t* ptr = static_cast<const uint8_t*>(data);
+ * mMagic = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
+ * mLength = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
+ * mTotalRecords = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
+ * mChecksum = BigEndian::readUint64(ptr);
+ * }
+ * ...
+ * };
+ */
+
+#ifndef mozilla_EndianUtils_h
+#define mozilla_EndianUtils_h
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Compiler.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/TypeTraits.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+# include <stdlib.h>
+# pragma intrinsic(_byteswap_ushort)
+# pragma intrinsic(_byteswap_ulong)
+# pragma intrinsic(_byteswap_uint64)
+#endif
+
+#if defined(_WIN64)
+# if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
+# define MOZ_LITTLE_ENDIAN 1
+# else
+# error "CPU type is unknown"
+# endif
+#elif defined(_WIN32)
+# if defined(_M_IX86)
+# define MOZ_LITTLE_ENDIAN 1
+# elif defined(_M_ARM)
+# define MOZ_LITTLE_ENDIAN 1
+# else
+# error "CPU type is unknown"
+# endif
+#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__) && \
+ defined(__ORDER_BIG_ENDIAN__)
+ /*
+ * Some versions of GCC provide architecture-independent macros for
+ * this. Yes, there are more than two values for __BYTE_ORDER__.
+ */
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define MOZ_LITTLE_ENDIAN 1
+# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define MOZ_BIG_ENDIAN 1
+# else
+# error "Can't handle mixed-endian architectures"
+# 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(__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__) || \
+ defined(__alpha__) || defined(__AARCH64EL__) || \
+ (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
+ (defined(__ia64) && !defined(__BIG_ENDIAN__))
+# define MOZ_LITTLE_ENDIAN 1
+#endif
+
+#if MOZ_BIG_ENDIAN
+# define MOZ_LITTLE_ENDIAN 0
+#elif MOZ_LITTLE_ENDIAN
+# define MOZ_BIG_ENDIAN 0
+#else
+# error "Cannot determine endianness"
+#endif
+
+#if defined(__clang__)
+# if __has_builtin(__builtin_bswap16)
+# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
+# endif
+#elif defined(__GNUC__)
+# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
+#elif defined(_MSC_VER)
+# define MOZ_HAVE_BUILTIN_BYTESWAP16 _byteswap_ushort
+#endif
+
+namespace mozilla {
+
+namespace detail {
+
+/*
+ * We need wrappers here because free functions with default template
+ * arguments and/or partial specialization of function templates are not
+ * supported by all the compilers we use.
+ */
+template<typename T, size_t Size = sizeof(T)>
+struct Swapper;
+
+template<typename T>
+struct Swapper<T, 2>
+{
+ static T swap(T aValue)
+ {
+#if defined(MOZ_HAVE_BUILTIN_BYTESWAP16)
+ return MOZ_HAVE_BUILTIN_BYTESWAP16(aValue);
+#else
+ return T(((aValue & 0x00ff) << 8) | ((aValue & 0xff00) >> 8));
+#endif
+ }
+};
+
+template<typename T>
+struct Swapper<T, 4>
+{
+ static T swap(T aValue)
+ {
+#if defined(__clang__) || defined(__GNUC__)
+ return T(__builtin_bswap32(aValue));
+#elif defined(_MSC_VER)
+ return T(_byteswap_ulong(aValue));
+#else
+ return T(((aValue & 0x000000ffU) << 24) |
+ ((aValue & 0x0000ff00U) << 8) |
+ ((aValue & 0x00ff0000U) >> 8) |
+ ((aValue & 0xff000000U) >> 24));
+#endif
+ }
+};
+
+template<typename T>
+struct Swapper<T, 8>
+{
+ static inline T swap(T aValue)
+ {
+#if defined(__clang__) || defined(__GNUC__)
+ return T(__builtin_bswap64(aValue));
+#elif defined(_MSC_VER)
+ return T(_byteswap_uint64(aValue));
+#else
+ return T(((aValue & 0x00000000000000ffULL) << 56) |
+ ((aValue & 0x000000000000ff00ULL) << 40) |
+ ((aValue & 0x0000000000ff0000ULL) << 24) |
+ ((aValue & 0x00000000ff000000ULL) << 8) |
+ ((aValue & 0x000000ff00000000ULL) >> 8) |
+ ((aValue & 0x0000ff0000000000ULL) >> 24) |
+ ((aValue & 0x00ff000000000000ULL) >> 40) |
+ ((aValue & 0xff00000000000000ULL) >> 56));
+#endif
+ }
+};
+
+enum Endianness { Little, Big };
+
+#if MOZ_BIG_ENDIAN
+# define MOZ_NATIVE_ENDIANNESS detail::Big
+#else
+# define MOZ_NATIVE_ENDIANNESS detail::Little
+#endif
+
+class EndianUtils
+{
+ /**
+ * Assert that the memory regions [aDest, aDest+aCount) and
+ * [aSrc, aSrc+aCount] do not overlap. aCount is given in bytes.
+ */
+ static void assertNoOverlap(const void* aDest, const void* aSrc,
+ size_t aCount)
+ {
+ DebugOnly<const uint8_t*> byteDestPtr = static_cast<const uint8_t*>(aDest);
+ DebugOnly<const uint8_t*> byteSrcPtr = static_cast<const uint8_t*>(aSrc);
+ MOZ_ASSERT((byteDestPtr <= byteSrcPtr &&
+ byteDestPtr + aCount <= byteSrcPtr) ||
+ (byteSrcPtr <= byteDestPtr &&
+ byteSrcPtr + aCount <= byteDestPtr));
+ }
+
+ template<typename T>
+ static void assertAligned(T* aPtr)
+ {
+ MOZ_ASSERT((uintptr_t(aPtr) % sizeof(T)) == 0, "Unaligned pointer!");
+ }
+
+protected:
+ /**
+ * Return |aValue| converted from SourceEndian encoding to DestEndian
+ * encoding.
+ */
+ template<Endianness SourceEndian, Endianness DestEndian, typename T>
+ static inline T maybeSwap(T aValue)
+ {
+ if (SourceEndian == DestEndian) {
+ return aValue;
+ }
+ return Swapper<T>::swap(aValue);
+ }
+
+ /**
+ * Convert |aCount| elements at |aPtr| from SourceEndian encoding to
+ * DestEndian encoding.
+ */
+ template<Endianness SourceEndian, Endianness DestEndian, typename T>
+ static inline void maybeSwapInPlace(T* aPtr, size_t aCount)
+ {
+ assertAligned(aPtr);
+
+ if (SourceEndian == DestEndian) {
+ return;
+ }
+ for (size_t i = 0; i < aCount; i++) {
+ aPtr[i] = Swapper<T>::swap(aPtr[i]);
+ }
+ }
+
+ /**
+ * Write |aCount| elements to the unaligned address |aDest| in DestEndian
+ * format, using elements found at |aSrc| in SourceEndian format.
+ */
+ template<Endianness SourceEndian, Endianness DestEndian, typename T>
+ static void copyAndSwapTo(void* aDest, const T* aSrc, size_t aCount)
+ {
+ assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
+ assertAligned(aSrc);
+
+ if (SourceEndian == DestEndian) {
+ memcpy(aDest, aSrc, aCount * sizeof(T));
+ return;
+ }
+
+ uint8_t* byteDestPtr = static_cast<uint8_t*>(aDest);
+ for (size_t i = 0; i < aCount; ++i) {
+ union
+ {
+ T mVal;
+ uint8_t mBuffer[sizeof(T)];
+ } u;
+ u.mVal = maybeSwap<SourceEndian, DestEndian>(aSrc[i]);
+ memcpy(byteDestPtr, u.mBuffer, sizeof(T));
+ byteDestPtr += sizeof(T);
+ }
+ }
+
+ /**
+ * Write |aCount| elements to |aDest| in DestEndian format, using elements
+ * found at the unaligned address |aSrc| in SourceEndian format.
+ */
+ template<Endianness SourceEndian, Endianness DestEndian, typename T>
+ static void copyAndSwapFrom(T* aDest, const void* aSrc, size_t aCount)
+ {
+ assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
+ assertAligned(aDest);
+
+ if (SourceEndian == DestEndian) {
+ memcpy(aDest, aSrc, aCount * sizeof(T));
+ return;
+ }
+
+ const uint8_t* byteSrcPtr = static_cast<const uint8_t*>(aSrc);
+ for (size_t i = 0; i < aCount; ++i) {
+ union
+ {
+ T mVal;
+ uint8_t mBuffer[sizeof(T)];
+ } u;
+ memcpy(u.mBuffer, byteSrcPtr, sizeof(T));
+ aDest[i] = maybeSwap<SourceEndian, DestEndian>(u.mVal);
+ byteSrcPtr += sizeof(T);
+ }
+ }
+};
+
+template<Endianness ThisEndian>
+class Endian : private EndianUtils
+{
+protected:
+ /** Read a uint16_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE uint16_t readUint16(const void* aPtr)
+ {
+ return read<uint16_t>(aPtr);
+ }
+
+ /** Read a uint32_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE uint32_t readUint32(const void* aPtr)
+ {
+ return read<uint32_t>(aPtr);
+ }
+
+ /** Read a uint64_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE uint64_t readUint64(const void* aPtr)
+ {
+ return read<uint64_t>(aPtr);
+ }
+
+ /** Read an int16_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE int16_t readInt16(const void* aPtr)
+ {
+ return read<int16_t>(aPtr);
+ }
+
+ /** Read an int32_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE int32_t readInt32(const void* aPtr)
+ {
+ return read<uint32_t>(aPtr);
+ }
+
+ /** Read an int64_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE int64_t readInt64(const void* aPtr)
+ {
+ return read<int64_t>(aPtr);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeUint16(void* aPtr, uint16_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeUint32(void* aPtr, uint32_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeUint64(void* aPtr, uint64_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeInt16(void* aPtr, int16_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeInt32(void* aPtr, int32_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeInt64(void* aPtr, int64_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /*
+ * Converts a value of type T to little-endian format.
+ *
+ * This function is intended for cases where you have data in your
+ * native-endian format and you need it to appear in little-endian
+ * format for transmission.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapToLittleEndian(T aValue)
+ {
+ return maybeSwap<ThisEndian, Little>(aValue);
+ }
+
+ /*
+ * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
+ * them to little-endian format if ThisEndian is Big.
+ * As with memcpy, |aDest| and |aSrc| must not overlap.
+ */
+ template<typename T>
+ static void copyAndSwapToLittleEndian(void* aDest, const T* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapTo<ThisEndian, Little>(aDest, aSrc, aCount);
+ }
+
+ /*
+ * Likewise, but converts values in place.
+ */
+ template<typename T>
+ static void swapToLittleEndianInPlace(T* aPtr, size_t aCount)
+ {
+ maybeSwapInPlace<ThisEndian, Little>(aPtr, aCount);
+ }
+
+ /*
+ * Converts a value of type T to big-endian format.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapToBigEndian(T aValue)
+ {
+ return maybeSwap<ThisEndian, Big>(aValue);
+ }
+
+ /*
+ * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
+ * them to big-endian format if ThisEndian is Little.
+ * As with memcpy, |aDest| and |aSrc| must not overlap.
+ */
+ template<typename T>
+ static void copyAndSwapToBigEndian(void* aDest, const T* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapTo<ThisEndian, Big>(aDest, aSrc, aCount);
+ }
+
+ /*
+ * Likewise, but converts values in place.
+ */
+ template<typename T>
+ static void swapToBigEndianInPlace(T* aPtr, size_t aCount)
+ {
+ maybeSwapInPlace<ThisEndian, Big>(aPtr, aCount);
+ }
+
+ /*
+ * Synonyms for the big-endian functions, for better readability
+ * in network code.
+ */
+
+ template<typename T>
+ MOZ_MUST_USE static T swapToNetworkOrder(T aValue)
+ {
+ return swapToBigEndian(aValue);
+ }
+
+ template<typename T>
+ static void
+ copyAndSwapToNetworkOrder(void* aDest, const T* aSrc, size_t aCount)
+ {
+ copyAndSwapToBigEndian(aDest, aSrc, aCount);
+ }
+
+ template<typename T>
+ static void
+ swapToNetworkOrderInPlace(T* aPtr, size_t aCount)
+ {
+ swapToBigEndianInPlace(aPtr, aCount);
+ }
+
+ /*
+ * Converts a value of type T from little-endian format.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapFromLittleEndian(T aValue)
+ {
+ return maybeSwap<Little, ThisEndian>(aValue);
+ }
+
+ /*
+ * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
+ * them to little-endian format if ThisEndian is Big.
+ * As with memcpy, |aDest| and |aSrc| must not overlap.
+ */
+ template<typename T>
+ static void copyAndSwapFromLittleEndian(T* aDest, const void* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapFrom<Little, ThisEndian>(aDest, aSrc, aCount);
+ }
+
+ /*
+ * Likewise, but converts values in place.
+ */
+ template<typename T>
+ static void swapFromLittleEndianInPlace(T* aPtr, size_t aCount)
+ {
+ maybeSwapInPlace<Little, ThisEndian>(aPtr, aCount);
+ }
+
+ /*
+ * Converts a value of type T from big-endian format.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapFromBigEndian(T aValue)
+ {
+ return maybeSwap<Big, ThisEndian>(aValue);
+ }
+
+ /*
+ * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
+ * them to big-endian format if ThisEndian is Little.
+ * As with memcpy, |aDest| and |aSrc| must not overlap.
+ */
+ template<typename T>
+ static void copyAndSwapFromBigEndian(T* aDest, const void* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapFrom<Big, ThisEndian>(aDest, aSrc, aCount);
+ }
+
+ /*
+ * Likewise, but converts values in place.
+ */
+ template<typename T>
+ static void swapFromBigEndianInPlace(T* aPtr, size_t aCount)
+ {
+ maybeSwapInPlace<Big, ThisEndian>(aPtr, aCount);
+ }
+
+ /*
+ * Synonyms for the big-endian functions, for better readability
+ * in network code.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapFromNetworkOrder(T aValue)
+ {
+ return swapFromBigEndian(aValue);
+ }
+
+ template<typename T>
+ static void copyAndSwapFromNetworkOrder(T* aDest, const void* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapFromBigEndian(aDest, aSrc, aCount);
+ }
+
+ template<typename T>
+ static void swapFromNetworkOrderInPlace(T* aPtr, size_t aCount)
+ {
+ swapFromBigEndianInPlace(aPtr, aCount);
+ }
+
+private:
+ /**
+ * Read a value of type T, encoded in endianness ThisEndian from |aPtr|.
+ * Return that value encoded in native endianness.
+ */
+ template<typename T>
+ static T read(const void* aPtr)
+ {
+ union
+ {
+ T mVal;
+ uint8_t mBuffer[sizeof(T)];
+ } u;
+ memcpy(u.mBuffer, aPtr, sizeof(T));
+ return maybeSwap<ThisEndian, MOZ_NATIVE_ENDIANNESS>(u.mVal);
+ }
+
+ /**
+ * Write a value of type T, in native endianness, to |aPtr|, in ThisEndian
+ * endianness.
+ */
+ template<typename T>
+ static void write(void* aPtr, T aValue)
+ {
+ T tmp = maybeSwap<MOZ_NATIVE_ENDIANNESS, ThisEndian>(aValue);
+ memcpy(aPtr, &tmp, sizeof(T));
+ }
+
+ Endian() = delete;
+ Endian(const Endian& aTther) = delete;
+ void operator=(const Endian& aOther) = delete;
+};
+
+template<Endianness ThisEndian>
+class EndianReadWrite : public Endian<ThisEndian>
+{
+private:
+ typedef Endian<ThisEndian> super;
+
+public:
+ using super::readUint16;
+ using super::readUint32;
+ using super::readUint64;
+ using super::readInt16;
+ using super::readInt32;
+ using super::readInt64;
+ using super::writeUint16;
+ using super::writeUint32;
+ using super::writeUint64;
+ using super::writeInt16;
+ using super::writeInt32;
+ using super::writeInt64;
+};
+
+} /* namespace detail */
+
+class LittleEndian final : public detail::EndianReadWrite<detail::Little>
+{};
+
+class BigEndian final : public detail::EndianReadWrite<detail::Big>
+{};
+
+typedef BigEndian NetworkEndian;
+
+class NativeEndian final : public detail::Endian<MOZ_NATIVE_ENDIANNESS>
+{
+private:
+ typedef detail::Endian<MOZ_NATIVE_ENDIANNESS> super;
+
+public:
+ /*
+ * These functions are intended for cases where you have data in your
+ * native-endian format and you need the data to appear in the appropriate
+ * endianness for transmission, serialization, etc.
+ */
+ using super::swapToLittleEndian;
+ using super::copyAndSwapToLittleEndian;
+ using super::swapToLittleEndianInPlace;
+ using super::swapToBigEndian;
+ using super::copyAndSwapToBigEndian;
+ using super::swapToBigEndianInPlace;
+ using super::swapToNetworkOrder;
+ using super::copyAndSwapToNetworkOrder;
+ using super::swapToNetworkOrderInPlace;
+
+ /*
+ * These functions are intended for cases where you have data in the
+ * given endianness (e.g. reading from disk or a file-format) and you
+ * need the data to appear in native-endian format for processing.
+ */
+ using super::swapFromLittleEndian;
+ using super::copyAndSwapFromLittleEndian;
+ using super::swapFromLittleEndianInPlace;
+ using super::swapFromBigEndian;
+ using super::copyAndSwapFromBigEndian;
+ using super::swapFromBigEndianInPlace;
+ using super::swapFromNetworkOrder;
+ using super::copyAndSwapFromNetworkOrder;
+ using super::swapFromNetworkOrderInPlace;
+};
+
+#undef MOZ_NATIVE_ENDIANNESS
+
+} /* namespace mozilla */
+
+#endif /* mozilla_EndianUtils_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumSet.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumSet.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumSet.h
@@ -12,6 +12,8 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
+#include <initializer_list>
+
#include <stdint.h>
namespace mozilla {
@@ -27,7 +29,9 @@
public:
EnumSet()
: mBitField(0)
- { }
+ {
+ initVersion();
+ }
MOZ_IMPLICIT EnumSet(T aEnum)
: mBitField(bitFor(aEnum))
@@ -36,30 +40,48 @@
EnumSet(T aEnum1, T aEnum2)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2))
- { }
+ {
+ initVersion();
+ }
EnumSet(T aEnum1, T aEnum2, T aEnum3)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2) |
bitFor(aEnum3))
- { }
+ {
+ initVersion();
+ }
EnumSet(T aEnum1, T aEnum2, T aEnum3, T aEnum4)
- : mBitField(bitFor(aEnum1) |
- bitFor(aEnum2) |
- bitFor(aEnum3) |
- bitFor(aEnum4))
- { }
+ : mBitField(bitFor(aEnum1) |
+ bitFor(aEnum2) |
+ bitFor(aEnum3) |
+ bitFor(aEnum4))
+ {
+ initVersion();
+ }
+
+ MOZ_IMPLICIT EnumSet(std::initializer_list<T> list)
+ : mBitField(0)
+ {
+ for (auto value : list) {
+ (*this) += value;
+ }
+ initVersion();
+ }
EnumSet(const EnumSet& aEnumSet)
- : mBitField(aEnumSet.mBitField)
- { }
+ : mBitField(aEnumSet.mBitField)
+ {
+ initVersion();
+ }
/**
* Add an element
*/
void operator+=(T aEnum)
{
+ incVersion();
mBitField |= bitFor(aEnum);
}
@@ -78,6 +100,7 @@
*/
void operator+=(const EnumSet<T> aEnumSet)
{
+ incVersion();
mBitField |= aEnumSet.mBitField;
}
@@ -96,6 +119,7 @@
*/
void operator-=(T aEnum)
{
+ incVersion();
mBitField &= ~(bitFor(aEnum));
}
@@ -114,6 +138,7 @@
*/
void operator-=(const EnumSet<T> aEnumSet)
{
+ incVersion();
mBitField &= ~(aEnumSet.mBitField);
}
@@ -132,6 +157,7 @@
*/
void clear()
{
+ incVersion();
mBitField = 0;
}
@@ -140,6 +166,7 @@
*/
void operator&=(const EnumSet<T> aEnumSet)
{
+ incVersion();
mBitField &= aEnumSet.mBitField;
}
@@ -172,7 +199,7 @@
/**
* Return the number of elements in the set.
*/
- uint8_t size()
+ uint8_t size() const
{
uint8_t count = 0;
for (uint32_t bitField = mBitField; bitField; bitField >>= 1) {
@@ -195,18 +222,121 @@
void deserialize(uint32_t aValue)
{
+ incVersion();
mBitField = aValue;
}
+ class ConstIterator
+ {
+ const EnumSet<T>* mSet;
+ uint32_t mPos;
+#ifdef DEBUG
+ uint64_t mVersion;
+#endif
+
+ void checkVersion() {
+ // Check that the set has not been modified while being iterated.
+ MOZ_ASSERT_IF(mSet, mSet->mVersion == mVersion);
+ }
+
+ public:
+ ConstIterator(const EnumSet<T>& aSet, uint32_t aPos)
+ : mSet(&aSet), mPos(aPos)
+ {
+#ifdef DEBUG
+ mVersion = mSet->mVersion;
+#endif
+ MOZ_ASSERT(aPos <= kMaxBits);
+ if (aPos != kMaxBits && !mSet->contains(T(mPos)))
+ ++*this;
+ }
+
+ ConstIterator(const ConstIterator& aOther)
+ : mSet(aOther.mSet), mPos(aOther.mPos)
+ {
+#ifdef DEBUG
+ mVersion = aOther.mVersion;
+ checkVersion();
+#endif
+ }
+
+ ConstIterator(ConstIterator&& aOther)
+ : mSet(aOther.mSet), mPos(aOther.mPos)
+ {
+#ifdef DEBUG
+ mVersion = aOther.mVersion;
+ checkVersion();
+#endif
+ aOther.mSet = nullptr;
+ }
+
+ ~ConstIterator() {
+ checkVersion();
+ }
+
+ bool operator==(const ConstIterator& other) {
+ MOZ_ASSERT(mSet == other.mSet);
+ checkVersion();
+ return mPos == other.mPos;
+ }
+
+ bool operator!=(const ConstIterator& other) {
+ return !(*this == other);
+ }
+
+ T operator*() {
+ MOZ_ASSERT(mSet);
+ MOZ_ASSERT(mPos < kMaxBits);
+ MOZ_ASSERT(mSet->contains(T(mPos)));
+ checkVersion();
+ return T(mPos);
+ }
+
+ ConstIterator& operator++() {
+ MOZ_ASSERT(mSet);
+ MOZ_ASSERT(mPos < kMaxBits);
+ checkVersion();
+ do {
+ mPos++;
+ } while (mPos < kMaxBits && !mSet->contains(T(mPos)));
+ return *this;
+ }
+ };
+
+ ConstIterator begin() const {
+ return ConstIterator(*this, 0);
+ }
+
+ ConstIterator end() const {
+ return ConstIterator(*this, kMaxBits);
+ }
+
private:
static uint32_t bitFor(T aEnum)
{
uint32_t bitNumber = (uint32_t)aEnum;
- MOZ_ASSERT(bitNumber < 32);
+ MOZ_ASSERT(bitNumber < kMaxBits);
return 1U << bitNumber;
}
+ void initVersion() {
+#ifdef DEBUG
+ mVersion = 0;
+#endif
+ }
+
+ void incVersion() {
+#ifdef DEBUG
+ mVersion++;
+#endif
+ }
+
+ static const size_t kMaxBits = 32;
uint32_t mBitField;
+
+#ifdef DEBUG
+ uint64_t mVersion;
+#endif
};
} // namespace mozilla
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumTypeTraits.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumTypeTraits.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumTypeTraits.h
@@ -0,0 +1,70 @@
+/* -*- 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/. */
+
+/* Type traits for enums. */
+
+#ifndef mozilla_EnumTypeTraits_h
+#define mozilla_EnumTypeTraits_h
+
+#include <type_traits>
+
+namespace mozilla {
+
+namespace detail {
+
+template<size_t EnumSize, bool EnumSigned, size_t StorageSize, bool StorageSigned>
+struct EnumFitsWithinHelper;
+
+// Signed enum, signed storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, true, StorageSize, true>
+ : public std::integral_constant<bool, (EnumSize <= StorageSize)>
+{};
+
+// Signed enum, unsigned storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, true, StorageSize, false>
+ : public std::integral_constant<bool, false>
+{};
+
+// Unsigned enum, signed storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, false, StorageSize, true>
+ : public std::integral_constant<bool, (EnumSize * 2 <= StorageSize)>
+{};
+
+// Unsigned enum, unsigned storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, false, StorageSize, false>
+ : public std::integral_constant<bool, (EnumSize <= StorageSize)>
+{};
+
+} // namespace detail
+
+/*
+ * Type trait that determines whether the enum type T can fit within the
+ * integral type Storage without data loss. This trait should be used with
+ * caution with an enum type whose underlying type has not been explicitly
+ * specified: for such enums, the C++ implementation is free to choose a type
+ * no smaller than int whose range encompasses all possible values of the enum.
+ * So for an enum with only small non-negative values, the underlying type may
+ * be either int or unsigned int, depending on the whims of the implementation.
+ */
+template<typename T, typename Storage>
+struct EnumTypeFitsWithin
+ : public detail::EnumFitsWithinHelper<
+ sizeof(T),
+ std::is_signed<typename std::underlying_type<T>::type>::value,
+ sizeof(Storage),
+ std::is_signed<Storage>::value
+ >
+{
+ static_assert(std::is_enum<T>::value, "must provide an enum type");
+ static_assert(std::is_integral<Storage>::value, "must provide an integral type");
+};
+
+} // namespace mozilla
+
+#endif /* mozilla_EnumTypeTraits_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumeratedArray.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumeratedArray.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumeratedArray.h
@@ -10,6 +10,7 @@
#define mozilla_EnumeratedArray_h
#include "mozilla/Array.h"
+#include "mozilla/Move.h"
namespace mozilla {
@@ -53,6 +54,11 @@
public:
EnumeratedArray() {}
+ template <typename... Args>
+ MOZ_IMPLICIT EnumeratedArray(Args&&... aArgs)
+ : mArray{mozilla::Forward<Args>(aArgs)...}
+ {}
+
explicit EnumeratedArray(const EnumeratedArray& aOther)
{
for (size_t i = 0; i < kSize; i++) {
@@ -60,6 +66,13 @@
}
}
+ EnumeratedArray(EnumeratedArray&& aOther)
+ {
+ for (size_t i = 0; i < kSize; i++) {
+ mArray[i] = Move(aOther.mArray[i]);
+ }
+ }
+
ValueType& operator[](IndexType aIndex)
{
return mArray[size_t(aIndex)];
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumeratedRange.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumeratedRange.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/EnumeratedRange.h
@@ -20,23 +20,26 @@
#ifndef mozilla_EnumeratedRange_h
#define mozilla_EnumeratedRange_h
-#include "mozilla/IntegerTypeTraits.h"
+#include <type_traits>
+
#include "mozilla/ReverseIterator.h"
namespace mozilla {
namespace detail {
-template<typename IntTypeT, typename EnumTypeT>
+template<typename EnumTypeT>
class EnumeratedIterator
{
public:
+ typedef typename std::underlying_type<EnumTypeT>::type IntTypeT;
+
template<typename EnumType>
explicit EnumeratedIterator(EnumType aCurrent)
: mCurrent(aCurrent) { }
- template<typename IntType, typename EnumType>
- explicit EnumeratedIterator(const EnumeratedIterator<IntType, EnumType>& aOther)
+ template<typename EnumType>
+ explicit EnumeratedIterator(const EnumeratedIterator<EnumType>& aOther)
: mCurrent(aOther.mCurrent) { }
EnumTypeT operator*() const { return mCurrent; }
@@ -68,77 +71,77 @@
/* Comparison operators */
- template<typename IntType, typename EnumType>
- friend bool operator==(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator!=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator<(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator<=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator>(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator>=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator==(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator<(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator>(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
private:
EnumTypeT mCurrent;
};
-template<typename IntType, typename EnumType>
-bool operator==(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator==(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent == aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator!=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent != aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator<(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator<(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent < aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator<=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent <= aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator>(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator>(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent > aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator>=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent >= aIter2.mCurrent;
}
-template<typename IntTypeT, typename EnumTypeT>
+template<typename EnumTypeT>
class EnumeratedRange
{
public:
- typedef EnumeratedIterator<IntTypeT, EnumTypeT> iterator;
- typedef EnumeratedIterator<IntTypeT, EnumTypeT> const_iterator;
+ typedef EnumeratedIterator<EnumTypeT> iterator;
+ typedef EnumeratedIterator<EnumTypeT> const_iterator;
typedef ReverseIterator<iterator> reverse_iterator;
typedef ReverseIterator<const_iterator> const_reverse_iterator;
@@ -171,38 +174,21 @@
#endif
// Create a range to iterate from aBegin to aEnd, exclusive.
-//
-// (Once we can rely on std::underlying_type, we can remove the IntType
-// template parameter.)
-template<typename IntType, typename EnumType>
-inline detail::EnumeratedRange<IntType, EnumType>
+template<typename EnumType>
+inline detail::EnumeratedRange<EnumType>
MakeEnumeratedRange(EnumType aBegin, EnumType aEnd)
{
-#ifdef DEBUG
- typedef typename MakeUnsigned<IntType>::Type UnsignedType;
-#endif
- static_assert(sizeof(IntType) >= sizeof(EnumType),
- "IntType should be at least as big as EnumType!");
MOZ_ASSERT(aBegin <= aEnd, "Cannot generate invalid, unbounded range!");
- MOZ_ASSERT_IF(aBegin < EnumType(0), IsSigned<IntType>::value);
- MOZ_ASSERT_IF(aBegin >= EnumType(0) && IsSigned<IntType>::value,
- UnsignedType(aEnd) <= UnsignedType(MaxValue<IntType>::value));
- return detail::EnumeratedRange<IntType, EnumType>(aBegin, aEnd);
+ return detail::EnumeratedRange<EnumType>(aBegin, aEnd);
}
// Create a range to iterate from EnumType(0) to aEnd, exclusive. EnumType(0)
// should exist, but note that there is no way for us to ensure that it does!
-// Since the enumeration starts at EnumType(0), we know for sure that the values
-// will be in range of our deduced IntType.
template<typename EnumType>
-inline detail::EnumeratedRange<
- typename UnsignedStdintTypeForSize<sizeof(EnumType)>::Type,
- EnumType>
+inline detail::EnumeratedRange<EnumType>
MakeEnumeratedRange(EnumType aEnd)
{
- return MakeEnumeratedRange<
- typename UnsignedStdintTypeForSize<sizeof(EnumType)>::Type>(EnumType(0),
- aEnd);
+ return MakeEnumeratedRange(EnumType(0), aEnd);
}
#ifdef __GNUC__
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/FastBernoulliTrial.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/FastBernoulliTrial.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/FastBernoulliTrial.h
@@ -177,7 +177,10 @@
* random number generator; both may not be zero.
*/
FastBernoulliTrial(double aProbability, uint64_t aState0, uint64_t aState1)
- : mGenerator(aState0, aState1)
+ : mProbability(0)
+ , mInvLogNotProbability(0)
+ , mGenerator(aState0, aState1)
+ , mSkipCount(0)
{
setProbability(aProbability);
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/FloatingPoint.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/FloatingPoint.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/FloatingPoint.h
@@ -117,7 +117,7 @@
/** Determines whether a float/double is NaN. */
template<typename T>
-static MOZ_ALWAYS_INLINE MOZ_CONSTEXPR bool
+static MOZ_ALWAYS_INLINE bool
IsNaN(T aValue)
{
/*
@@ -186,6 +186,18 @@
return bits == Traits::kSignBit;
}
+/** Determines wether a float/double represents +0. */
+template<typename T>
+static MOZ_ALWAYS_INLINE bool
+IsPositiveZero(T aValue)
+{
+ /* All bits are zero if the value is +0. */
+ typedef FloatingPoint<T> Traits;
+ typedef typename Traits::Bits Bits;
+ Bits bits = BitwiseCast<Bits>(aValue);
+ return bits == 0;
+}
+
/**
* Returns 0 if a float/double is NaN or infinite;
* otherwise, the float/double is returned.
@@ -244,21 +256,65 @@
return BitwiseCast<T>(Traits::kSignBit | Traits::kExponentBits);
}
+/**
+ * Computes the bit pattern for a NaN with the specified sign bit and
+ * significand bits.
+ */
+template<typename T,
+ int SignBit,
+ typename FloatingPoint<T>::Bits Significand>
+struct SpecificNaNBits
+{
+ using Traits = FloatingPoint<T>;
+
+ static_assert(SignBit == 0 || SignBit == 1, "bad sign bit");
+ static_assert((Significand & ~Traits::kSignificandBits) == 0,
+ "significand must only have significand bits set");
+ static_assert(Significand & Traits::kSignificandBits,
+ "significand must be nonzero");
-/** Constructs a NaN value with the specified sign bit and significand bits. */
+ static constexpr typename Traits::Bits value =
+ (SignBit * Traits::kSignBit) | Traits::kExponentBits | Significand;
+};
+
+/**
+ * Constructs a NaN value with the specified sign bit and significand bits.
+ *
+ * There is also a variant that returns the value directly. In most cases, the
+ * two variants should be identical. However, in the specific case of x86
+ * chips, the behavior differs: returning floating-point values directly is done
+ * through the x87 stack, and x87 loads and stores turn signaling NaNs into
+ * quiet NaNs... silently. Returning floating-point values via outparam,
+ * however, is done entirely within the SSE registers when SSE2 floating-point
+ * is enabled in the compiler, which has semantics-preserving behavior you would
+ * expect.
+ *
+ * If preserving the distinction between signaling NaNs and quiet NaNs is
+ * important to you, you should use the outparam version. In all other cases,
+ * you should use the direct return version.
+ */
template<typename T>
-static MOZ_ALWAYS_INLINE T
-SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand)
+static MOZ_ALWAYS_INLINE void
+SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand, T* result)
{
typedef FloatingPoint<T> Traits;
MOZ_ASSERT(signbit == 0 || signbit == 1);
MOZ_ASSERT((significand & ~Traits::kSignificandBits) == 0);
MOZ_ASSERT(significand & Traits::kSignificandBits);
- T t = BitwiseCast<T>((signbit ? Traits::kSignBit : 0) |
- Traits::kExponentBits |
- significand);
- MOZ_ASSERT(IsNaN(t));
+ BitwiseCast<T>((signbit ? Traits::kSignBit : 0) |
+ Traits::kExponentBits |
+ significand,
+ result);
+ MOZ_ASSERT(IsNaN(*result));
+}
+
+template<typename T>
+static MOZ_ALWAYS_INLINE T
+SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand)
+{
+ T t;
+ SpecificNaN(signbit, significand, &t);
return t;
}
@@ -401,13 +457,6 @@
T aEpsilon = detail::FuzzyEqualsEpsilon<T>::value())
{
static_assert(IsFloatingPoint<T>::value, "floating point type required");
-
- // Short-circuit the common case in order to avoid the expensive operations
- // below.
- if (aValue1 == aValue2) {
- return true;
- }
-
// can't use std::min because of bug 965340
T smaller = Abs(aValue1) < Abs(aValue2) ? Abs(aValue1) : Abs(aValue2);
return Abs(aValue1 - aValue2) <= aEpsilon * smaller;
@@ -421,7 +470,7 @@
*
* This function isn't inlined to avoid buggy optimizations by MSVC.
*/
-MOZ_WARN_UNUSED_RESULT
+MOZ_MUST_USE
extern MFBT_API bool
IsFloat32Representable(double aFloat32);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Function.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Function.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Function.h
@@ -11,9 +11,10 @@
#include "mozilla/Attributes.h" // for MOZ_IMPLICIT
#include "mozilla/Move.h"
-#include "mozilla/UniquePtr.h"
+#include "mozilla/RefCounted.h"
+#include "mozilla/RefPtr.h"
-// |Function<Signature>| is a wrapper that can hold any type of callable
+// |function<Signature>| is a wrapper that can hold any type of callable
// object that can be invoked in a way that's compatible with |Signature|.
// The standard "type erasure" technique is used to avoid the type of the
// wrapper depending on the concrete type of the wrapped callable.
@@ -28,7 +29,7 @@
// this is a function type; it's not used in any way other than serving as a
// vehicle to encode the return and argument types into a single type.
//
-// |Function| is default-constructible. A default-constructed instance is
+// |function| is default-constructible. A default-constructed instance is
// considered "empty". Invoking an empty instance is undefined behaviour.
// An empty instance can be populated with a callable by assigning to it.
//
@@ -40,9 +41,11 @@
namespace detail {
template<typename ReturnType, typename... Arguments>
-class FunctionImplBase
+class FunctionImplBase : public mozilla::RefCounted<FunctionImplBase<ReturnType, Arguments...>>
{
public:
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(FunctionImplBase)
+
virtual ~FunctionImplBase() {}
virtual ReturnType call(Arguments... aArguments) = 0;
};
@@ -126,32 +129,47 @@
// and |Arguments| in the definition of the specialization without having to
// introspect |Signature|.
template<typename Signature>
-class Function;
+class function;
template<typename ReturnType, typename... Arguments>
-class Function<ReturnType(Arguments...)>
+class function<ReturnType(Arguments...)>
{
public:
- Function() {}
+ function() {}
// This constructor is implicit to match the interface of |std::function|.
template <typename Callable>
- MOZ_IMPLICIT Function(const Callable& aCallable)
- : mImpl(MakeUnique<detail::FunctionImpl<Callable, ReturnType, Arguments...>>(aCallable))
+ MOZ_IMPLICIT function(const Callable& aCallable)
+ : mImpl(new detail::FunctionImpl<Callable, ReturnType, Arguments...>(aCallable))
+ {}
+ MOZ_IMPLICIT function(const function& aFunction)
+ : mImpl(aFunction.mImpl)
+ {}
+ MOZ_IMPLICIT function(decltype(nullptr))
{}
// Move constructor and move assingment operator.
// These should be generated automatically, but MSVC doesn't do that yet.
- Function(Function&& aOther) : mImpl(Move(aOther.mImpl)) {}
- Function& operator=(Function&& aOther) {
+ function(function&& aOther) : mImpl(Move(aOther.mImpl)) {}
+ function& operator=(function&& aOther) {
mImpl = Move(aOther.mImpl);
return *this;
}
template <typename Callable>
- Function& operator=(const Callable& aCallable)
+ function& operator=(const Callable& aCallable)
{
- mImpl = MakeUnique<detail::FunctionImpl<Callable, ReturnType, Arguments...>>(aCallable);
+ mImpl = new detail::FunctionImpl<Callable, ReturnType, Arguments...>(aCallable);
+ return *this;
+ }
+ function& operator=(const function& aFunction)
+ {
+ mImpl = aFunction.mImpl;
+ return *this;
+ }
+ function& operator=(decltype(nullptr))
+ {
+ mImpl = nullptr;
return *this;
}
@@ -161,11 +179,45 @@
MOZ_ASSERT(mImpl);
return mImpl->call(Forward<Args>(aArguments)...);
}
+
+ explicit operator bool() const
+ {
+ return bool(mImpl);
+ }
+
private:
// TODO: Consider implementing a small object optimization.
- UniquePtr<detail::FunctionImplBase<ReturnType, Arguments...>> mImpl;
+ RefPtr<detail::FunctionImplBase<ReturnType, Arguments...>> mImpl;
};
+template<typename Signature>
+bool
+operator==(const function<Signature>& aX, decltype(nullptr))
+{
+ return !aX;
+}
+
+template<typename Signature>
+bool
+operator==(decltype(nullptr), const function<Signature>& aX)
+{
+ return !aX;
+}
+
+template<typename Signature>
+bool
+operator!=(const function<Signature>& aX, decltype(nullptr))
+{
+ return bool(aX);
+}
+
+template<typename Signature>
+bool
+operator!=(decltype(nullptr), const function<Signature>& aX)
+{
+ return bool(aX);
+}
+
} // namespace mozilla
#endif /* mozilla_Function_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/HashFunctions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/HashFunctions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/HashFunctions.h
@@ -10,7 +10,7 @@
* This file exports functions for hashing data down to a 32-bit value,
* including:
*
- * - HashString Hash a char* or uint16_t/wchar_t* of known or unknown
+ * - HashString Hash a char* or char16_t/wchar_t* of known or unknown
* length.
*
* - HashBytes Hash a byte array of known length.
@@ -50,6 +50,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Char16.h"
+#include "mozilla/MathAlgorithms.h"
#include "mozilla/Types.h"
#include <stdint.h>
@@ -156,7 +157,7 @@
* convert to uint32_t, data pointers, and function pointers.
*/
template<typename A>
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
AddToHash(uint32_t aHash, A aA)
{
/*
@@ -167,7 +168,7 @@
}
template<typename A>
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
AddToHash(uint32_t aHash, A* aA)
{
/*
@@ -181,14 +182,14 @@
}
template<>
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
AddToHash(uint32_t aHash, uintptr_t aA)
{
return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, aA);
}
template<typename A, typename... Args>
-MOZ_WARN_UNUSED_RESULT uint32_t
+MOZ_MUST_USE uint32_t
AddToHash(uint32_t aHash, A aArg, Args... aArgs)
{
return AddToHash(AddToHash(aHash, aArg), aArgs...);
@@ -202,7 +203,7 @@
* that x has already been hashed.
*/
template<typename... Args>
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashGeneric(Args... aArgs)
{
return AddToHash(0, aArgs...);
@@ -240,63 +241,49 @@
* If you have the string's length, you might as well call the overload which
* includes the length. It may be marginally faster.
*/
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const char* aStr)
{
return detail::HashUntilZero(reinterpret_cast<const unsigned char*>(aStr));
}
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const char* aStr, size_t aLength)
{
return detail::HashKnownLength(reinterpret_cast<const unsigned char*>(aStr), aLength);
}
-MOZ_WARN_UNUSED_RESULT
+MOZ_MUST_USE
inline uint32_t
HashString(const unsigned char* aStr, size_t aLength)
{
return detail::HashKnownLength(aStr, aLength);
}
-MOZ_WARN_UNUSED_RESULT inline uint32_t
-HashString(const uint16_t* aStr)
-{
- return detail::HashUntilZero(aStr);
-}
-
-MOZ_WARN_UNUSED_RESULT inline uint32_t
-HashString(const uint16_t* aStr, size_t aLength)
-{
- return detail::HashKnownLength(aStr, aLength);
-}
-
-#ifdef MOZ_CHAR16_IS_NOT_WCHAR
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const char16_t* aStr)
{
return detail::HashUntilZero(aStr);
}
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const char16_t* aStr, size_t aLength)
{
return detail::HashKnownLength(aStr, aLength);
}
-#endif
/*
- * On Windows, wchar_t (char16_t) is not the same as uint16_t, even though it's
+ * On Windows, wchar_t is not the same as char16_t, even though it's
* the same width!
*/
#ifdef WIN32
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const wchar_t* aStr)
{
return detail::HashUntilZero(aStr);
}
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const wchar_t* aStr, size_t aLength)
{
return detail::HashKnownLength(aStr, aLength);
@@ -309,9 +296,93 @@
* This hash walks word-by-word, rather than byte-by-byte, so you won't get the
* same result out of HashBytes as you would out of HashString.
*/
-MOZ_WARN_UNUSED_RESULT extern MFBT_API uint32_t
+MOZ_MUST_USE extern MFBT_API uint32_t
HashBytes(const void* bytes, size_t aLength);
+/**
+ * A pseudorandom function mapping 32-bit integers to 32-bit integers.
+ *
+ * This is for when you're feeding private data (like pointer values or credit
+ * card numbers) to a non-crypto hash function (like HashBytes) and then using
+ * the hash code for something that untrusted parties could observe (like a JS
+ * Map). Plug in a HashCodeScrambler before that last step to avoid leaking the
+ * private data.
+ *
+ * By itself, this does not prevent hash-flooding DoS attacks, because an
+ * attacker can still generate many values with exactly equal hash codes by
+ * attacking the non-crypto hash function alone. Equal hash codes will, of
+ * course, still be equal however much you scramble them.
+ *
+ * The algorithm is SipHash-1-3. See <https://131002.net/siphash/>.
+ */
+class HashCodeScrambler
+{
+ struct SipHasher;
+
+ uint64_t mK0, mK1;
+
+public:
+ /** Creates a new scrambler with the given 128-bit key. */
+ constexpr HashCodeScrambler(uint64_t aK0, uint64_t aK1) : mK0(aK0), mK1(aK1) {}
+
+ /**
+ * Scramble a hash code. Always produces the same result for the same
+ * combination of key and hash code.
+ */
+ uint32_t scramble(uint32_t aHashCode) const
+ {
+ SipHasher hasher(mK0, mK1);
+ return uint32_t(hasher.sipHash(aHashCode));
+ }
+
+private:
+ struct SipHasher
+ {
+ SipHasher(uint64_t aK0, uint64_t aK1)
+ {
+ // 1. Initialization.
+ mV0 = aK0 ^ UINT64_C(0x736f6d6570736575);
+ mV1 = aK1 ^ UINT64_C(0x646f72616e646f6d);
+ mV2 = aK0 ^ UINT64_C(0x6c7967656e657261);
+ mV3 = aK1 ^ UINT64_C(0x7465646279746573);
+ }
+
+ uint64_t sipHash(uint64_t aM)
+ {
+ // 2. Compression.
+ mV3 ^= aM;
+ sipRound();
+ mV0 ^= aM;
+
+ // 3. Finalization.
+ mV2 ^= 0xff;
+ for (int i = 0; i < 3; i++)
+ sipRound();
+ return mV0 ^ mV1 ^ mV2 ^ mV3;
+ }
+
+ void sipRound()
+ {
+ mV0 += mV1;
+ mV1 = RotateLeft(mV1, 13);
+ mV1 ^= mV0;
+ mV0 = RotateLeft(mV0, 32);
+ mV2 += mV3;
+ mV3 = RotateLeft(mV3, 16);
+ mV3 ^= mV2;
+ mV0 += mV3;
+ mV3 = RotateLeft(mV3, 21);
+ mV3 ^= mV0;
+ mV2 += mV1;
+ mV1 = RotateLeft(mV1, 17);
+ mV1 ^= mV2;
+ mV2 = RotateLeft(mV2, 32);
+ }
+
+ uint64_t mV0, mV1, mV2, mV3;
+ };
+};
+
} /* namespace mozilla */
#endif /* __cplusplus */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/IndexSequence.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/IndexSequence.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/IndexSequence.h
@@ -74,7 +74,7 @@
template<size_t... Indices>
struct IndexSequence
{
- static MOZ_CONSTEXPR size_t Size() { return sizeof...(Indices); }
+ static constexpr size_t Size() { return sizeof...(Indices); }
};
namespace detail {
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/JSONWriter.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/JSONWriter.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/JSONWriter.h
@@ -95,7 +95,7 @@
#include "mozilla/double-conversion.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/PodOperations.h"
-#include "mozilla/Snprintf.h"
+#include "mozilla/Sprintf.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Vector.h"
@@ -389,7 +389,7 @@
void IntProperty(const char* aName, int64_t aInt)
{
char buf[64];
- snprintf_literal(buf, "%" PRId64, aInt);
+ SprintfLiteral(buf, "%" PRId64, aInt);
Scalar(aName, buf);
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/LinkedList.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/LinkedList.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/LinkedList.h
@@ -68,17 +68,65 @@
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
+#include "mozilla/RefPtr.h"
#ifdef __cplusplus
namespace mozilla {
template<typename T>
+class LinkedListElement;
+
+namespace detail {
+
+/**
+ * LinkedList supports refcounted elements using this adapter class. Clients
+ * using LinkedList<RefPtr<T>> will get a data structure that holds a strong
+ * reference to T as long as T is in the list.
+ */
+template<typename T>
+struct LinkedListElementTraits
+{
+ typedef T* RawType;
+ typedef const T* ConstRawType;
+ typedef T* ClientType;
+ typedef const T* ConstClientType;
+
+ // These static methods are called when an element is added to or removed from
+ // a linked list. It can be used to keep track ownership in lists that are
+ // supposed to own their elements. If elements are transferred from one list
+ // to another, no enter or exit calls happen since the elements still belong
+ // to a list.
+ static void enterList(LinkedListElement<T>* elt) {}
+ static void exitList(LinkedListElement<T>* elt) {}
+};
+
+template<typename T>
+struct LinkedListElementTraits<RefPtr<T>>
+{
+ typedef T* RawType;
+ typedef const T* ConstRawType;
+ typedef RefPtr<T> ClientType;
+ typedef RefPtr<const T> ConstClientType;
+
+ static void enterList(LinkedListElement<RefPtr<T>>* elt) { elt->asT()->AddRef(); }
+ static void exitList(LinkedListElement<RefPtr<T>>* elt) { elt->asT()->Release(); }
+};
+
+} /* namespace detail */
+
+template<typename T>
class LinkedList;
template<typename T>
class LinkedListElement
{
+ typedef typename detail::LinkedListElementTraits<T> Traits;
+ typedef typename Traits::RawType RawType;
+ typedef typename Traits::ConstRawType ConstRawType;
+ typedef typename Traits::ClientType ClientType;
+ typedef typename Traits::ConstClientType ConstClientType;
+
/*
* It's convenient that we return nullptr when getNext() or getPrevious()
* hits the end of the list, but doing so costs an extra word of storage in
@@ -125,34 +173,23 @@
mIsSentinel(false)
{ }
- LinkedListElement(LinkedListElement<T>&& other)
- : mIsSentinel(other.mIsSentinel)
+ /*
+ * Moves |aOther| into |*this|. If |aOther| is already in a list, then
+ * |aOther| is removed from the list and replaced by |*this|.
+ */
+ LinkedListElement(LinkedListElement<T>&& aOther)
+ : mIsSentinel(aOther.mIsSentinel)
{
- if (!other.isInList()) {
- mNext = this;
- mPrev = this;
- return;
- }
-
- MOZ_ASSERT(other.mNext->mPrev == &other);
- MOZ_ASSERT(other.mPrev->mNext == &other);
-
- /*
- * Initialize |this| with |other|'s mPrev/mNext pointers, and adjust those
- * element to point to this one.
- */
- mNext = other.mNext;
- mPrev = other.mPrev;
-
- mNext->mPrev = this;
- mPrev->mNext = this;
+ adjustLinkForMove(Move(aOther));
+ }
- /*
- * Adjust |other| so it doesn't think it's in a list. This makes it
- * safely destructable.
- */
- other.mNext = &other;
- other.mPrev = &other;
+ LinkedListElement& operator=(LinkedListElement<T>&& aOther)
+ {
+ MOZ_ASSERT(mIsSentinel == aOther.mIsSentinel, "Mismatch NodeKind!");
+ MOZ_ASSERT(!isInList(),
+ "Assigning to an element in a list messes up that list!");
+ adjustLinkForMove(Move(aOther));
+ return *this;
}
~LinkedListElement()
@@ -166,21 +203,21 @@
* Get the next element in the list, or nullptr if this is the last element
* in the list.
*/
- T* getNext() { return mNext->asT(); }
- const T* getNext() const { return mNext->asT(); }
+ RawType getNext() { return mNext->asT(); }
+ ConstRawType getNext() const { return mNext->asT(); }
/*
* Get the previous element in the list, or nullptr if this is the first
* element in the list.
*/
- T* getPrevious() { return mPrev->asT(); }
- const T* getPrevious() const { return mPrev->asT(); }
+ RawType getPrevious() { return mPrev->asT(); }
+ ConstRawType getPrevious() const { return mPrev->asT(); }
/*
* Insert aElem after this element in the list. |this| must be part of a
* linked list when you call setNext(); otherwise, this method will assert.
*/
- void setNext(T* aElem)
+ void setNext(RawType aElem)
{
MOZ_ASSERT(isInList());
setNextUnsafe(aElem);
@@ -191,7 +228,7 @@
* linked list when you call setPrevious(); otherwise, this method will
* assert.
*/
- void setPrevious(T* aElem)
+ void setPrevious(RawType aElem)
{
MOZ_ASSERT(isInList());
setPreviousUnsafe(aElem);
@@ -209,6 +246,32 @@
mNext->mPrev = mPrev;
mNext = this;
mPrev = this;
+
+ Traits::exitList(this);
+ }
+
+ /*
+ * Remove this element from the list containing it. Returns a pointer to the
+ * element that follows this element (before it was removed). This method
+ * asserts if the element does not belong to a list.
+ */
+ ClientType removeAndGetNext()
+ {
+ ClientType r = getNext();
+ remove();
+ return r;
+ }
+
+ /*
+ * Remove this element from the list containing it. Returns a pointer to the
+ * previous element in the containing list (before the removal). This method
+ * asserts if the element does not belong to a list.
+ */
+ ClientType removeAndGetPrevious()
+ {
+ ClientType r = getPrevious();
+ remove();
+ return r;
}
/*
@@ -232,36 +295,37 @@
private:
friend class LinkedList<T>;
+ friend struct detail::LinkedListElementTraits<T>;
- enum NodeKind {
- NODE_KIND_NORMAL,
- NODE_KIND_SENTINEL
+ enum class NodeKind {
+ Normal,
+ Sentinel
};
explicit LinkedListElement(NodeKind nodeKind)
: mNext(this),
mPrev(this),
- mIsSentinel(nodeKind == NODE_KIND_SENTINEL)
+ mIsSentinel(nodeKind == NodeKind::Sentinel)
{ }
/*
* Return |this| cast to T* if we're a normal node, or return nullptr if
* we're a sentinel node.
*/
- T* asT()
+ RawType asT()
{
- return mIsSentinel ? nullptr : static_cast<T*>(this);
+ return mIsSentinel ? nullptr : static_cast<RawType>(this);
}
- const T* asT() const
+ ConstRawType asT() const
{
- return mIsSentinel ? nullptr : static_cast<const T*>(this);
+ return mIsSentinel ? nullptr : static_cast<ConstRawType>(this);
}
/*
* Insert aElem after this element, but don't check that this element is in
* the list. This is called by LinkedList::insertFront().
*/
- void setNextUnsafe(T* aElem)
+ void setNextUnsafe(RawType aElem)
{
LinkedListElement *listElem = static_cast<LinkedListElement*>(aElem);
MOZ_ASSERT(!listElem->isInList());
@@ -270,13 +334,15 @@
listElem->mPrev = this;
this->mNext->mPrev = listElem;
this->mNext = listElem;
+
+ Traits::enterList(aElem);
}
/*
* Insert aElem before this element, but don't check that this element is in
* the list. This is called by LinkedList::insertBack().
*/
- void setPreviousUnsafe(T* aElem)
+ void setPreviousUnsafe(RawType aElem)
{
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(aElem);
MOZ_ASSERT(!listElem->isInList());
@@ -285,9 +351,51 @@
listElem->mPrev = this->mPrev;
this->mPrev->mNext = listElem;
this->mPrev = listElem;
+
+ Traits::enterList(aElem);
+ }
+
+ /*
+ * Adjust mNext and mPrev for implementing move constructor and move
+ * assignment.
+ */
+ void adjustLinkForMove(LinkedListElement<T>&& aOther)
+ {
+ if (!aOther.isInList()) {
+ mNext = this;
+ mPrev = this;
+ return;
+ }
+
+ if (!mIsSentinel) {
+ Traits::enterList(this);
+ }
+
+ MOZ_ASSERT(aOther.mNext->mPrev == &aOther);
+ MOZ_ASSERT(aOther.mPrev->mNext == &aOther);
+
+ /*
+ * Initialize |this| with |aOther|'s mPrev/mNext pointers, and adjust those
+ * element to point to this one.
+ */
+ mNext = aOther.mNext;
+ mPrev = aOther.mPrev;
+
+ mNext->mPrev = this;
+ mPrev->mNext = this;
+
+ /*
+ * Adjust |aOther| so it doesn't think it's in a list. This makes it
+ * safely destructable.
+ */
+ aOther.mNext = &aOther;
+ aOther.mPrev = &aOther;
+
+ if (!mIsSentinel) {
+ Traits::exitList(&aOther);
+ }
}
-private:
LinkedListElement& operator=(const LinkedListElement<T>& aOther) = delete;
LinkedListElement(const LinkedListElement<T>& aOther) = delete;
};
@@ -296,16 +404,22 @@
class LinkedList
{
private:
+ typedef typename detail::LinkedListElementTraits<T> Traits;
+ typedef typename Traits::RawType RawType;
+ typedef typename Traits::ConstRawType ConstRawType;
+ typedef typename Traits::ClientType ClientType;
+ typedef typename Traits::ConstClientType ConstClientType;
+
LinkedListElement<T> sentinel;
public:
class Iterator {
- T* mCurrent;
+ RawType mCurrent;
public:
- explicit Iterator(T* aCurrent) : mCurrent(aCurrent) {}
+ explicit Iterator(RawType aCurrent) : mCurrent(aCurrent) {}
- T* operator *() const {
+ RawType operator *() const {
return mCurrent;
}
@@ -319,18 +433,30 @@
}
};
- LinkedList() : sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL) { }
+ LinkedList() : sentinel(LinkedListElement<T>::NodeKind::Sentinel) { }
LinkedList(LinkedList<T>&& aOther)
: sentinel(mozilla::Move(aOther.sentinel))
{ }
- ~LinkedList() { MOZ_ASSERT(isEmpty()); }
+ LinkedList& operator=(LinkedList<T>&& aOther)
+ {
+ MOZ_ASSERT(isEmpty(), "Assigning to a non-empty list leaks elements in that list!");
+ sentinel = mozilla::Move(aOther.sentinel);
+ return *this;
+ }
+
+ ~LinkedList() {
+ MOZ_ASSERT(isEmpty(),
+ "failing this assertion means this LinkedList's creator is "
+ "buggy: it should have removed all this list's elements before "
+ "the list's destruction");
+ }
/*
* Add aElem to the front of the list.
*/
- void insertFront(T* aElem)
+ void insertFront(RawType aElem)
{
/* Bypass setNext()'s this->isInList() assertion. */
sentinel.setNextUnsafe(aElem);
@@ -339,7 +465,7 @@
/*
* Add aElem to the back of the list.
*/
- void insertBack(T* aElem)
+ void insertBack(RawType aElem)
{
sentinel.setPreviousUnsafe(aElem);
}
@@ -347,24 +473,24 @@
/*
* Get the first element of the list, or nullptr if the list is empty.
*/
- T* getFirst() { return sentinel.getNext(); }
- const T* getFirst() const { return sentinel.getNext(); }
+ RawType getFirst() { return sentinel.getNext(); }
+ ConstRawType getFirst() const { return sentinel.getNext(); }
/*
* Get the last element of the list, or nullptr if the list is empty.
*/
- T* getLast() { return sentinel.getPrevious(); }
- const T* getLast() const { return sentinel.getPrevious(); }
+ RawType getLast() { return sentinel.getPrevious(); }
+ ConstRawType getLast() const { return sentinel.getPrevious(); }
/*
* Get and remove the first element of the list. If the list is empty,
* return nullptr.
*/
- T* popFirst()
+ ClientType popFirst()
{
- T* ret = sentinel.getNext();
+ ClientType ret = sentinel.getNext();
if (ret) {
- static_cast<LinkedListElement<T>*>(ret)->remove();
+ static_cast<LinkedListElement<T>*>(RawType(ret))->remove();
}
return ret;
}
@@ -373,11 +499,11 @@
* Get and remove the last element of the list. If the list is empty,
* return nullptr.
*/
- T* popLast()
+ ClientType popLast()
{
- T* ret = sentinel.getPrevious();
+ ClientType ret = sentinel.getPrevious();
if (ret) {
- static_cast<LinkedListElement<T>*>(ret)->remove();
+ static_cast<LinkedListElement<T>*>(RawType(ret))->remove();
}
return ret;
}
@@ -498,10 +624,10 @@
private:
friend class LinkedListElement<T>;
- void assertContains(const T* aValue) const
+ void assertContains(const RawType aValue) const
{
#ifdef DEBUG
- for (const T* elem = getFirst(); elem; elem = elem->getNext()) {
+ for (ConstRawType elem = getFirst(); elem; elem = elem->getNext()) {
if (elem == aValue) {
return;
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/MacroArgs.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/MacroArgs.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/MacroArgs.h
@@ -11,6 +11,10 @@
#ifndef mozilla_MacroArgs_h
#define mozilla_MacroArgs_h
+// Concatenates pre-processor tokens in a way that can be used with __LINE__.
+#define MOZ_CONCAT2(x, y) x ## y
+#define MOZ_CONCAT(x, y) MOZ_CONCAT2(x, y)
+
/*
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) counts the number of variadic
* arguments and prefixes it with |aPrefix|. For example:
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/MathAlgorithms.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/MathAlgorithms.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/MathAlgorithms.h
@@ -340,7 +340,7 @@
return detail::CountPopulation32(aValue);
}
-/** Analogous to CoutPopulation32, but for 64-bit numbers */
+/** Analogous to CountPopulation32, but for 64-bit numbers */
inline uint_fast8_t
CountPopulation64(uint64_t aValue)
{
@@ -515,7 +515,7 @@
* Zero is not an integer power of two. (-Inf is not an integer)
*/
template<typename T>
-inline bool
+constexpr bool
IsPowerOfTwo(T x)
{
static_assert(IsUnsigned<T>::value,
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Maybe.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Maybe.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Maybe.h
@@ -16,6 +16,7 @@
#include "mozilla/TypeTraits.h"
#include <new> // for placement new
+#include <type_traits>
namespace mozilla {
@@ -101,6 +102,26 @@
}
}
+ /**
+ * Maybe<T*> can be copy-constructed from a Maybe<U*> if U* and T* are
+ * compatible, or from Maybe<decltype(nullptr)>.
+ */
+ template<typename U,
+ typename =
+ typename std::enable_if<std::is_pointer<T>::value &&
+ (std::is_same<U, decltype(nullptr)>::value ||
+ (std::is_pointer<U>::value &&
+ std::is_base_of<typename std::remove_pointer<T>::type,
+ typename std::remove_pointer<U>::type>::value))>::type>
+ MOZ_IMPLICIT
+ Maybe(const Maybe<U>& aOther)
+ : mIsSome(false)
+ {
+ if (aOther.isSome()) {
+ emplace(*aOther);
+ }
+ }
+
Maybe(Maybe&& aOther)
: mIsSome(false)
{
@@ -110,6 +131,27 @@
}
}
+ /**
+ * Maybe<T*> can be move-constructed from a Maybe<U*> if U* and T* are
+ * compatible, or from Maybe<decltype(nullptr)>.
+ */
+ template<typename U,
+ typename =
+ typename std::enable_if<std::is_pointer<T>::value &&
+ (std::is_same<U, decltype(nullptr)>::value ||
+ (std::is_pointer<U>::value &&
+ std::is_base_of<typename std::remove_pointer<T>::type,
+ typename std::remove_pointer<U>::type>::value))>::type>
+ MOZ_IMPLICIT
+ Maybe(Maybe<U>&& aOther)
+ : mIsSome(false)
+ {
+ if (aOther.isSome()) {
+ emplace(Move(*aOther));
+ aOther.reset();
+ }
+ }
+
Maybe& operator=(const Maybe& aOther)
{
if (&aOther != this) {
@@ -324,53 +366,57 @@
/* If |isSome()|, runs the provided function or functor on the contents of
* this Maybe. */
- template<typename F, typename... Args>
- void apply(F&& aFunc, Args&&... aArgs)
+ template<typename Func>
+ Maybe& apply(Func aFunc)
{
if (isSome()) {
- aFunc(ref(), Forward<Args>(aArgs)...);
+ aFunc(ref());
}
+ return *this;
}
- template<typename F, typename... Args>
- void apply(F&& aFunc, Args&&... aArgs) const
+ template<typename Func>
+ const Maybe& apply(Func aFunc) const
{
if (isSome()) {
- aFunc(ref(), Forward<Args>(aArgs)...);
+ aFunc(ref());
}
+ return *this;
}
/*
* If |isSome()|, runs the provided function and returns the result wrapped
* in a Maybe. If |isNothing()|, returns an empty Maybe value.
*/
- template<typename R, typename... FArgs, typename... Args>
- Maybe<R> map(R (*aFunc)(T&, FArgs...), Args&&... aArgs)
+ template<typename Func>
+ auto map(Func aFunc) -> Maybe<decltype(aFunc(DeclVal<Maybe<T>>().ref()))>
{
+ using ReturnType = decltype(aFunc(ref()));
if (isSome()) {
- Maybe<R> val;
- val.emplace(aFunc(ref(), Forward<Args>(aArgs)...));
+ Maybe<ReturnType> val;
+ val.emplace(aFunc(ref()));
return val;
}
- return Maybe<R>();
+ return Maybe<ReturnType>();
}
- template<typename R, typename... FArgs, typename... Args>
- Maybe<R> map(R (*aFunc)(const T&, FArgs...), Args&&... aArgs) const
+ template<typename Func>
+ auto map(Func aFunc) const -> Maybe<decltype(aFunc(DeclVal<Maybe<T>>().ref()))>
{
+ using ReturnType = decltype(aFunc(ref()));
if (isSome()) {
- Maybe<R> val;
- val.emplace(aFunc(ref(), Forward<Args>(aArgs)...));
+ Maybe<ReturnType> val;
+ val.emplace(aFunc(ref()));
return val;
}
- return Maybe<R>();
+ return Maybe<ReturnType>();
}
/* If |isSome()|, empties this Maybe and destroys its contents. */
void reset()
{
if (isSome()) {
- ref().~T();
+ ref().T::~T();
mIsSome = false;
}
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/NotNull.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/NotNull.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/NotNull.h
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_NotNull_h
+#define mozilla_NotNull_h
+
+// It's often unclear if a particular pointer, be it raw (T*) or smart
+// (RefPtr<T>, nsCOMPtr<T>, etc.) can be null. This leads to missing null
+// checks (which can cause crashes) and unnecessary null checks (which clutter
+// the code).
+//
+// C++ has a built-in alternative that avoids these problems: references. This
+// module defines another alternative, NotNull, which can be used in cases
+// where references are not suitable.
+//
+// In the comments below we use the word "handle" to cover all varieties of
+// pointers and references.
+//
+// References
+// ----------
+// References are always non-null. (You can do |T& r = *p;| where |p| is null,
+// but that's undefined behaviour. C++ doesn't provide any built-in, ironclad
+// guarantee of non-nullness.)
+//
+// A reference works well when you need a temporary handle to an existing
+// single object, e.g. for passing a handle to a function, or as a local handle
+// within another object. (In Rust parlance, this is a "borrow".)
+//
+// A reference is less appropriate in the following cases.
+//
+// - As a primary handle to an object. E.g. code such as this is possible but
+// strange: |T& t = *new T(); ...; delete &t;|
+//
+// - As a handle to an array. It's common for |T*| to refer to either a single
+// |T| or an array of |T|, but |T&| cannot refer to an array of |T| because
+// you can't index off a reference (at least, not without first converting it
+// to a pointer).
+//
+// - When the handle identity is meaningful, e.g. if you have a hashtable of
+// handles, because you have to use |&| on the reference to convert it to a
+// pointer.
+//
+// - Some people don't like using non-const references as function parameters,
+// because it is not clear at the call site that the argument might be
+// modified.
+//
+// - When you need "smart" behaviour. E.g. we lack reference equivalents to
+// RefPtr and nsCOMPtr.
+//
+// - When interfacing with code that uses pointers a lot, sometimes using a
+// reference just feels like an odd fit.
+//
+// Furthermore, a reference is impossible in the following cases.
+//
+// - When the handle is rebound to another object. References don't allow this.
+//
+// - When the handle has type |void|. |void&| is not allowed.
+//
+// NotNull is an alternative that can be used in any of the above cases except
+// for the last one, where the handle type is |void|. See below.
+
+#include "mozilla/Assertions.h"
+
+namespace mozilla {
+
+// NotNull can be used to wrap a "base" pointer (raw or smart) to indicate it
+// is not null. Some examples:
+//
+// - NotNull<char*>
+// - NotNull<RefPtr<Event>>
+// - NotNull<nsCOMPtr<Event>>
+//
+// NotNull has the following notable properties.
+//
+// - It has zero space overhead.
+//
+// - It must be initialized explicitly. There is no default initialization.
+//
+// - It auto-converts to the base pointer type.
+//
+// - It does not auto-convert from a base pointer. Implicit conversion from a
+// less-constrained type (e.g. T*) to a more-constrained type (e.g.
+// NotNull<T*>) is dangerous. Creation and assignment from a base pointer can
+// only be done with WrapNotNull(), which makes them impossible to overlook,
+// both when writing and reading code.
+//
+// - When initialized (or assigned) it is checked, and if it is null we abort.
+// This guarantees that it cannot be null.
+//
+// - |operator bool()| is deleted. This means you cannot check a NotNull in a
+// boolean context, which eliminates the possibility of unnecessary null
+// checks.
+//
+// NotNull currently doesn't work with UniquePtr. See
+// https://github.com/Microsoft/GSL/issues/89 for some discussion.
+//
+template <typename T>
+class NotNull
+{
+ template <typename U> friend NotNull<U> WrapNotNull(U aBasePtr);
+
+ T mBasePtr;
+
+ // This constructor is only used by WrapNotNull().
+ template <typename U>
+ explicit NotNull(U aBasePtr) : mBasePtr(aBasePtr) {}
+
+public:
+ // Disallow default construction.
+ NotNull() = delete;
+
+ // Construct/assign from another NotNull with a compatible base pointer type.
+ template <typename U>
+ MOZ_IMPLICIT NotNull(const NotNull<U>& aOther) : mBasePtr(aOther.get()) {}
+
+ // Default copy/move construction and assignment.
+ NotNull(const NotNull<T>&) = default;
+ NotNull<T>& operator=(const NotNull<T>&) = default;
+ NotNull(NotNull<T>&&) = default;
+ NotNull<T>& operator=(NotNull<T>&&) = default;
+
+ // Disallow null checks, which are unnecessary for this type.
+ explicit operator bool() const = delete;
+
+ // Explicit conversion to a base pointer. Use only to resolve ambiguity or to
+ // get a castable pointer.
+ const T& get() const { return mBasePtr; }
+
+ // Implicit conversion to a base pointer. Preferable to get().
+ operator const T&() const { return get(); }
+
+ // Dereference operators.
+ const T& operator->() const { return get(); }
+ decltype(*mBasePtr) operator*() const { return *mBasePtr; }
+};
+
+template <typename T>
+NotNull<T>
+WrapNotNull(const T aBasePtr)
+{
+ NotNull<T> notNull(aBasePtr);
+ MOZ_RELEASE_ASSERT(aBasePtr);
+ return notNull;
+}
+
+// Compare two NotNulls.
+template <typename T, typename U>
+inline bool
+operator==(const NotNull<T>& aLhs, const NotNull<U>& aRhs)
+{
+ return aLhs.get() == aRhs.get();
+}
+template <typename T, typename U>
+inline bool
+operator!=(const NotNull<T>& aLhs, const NotNull<U>& aRhs)
+{
+ return aLhs.get() != aRhs.get();
+}
+
+// Compare a NotNull to a base pointer.
+template <typename T, typename U>
+inline bool
+operator==(const NotNull<T>& aLhs, const U& aRhs)
+{
+ return aLhs.get() == aRhs;
+}
+template <typename T, typename U>
+inline bool
+operator!=(const NotNull<T>& aLhs, const U& aRhs)
+{
+ return aLhs.get() != aRhs;
+}
+
+// Compare a base pointer to a NotNull.
+template <typename T, typename U>
+inline bool
+operator==(const T& aLhs, const NotNull<U>& aRhs)
+{
+ return aLhs == aRhs.get();
+}
+template <typename T, typename U>
+inline bool
+operator!=(const T& aLhs, const NotNull<U>& aRhs)
+{
+ return aLhs != aRhs.get();
+}
+
+// Disallow comparing a NotNull to a nullptr.
+template <typename T>
+bool
+operator==(const NotNull<T>&, decltype(nullptr)) = delete;
+template <typename T>
+bool
+operator!=(const NotNull<T>&, decltype(nullptr)) = delete;
+
+// Disallow comparing a nullptr to a NotNull.
+template <typename T>
+bool
+operator==(decltype(nullptr), const NotNull<T>&) = delete;
+template <typename T>
+bool
+operator!=(decltype(nullptr), const NotNull<T>&) = delete;
+
+} // namespace mozilla
+
+#endif /* mozilla_NotNull_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/NumericLimits.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/NumericLimits.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/NumericLimits.h
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/* Compatibility with std::numeric_limits<char16_t>. */
-
-#ifndef mozilla_NumericLimits_h
-#define mozilla_NumericLimits_h
-
-#include "mozilla/Char16.h"
-
-#include <limits>
-#include <stdint.h>
-
-namespace mozilla {
-
-/**
- * The NumericLimits class provides a compatibility layer with
- * std::numeric_limits for char16_t, otherwise it is exactly the same as
- * std::numeric_limits. Code which does not need std::numeric_limits<char16_t>
- * should avoid using NumericLimits.
- */
-template<typename T>
-class NumericLimits : public std::numeric_limits<T>
-{
-};
-
-#ifdef MOZ_CHAR16_IS_NOT_WCHAR
-template<>
-class NumericLimits<char16_t> : public std::numeric_limits<uint16_t>
-{
- // char16_t and uint16_t numeric limits should be exactly the same.
-};
-#endif
-
-} // namespace mozilla
-
-#endif /* mozilla_NumericLimits_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/OperatorNewExtensions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/OperatorNewExtensions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/OperatorNewExtensions.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* A version of |operator new| that eschews mandatory null-checks. */
+
+#ifndef mozilla_OperatorNewExtensions_h
+#define mozilla_OperatorNewExtensions_h
+
+#include "mozilla/Assertions.h"
+
+// Credit goes to WebKit for this implementation, cf.
+// https://bugs.webkit.org/show_bug.cgi?id=74676
+namespace mozilla {
+enum NotNullTag {
+ KnownNotNull,
+};
+} // namespace mozilla
+
+/*
+ * The logic here is a little subtle. [expr.new] states that if the allocation
+ * function being called returns null, then object initialization must not be
+ * done, and the entirety of the new expression must return null. Non-throwing
+ * (noexcept) functions are defined to return null to indicate failure. The
+ * standard placement operator new is defined in such a way, and so it requires
+ * a null check, even when that null check would be extraneous. Functions
+ * declared without such a specification are defined to throw std::bad_alloc if
+ * they fail, and return a non-null pointer otherwise. We compile without
+ * exceptions, so any placement new overload we define that doesn't declare
+ * itself as noexcept must therefore avoid generating a null check. Below is
+ * just such an overload.
+ *
+ * You might think that MOZ_NONNULL might perform the same function, but
+ * MOZ_NONNULL isn't supported on all of our compilers, and even when it is
+ * supported, doesn't work on all the versions we support. And even keeping
+ * those limitations in mind, we can't put MOZ_NONNULL on the global,
+ * standardized placement new function in any event.
+ *
+ * We deliberately don't add MOZ_NONNULL(3) to tag |p| as non-null, to benefit
+ * hypothetical static analyzers. Doing so makes |MOZ_ASSERT(p)|'s internal
+ * test vacuous, and some compilers warn about such vacuous tests.
+ */
+inline void*
+operator new(size_t, mozilla::NotNullTag, void* p)
+{
+ MOZ_ASSERT(p);
+ return p;
+}
+
+#endif // mozilla_OperatorNewExtensions_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Poison.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Poison.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Poison.h
@@ -59,4 +59,50 @@
MOZ_END_EXTERN_C
+#if defined(__cplusplus)
+
+namespace mozilla {
+
+/**
+ * This class is designed to cause crashes when various kinds of memory
+ * corruption are observed. For instance, let's say we have a class C where we
+ * suspect out-of-bounds writes to some members. We can insert a member of type
+ * Poison near the members we suspect are being corrupted by out-of-bounds
+ * writes. Or perhaps we have a class K we suspect is subject to use-after-free
+ * violations, in which case it doesn't particularly matter where in the class
+ * we add the member of type Poison.
+ *
+ * In either case, we then insert calls to Check() throughout the code. Doing
+ * so enables us to narrow down the location where the corruption is occurring.
+ * A pleasant side-effect of these additional Check() calls is that crash
+ * signatures may become more regular, as crashes will ideally occur
+ * consolidated at the point of a Check(), rather than scattered about at
+ * various uses of the corrupted memory.
+ */
+class CorruptionCanary {
+public:
+ CorruptionCanary() {
+ mValue = kCanarySet;
+ }
+
+ ~CorruptionCanary() {
+ Check();
+ mValue = mozPoisonValue();
+ }
+
+ void Check() const {
+ if (mValue != kCanarySet) {
+ MOZ_CRASH("Canary check failed, check lifetime");
+ }
+ }
+
+private:
+ static const uintptr_t kCanarySet = 0x0f0b0f0b;
+ uintptr_t mValue;
+};
+
+} // mozilla
+
+#endif
+
#endif /* mozilla_Poison_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Range.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Range.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Range.h
@@ -8,6 +8,7 @@
#define mozilla_Range_h
#include "mozilla/RangedPtr.h"
+#include "mozilla/TypeTraits.h"
#include <stddef.h>
@@ -26,8 +27,24 @@
: mStart(aPtr, aPtr, aPtr + aLength),
mEnd(aPtr + aLength, aPtr, aPtr + aLength)
{}
+ Range(const RangedPtr<T>& aStart, const RangedPtr<T>& aEnd)
+ : mStart(aStart.get(), aStart.get(), aEnd.get()),
+ mEnd(aEnd.get(), aStart.get(), aEnd.get())
+ {
+ // Only accept two RangedPtrs within the same range.
+ aStart.checkIdenticalRange(aEnd);
+ MOZ_ASSERT(aStart <= aEnd);
+ }
+
+ template<typename U,
+ class = typename EnableIf<IsConvertible<U (*)[], T (*)[]>::value,
+ int>::Type>
+ MOZ_IMPLICIT Range(const Range<U>& aOther)
+ : mStart(aOther.mStart),
+ mEnd(aOther.mEnd)
+ {}
- RangedPtr<T> start() const { return mStart; }
+ RangedPtr<T> begin() const { return mStart; }
RangedPtr<T> end() const { return mEnd; }
size_t length() const { return mEnd - mStart; }
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RangedPtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RangedPtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RangedPtr.h
@@ -117,6 +117,12 @@
explicit operator bool() const { return mPtr != nullptr; }
+ void checkIdenticalRange(const RangedPtr<T>& aOther) const
+ {
+ MOZ_ASSERT(mRangeStart == aOther.mRangeStart);
+ MOZ_ASSERT(mRangeEnd == aOther.mRangeEnd);
+ }
+
/*
* You can only assign one RangedPtr into another if the two pointers have
* the same valid range:
@@ -129,21 +135,20 @@
*/
RangedPtr<T>& operator=(const RangedPtr<T>& aOther)
{
- MOZ_ASSERT(mRangeStart == aOther.mRangeStart);
- MOZ_ASSERT(mRangeEnd == aOther.mRangeEnd);
+ checkIdenticalRange(aOther);
mPtr = aOther.mPtr;
checkSanity();
return *this;
}
- RangedPtr<T> operator+(size_t aInc)
+ RangedPtr<T> operator+(size_t aInc) const
{
MOZ_ASSERT(aInc <= size_t(-1) / sizeof(T));
MOZ_ASSERT(asUintptr() + aInc * sizeof(T) >= asUintptr());
return create(mPtr + aInc);
}
- RangedPtr<T> operator-(size_t aDec)
+ RangedPtr<T> operator-(size_t aDec) const
{
MOZ_ASSERT(aDec <= size_t(-1) / sizeof(T));
MOZ_ASSERT(asUintptr() - aDec * sizeof(T) <= asUintptr());
@@ -220,6 +225,13 @@
return *mPtr;
}
+ T* operator->() const
+ {
+ MOZ_ASSERT(mPtr >= mRangeStart);
+ MOZ_ASSERT(mPtr < mRangeEnd);
+ return mPtr;
+ }
+
template <typename U>
bool operator==(const RangedPtr<U>& aOther) const
{
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RefCounted.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RefCounted.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RefCounted.h
@@ -22,7 +22,6 @@
#endif
#if defined(MOZILLA_INTERNAL_API) && \
- !defined(MOZILLA_XPCOMRT_API) && \
(defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
#define MOZ_REFCOUNTED_LEAK_CHECKING
#endif
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RefPtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RefPtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/RefPtr.h
@@ -19,6 +19,28 @@
namespace mozilla {
template<class T> class OwningNonNull;
+template<class T> class StaticRefPtr;
+
+// Traditionally, RefPtr supports automatic refcounting of any pointer type
+// with AddRef() and Release() methods that follow the traditional semantics.
+//
+// This traits class can be specialized to operate on other pointer types. For
+// example, we specialize this trait for opaque FFI types that represent
+// refcounted objects in Rust.
+//
+// Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
+// qualified type.
+template<class U>
+struct RefPtrTraits
+{
+ static void AddRef(U* aPtr) {
+ aPtr->AddRef();
+ }
+ static void Release(U* aPtr) {
+ aPtr->Release();
+ }
+};
+
} // namespace mozilla
template <class T>
@@ -29,7 +51,7 @@
assign_with_AddRef(T* aRawPtr)
{
if (aRawPtr) {
- AddRefTraits<T>::AddRef(aRawPtr);
+ ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
}
assign_assuming_AddRef(aRawPtr);
}
@@ -40,7 +62,7 @@
T* oldPtr = mRawPtr;
mRawPtr = aNewPtr;
if (oldPtr) {
- AddRefTraits<T>::Release(oldPtr);
+ ConstRemovingRefPtrTraits<T>::Release(oldPtr);
}
}
@@ -53,14 +75,14 @@
~RefPtr()
{
if (mRawPtr) {
- AddRefTraits<T>::Release(mRawPtr);
+ ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
}
}
// Constructors
RefPtr()
- : mRawPtr(0)
+ : mRawPtr(nullptr)
// default constructor
{
}
@@ -70,7 +92,7 @@
// copy-constructor
{
if (mRawPtr) {
- AddRefTraits<T>::AddRef(mRawPtr);
+ ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
}
}
@@ -86,10 +108,15 @@
: mRawPtr(aRawPtr)
{
if (mRawPtr) {
- AddRefTraits<T>::AddRef(mRawPtr);
+ ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
}
}
+ MOZ_IMPLICIT RefPtr(decltype(nullptr))
+ : mRawPtr(nullptr)
+ {
+ }
+
template <typename I>
MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
: mRawPtr(aSmartPtr.take())
@@ -110,7 +137,7 @@
// copy-construct from a smart pointer with a related pointer type
{
if (mRawPtr) {
- AddRefTraits<T>::AddRef(mRawPtr);
+ ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
}
}
@@ -127,9 +154,20 @@
template<class U>
MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther);
+ // Defined in StaticPtr.h
+ template<class U>
+ MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
+
// Assignment operators
RefPtr<T>&
+ operator=(decltype(nullptr))
+ {
+ assign_assuming_AddRef(nullptr);
+ return *this;
+ }
+
+ RefPtr<T>&
operator=(const RefPtr<T>& aRhs)
// copy assignment operator
{
@@ -187,6 +225,11 @@
RefPtr<T>&
operator=(const mozilla::OwningNonNull<U>& aOther);
+ // Defined in StaticPtr.h
+ template<class U>
+ RefPtr<T>&
+ operator=(const mozilla::StaticRefPtr<U>& aOther);
+
// Other pointer operators
void
@@ -212,7 +255,7 @@
// return the value of mRawPtr and null out mRawPtr. Useful for
// already_AddRefed return values.
{
- T* temp = 0;
+ T* temp = nullptr;
swap(temp);
return already_AddRefed<T>(temp);
}
@@ -227,7 +270,7 @@
{
MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
*aRhs = mRawPtr;
- mRawPtr = 0;
+ mRawPtr = nullptr;
}
T*
@@ -272,7 +315,7 @@
T*
operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
{
- MOZ_ASSERT(mRawPtr != 0,
+ MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator->().");
return get();
}
@@ -299,7 +342,7 @@
template <typename R, typename... Args>
Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const
{
- MOZ_ASSERT(mRawPtr != 0,
+ MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator->*().");
return Proxy<R, Args...>(get(), aFptr);
}
@@ -324,7 +367,7 @@
T&
operator*() const
{
- MOZ_ASSERT(mRawPtr != 0,
+ MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator*().");
return *get();
}
@@ -332,7 +375,7 @@
T**
StartAssignment()
{
- assign_assuming_AddRef(0);
+ assign_assuming_AddRef(nullptr);
return reinterpret_cast<T**>(&mRawPtr);
}
private:
@@ -346,40 +389,24 @@
// This should be sound because while |RefPtr<const T>| provides a
// const view of an object, the object itself should not be const (it
// would have to be allocated as |new const T| or similar to be const).
-
- // Because some classes make their AddRef/Release implementations private
- // and then friend RefPtr to make them visible, we redirect AddRefTraits's
- // calls to static helper functions in RefPtr so we don't have to figure
- // out how to make AddRefTraits visible to *those* classes.
- static MOZ_ALWAYS_INLINE void
- AddRefTraitsAddRefHelper(typename mozilla::RemoveConst<T>::Type* aPtr)
- {
- aPtr->AddRef();
- }
- static MOZ_ALWAYS_INLINE void
- AddRefTraitsReleaseHelper(typename mozilla::RemoveConst<T>::Type* aPtr)
- {
- aPtr->Release();
- }
-
template<class U>
- struct AddRefTraits
+ struct ConstRemovingRefPtrTraits
{
static void AddRef(U* aPtr) {
- RefPtr<T>::AddRefTraitsAddRefHelper(aPtr);
+ mozilla::RefPtrTraits<U>::AddRef(aPtr);
}
static void Release(U* aPtr) {
- RefPtr<T>::AddRefTraitsReleaseHelper(aPtr);
+ mozilla::RefPtrTraits<U>::Release(aPtr);
}
};
template<class U>
- struct AddRefTraits<const U>
+ struct ConstRemovingRefPtrTraits<const U>
{
static void AddRef(const U* aPtr) {
- RefPtr<T>::AddRefTraitsAddRefHelper(const_cast<U*>(aPtr));
+ mozilla::RefPtrTraits<U>::AddRef(const_cast<U*>(aPtr));
}
static void Release(const U* aPtr) {
- RefPtr<T>::AddRefTraitsReleaseHelper(const_cast<U*>(aPtr));
+ mozilla::RefPtrTraits<U>::Release(const_cast<U*>(aPtr));
}
};
};
@@ -591,7 +618,15 @@
template <class T>
inline already_AddRefed<T>
-do_AddRef(T*&& aObj)
+do_AddRef(T* aObj)
+{
+ RefPtr<T> ref(aObj);
+ return ref.forget();
+}
+
+template <class T>
+inline already_AddRefed<T>
+do_AddRef(const RefPtr<T>& aObj)
{
RefPtr<T> ref(aObj);
return ref.forget();
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Saturate.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Saturate.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Saturate.h
@@ -0,0 +1,288 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Provides saturation arithmetics for scalar types. */
+
+#ifndef mozilla_Saturate_h
+#define mozilla_Saturate_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Move.h"
+#include "mozilla/TypeTraits.h"
+
+#include <limits>
+
+namespace mozilla {
+namespace detail {
+
+/**
+ * |SaturateOp<T>| wraps scalar values for saturation arithmetics. Usage:
+ *
+ * uint32_t value = 1;
+ *
+ * ++SaturateOp<uint32_t>(value); // value is 2
+ * --SaturateOp<uint32_t>(value); // value is 1
+ * --SaturateOp<uint32_t>(value); // value is 0
+ * --SaturateOp<uint32_t>(value); // value is still 0
+ *
+ * Please add new operators when required.
+ *
+ * |SaturateOp<T>| will saturate at the minimum and maximum values of
+ * type T. If you need other bounds, implement a clamped-type class and
+ * specialize the type traits accordingly.
+ */
+template <typename T>
+class SaturateOp
+{
+public:
+ explicit SaturateOp(T& aValue)
+ : mValue(aValue)
+ {
+ // We should actually check for |std::is_scalar<T>::value| to be
+ // true, but this type trait is not available everywhere. Relax
+ // this assertion if you want to use floating point values as well.
+ static_assert(IsIntegral<T>::value,
+ "Integral type required in instantiation");
+ }
+
+ // Add and subtract operators
+
+ T operator+(const T& aRhs) const
+ {
+ return T(mValue) += aRhs;
+ }
+
+ T operator-(const T& aRhs) const
+ {
+ return T(mValue) -= aRhs;
+ }
+
+ // Compound operators
+
+ const T& operator+=(const T& aRhs) const
+ {
+ const T min = std::numeric_limits<T>::min();
+ const T max = std::numeric_limits<T>::max();
+
+ if (aRhs > static_cast<T>(0)) {
+ mValue = (max - aRhs) < mValue ? max : mValue + aRhs;
+ } else {
+ mValue = (min - aRhs) > mValue ? min : mValue + aRhs;
+ }
+ return mValue;
+ }
+
+ const T& operator-=(const T& aRhs) const
+ {
+ const T min = std::numeric_limits<T>::min();
+ const T max = std::numeric_limits<T>::max();
+
+ if (aRhs > static_cast<T>(0)) {
+ mValue = (min + aRhs) > mValue ? min : mValue - aRhs;
+ } else {
+ mValue = (max + aRhs) < mValue ? max : mValue - aRhs;
+ }
+ return mValue;
+ }
+
+ // Increment and decrement operators
+
+ const T& operator++() const // prefix
+ {
+ return operator+=(static_cast<T>(1));
+ }
+
+ T operator++(int) const // postfix
+ {
+ const T value(mValue);
+ operator++();
+ return value;
+ }
+
+ const T& operator--() const // prefix
+ {
+ return operator-=(static_cast<T>(1));
+ }
+
+ T operator--(int) const // postfix
+ {
+ const T value(mValue);
+ operator--();
+ return value;
+ }
+
+private:
+ SaturateOp(const SaturateOp<T>&) = delete;
+ SaturateOp(SaturateOp<T>&&) = delete;
+ SaturateOp& operator=(const SaturateOp<T>&) = delete;
+ SaturateOp& operator=(SaturateOp<T>&&) = delete;
+
+ T& mValue;
+};
+
+/**
+ * |Saturate<T>| is a value type for saturation arithmetics. It's
+ * build on top of |SaturateOp<T>|.
+ */
+template <typename T>
+class Saturate
+{
+public:
+ Saturate() = default;
+ MOZ_IMPLICIT Saturate(const Saturate<T>&) = default;
+
+ MOZ_IMPLICIT Saturate(Saturate<T>&& aValue)
+ {
+ mValue = Move(aValue.mValue);
+ }
+
+ explicit Saturate(const T& aValue)
+ : mValue(aValue)
+ { }
+
+ const T& value() const
+ {
+ return mValue;
+ }
+
+ // Compare operators
+
+ bool operator==(const Saturate<T>& aRhs) const
+ {
+ return mValue == aRhs.mValue;
+ }
+
+ bool operator!=(const Saturate<T>& aRhs) const
+ {
+ return !operator==(aRhs);
+ }
+
+ bool operator==(const T& aRhs) const
+ {
+ return mValue == aRhs;
+ }
+
+ bool operator!=(const T& aRhs) const
+ {
+ return !operator==(aRhs);
+ }
+
+ // Assignment operators
+
+ Saturate<T>& operator=(const Saturate<T>&) = default;
+
+ Saturate<T>& operator=(Saturate<T>&& aRhs)
+ {
+ mValue = Move(aRhs.mValue);
+ return *this;
+ }
+
+ // Add and subtract operators
+
+ Saturate<T> operator+(const Saturate<T>& aRhs) const
+ {
+ Saturate<T> lhs(mValue);
+ return lhs += aRhs.mValue;
+ }
+
+ Saturate<T> operator+(const T& aRhs) const
+ {
+ Saturate<T> lhs(mValue);
+ return lhs += aRhs;
+ }
+
+ Saturate<T> operator-(const Saturate<T>& aRhs) const
+ {
+ Saturate<T> lhs(mValue);
+ return lhs -= aRhs.mValue;
+ }
+
+ Saturate<T> operator-(const T& aRhs) const
+ {
+ Saturate<T> lhs(mValue);
+ return lhs -= aRhs;
+ }
+
+ // Compound operators
+
+ Saturate<T>& operator+=(const Saturate<T>& aRhs)
+ {
+ SaturateOp<T>(mValue) += aRhs.mValue;
+ return *this;
+ }
+
+ Saturate<T>& operator+=(const T& aRhs)
+ {
+ SaturateOp<T>(mValue) += aRhs;
+ return *this;
+ }
+
+ Saturate<T>& operator-=(const Saturate<T>& aRhs)
+ {
+ SaturateOp<T>(mValue) -= aRhs.mValue;
+ return *this;
+ }
+
+ Saturate<T>& operator-=(const T& aRhs)
+ {
+ SaturateOp<T>(mValue) -= aRhs;
+ return *this;
+ }
+
+ // Increment and decrement operators
+
+ Saturate<T>& operator++() // prefix
+ {
+ ++SaturateOp<T>(mValue);
+ return *this;
+ }
+
+ Saturate<T> operator++(int) // postfix
+ {
+ return Saturate<T>(SaturateOp<T>(mValue)++);
+ }
+
+ Saturate<T>& operator--() // prefix
+ {
+ --SaturateOp<T>(mValue);
+ return *this;
+ }
+
+ Saturate<T> operator--(int) // postfix
+ {
+ return Saturate<T>(SaturateOp<T>(mValue)--);
+ }
+
+private:
+ T mValue;
+};
+
+} // namespace detail
+
+typedef detail::Saturate<int8_t> SaturateInt8;
+typedef detail::Saturate<int16_t> SaturateInt16;
+typedef detail::Saturate<int32_t> SaturateInt32;
+typedef detail::Saturate<uint8_t> SaturateUint8;
+typedef detail::Saturate<uint16_t> SaturateUint16;
+typedef detail::Saturate<uint32_t> SaturateUint32;
+
+} // namespace mozilla
+
+template<typename LhsT, typename RhsT>
+bool
+operator==(LhsT aLhs, const mozilla::detail::Saturate<RhsT>& aRhs)
+{
+ return aRhs.operator==(static_cast<RhsT>(aLhs));
+}
+
+template<typename LhsT, typename RhsT>
+bool
+operator!=(LhsT aLhs, const mozilla::detail::Saturate<RhsT>& aRhs)
+{
+ return !(aLhs == aRhs);
+}
+
+#endif // mozilla_Saturate_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Scoped.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Scoped.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Scoped.h
@@ -15,20 +15,16 @@
* Resource Acquisition Is Initialization is a programming idiom used
* to write robust code that is able to deallocate resources properly,
* even in presence of execution errors or exceptions that need to be
- * propagated. The Scoped* classes defined in this header perform the
+ * propagated. The Scoped* classes defined via the |SCOPED_TEMPLATE|
+ * and |MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLTE| macros perform the
* deallocation of the resource they hold once program execution
* reaches the end of the scope for which they have been defined.
+ * These macros have been used to automatically close file
+ * descriptors/file handles when reaching the end of the scope,
+ * graphics contexts, etc.
*
- * This header provides the following RAII classes:
- *
- * - |ScopedFreePtr| - a container for a pointer, that automatically calls
- * |free()| at the end of the scope;
- * - |ScopedDeletePtr| - a container for a pointer, that automatically calls
- * |delete| at the end of the scope;
- *
- * |ScopedDeleteArray| is removed in favor of |UniquePtr<T[]>|.
- *
- * The general scenario for each of the RAII classes is the following:
+ * The general scenario for RAII classes created by the above macros
+ * is the following:
*
* ScopedClass foo(create_value());
* // ... In this scope, |foo| is defined. Use |foo.get()| or |foo.rwget()|
@@ -44,14 +40,6 @@
* the end of the scope;
* - if |forget()| has been called, any control on the resource is unbound
* and the resource is not deallocated by the class.
- *
- * Extension:
- *
- * In addition, this header provides class |Scoped| and macros |SCOPED_TEMPLATE|
- * and |MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE| to simplify the definition
- * of RAII classes for other scenarios. These macros have been used to
- * automatically close file descriptors/file handles when reaching the end of
- * the scope, graphics contexts, etc.
*/
#include "mozilla/Assertions.h"
@@ -220,35 +208,6 @@
};
/*
- * ScopedFreePtr is a RAII wrapper for pointers that need to be free()d.
- *
- * struct S { ... };
- * ScopedFreePtr<S> foo = malloc(sizeof(S));
- * ScopedFreePtr<char> bar = strdup(str);
- */
-template<typename T>
-struct ScopedFreePtrTraits
-{
- typedef T* type;
- static T* empty() { return nullptr; }
- static void release(T* aPtr) { free(aPtr); }
-};
-SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
-
-/*
- * ScopedDeletePtr is a RAII wrapper for pointers that need to be deleted.
- *
- * struct S { ... };
- * ScopedDeletePtr<S> foo = new S();
- */
-template<typename T>
-struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
-{
- static void release(T* aPtr) { delete aPtr; }
-};
-SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
-
-/*
* MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE makes it easy to create scoped
* pointers for types with custom deleters; just overload
* TypeSpecificDelete(T*) in the same namespace as T to call the deleter for
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/SegmentedVector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/SegmentedVector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/SegmentedVector.h
@@ -159,7 +159,7 @@
// Returns false if the allocation failed. (If you are using an infallible
// allocation policy, use InfallibleAppend() instead.)
template<typename U>
- MOZ_WARN_UNUSED_RESULT bool Append(U&& aU)
+ MOZ_MUST_USE bool Append(U&& aU)
{
Segment* last = mSegments.getLast();
if (!last || last->Length() == kSegmentCapacity) {
@@ -218,6 +218,56 @@
}
}
+ // Equivalent to calling |PopLast| |aNumElements| times, but potentially
+ // more efficient.
+ void PopLastN(uint32_t aNumElements)
+ {
+ MOZ_ASSERT(aNumElements <= Length());
+
+ Segment* last;
+
+ // Pop full segments for as long as we can. Note that this loop
+ // cleanly handles the case when the initial last segment is not
+ // full and we are popping more elements than said segment contains.
+ do {
+ last = mSegments.getLast();
+
+ // The list is empty. We're all done.
+ if (!last) {
+ return;
+ }
+
+ // Check to see if the list contains too many elements. Handle
+ // that in the epilogue.
+ uint32_t segmentLen = last->Length();
+ if (segmentLen > aNumElements) {
+ break;
+ }
+
+ // Destroying the segment destroys all elements contained therein.
+ mSegments.popLast();
+ last->~Segment();
+ this->free_(last);
+
+ MOZ_ASSERT(aNumElements >= segmentLen);
+ aNumElements -= segmentLen;
+ if (aNumElements == 0) {
+ return;
+ }
+ } while (true);
+
+ // Handle the case where the last segment contains more elements
+ // than we want to pop.
+ MOZ_ASSERT(last);
+ MOZ_ASSERT(last == mSegments.getLast());
+ MOZ_ASSERT(aNumElements != 0);
+ MOZ_ASSERT(aNumElements < last->Length());
+ for (uint32_t i = 0; i < aNumElements; ++i) {
+ last->PopLast();
+ }
+ MOZ_ASSERT(last->Length() != 0);
+ }
+
// Use this class to iterate over a SegmentedVector, like so:
//
// for (auto iter = v.Iter(); !iter.Done(); iter.Next()) {
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Snprintf.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Snprintf.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Snprintf.h
@@ -1,50 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/* Polyfills snprintf() on platforms that don't provide it, and provides
- * related utilities. */
-
-#ifndef mozilla_Snprintf_h_
-#define mozilla_Snprintf_h_
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-// Older MSVC versions do not provide snprintf(), but they do provide
-// vsnprintf(), which has the same semantics except that if the number of
-// characters written equals the buffer size, it does not write a null
-// terminator, so we wrap it to do so.
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#include "mozilla/Attributes.h"
-MOZ_ALWAYS_INLINE int snprintf(char* buffer, size_t n, const char* format, ...)
-{
- va_list args;
- va_start(args, format);
- int result = vsnprintf(buffer, n, format, args);
- va_end(args);
- buffer[n - 1] = '\0';
- return result;
-}
-#endif
-
-// In addition, in C++ code, on all platforms, provide an snprintf_literal()
-// function which uses template argument deduction to deduce the size of the
-// buffer, avoiding the need for the user to pass it in explicitly.
-#ifdef __cplusplus
-template <size_t N>
-int snprintf_literal(char (&buffer)[N], const char* format, ...)
-{
- va_list args;
- va_start(args, format);
- int result = vsnprintf(buffer, N, format, args);
- va_end(args);
- buffer[N - 1] = '\0';
- return result;
-}
-#endif
-
-#endif /* mozilla_Snprintf_h_ */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/SplayTree.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/SplayTree.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/SplayTree.h
@@ -56,7 +56,7 @@
T* mRoot;
public:
- MOZ_CONSTEXPR SplayTree()
+ constexpr SplayTree()
: mRoot(nullptr)
{}
@@ -76,19 +76,19 @@
return Comparator::compare(aValue, *last) == 0 ? last : nullptr;
}
- bool insert(T* aValue)
+ void insert(T* aValue)
{
MOZ_ASSERT(!find(*aValue), "Duplicate elements are not allowed.");
if (!mRoot) {
mRoot = aValue;
- return true;
+ return;
}
T* last = lookup(*aValue);
int cmp = Comparator::compare(*aValue, *last);
finishInsertion(last, cmp, aValue);
- return true;
+ return;
}
T* findOrInsert(const T& aValue);
@@ -194,7 +194,7 @@
return parent;
}
- T* finishInsertion(T* aLast, int32_t aCmp, T* aNew)
+ void finishInsertion(T* aLast, int32_t aCmp, T* aNew)
{
MOZ_ASSERT(aCmp, "Nodes shouldn't be equal!");
@@ -204,7 +204,6 @@
aNew->mParent = aLast;
splay(aNew);
- return aNew;
}
/**
@@ -321,7 +320,9 @@
return last;
}
- return finishInsertion(last, cmp, new T(aValue));
+ T* t = new T(aValue);
+ finishInsertion(last, cmp, t);
+ return t;
}
} /* namespace mozilla */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Sprintf.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Sprintf.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Sprintf.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Provides a safer sprintf for printing to fixed-size character arrays. */
+
+#ifndef mozilla_Sprintf_h_
+#define mozilla_Sprintf_h_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+
+#ifdef __cplusplus
+
+template <size_t N>
+int VsprintfLiteral(char (&buffer)[N], const char* format, va_list args)
+{
+ MOZ_ASSERT(format != buffer);
+ int result = vsnprintf(buffer, N, format, args);
+ buffer[N - 1] = '\0';
+ return result;
+}
+
+template <size_t N>
+MOZ_FORMAT_PRINTF(2, 3)
+int SprintfLiteral(char (&buffer)[N], const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ int result = VsprintfLiteral(buffer, format, args);
+ va_end(args);
+ return result;
+}
+
+#endif
+#endif /* mozilla_Sprintf_h_ */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StackWalk.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StackWalk.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StackWalk.h
@@ -52,8 +52,6 @@
* May skip some stack frames due to compiler optimizations or code
* generation.
*
- * Note: this (and other helper methods) will only be available when
- * MOZ_STACKWALKING is defined, so any new consumers must #if based on that.
*/
MFBT_API bool
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StackWalk_windows.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StackWalk_windows.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StackWalk_windows.h
@@ -0,0 +1,21 @@
+#ifndef mozilla_StackWalk_windows_h
+#define mozilla_StackWalk_windows_h
+
+#include "mozilla/Types.h"
+
+/**
+ * Allow stack walkers to work around the egregious win64 dynamic lookup table
+ * list API by locking around SuspendThread to avoid deadlock.
+ *
+ * See comment in StackWalk.cpp
+ */
+MFBT_API void
+AcquireStackWalkWorkaroundLock();
+
+MFBT_API bool
+TryAcquireStackWalkWorkaroundLock();
+
+MFBT_API void
+ReleaseStackWalkWorkaroundLock();
+
+#endif // mozilla_StackWalk_windows_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StaticAnalysisFunctions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StaticAnalysisFunctions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/StaticAnalysisFunctions.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_StaticAnalysisFunctions_h
+#define mozilla_StaticAnalysisFunctions_h
+
+#ifndef __cplusplus
+#ifndef bool
+#include <stdbool.h>
+#endif
+#endif
+/*
+ * Functions that are used as markers in Gecko code for static analysis. Their
+ * purpose is to have different AST nodes generated during compile time and to
+ * match them based on different checkers implemented in build/clang-plugin
+ */
+
+#ifdef MOZ_CLANG_PLUGIN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * MOZ_AssertAssignmentTest - used in MOZ_ASSERT in order to test the possible
+ * presence of assignment instead of logical comparisons.
+ *
+ * Example:
+ * MOZ_ASSERT(retVal = true);
+ */
+static MOZ_ALWAYS_INLINE bool MOZ_AssertAssignmentTest(bool exprResult) {
+ return exprResult;
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#define MOZ_CHECK_ASSERT_ASSIGNMENT(expr) MOZ_AssertAssignmentTest(!!(expr))
+
+#else
+
+#define MOZ_CHECK_ASSERT_ASSIGNMENT(expr) (!!(expr))
+
+#endif /* MOZ_CLANG_PLUGIN */
+#endif /* StaticAnalysisFunctions_h */
\ No newline at end of file
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TextUtils.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TextUtils.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TextUtils.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Character/text operations. */
+
+#ifndef mozilla_TextUtils_h
+#define mozilla_TextUtils_h
+
+#include "mozilla/TypeTraits.h"
+
+namespace mozilla {
+
+namespace detail {
+
+template<typename Char>
+class MakeUnsignedChar
+ : public MakeUnsigned<Char>
+{};
+
+template<>
+class MakeUnsignedChar<char16_t>
+{
+public:
+ using Type = char16_t;
+};
+
+template<>
+class MakeUnsignedChar<char32_t>
+{
+public:
+ using Type = char32_t;
+};
+
+} // namespace detail
+
+/**
+ * Returns true iff |aChar| matches [a-zA-Z].
+ *
+ * This function is basically what you thought isalpha was, except its behavior
+ * doesn't depend on the user's current locale.
+ */
+template<typename Char>
+constexpr bool
+IsAsciiAlpha(Char aChar)
+{
+ using UnsignedChar = typename detail::MakeUnsignedChar<Char>::Type;
+ return ('a' <= static_cast<UnsignedChar>(aChar) &&
+ static_cast<UnsignedChar>(aChar) <= 'z') ||
+ ('A' <= static_cast<UnsignedChar>(aChar) &&
+ static_cast<UnsignedChar>(aChar) <= 'Z');
+}
+
+} // namespace mozilla
+
+#endif /* mozilla_TextUtils_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ThreadLocal.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ThreadLocal.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/ThreadLocal.h
@@ -42,11 +42,28 @@
typedef sig_atomic_t sig_safe_t;
#endif
+namespace detail {
+
+#if defined(HAVE_THREAD_TLS_KEYWORD)
+#define MOZ_HAS_THREAD_LOCAL
+#endif
+
/*
* Thread Local Storage helpers.
*
* Usage:
*
+ * Do not directly instantiate this class. Instead, use the
+ * MOZ_THREAD_LOCAL macro to declare or define instances. The macro
+ * takes a type name as its argument.
+ *
+ * Declare like this:
+ * extern MOZ_THREAD_LOCAL(int) tlsInt;
+ * Define like this:
+ * MOZ_THREAD_LOCAL(int) tlsInt;
+ * or:
+ * static MOZ_THREAD_LOCAL(int) tlsInt;
+ *
* Only static-storage-duration (e.g. global variables, or static class members)
* objects of this class should be instantiated. This class relies on
* zero-initialization, which is implicit for static-storage-duration objects.
@@ -56,9 +73,10 @@
*
* // Create a TLS item.
* //
- * // Note that init() should be invoked exactly once, before any usage of set()
- * // or get().
- * mozilla::ThreadLocal<int> tlsKey;
+ * // Note that init() should be invoked before the first use of set()
+ * // or get(). It is ok to call it multiple times. This must be
+ * // called in a way that avoids possible races with other threads.
+ * MOZ_THREAD_LOCAL(int) tlsKey;
* if (!tlsKey.init()) {
* // deal with the error
* }
@@ -72,6 +90,7 @@
template<typename T>
class ThreadLocal
{
+#ifndef MOZ_HAS_THREAD_LOCAL
#if defined(XP_WIN)
typedef unsigned long key_t;
#else
@@ -93,19 +112,38 @@
{
typedef S *Type;
};
+#endif
+
+ bool initialized() const {
+#ifdef MOZ_HAS_THREAD_LOCAL
+ return true;
+#else
+ return mInited;
+#endif
+ }
public:
- MOZ_WARN_UNUSED_RESULT inline bool init();
+ // __thread does not allow non-trivial constructors, but we can
+ // instead rely on zero-initialization.
+#ifndef MOZ_HAS_THREAD_LOCAL
+ ThreadLocal()
+ : mKey(0), mInited(false)
+ {}
+#endif
+
+ MOZ_MUST_USE inline bool init();
inline T get() const;
inline void set(const T aValue);
- bool initialized() const { return mInited; }
-
private:
+#ifdef MOZ_HAS_THREAD_LOCAL
+ T mValue;
+#else
key_t mKey;
bool mInited;
+#endif
};
template<typename T>
@@ -118,20 +156,29 @@
static_assert(sizeof(T) <= sizeof(void*),
"mozilla::ThreadLocal can't be used for types larger than "
"a pointer");
- MOZ_ASSERT(!initialized());
+
+#ifdef MOZ_HAS_THREAD_LOCAL
+ return true;
+#else
+ if (!initialized()) {
#ifdef XP_WIN
- mKey = TlsAlloc();
- mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
+ mKey = TlsAlloc();
+ mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
#else
- mInited = !pthread_key_create(&mKey, nullptr);
+ mInited = !pthread_key_create(&mKey, nullptr);
#endif
+ }
return mInited;
+#endif
}
template<typename T>
inline T
ThreadLocal<T>::get() const
{
+#ifdef MOZ_HAS_THREAD_LOCAL
+ return mValue;
+#else
MOZ_ASSERT(initialized());
void* h;
#ifdef XP_WIN
@@ -140,12 +187,16 @@
h = pthread_getspecific(mKey);
#endif
return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
+#endif
}
template<typename T>
inline void
ThreadLocal<T>::set(const T aValue)
{
+#ifdef MOZ_HAS_THREAD_LOCAL
+ mValue = aValue;
+#else
MOZ_ASSERT(initialized());
void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
#ifdef XP_WIN
@@ -156,8 +207,16 @@
if (!succeeded) {
MOZ_CRASH();
}
+#endif
}
+#ifdef MOZ_HAS_THREAD_LOCAL
+#define MOZ_THREAD_LOCAL(TYPE) __thread mozilla::detail::ThreadLocal<TYPE>
+#else
+#define MOZ_THREAD_LOCAL(TYPE) mozilla::detail::ThreadLocal<TYPE>
+#endif
+
+} // namespace detail
} // namespace mozilla
#endif /* mozilla_ThreadLocal_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TimeStamp.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TimeStamp.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TimeStamp.h
@@ -62,7 +62,7 @@
{
public:
// The default duration is 0.
- MOZ_CONSTEXPR BaseTimeDuration() : mValue(0) {}
+ constexpr BaseTimeDuration() : mValue(0) {}
// Allow construction using '0' as the initial value, for readability,
// but no other numbers (so we don't have any implicit unit conversions).
struct _SomethingVeryRandomHere;
@@ -395,7 +395,7 @@
/**
* Initialize to the "null" moment
*/
- MOZ_CONSTEXPR TimeStamp() : mValue(0) {}
+ constexpr TimeStamp() : mValue(0) {}
// Default copy-constructor and assignment are OK
/**
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TimeStamp_windows.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TimeStamp_windows.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TimeStamp_windows.h
@@ -30,7 +30,7 @@
MFBT_API uint64_t CheckQPC(const TimeStampValue& aOther) const;
struct _SomethingVeryRandomHere;
- MOZ_CONSTEXPR TimeStampValue(_SomethingVeryRandomHere* aNullValue)
+ constexpr TimeStampValue(_SomethingVeryRandomHere* aNullValue)
: mGTC(0)
, mQPC(0)
, mHasQPC(false)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Tuple.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Tuple.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Tuple.h
@@ -95,7 +95,12 @@
* of an empty tuple).
*/
template<std::size_t Index>
-struct TupleImpl<Index> {};
+struct TupleImpl<Index> {
+ bool operator==(const TupleImpl<Index>& aOther) const
+ {
+ return true;
+ }
+};
/*
* One node of the recursive inheritance hierarchy. It stores the element at
@@ -182,6 +187,10 @@
Tail(*this) = Move(Tail(aOther));
return *this;
}
+ bool operator==(const TupleImpl& aOther) const
+ {
+ return Head(*this) == Head(aOther) && Tail(*this) == Tail(aOther);
+ }
private:
HeadT mHead; // The element stored at this index in the tuple.
};
@@ -246,6 +255,10 @@
static_cast<Impl&>(*this) = Move(aOther);
return *this;
}
+ bool operator==(const Tuple& aOther) const
+ {
+ return static_cast<const Impl&>(*this) == static_cast<const Impl&>(aOther);
+ }
};
/**
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TypeTraits.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TypeTraits.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TypeTraits.h
@@ -98,9 +98,7 @@
template<> struct IsIntegralHelper<unsigned long long> : TrueType {};
template<> struct IsIntegralHelper<bool> : TrueType {};
template<> struct IsIntegralHelper<wchar_t> : TrueType {};
-#ifdef MOZ_CHAR16_IS_NOT_WCHAR
template<> struct IsIntegralHelper<char16_t> : TrueType {};
-#endif
} /* namespace detail */
@@ -112,9 +110,6 @@
* mozilla::IsIntegral<const long>::value is true;
* mozilla::IsIntegral<int*>::value is false;
* mozilla::IsIntegral<double>::value is false;
- *
- * Note that the behavior of IsIntegral on char16_t and char32_t is
- * unspecified.
*/
template<typename T>
struct IsIntegral : detail::IsIntegralHelper<typename RemoveCV<T>::Type>
@@ -355,6 +350,41 @@
: IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value>
{};
+namespace detail {
+
+template<typename T>
+struct IsMemberPointerHelper : FalseType {};
+
+template<typename T, typename U>
+struct IsMemberPointerHelper<T U::*> : TrueType {};
+
+} // namespace detail
+
+/**
+ * IsMemberPointer determines whether a type is pointer to non-static member
+ * object or a pointer to non-static member function.
+ *
+ * mozilla::IsMemberPointer<int(cls::*)>::value is true
+ * mozilla::IsMemberPointer<int*>::value is false
+ */
+template<typename T>
+struct IsMemberPointer
+ : detail::IsMemberPointerHelper<typename RemoveCV<T>::Type>
+{};
+
+/**
+ * IsScalar determines whether a type is a scalar type.
+ *
+ * mozilla::IsScalar<int>::value is true
+ * mozilla::IsScalar<int*>::value is true
+ * mozilla::IsScalar<cls>::value is false
+ */
+template<typename T>
+struct IsScalar
+ : IntegralConstant<bool, IsArithmetic<T>::value || IsEnum<T>::value ||
+ IsPointer<T>::value || IsMemberPointer<T>::value>
+{};
+
/* 20.9.4.3 Type properties [meta.unary.prop] */
/**
@@ -409,9 +439,7 @@
template<> struct IsPod<float> : TrueType {};
template<> struct IsPod<double> : TrueType {};
template<> struct IsPod<wchar_t> : TrueType {};
-#ifdef MOZ_CHAR16_IS_NOT_WCHAR
template<> struct IsPod<char16_t> : TrueType {};
-#endif
template<typename T> struct IsPod<T*> : TrueType {};
namespace detail {
@@ -544,6 +572,27 @@
template<typename T>
struct IsUnsigned : detail::IsUnsignedHelper<T> {};
+namespace detail {
+
+struct DoIsDestructibleImpl
+{
+ template<typename T, typename = decltype(DeclVal<T&>().~T())>
+ static TrueType test(int);
+ template<typename T>
+ static FalseType test(...);
+};
+
+template<typename T>
+struct IsDestructibleImpl : public DoIsDestructibleImpl
+{
+ typedef decltype(test<T>(0)) Type;
+};
+
+} // namespace detail
+
+template<typename T>
+struct IsDestructible : public detail::IsDestructibleImpl<T>::Type {};
+
/* 20.9.5 Type property queries [meta.unary.prop.query] */
/* 20.9.6 Relationships between types [meta.rel] */
@@ -644,18 +693,15 @@
namespace detail {
-// This belongs inside ConvertibleTester, but it's pulled out to
-// work around a bug in the compiler used for hazard builds.
-template <typename To>
-static void ConvertibleTestHelper(To);
-
template<typename From, typename To>
struct ConvertibleTester
{
private:
- template<typename From1, typename To1,
- typename = decltype(ConvertibleTestHelper<To1>(DeclVal<From>()))>
- static char test(int);
+ template<typename To1>
+ static char test_helper(To1);
+
+ template<typename From1, typename To1>
+ static decltype(test_helper<To1>(DeclVal<From1>())) test(int);
template<typename From1, typename To1>
static int test(...);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TypedEnumBits.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TypedEnumBits.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/TypedEnumBits.h
@@ -47,34 +47,34 @@
const E mValue;
public:
- explicit MOZ_CONSTEXPR CastableTypedEnumResult(E aValue)
+ explicit constexpr CastableTypedEnumResult(E aValue)
: mValue(aValue)
{}
- MOZ_CONSTEXPR operator E() const { return mValue; }
+ constexpr operator E() const { return mValue; }
template<typename DestinationType>
- MOZ_EXPLICIT_CONVERSION MOZ_CONSTEXPR
+ explicit constexpr
operator DestinationType() const { return DestinationType(mValue); }
- MOZ_CONSTEXPR bool operator !() const { return !bool(mValue); }
+ constexpr bool operator !() const { return !bool(mValue); }
};
#define MOZ_CASTABLETYPEDENUMRESULT_BINOP(Op, OtherType, ReturnType) \
template<typename E> \
-MOZ_CONSTEXPR ReturnType \
+constexpr ReturnType \
operator Op(const OtherType& aE, const CastableTypedEnumResult<E>& aR) \
{ \
return ReturnType(aE Op OtherType(aR)); \
} \
template<typename E> \
-MOZ_CONSTEXPR ReturnType \
+constexpr ReturnType \
operator Op(const CastableTypedEnumResult<E>& aR, const OtherType& aE) \
{ \
return ReturnType(OtherType(aR) Op aE); \
} \
template<typename E> \
-MOZ_CONSTEXPR ReturnType \
+constexpr ReturnType \
operator Op(const CastableTypedEnumResult<E>& aR1, \
const CastableTypedEnumResult<E>& aR2) \
{ \
@@ -90,7 +90,7 @@
MOZ_CASTABLETYPEDENUMRESULT_BINOP(&&, bool, bool)
template <typename E>
-MOZ_CONSTEXPR CastableTypedEnumResult<E>
+constexpr CastableTypedEnumResult<E>
operator ~(const CastableTypedEnumResult<E>& aR)
{
return CastableTypedEnumResult<E>(~(E(aR)));
@@ -123,7 +123,7 @@
} // namespace mozilla
#define MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, Op) \
- inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
+ inline constexpr mozilla::CastableTypedEnumResult<Name> \
operator Op(Name a, Name b) \
{ \
typedef mozilla::CastableTypedEnumResult<Name> Result; \
@@ -145,7 +145,7 @@
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, |) \
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, &) \
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, ^) \
- inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
+ inline constexpr mozilla::CastableTypedEnumResult<Name> \
operator~(Name a) \
{ \
typedef mozilla::CastableTypedEnumResult<Name> Result; \
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Types.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Types.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Types.h
@@ -89,7 +89,7 @@
* symbols. We add the weak attribute to the import version of the MFBT API
* macros to exploit this.
*/
-# if defined(MOZ_GLUE_IN_PROGRAM) && !defined(MOZILLA_XPCOMRT_API)
+# if defined(MOZ_GLUE_IN_PROGRAM)
# define MFBT_API __attribute__((weak)) MOZ_IMPORT_API
# define MFBT_DATA __attribute__((weak)) MOZ_IMPORT_DATA
# else
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/UniquePtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/UniquePtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/UniquePtr.h
@@ -25,6 +25,39 @@
namespace mozilla {
+namespace detail {
+
+struct HasPointerTypeHelper
+{
+ template <class U> static double Test(...);
+ template <class U> static char Test(typename U::pointer* = 0);
+};
+
+template <class T>
+class HasPointerType : public IntegralConstant<bool, sizeof(HasPointerTypeHelper::Test<T>(0)) == 1>
+{
+};
+
+template <class T, class D, bool = HasPointerType<D>::value>
+struct PointerTypeImpl
+{
+ typedef typename D::pointer Type;
+};
+
+template <class T, class D>
+struct PointerTypeImpl<T, D, false>
+{
+ typedef T* Type;
+};
+
+template <class T, class D>
+struct PointerType
+{
+ typedef typename PointerTypeImpl<T, typename RemoveReference<D>::Type>::Type Type;
+};
+
+} // namespace detail
+
/**
* UniquePtr is a smart pointer that wholly owns a resource. Ownership may be
* transferred out of a UniquePtr through explicit action, but otherwise the
@@ -127,10 +160,11 @@
* The constructors and mutating methods only accept array pointers (not T*, U*
* that converts to T*, or UniquePtr<U[]> or UniquePtr<U>) or |nullptr|.
*
- * It's perfectly okay to return a UniquePtr from a method to assure the related
- * resource is properly deleted. You'll need to use |Move()| when returning a
- * local UniquePtr. Otherwise you can return |nullptr|, or you can return
- * |UniquePtr(ptr)|.
+ * It's perfectly okay for a function to return a UniquePtr. This transfers
+ * the UniquePtr's sole ownership of the data, to the fresh UniquePtr created
+ * in the calling function, that will then solely own that data. Such functions
+ * can return a local variable UniquePtr, |nullptr|, |UniquePtr(ptr)| where
+ * |ptr| is a |T*|, or a UniquePtr |Move()|'d from elsewhere.
*
* UniquePtr will commonly be a member of a class, with lifetime equivalent to
* that of that class. If you want to expose the related resource, you could
@@ -154,9 +188,9 @@
class UniquePtr
{
public:
- typedef T* Pointer;
typedef T ElementType;
typedef D DeleterType;
+ typedef typename detail::PointerType<T, DeleterType>::Type Pointer;
private:
Pair<Pointer, DeleterType> mTuple;
@@ -171,7 +205,7 @@
/**
* Construct a UniquePtr containing |nullptr|.
*/
- MOZ_CONSTEXPR UniquePtr()
+ constexpr UniquePtr()
: mTuple(static_cast<Pointer>(nullptr), DeleterType())
{
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
@@ -226,7 +260,7 @@
}
UniquePtr(UniquePtr&& aOther)
- : mTuple(aOther.release(), Forward<DeleterType>(aOther.getDeleter()))
+ : mTuple(aOther.release(), Forward<DeleterType>(aOther.get_deleter()))
{}
MOZ_IMPLICIT
@@ -247,7 +281,7 @@
? IsSame<D, E>::value
: IsConvertible<E, D>::value),
int>::Type aDummy = 0)
- : mTuple(aOther.release(), Forward<E>(aOther.getDeleter()))
+ : mTuple(aOther.release(), Forward<E>(aOther.get_deleter()))
{
}
@@ -256,7 +290,7 @@
UniquePtr& operator=(UniquePtr&& aOther)
{
reset(aOther.release());
- getDeleter() = Forward<DeleterType>(aOther.getDeleter());
+ get_deleter() = Forward<DeleterType>(aOther.get_deleter());
return *this;
}
@@ -270,7 +304,7 @@
"can't assign from UniquePtr holding an array");
reset(aOther.release());
- getDeleter() = Forward<E>(aOther.getDeleter());
+ get_deleter() = Forward<E>(aOther.get_deleter());
return *this;
}
@@ -291,10 +325,10 @@
Pointer get() const { return ptr(); }
- DeleterType& getDeleter() { return del(); }
- const DeleterType& getDeleter() const { return del(); }
+ DeleterType& get_deleter() { return del(); }
+ const DeleterType& get_deleter() const { return del(); }
- Pointer release()
+ MOZ_MUST_USE Pointer release()
{
Pointer p = ptr();
ptr() = nullptr;
@@ -306,7 +340,7 @@
Pointer old = ptr();
ptr() = aPtr;
if (old != nullptr) {
- getDeleter()(old);
+ get_deleter()(old);
}
}
@@ -338,7 +372,7 @@
/**
* Construct a UniquePtr containing nullptr.
*/
- MOZ_CONSTEXPR UniquePtr()
+ constexpr UniquePtr()
: mTuple(static_cast<Pointer>(nullptr), DeleterType())
{
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
@@ -395,7 +429,7 @@
= delete;
UniquePtr(UniquePtr&& aOther)
- : mTuple(aOther.release(), Forward<DeleterType>(aOther.getDeleter()))
+ : mTuple(aOther.release(), Forward<DeleterType>(aOther.get_deleter()))
{}
MOZ_IMPLICIT
@@ -411,7 +445,7 @@
UniquePtr& operator=(UniquePtr&& aOther)
{
reset(aOther.release());
- getDeleter() = Forward<DeleterType>(aOther.getDeleter());
+ get_deleter() = Forward<DeleterType>(aOther.get_deleter());
return *this;
}
@@ -426,10 +460,10 @@
T& operator[](decltype(sizeof(int)) aIndex) const { return get()[aIndex]; }
Pointer get() const { return mTuple.first(); }
- DeleterType& getDeleter() { return mTuple.second(); }
- const DeleterType& getDeleter() const { return mTuple.second(); }
+ DeleterType& get_deleter() { return mTuple.second(); }
+ const DeleterType& get_deleter() const { return mTuple.second(); }
- Pointer release()
+ MOZ_MUST_USE Pointer release()
{
Pointer p = mTuple.first();
mTuple.first() = nullptr;
@@ -463,12 +497,24 @@
void operator=(const UniquePtr& aOther) = delete; // assign using Move()!
};
-/** A default deletion policy using plain old operator delete. */
+/**
+ * A default deletion policy using plain old operator delete.
+ *
+ * Note that this type can be specialized, but authors should beware of the risk
+ * that the specialization may at some point cease to match (either because it
+ * gets moved to a different compilation unit or the signature changes). If the
+ * non-specialized (|delete|-based) version compiles for that type but does the
+ * wrong thing, bad things could happen.
+ *
+ * This is a non-issue for types which are always incomplete (i.e. opaque handle
+ * types), since |delete|-ing such a type will always trigger a compilation
+ * error.
+ */
template<typename T>
class DefaultDelete
{
public:
- MOZ_CONSTEXPR DefaultDelete() {}
+ constexpr DefaultDelete() {}
template<typename U>
MOZ_IMPLICIT DefaultDelete(const DefaultDelete<U>& aOther,
@@ -488,7 +534,7 @@
class DefaultDelete<T[]>
{
public:
- MOZ_CONSTEXPR DefaultDelete() {}
+ constexpr DefaultDelete() {}
void operator()(T* aPtr) const
{
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/UniquePtrExtensions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/UniquePtrExtensions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/UniquePtrExtensions.h
@@ -37,6 +37,21 @@
typename detail::UniqueSelector<T>::KnownBound
MakeUniqueFallible(Args&&... aArgs) = delete;
+namespace detail {
+
+template<typename T>
+struct FreePolicy
+{
+ void operator()(const void* ptr) {
+ free(const_cast<void*>(ptr));
+ }
+};
+
+} // namespace detail
+
+template<typename T>
+using UniqueFreePtr = UniquePtr<T, detail::FreePolicy<T>>;
+
} // namespace mozilla
#endif // mozilla_UniquePtrExtensions_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Variant.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Variant.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Variant.h
@@ -7,10 +7,12 @@
/* A template class for tagged unions. */
#include <new>
+#include <stdint.h>
#include "mozilla/Alignment.h"
#include "mozilla/Assertions.h"
#include "mozilla/Move.h"
+#include "mozilla/TypeTraits.h"
#ifndef mozilla_Variant_h
#define mozilla_Variant_h
@@ -61,43 +63,112 @@
template<typename Needle, typename T, typename... Haystack>
struct IsVariant<Needle, T, Haystack...> : public IsVariant<Needle, Haystack...> { };
+/// SelectVariantTypeHelper is used in the implementation of SelectVariantType.
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper;
+
+template<typename T>
+struct SelectVariantTypeHelper<T>
+{ };
+
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper<T, T, Variants...>
+{
+ typedef T Type;
+};
+
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper<T, const T, Variants...>
+{
+ typedef const T Type;
+};
+
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper<T, const T&, Variants...>
+{
+ typedef const T& Type;
+};
+
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper<T, T&&, Variants...>
+{
+ typedef T&& Type;
+};
+
+template<typename T, typename Head, typename... Variants>
+struct SelectVariantTypeHelper<T, Head, Variants...>
+ : public SelectVariantTypeHelper<T, Variants...>
+{ };
+
+/**
+ * SelectVariantType takes a type T and a list of variant types Variants and
+ * yields a type Type, selected from Variants, that can store a value of type T
+ * or a reference to type T. If no such type was found, Type is not defined.
+ */
+template <typename T, typename... Variants>
+struct SelectVariantType
+ : public SelectVariantTypeHelper<typename RemoveConst<typename RemoveReference<T>::Type>::Type,
+ Variants...>
+{ };
+
+// Compute a fast, compact type that can be used to hold integral values that
+// distinctly map to every type in Ts.
+template<typename... Ts>
+struct VariantTag
+{
+private:
+ static const size_t TypeCount = sizeof...(Ts);
+
+public:
+ using Type =
+ typename Conditional<TypeCount < 3,
+ bool,
+ typename Conditional<TypeCount < (1 << 8),
+ uint_fast8_t,
+ size_t // stop caring past a certain point :-)
+ >::Type
+ >::Type;
+};
+
// TagHelper gets the given sentinel tag value for the given type T. This has to
-// be split out from VariantImplementation because you can't nest a partial template
-// specialization within a template class.
+// be split out from VariantImplementation because you can't nest a partial
+// template specialization within a template class.
-template<size_t N, typename T, typename U, typename Next, bool isMatch>
+template<typename Tag, size_t N, typename T, typename U, typename Next, bool isMatch>
struct TagHelper;
// In the case where T != U, we continue recursion.
-template<size_t N, typename T, typename U, typename Next>
-struct TagHelper<N, T, U, Next, false>
+template<typename Tag, size_t N, typename T, typename U, typename Next>
+struct TagHelper<Tag, N, T, U, Next, false>
{
- static size_t tag() { return Next::template tag<U>(); }
+ static Tag tag() { return Next::template tag<U>(); }
};
// In the case where T == U, return the tag number.
-template<size_t N, typename T, typename U, typename Next>
-struct TagHelper<N, T, U, Next, true>
+template<typename Tag, size_t N, typename T, typename U, typename Next>
+struct TagHelper<Tag, N, T, U, Next, true>
{
- static size_t tag() { return N; }
+ static Tag tag() { return Tag(N); }
};
-// The VariantImplementation template provides the guts of mozilla::Variant. We create
-// an VariantImplementation for each T in Ts... which handles construction,
-// destruction, etc for when the Variant's type is T. If the Variant's type is
-// not T, it punts the request on to the next VariantImplementation.
+// The VariantImplementation template provides the guts of mozilla::Variant. We
+// create a VariantImplementation for each T in Ts... which handles
+// construction, destruction, etc for when the Variant's type is T. If the
+// Variant's type isn't T, it punts the request on to the next
+// VariantImplementation.
-template<size_t N, typename... Ts>
+template<typename Tag, size_t N, typename... Ts>
struct VariantImplementation;
// The singly typed Variant / recursion base case.
-template<size_t N, typename T>
-struct VariantImplementation<N, T> {
+template<typename Tag, size_t N, typename T>
+struct VariantImplementation<Tag, N, T>
+{
template<typename U>
- static size_t tag() {
+ static Tag tag() {
static_assert(mozilla::IsSame<T, U>::value,
"mozilla::Variant: tag: bad type!");
- return N;
+ return Tag(N);
}
template<typename Variant>
@@ -122,22 +193,24 @@
}
template<typename Matcher, typename ConcreteVariant>
- static typename Matcher::ReturnType
- match(Matcher& aMatcher, ConcreteVariant& aV) {
+ static auto
+ match(Matcher&& aMatcher, ConcreteVariant& aV)
+ -> decltype(aMatcher.match(aV.template as<T>()))
+ {
return aMatcher.match(aV.template as<T>());
}
};
// VariantImplementation for some variant type T.
-template<size_t N, typename T, typename... Ts>
-struct VariantImplementation<N, T, Ts...>
+template<typename Tag, size_t N, typename T, typename... Ts>
+struct VariantImplementation<Tag, N, T, Ts...>
{
// The next recursive VariantImplementation.
- using Next = VariantImplementation<N + 1, Ts...>;
+ using Next = VariantImplementation<Tag, N + 1, Ts...>;
template<typename U>
- static size_t tag() {
- return TagHelper<N, T, U, Next, IsSame<T, U>::value>::tag();
+ static Tag tag() {
+ return TagHelper<Tag, N, T, U, Next, IsSame<T, U>::value>::tag();
}
template<typename Variant>
@@ -178,8 +251,9 @@
}
template<typename Matcher, typename ConcreteVariant>
- static typename Matcher::ReturnType
- match(Matcher& aMatcher, ConcreteVariant& aV)
+ static auto
+ match(Matcher&& aMatcher, ConcreteVariant& aV)
+ -> decltype(aMatcher.match(aV.template as<T>()))
{
if (aV.template is<T>()) {
return aMatcher.match(aV.template as<T>());
@@ -199,6 +273,39 @@
}
};
+/**
+ * AsVariantTemporary stores a value of type T to allow construction of a
+ * Variant value via type inference. Because T is copied and there's no
+ * guarantee that the copy can be elided, AsVariantTemporary is best used with
+ * primitive or very small types.
+ */
+template <typename T>
+struct AsVariantTemporary
+{
+ explicit AsVariantTemporary(const T& aValue)
+ : mValue(aValue)
+ {}
+
+ template<typename U>
+ explicit AsVariantTemporary(U&& aValue)
+ : mValue(Forward<U>(aValue))
+ {}
+
+ AsVariantTemporary(const AsVariantTemporary& aOther)
+ : mValue(aOther.mValue)
+ {}
+
+ AsVariantTemporary(AsVariantTemporary&& aOther)
+ : mValue(Move(aOther.mValue))
+ {}
+
+ AsVariantTemporary() = delete;
+ void operator=(const AsVariantTemporary&) = delete;
+ void operator=(AsVariantTemporary&&) = delete;
+
+ typename RemoveConst<typename RemoveReference<T>::Type>::Type mValue;
+};
+
} // namespace detail
/**
@@ -222,6 +329,18 @@
* Variant<char, uint32_t> v1('a');
* Variant<UniquePtr<A>, B, C> v2(MakeUnique<A>());
*
+ * Because specifying the full type of a Variant value is often verbose,
+ * AsVariant() can be used to construct a Variant value using type inference in
+ * contexts such as expressions or when returning values from functions. Because
+ * AsVariant() must copy or move the value into a temporary and this cannot
+ * necessarily be elided by the compiler, it's mostly appropriate only for use
+ * with primitive or very small types.
+ *
+ *
+ * Variant<char, uint32_t> Foo() { return AsVariant('x'); }
+ * // ...
+ * Variant<char, uint32_t> v1 = Foo(); // v1 holds char('x').
+ *
* All access to the contained value goes through type-safe accessors.
*
* void
@@ -275,11 +394,11 @@
* // Good!
* struct FooMatcher
* {
- * using ReturnType = char*;
- * ReturnType match(A& a) { ... }
- * ReturnType match(B& b) { ... }
- * ReturnType match(C& c) { ... }
- * ReturnType match(D& d) { ... } // Compile-time error to forget D!
+ * // The return type of all matchers must be identical.
+ * char* match(A& a) { ... }
+ * char* match(B& b) { ... }
+ * char* match(C& c) { ... }
+ * char* match(D& d) { ... } // Compile-time error to forget D!
* }
* char* foo(Variant<A, B, C, D>& v) {
* return v.match(FooMatcher());
@@ -313,18 +432,19 @@
* };
*/
template<typename... Ts>
-class Variant
+class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Variant
{
- using Impl = detail::VariantImplementation<0, Ts...>;
+ using Tag = typename detail::VariantTag<Ts...>::Type;
+ using Impl = detail::VariantImplementation<Tag, 0, Ts...>;
using RawData = AlignedStorage<detail::MaxSizeOf<Ts...>::size>;
- // Each type is given a unique size_t sentinel. This tag lets us keep track of
- // the contained variant value's type.
- size_t tag;
-
// Raw storage for the contained variant value.
RawData raw;
+ // Each type is given a unique tag value that lets us keep track of the
+ // contained variant value's type.
+ Tag tag;
+
void* ptr() {
return reinterpret_cast<void*>(&raw);
}
@@ -336,12 +456,24 @@
// perfect forwarding), so we have to remove those qualifiers here
// when ensuring that T is a variant of this type, and getting T's
// tag, etc.
- typename T = typename RemoveReference<typename RemoveConst<RefT>::Type>::Type,
- typename = typename EnableIf<detail::IsVariant<T, Ts...>::value, void>::Type>
+ typename T = typename detail::SelectVariantType<RefT, Ts...>::Type>
explicit Variant(RefT&& aT)
: tag(Impl::template tag<T>())
{
- new (ptr()) T(Forward<T>(aT));
+ new (ptr()) T(Forward<RefT>(aT));
+ }
+
+ /**
+ * Constructs this Variant from an AsVariantTemporary<T> such that T can be
+ * stored in one of the types allowable in this Variant. This is used in the
+ * implementation of AsVariant().
+ */
+ template<typename RefT,
+ typename T = typename detail::SelectVariantType<RefT, Ts...>::Type>
+ MOZ_IMPLICIT Variant(detail::AsVariantTemporary<RefT>&& aValue)
+ : tag(Impl::template tag<T>())
+ {
+ new (ptr()) T(Move(aValue.mValue));
}
/** Copy construction. */
@@ -374,6 +506,15 @@
return *this;
}
+ /** Move assignment from AsVariant(). */
+ template <typename T>
+ Variant& operator=(detail::AsVariantTemporary<T>&& aValue)
+ {
+ this->~Variant();
+ new (this) Variant(Move(aValue));
+ return *this;
+ }
+
~Variant()
{
Impl::destroy(*this);
@@ -438,23 +579,47 @@
return T(Move(as<T>()));
}
- // Exhaustive matching of all variant types no the contained value.
+ // Exhaustive matching of all variant types on the contained value.
/** Match on an immutable const reference. */
template<typename Matcher>
- typename Matcher::ReturnType
- match(Matcher& aMatcher) const {
+ auto
+ match(Matcher&& aMatcher) const
+ -> decltype(Impl::match(aMatcher, *this))
+ {
return Impl::match(aMatcher, *this);
}
- /** Match on a mutable non-const reference. */
+ /** Match on a mutable non-const reference. */
template<typename Matcher>
- typename Matcher::ReturnType
- match(Matcher& aMatcher) {
+ auto
+ match(Matcher&& aMatcher)
+ -> decltype(Impl::match(aMatcher, *this))
+ {
return Impl::match(aMatcher, *this);
}
};
+/*
+ * AsVariant() is used to construct a Variant<T,...> value containing the
+ * provided T value using type inference. It can be used to construct Variant
+ * values in expressions or return them from functions without specifying the
+ * entire Variant type.
+ *
+ * Because AsVariant() must copy or move the value into a temporary and this
+ * cannot necessarily be elided by the compiler, it's mostly appropriate only
+ * for use with primitive or very small types.
+ *
+ * AsVariant() returns a AsVariantTemporary value which is implicitly
+ * convertible to any Variant that can hold a value of type T.
+ */
+template<typename T>
+detail::AsVariantTemporary<T>
+AsVariant(T&& aValue)
+{
+ return detail::AsVariantTemporary<T>(Forward<T>(aValue));
+}
+
} // namespace mozilla
#endif /* mozilla_Variant_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Vector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Vector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/Vector.h
@@ -17,6 +17,7 @@
#include "mozilla/MathAlgorithms.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
+#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/ReentrancyGuard.h"
#include "mozilla/TemplateLib.h"
#include "mozilla/TypeTraits.h"
@@ -56,22 +57,13 @@
struct VectorImpl
{
/*
- * Constructs a default object in the uninitialized memory at *aDst.
+ * Constructs an object in the uninitialized memory at *aDst with aArgs.
*/
+ template<typename... Args>
MOZ_NONNULL(1)
- static inline void new_(T* aDst)
- {
- new(aDst) T();
- }
-
- /*
- * Constructs an object in the uninitialized memory at *aDst from aSrc.
- */
- template<typename U>
- MOZ_NONNULL(1)
- static inline void new_(T* aDst, U&& aU)
+ static inline void new_(T* aDst, Args&&... aArgs)
{
- new(aDst) T(Forward<U>(aU));
+ new(KnownNotNull, aDst) T(Forward<Args>(aArgs)...);
}
/* Destroys constructed objects in the range [aBegin, aEnd). */
@@ -137,7 +129,7 @@
* aNewCap has not overflowed, and (2) multiplying aNewCap by sizeof(T) will
* not overflow.
*/
- static inline bool
+ static inline MOZ_MUST_USE bool
growTo(Vector<T, N, AP>& aV, size_t aNewCap)
{
MOZ_ASSERT(!aV.usingInlineStorage());
@@ -168,15 +160,16 @@
template<typename T, size_t N, class AP>
struct VectorImpl<T, N, AP, true>
{
- static inline void new_(T* aDst)
- {
- *aDst = T();
- }
-
- template<typename U>
- static inline void new_(T* aDst, U&& aU)
+ template<typename... Args>
+ MOZ_NONNULL(1)
+ static inline void new_(T* aDst, Args&&... aArgs)
{
- *aDst = Forward<U>(aU);
+ // Explicitly construct a local object instead of using a temporary since
+ // T(args...) will be treated like a C-style cast in the unary case and
+ // allow unsafe conversions. Both forms should be equivalent to an
+ // optimizing compiler.
+ T temp(Forward<Args>(aArgs)...);
+ *aDst = temp;
}
static inline void destroy(T*, T*) {}
@@ -228,7 +221,7 @@
}
}
- static inline bool
+ static inline MOZ_MUST_USE bool
growTo(Vector<T, N, AP>& aV, size_t aNewCap)
{
MOZ_ASSERT(!aV.usingInlineStorage());
@@ -242,6 +235,20 @@
aV.mCapacity = aNewCap;
return true;
}
+
+ static inline void
+ podResizeToFit(Vector<T, N, AP>& aV)
+ {
+ if (aV.usingInlineStorage() || aV.mLength == aV.mCapacity) {
+ return;
+ }
+ T* newbuf = aV.template pod_realloc<T>(aV.mBegin, aV.mCapacity, aV.mLength);
+ if (MOZ_UNLIKELY(!newbuf)) {
+ return;
+ }
+ aV.mBegin = newbuf;
+ aV.mCapacity = aV.mLength;
+ }
};
// A struct for TestVector.cpp to access private internal fields.
@@ -281,8 +288,9 @@
friend struct detail::VectorTesting;
- bool growStorageBy(size_t aIncr);
- bool convertToHeapStorage(size_t aNewCap);
+ MOZ_MUST_USE bool growStorageBy(size_t aIncr);
+ MOZ_MUST_USE bool convertToHeapStorage(size_t aNewCap);
+ MOZ_MUST_USE bool maybeCheckSimulatedOOM(size_t aRequestedSize);
/* magic constants */
@@ -519,10 +527,24 @@
/* mutators */
/**
- * Given that the vector is empty and has no inline storage, grow to
- * |capacity|.
+ * Reverse the order of the elements in the vector in place.
+ */
+ void reverse();
+
+ /**
+ * Given that the vector is empty, grow the internal capacity to |aRequest|,
+ * keeping the length 0.
+ */
+ MOZ_MUST_USE bool initCapacity(size_t aRequest);
+
+ /**
+ * Given that the vector is empty, grow the internal capacity and length to
+ * |aRequest| leaving the elements' memory completely uninitialized (with all
+ * the associated hazards and caveats). This avoids the usual allocation-size
+ * rounding that happens in resize and overhead of initialization for elements
+ * that are about to be overwritten.
*/
- bool initCapacity(size_t aRequest);
+ MOZ_MUST_USE bool initLengthUninitialized(size_t aRequest);
/**
* If reserve(aRequest) succeeds and |aRequest >= length()|, then appending
@@ -532,7 +554,7 @@
* A request to reserve an amount less than the current length does not affect
* reserved space.
*/
- bool reserve(size_t aRequest);
+ MOZ_MUST_USE bool reserve(size_t aRequest);
/**
* Destroy elements in the range [end() - aIncr, end()). Does not deallocate
@@ -540,19 +562,25 @@
*/
void shrinkBy(size_t aIncr);
+ /**
+ * Destroy elements in the range [aNewLength, end()). Does not deallocate
+ * or unreserve storage for those elements.
+ */
+ void shrinkTo(size_t aNewLength);
+
/** Grow the vector by aIncr elements. */
- bool growBy(size_t aIncr);
+ MOZ_MUST_USE bool growBy(size_t aIncr);
/** Call shrinkBy or growBy based on whether newSize > length(). */
- bool resize(size_t aNewLength);
+ MOZ_MUST_USE bool resize(size_t aNewLength);
/**
* Increase the length of the vector, but don't initialize the new elements
* -- leave them as uninitialized memory.
*/
- bool growByUninitialized(size_t aIncr);
+ MOZ_MUST_USE bool growByUninitialized(size_t aIncr);
void infallibleGrowByUninitialized(size_t aIncr);
- bool resizeUninitialized(size_t aNewLength);
+ MOZ_MUST_USE bool resizeUninitialized(size_t aNewLength);
/** Shorthand for shrinkBy(length()). */
void clear();
@@ -561,6 +589,13 @@
void clearAndFree();
/**
+ * Calls the AllocPolicy's pod_realloc to release excess capacity. Since
+ * realloc is only safe on PODs, this method fails to compile if IsPod<T>
+ * is false.
+ */
+ void podResizeToFit();
+
+ /**
* If true, appending |aNeeded| elements won't reallocate elements storage.
* This *doesn't* mean that infallibleAppend may be used! You still must
* reserve the extra space, even if this method indicates that appends won't
@@ -575,25 +610,25 @@
* vector, instead of copying it. If it fails, |aU| is left unmoved. ("We are
* not amused.")
*/
- template<typename U> bool append(U&& aU);
+ template<typename U> MOZ_MUST_USE bool append(U&& aU);
/**
* Construct a T in-place as a new entry at the end of this vector.
*/
template<typename... Args>
- bool emplaceBack(Args&&... aArgs)
+ MOZ_MUST_USE bool emplaceBack(Args&&... aArgs)
{
if (!growByUninitialized(1))
return false;
- new (&back()) T(Forward<Args>(aArgs)...);
+ Impl::new_(&back(), Forward<Args>(aArgs)...);
return true;
}
template<typename U, size_t O, class BP>
- bool appendAll(const Vector<U, O, BP>& aU);
- bool appendN(const T& aT, size_t aN);
- template<typename U> bool append(const U* aBegin, const U* aEnd);
- template<typename U> bool append(const U* aBegin, size_t aLength);
+ MOZ_MUST_USE bool appendAll(const Vector<U, O, BP>& aU);
+ MOZ_MUST_USE bool appendN(const T& aT, size_t aN);
+ template<typename U> MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd);
+ template<typename U> MOZ_MUST_USE bool append(const U* aBegin, size_t aLength);
/*
* Guaranteed-infallible append operations for use upon vectors whose
@@ -620,7 +655,7 @@
void infallibleEmplaceBack(Args&&... aArgs)
{
infallibleGrowByUninitialized(1);
- new (&back()) T(Forward<Args>(aArgs)...);
+ Impl::new_(&back(), Forward<Args>(aArgs)...);
}
void popBack();
@@ -628,16 +663,34 @@
T popCopy();
/**
- * Transfers ownership of the internal buffer used by this vector to the
- * caller. (It's the caller's responsibility to properly deallocate this
- * buffer, in accordance with this vector's AllocPolicy.) After this call,
- * the vector is empty. Since the returned buffer may need to be allocated
- * (if the elements are currently stored in-place), the call can fail,
- * returning nullptr.
+ * If elements are stored in-place, return nullptr and leave this vector
+ * unmodified.
+ *
+ * Otherwise return this vector's elements buffer, and clear this vector as if
+ * by clearAndFree(). The caller now owns the buffer and is responsible for
+ * deallocating it consistent with this vector's AllocPolicy.
*
* N.B. Although a T*, only the range [0, length()) is constructed.
*/
- T* extractRawBuffer();
+ MOZ_MUST_USE T* extractRawBuffer();
+
+ /**
+ * If elements are stored in-place, allocate a new buffer, move this vector's
+ * elements into it, and return that buffer.
+ *
+ * Otherwise return this vector's elements buffer. The caller now owns the
+ * buffer and is responsible for deallocating it consistent with this vector's
+ * AllocPolicy.
+ *
+ * This vector is cleared, as if by clearAndFree(), when this method
+ * succeeds. This method fails and returns nullptr only if new elements buffer
+ * allocation fails.
+ *
+ * N.B. Only the range [0, length()) of the returned buffer is constructed.
+ * If any of these elements are uninitialized (as growByUninitialized
+ * enables), behavior is undefined.
+ */
+ MOZ_MUST_USE T* extractOrCopyRawBuffer();
/**
* Transfer ownership of an array of objects into the vector. The caller
@@ -665,7 +718,7 @@
* This is inherently a linear-time operation. Be careful!
*/
template<typename U>
- T* insert(T* aP, U&& aVal);
+ MOZ_MUST_USE T* insert(T* aP, U&& aVal);
/**
* Removes the element |aT|, which must fall in the bounds [begin, end),
@@ -767,7 +820,7 @@
{
MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
this->~Vector();
- new(this) Vector(Move(aRhs));
+ new(KnownNotNull, this) Vector(Move(aRhs));
return *this;
}
@@ -782,6 +835,18 @@
}
}
+template<typename T, size_t N, class AP>
+MOZ_ALWAYS_INLINE void
+Vector<T, N, AP>::reverse() {
+ MOZ_REENTRANCY_GUARD_ET_AL;
+ T* elems = mBegin;
+ size_t len = mLength;
+ size_t mid = len / 2;
+ for (size_t i = 0; i < mid; i++) {
+ Swap(elems[i], elems[len - i - 1]);
+ }
+}
+
/*
* This function will create a new heap buffer with capacity aNewCap,
* move all elements in the inline buffer to this new buffer,
@@ -916,6 +981,34 @@
template<typename T, size_t N, class AP>
inline bool
+Vector<T, N, AP>::initLengthUninitialized(size_t aRequest)
+{
+ if (!initCapacity(aRequest)) {
+ return false;
+ }
+ infallibleGrowByUninitialized(aRequest);
+ return true;
+}
+
+template<typename T, size_t N, class AP>
+inline bool
+Vector<T, N, AP>::maybeCheckSimulatedOOM(size_t aRequestedSize)
+{
+ if (aRequestedSize <= N) {
+ return true;
+ }
+
+#ifdef DEBUG
+ if (aRequestedSize <= mReserved) {
+ return true;
+ }
+#endif
+
+ return allocPolicy().checkSimulatedOOM();
+}
+
+template<typename T, size_t N, class AP>
+inline bool
Vector<T, N, AP>::reserve(size_t aRequest)
{
MOZ_REENTRANCY_GUARD_ET_AL;
@@ -923,10 +1016,8 @@
if (MOZ_UNLIKELY(!growStorageBy(aRequest - mLength))) {
return false;
}
- } else if (aRequest > N) {
- if (!allocPolicy().checkSimulatedOOM()) {
- return false;
- }
+ } else if (!maybeCheckSimulatedOOM(aRequest)) {
+ return false;
}
#ifdef DEBUG
if (aRequest > mReserved) {
@@ -949,6 +1040,14 @@
}
template<typename T, size_t N, class AP>
+MOZ_ALWAYS_INLINE void
+Vector<T, N, AP>::shrinkTo(size_t aNewLength)
+{
+ MOZ_ASSERT(aNewLength <= mLength);
+ shrinkBy(mLength - aNewLength);
+}
+
+template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE bool
Vector<T, N, AP>::growBy(size_t aIncr)
{
@@ -957,10 +1056,8 @@
if (MOZ_UNLIKELY(!growStorageBy(aIncr))) {
return false;
}
- } else if (aIncr + mLength > N) {
- if (!allocPolicy().checkSimulatedOOM()) {
- return false;
- }
+ } else if (!maybeCheckSimulatedOOM(mLength + aIncr)) {
+ return false;
}
MOZ_ASSERT(mLength + aIncr <= mCapacity);
T* newend = endNoCheck() + aIncr;
@@ -983,11 +1080,14 @@
if (MOZ_UNLIKELY(!growStorageBy(aIncr))) {
return false;
}
- } else if (aIncr + mLength > N) {
- if (!allocPolicy().checkSimulatedOOM()) {
- return false;
- }
+ } else if (!maybeCheckSimulatedOOM(mLength + aIncr)) {
+ return false;
}
+#ifdef DEBUG
+ if (mLength + aIncr > mReserved) {
+ mReserved = mLength + aIncr;
+ }
+#endif
infallibleGrowByUninitialized(aIncr);
return true;
}
@@ -996,13 +1096,8 @@
MOZ_ALWAYS_INLINE void
Vector<T, N, AP>::infallibleGrowByUninitialized(size_t aIncr)
{
- MOZ_ASSERT(mLength + aIncr <= mCapacity);
+ MOZ_ASSERT(mLength + aIncr <= reserved());
mLength += aIncr;
-#ifdef DEBUG
- if (mLength > mReserved) {
- mReserved = mLength;
- }
-#endif
}
template<typename T, size_t N, class AP>
@@ -1056,6 +1151,15 @@
}
template<typename T, size_t N, class AP>
+inline void
+Vector<T, N, AP>::podResizeToFit()
+{
+ // This function is only defined if IsPod is true and will fail to compile
+ // otherwise.
+ Impl::podResizeToFit(*this);
+}
+
+template<typename T, size_t N, class AP>
inline bool
Vector<T, N, AP>::canAppendWithoutRealloc(size_t aNeeded) const
{
@@ -1090,9 +1194,8 @@
if (MOZ_UNLIKELY(!growStorageBy(aNeeded))) {
return false;
}
- } else if (mLength + aNeeded > N) {
- if (!allocPolicy().checkSimulatedOOM())
- return false;
+ } else if (!maybeCheckSimulatedOOM(mLength + aNeeded)) {
+ return false;
}
#ifdef DEBUG
if (mLength + aNeeded > mReserved) {
@@ -1177,8 +1280,7 @@
if (MOZ_UNLIKELY(!growStorageBy(aNeeded))) {
return false;
}
- } else if (mLength + aNeeded > N) {
- if (!allocPolicy().checkSimulatedOOM())
+ } else if (!maybeCheckSimulatedOOM(mLength + aNeeded)) {
return false;
}
#ifdef DEBUG
@@ -1211,8 +1313,7 @@
if (MOZ_UNLIKELY(!growStorageBy(1))) {
return false;
}
- } else if (mLength + 1 > N) {
- if (!allocPolicy().checkSimulatedOOM())
+ } else if (!maybeCheckSimulatedOOM(mLength + 1)) {
return false;
}
#ifdef DEBUG
@@ -1263,29 +1364,49 @@
inline T*
Vector<T, N, AP>::extractRawBuffer()
{
- T* ret;
+ MOZ_REENTRANCY_GUARD_ET_AL;
+
if (usingInlineStorage()) {
- ret = this->template pod_malloc<T>(mLength);
- if (!ret) {
- return nullptr;
- }
- Impl::copyConstruct(ret, beginNoCheck(), endNoCheck());
- Impl::destroy(beginNoCheck(), endNoCheck());
- /* mBegin, mCapacity are unchanged. */
- mLength = 0;
- } else {
- ret = mBegin;
- mBegin = static_cast<T*>(mStorage.addr());
- mLength = 0;
- mCapacity = kInlineCapacity;
+ return nullptr;
+ }
+
+ T* ret = mBegin;
+ mBegin = static_cast<T*>(mStorage.addr());
+ mLength = 0;
+ mCapacity = kInlineCapacity;
#ifdef DEBUG
- mReserved = 0;
+ mReserved = 0;
#endif
- }
return ret;
}
template<typename T, size_t N, class AP>
+inline T*
+Vector<T, N, AP>::extractOrCopyRawBuffer()
+{
+ if (T* ret = extractRawBuffer()) {
+ return ret;
+ }
+
+ MOZ_REENTRANCY_GUARD_ET_AL;
+
+ T* copy = this->template pod_malloc<T>(mLength);
+ if (!copy) {
+ return nullptr;
+ }
+
+ Impl::moveConstruct(copy, beginNoCheck(), endNoCheck());
+ Impl::destroy(beginNoCheck(), endNoCheck());
+ mBegin = static_cast<T*>(mStorage.addr());
+ mLength = 0;
+ mCapacity = kInlineCapacity;
+#ifdef DEBUG
+ mReserved = 0;
+#endif
+ return copy;
+}
+
+template<typename T, size_t N, class AP>
inline void
Vector<T, N, AP>::replaceRawBuffer(T* aP, size_t aLength)
{
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/WeakPtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/WeakPtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/WeakPtr.h
@@ -76,6 +76,58 @@
#include <string.h>
+// Weak referencing is not implemeted as thread safe. When a WeakPtr
+// is created or dereferenced on thread A but the real object is just
+// being Released() on thread B, there is a possibility of a race
+// when the proxy object (detail::WeakReference) is notified about
+// the real object destruction just between when thread A is storing
+// the object pointer locally and is about to add a reference to it.
+//
+// Hence, a non-null weak proxy object is considered to have a single
+// "owning thread". It means that each query for a weak reference,
+// its dereference, and destruction of the real object must all happen
+// on a single thread. The following macros implement assertions for
+// checking these conditions.
+//
+// We disable this on MinGW. MinGW has two threading models: win32
+// API based, which disables std::thread; and POSIX based which
+// enables it but requires an emulation library (winpthreads).
+// Rather than attempting to switch to pthread emulation at this point,
+// we are disabling the std::thread based assertion checking.
+//
+// In the future, to enable it we could
+// a. have libgcc/stdc++ support win32 threads natively
+// b. switch to POSIX-based threading in MinGW with pthread emulation
+// c. refactor it to not use std::thread
+
+#if !defined(__MINGW32__) && (defined(DEBUG) || (defined(NIGHTLY_BUILD) && !defined(MOZ_PROFILING)))
+
+#include <thread>
+#define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK \
+ std::thread::id _owningThread; \
+ bool _empty; // If it was initialized as a placeholder with mPtr = nullptr.
+#define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() \
+ do { \
+ _owningThread = std::this_thread::get_id(); \
+ _empty = !p; \
+ } while (false)
+#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() \
+ MOZ_DIAGNOSTIC_ASSERT(_empty || _owningThread == std::this_thread::get_id(), \
+ "WeakPtr used on multiple threads")
+#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(that) \
+ (that)->AssertThreadSafety();
+
+#define MOZ_WEAKPTR_THREAD_SAFETY_CHECKING 1
+
+#else
+
+#define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK
+#define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() do { } while (false)
+#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() do { } while (false)
+#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(that) do { } while (false)
+
+#endif
+
namespace mozilla {
template <typename T> class WeakPtr;
@@ -96,9 +148,15 @@
class WeakReference : public ::mozilla::RefCounted<WeakReference<T> >
{
public:
- explicit WeakReference(T* p) : mPtr(p) {}
+ explicit WeakReference(T* p) : mPtr(p)
+ {
+ MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK();
+ }
- T* get() const { return mPtr; }
+ T* get() const {
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY();
+ return mPtr;
+ }
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
const char* typeName() const
@@ -110,12 +168,20 @@
size_t typeSize() const { return sizeof(*this); }
#endif
+#ifdef MOZ_WEAKPTR_THREAD_SAFETY_CHECKING
+ void AssertThreadSafety() { MOZ_WEAKPTR_ASSERT_THREAD_SAFETY(); }
+#endif
+
private:
friend class mozilla::SupportsWeakPtr<T>;
- void detach() { mPtr = nullptr; }
+ void detach() {
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY();
+ mPtr = nullptr;
+ }
T* MOZ_NON_OWNING_REF mPtr;
+ MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK
};
} // namespace detail
@@ -138,6 +204,8 @@
{
if (!mSelfReferencingWeakPtr) {
mSelfReferencingWeakPtr.mRef = new detail::WeakReference<T>(static_cast<T*>(this));
+ } else {
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mSelfReferencingWeakPtr.mRef);
}
return mSelfReferencingWeakPtr;
}
@@ -163,11 +231,13 @@
WeakPtr& operator=(const WeakPtr& aOther)
{
mRef = aOther.mRef;
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mRef);
return *this;
}
WeakPtr(const WeakPtr& aOther)
{
+ // The thread safety check is performed inside of the operator= method.
*this = aOther;
}
@@ -179,12 +249,15 @@
// Ensure that mRef is dereferenceable in the uninitialized state.
mRef = new WeakReference(nullptr);
}
+ // The thread safety check happens inside SelfReferencingWeakPtr
+ // or is initialized in the WeakReference constructor.
return *this;
}
MOZ_IMPLICIT WeakPtr(T* aOther)
{
*this = aOther;
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mRef);
}
// Ensure that mRef is dereferenceable in the uninitialized state.
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/WindowsVersion.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/WindowsVersion.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/WindowsVersion.h
@@ -172,6 +172,12 @@
}
MOZ_ALWAYS_INLINE bool
+IsWin8Point1OrLater()
+{
+ return IsWindowsVersionOrLater(0x06030000ul);
+}
+
+MOZ_ALWAYS_INLINE bool
IsWin10OrLater()
{
return IsWindowsVersionOrLater(0x0a000000ul);
@@ -184,6 +190,41 @@
IsWindowsBuildOrLater(7600);
}
+MOZ_ALWAYS_INLINE bool
+IsWin7AndPre2000Compatible() {
+ /*
+ * See Bug 1279171.
+ * We'd like to avoid using WMF on specific OS version when compatibility
+ * mode is in effect. The purpose of this function is to check if FF runs on
+ * Win7 OS with application compatibility mode being set to 95/98/ME.
+ * Those compatibility mode options (95/98/ME) can only display and
+ * be selected for 32-bit application.
+ * If the compatibility mode is in effect, the GetVersionEx function will
+ * report the OS as it identifies itself, which may not be the OS that is
+ * installed.
+ * Note : 1) We only target for Win7 build number greater than 7600.
+ * 2) GetVersionEx may be altered or unavailable for release after
+ * Win8.1. Set pragma to avoid build warning as error.
+ */
+ bool isWin7 = IsNotWin7PreRTM() && !IsWin8OrLater();
+ if (!isWin7) {
+ return false;
+ }
+
+ OSVERSIONINFOEX info;
+ ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
+
+ info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+#pragma warning(push)
+#pragma warning(disable:4996)
+ bool success = GetVersionEx((LPOSVERSIONINFO) &info);
+#pragma warning(pop)
+ if (!success) {
+ return false;
+ }
+ return info.dwMajorVersion < 5;
+}
+
} // namespace mozilla
#endif /* mozilla_WindowsVersion_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/XorShift128PlusRNG.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/XorShift128PlusRNG.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/XorShift128PlusRNG.h
@@ -33,6 +33,11 @@
* Intel(R) Core(TM) i7-4770 CPU @3.40GHz (Haswell). It is the fastest
* generator we are aware of with such empirical statistical properties.
*
+ * The stream of numbers produced by this method repeats every 2**128 - 1 calls
+ * (i.e. never, for all practical purposes). Zero appears 2**64 - 1 times in
+ * this period; all other numbers appear 2**64 times. Additionally, each *bit*
+ * in the produced numbers repeats every 2**128 - 1 calls.
+ *
* This generator is not suitable as a cryptographically secure random number
* generator.
*/
@@ -42,14 +47,20 @@
public:
/*
* Construct a xorshift128+ pseudo-random number stream using |aInitial0| and
- * |aInitial1| as the initial state. These may not both be zero; ideally, they
- * should have an almost even mix of zero and one bits.
+ * |aInitial1| as the initial state. These MUST NOT both be zero.
+ *
+ * If the initial states contain many zeros, for a few iterations you'll see
+ * many zeroes in the generated numbers. It's suggested to seed a SplitMix64
+ * generator <http://xorshift.di.unimi.it/splitmix64.c> and use its first two
+ * outputs to seed xorshift128+.
*/
XorShift128PlusRNG(uint64_t aInitial0, uint64_t aInitial1) {
setState(aInitial0, aInitial1);
}
- /* Return a pseudo-random 64-bit number. */
+ /**
+ * Return a pseudo-random 64-bit number.
+ */
uint64_t next() {
/*
* The offsetOfState*() methods below are provided so that exceedingly-rare
@@ -66,9 +77,10 @@
}
/*
- * Return a pseudo-random floating-point value in the range [0, 1).
- * More precisely, choose an integer in the range [0, 2**53) and
- * divide it by 2**53.
+ * Return a pseudo-random floating-point value in the range [0, 1). More
+ * precisely, choose an integer in the range [0, 2**53) and divide it by
+ * 2**53. Given the 2**128 - 1 period noted above, the produced doubles are
+ * all but uniformly distributed in this range.
*/
double nextDouble() {
/*
@@ -78,7 +90,7 @@
* is the width of the bitfield in the in-memory format, so we must add one
* to get the mantissa's range.
*/
- static MOZ_CONSTEXPR_VAR int kMantissaBits =
+ static constexpr int kMantissaBits =
mozilla::FloatingPoint<double>::kExponentShift + 1;
uint64_t mantissa = next() & ((UINT64_C(1) << kMantissaBits) - 1);
return double(mantissa) / (UINT64_C(1) << kMantissaBits);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/mozalloc.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/mozalloc.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-debug/mozilla/mozalloc.h
@@ -12,14 +12,22 @@
* https://bugzilla.mozilla.org/show_bug.cgi?id=427099
*/
-#include <stdlib.h>
-#include <string.h>
#if defined(__cplusplus)
# include <new>
+// Since libstdc++ 6, including the C headers (e.g. stdlib.h) instead of the
+// corresponding C++ header (e.g. cstdlib) can cause confusion in C++ code
+// using things defined there. Specifically, with stdlib.h, the use of abs()
+// in gfx/graphite2/src/inc/UtfCodec.h somehow ends up picking the wrong abs()
+# include <cstdlib>
+# include <cstring>
+#else
+# include <stdlib.h>
+# include <string.h>
#endif
#if defined(__cplusplus)
#include "mozilla/fallible.h"
+#include "mozilla/mozalloc_abort.h"
#include "mozilla/TemplateLib.h"
#endif
#include "mozilla/Attributes.h"
@@ -37,8 +45,8 @@
/* Workaround build problem with Sun Studio 12 */
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-# undef MOZ_WARN_UNUSED_RESULT
-# define MOZ_WARN_UNUSED_RESULT
+# undef MOZ_MUST_USE
+# define MOZ_MUST_USE
# undef MOZ_ALLOCATOR
# define MOZ_ALLOCATOR
#endif
@@ -97,10 +105,10 @@
#if defined(HAVE_POSIX_MEMALIGN)
-MFBT_API MOZ_WARN_UNUSED_RESULT
+MFBT_API MOZ_MUST_USE
int moz_xposix_memalign(void **ptr, size_t alignment, size_t size);
-MFBT_API MOZ_WARN_UNUSED_RESULT
+MFBT_API MOZ_MUST_USE
int moz_posix_memalign(void **ptr, size_t alignment, size_t size);
#endif /* if defined(HAVE_POSIX_MEMALIGN) */
@@ -282,10 +290,28 @@
{
public:
template <typename T>
+ T* maybe_pod_malloc(size_t aNumElems)
+ {
+ return pod_malloc<T>(aNumElems);
+ }
+
+ template <typename T>
+ T* maybe_pod_calloc(size_t aNumElems)
+ {
+ return pod_calloc<T>(aNumElems);
+ }
+
+ template <typename T>
+ T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
+ {
+ return pod_realloc<T>(aPtr, aOldSize, aNewSize);
+ }
+
+ template <typename T>
T* pod_malloc(size_t aNumElems)
{
if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
- return nullptr;
+ reportAllocOverflow();
}
return static_cast<T*>(moz_xmalloc(aNumElems * sizeof(T)));
}
@@ -300,7 +326,7 @@
T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
{
if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
- return nullptr;
+ reportAllocOverflow();
}
return static_cast<T*>(moz_xrealloc(aPtr, aNewSize * sizeof(T)));
}
@@ -312,6 +338,12 @@
void reportAllocOverflow() const
{
+ mozalloc_abort("alloc overflow");
+ }
+
+ bool checkSimulatedOOM() const
+ {
+ return true;
}
};
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/fdlibm.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/fdlibm.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/fdlibm.h
@@ -0,0 +1,65 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $FreeBSD$
+ */
+
+#ifndef mozilla_imported_fdlibm_h
+#define mozilla_imported_fdlibm_h
+
+namespace fdlibm {
+
+double acos(double);
+double asin(double);
+double atan(double);
+double atan2(double, double);
+
+double cosh(double);
+double sinh(double);
+double tanh(double);
+
+double exp(double);
+double log(double);
+double log10(double);
+
+double pow(double, double);
+double sqrt(double);
+double fabs(double);
+
+double floor(double);
+double trunc(double);
+double ceil(double);
+
+double acosh(double);
+double asinh(double);
+double atanh(double);
+double cbrt(double);
+double expm1(double);
+double hypot(double, double);
+double log1p(double);
+double log2(double);
+double rint(double);
+double copysign(double, double);
+double nearbyint(double);
+double scalbn(double, int);
+
+float ceilf(float);
+float floorf(float);
+
+float nearbyintf(float);
+float rintf(float);
+float truncf(float);
+
+} /* namespace fdlibm */
+
+#endif /* mozilla_imported_fdlibm_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js-config.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js-config.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js-config.h
@@ -15,6 +15,20 @@
/* Define to 1 if SpiderMonkey is in debug mode. */
/* #undef JS_DEBUG */
+/*
+ * NB: We have a special case for rust-bindgen, which wants to be able to
+ * generate both debug and release bindings on a single objdir.
+ */
+#ifdef JS_DEBUG
+#if !defined(DEBUG) && !defined(RUST_BINDGEN)
+# error "SpiderMonkey was configured with --enable-debug, so DEBUG must be defined when including this header"
+# endif
+#else
+# if defined(DEBUG) && !defined(RUST_BINDGEN)
+# error "SpiderMonkey was configured with --disable-debug, so DEBUG must be not defined when including this header"
+# endif
+#endif
+
/* Define to 1 if SpiderMonkey should not use struct types in debug builds. */
/* #undef JS_NO_JSVAL_JSID_STRUCT_TYPES */
@@ -34,18 +48,6 @@
/* Define to 1 to perform extra assertions and heap poisoning. */
/* #undef JS_CRASH_DIAGNOSTICS */
-/* Define to 1 if the <endian.h> header is present and
- useable. See jscpucfg.h. */
-/* #undef JS_HAVE_ENDIAN_H */
-
-/* Define to 1 if the <machine/endian.h> header is present and
- useable. See jscpucfg.h. */
-/* #undef JS_HAVE_MACHINE_ENDIAN_H */
-
-/* Define to 1 if the <sys/isa_defs.h> header is present and
- useable. See jscpucfg.h. */
-/* #undef JS_HAVE_SYS_ISA_DEFS_H */
-
/* Define to 1 if SpiderMonkey is in NUNBOX32 mode. */
#define JS_NUNBOX32 1
@@ -53,7 +55,7 @@
/* #undef JS_PUNBOX64 */
/* MOZILLA JSAPI version number components */
-#define MOZJS_MAJOR_VERSION 45
-#define MOZJS_MINOR_VERSION 0
+#define MOZJS_MAJOR_VERSION 52
+#define MOZJS_MINOR_VERSION 9
#endif /* js_config_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js.msg
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js.msg
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js.msg
@@ -34,14 +34,14 @@
*
* can be used:
*
- * JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
+ * JS_ReportErrorNumberASCII(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
*
* to report:
*
* "Rhino is not a member of the Monkey family"
*/
-MSG_DEF(JSMSG_NOT_AN_ERROR, 0, JSEXN_NONE, "<Error #0 is reserved>")
+MSG_DEF(JSMSG_NOT_AN_ERROR, 0, JSEXN_ERR, "<Error #0 is reserved>")
MSG_DEF(JSMSG_NOT_DEFINED, 1, JSEXN_REFERENCEERR, "{0} is not defined")
MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, JSEXN_TYPEERR, "{0} requires more than {1} argument{2}")
MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}")
@@ -63,7 +63,7 @@
MSG_DEF(JSMSG_BAD_WEAKMAP_KEY, 0, JSEXN_TYPEERR, "cannot use the given object as a weak map key")
MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 1, JSEXN_TYPEERR, "invalid {0} usage")
MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 0, JSEXN_RANGEERR, "invalid array length")
-MSG_DEF(JSMSG_REDECLARED_VAR, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}")
+MSG_DEF(JSMSG_REDECLARED_VAR, 2, JSEXN_SYNTAXERR, "redeclaration of {0} {1}")
MSG_DEF(JSMSG_UNDECLARED_VAR, 1, JSEXN_REFERENCEERR, "assignment to undeclared variable {0}")
MSG_DEF(JSMSG_GETTER_ONLY, 0, JSEXN_TYPEERR, "setting a property that has only a getter")
MSG_DEF(JSMSG_OVERWRITING_ACCESSOR, 1, JSEXN_TYPEERR, "can't overwrite accessor property {0}")
@@ -71,14 +71,12 @@
MSG_DEF(JSMSG_INVALID_MAP_ITERABLE, 1, JSEXN_TYPEERR, "iterable for {0} should have array-like objects")
MSG_DEF(JSMSG_NESTING_GENERATOR, 0, JSEXN_TYPEERR, "already executing generator")
MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
-MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED, 0, JSEXN_NONE, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead")
-MSG_DEF(JSMSG_TYPE_ERR_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
+MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED, 0, JSEXN_WARN, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead")
+MSG_DEF(JSMSG_ARRAYBUFFER_SLICE_DEPRECATED, 0, JSEXN_WARN, "ArrayBuffer.slice is deprecated; use ArrayBuffer.prototype.slice instead")
MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 1, JSEXN_TYPEERR, "bad surrogate character {0}")
MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large")
MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}")
-MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 1, JSEXN_TYPEERR, "wrong constructor called for {0}")
MSG_DEF(JSMSG_BUILTIN_CTOR_NO_NEW, 1, JSEXN_TYPEERR, "calling a builtin {0} constructor without new is forbidden")
-MSG_DEF(JSMSG_PROTO_SETTING_SLOW, 0, JSEXN_NONE, "mutating the [[Prototype]] of an object will cause your code to run very slowly; instead create the object with the correct initial [[Prototype]] value using Object.create")
MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 1, JSEXN_TYPEERR, "yield from closing generator {0}")
MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value")
MSG_DEF(JSMSG_UNEXPECTED_TYPE, 2, JSEXN_TYPEERR, "{0} is {1}")
@@ -89,14 +87,15 @@
MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 1, JSEXN_TYPEERR, "{0}: Object is not extensible")
MSG_DEF(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE, 2, JSEXN_TYPEERR, "can't define property {1}: {0} is not extensible")
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property {0}")
-MSG_DEF(JSMSG_CANT_APPEND_TO_ARRAY, 0, JSEXN_TYPEERR, "can't add elements past the end of an array if its length property is unwritable")
MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't redefine array length")
MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length")
MSG_DEF(JSMSG_BAD_GET_SET_FIELD, 1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function")
MSG_DEF(JSMSG_THROW_TYPE_ERROR, 0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them")
MSG_DEF(JSMSG_NOT_EXPECTED_TYPE, 3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}")
MSG_DEF(JSMSG_NOT_ITERABLE, 1, JSEXN_TYPEERR, "{0} is not iterable")
-MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 2, JSEXN_NONE, "{0} is being assigned a {1}, but already has one")
+MSG_DEF(JSMSG_NOT_ITERATOR, 1, JSEXN_TYPEERR, "{0} is not iterator")
+MSG_DEF(JSMSG_ALREADY_HAS_PRAGMA, 2, JSEXN_WARN, "{0} is being assigned a {1}, but already has one")
+MSG_DEF(JSMSG_GET_ITER_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "[Symbol.iterator]() returned a non-object value")
MSG_DEF(JSMSG_NEXT_RETURNED_PRIMITIVE, 0, JSEXN_TYPEERR, "iterator.next() returned a non-object value")
MSG_DEF(JSMSG_CANT_SET_PROTO, 0, JSEXN_TYPEERR, "can't set prototype of this object")
MSG_DEF(JSMSG_CANT_SET_PROTO_OF, 1, JSEXN_TYPEERR, "can't set prototype of {0}")
@@ -106,11 +105,12 @@
MSG_DEF(JSMSG_PROTO_NOT_OBJORNULL, 1, JSEXN_TYPEERR, "{0}.prototype is not an object or null")
MSG_DEF(JSMSG_CANT_CALL_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class constructors must be invoked with |new|")
MSG_DEF(JSMSG_UNINITIALIZED_THIS, 1, JSEXN_REFERENCEERR, "|this| used uninitialized in {0} class constructor")
+MSG_DEF(JSMSG_UNINITIALIZED_THIS_ARROW, 0, JSEXN_REFERENCEERR, "|this| used uninitialized in arrow function in class constructor")
MSG_DEF(JSMSG_BAD_DERIVED_RETURN, 1, JSEXN_TYPEERR, "derived class constructor returned invalid value {0}")
// JSON
MSG_DEF(JSMSG_JSON_BAD_PARSE, 3, JSEXN_SYNTAXERR, "JSON.parse: {0} at line {1} column {2} of the JSON data")
-MSG_DEF(JSMSG_JSON_CYCLIC_VALUE, 1, JSEXN_TYPEERR, "cyclic {0} value")
+MSG_DEF(JSMSG_JSON_CYCLIC_VALUE, 0, JSEXN_TYPEERR, "cyclic object value")
// Runtime errors
MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}")
@@ -121,6 +121,7 @@
MSG_DEF(JSMSG_TOO_MANY_FUN_SPREADARGS, 0, JSEXN_RANGEERR, "too many function arguments")
MSG_DEF(JSMSG_UNINITIALIZED_LEXICAL, 1, JSEXN_REFERENCEERR, "can't access lexical declaration `{0}' before initialization")
MSG_DEF(JSMSG_BAD_CONST_ASSIGN, 1, JSEXN_TYPEERR, "invalid assignment to const `{0}'")
+MSG_DEF(JSMSG_CANT_DECLARE_GLOBAL_BINDING, 2, JSEXN_TYPEERR, "cannot declare global binding `{0}': {1}")
// Date
MSG_DEF(JSMSG_INVALID_DATE, 0, JSEXN_RANGEERR, "invalid date")
@@ -132,7 +133,6 @@
MSG_DEF(JSMSG_NEGATIVE_REPETITION_COUNT, 0, JSEXN_RANGEERR, "repeat count must be non-negative")
MSG_DEF(JSMSG_NOT_A_CODEPOINT, 1, JSEXN_RANGEERR, "{0} is not a valid code point")
MSG_DEF(JSMSG_RESULTING_STRING_TOO_LARGE, 0, JSEXN_RANGEERR, "repeat count must be less than infinity and not overflow maximum string size")
-MSG_DEF(JSMSG_DEPRECATED_STRING_CONTAINS, 0, JSEXN_NONE, "String.prototype.contains() is deprecated and will be removed in a future release; use String.prototype.includes() instead")
// Number
MSG_DEF(JSMSG_BAD_RADIX, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36")
@@ -146,7 +146,7 @@
MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION, 1, JSEXN_TYPEERR, "{0} is not a scripted function")
MSG_DEF(JSMSG_NO_REST_NAME, 0, JSEXN_SYNTAXERR, "no parameter name after ...")
MSG_DEF(JSMSG_PARAMETER_AFTER_REST, 0, JSEXN_SYNTAXERR, "parameter after rest parameter")
-MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
+MSG_DEF(JSMSG_TOO_MANY_ARGUMENTS, 0, JSEXN_RANGEERR, "too many arguments provided for a function call")
// CSP
MSG_DEF(JSMSG_CSP_BLOCKED_EVAL, 0, JSEXN_ERR, "call to eval() blocked by CSP")
@@ -158,10 +158,7 @@
MSG_DEF(JSMSG_UNWRAP_DENIED, 0, JSEXN_ERR, "permission denied to unwrap object")
// JSAPI-only (Not thrown as JS exceptions)
-MSG_DEF(JSMSG_BAD_CHAR, 1, JSEXN_INTERNALERR, "invalid format character {0}")
MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE, 0, JSEXN_TYPEERR, "bad cloned function scope chain")
-MSG_DEF(JSMSG_BAD_NEW_RESULT, 1, JSEXN_TYPEERR, "invalid new expression result {0}")
-MSG_DEF(JSMSG_BAD_TYPE, 1, JSEXN_TYPEERR, "unknown type {0}")
MSG_DEF(JSMSG_CANT_CLONE_OBJECT, 0, JSEXN_TYPEERR, "can't clone object")
MSG_DEF(JSMSG_CANT_OPEN, 2, JSEXN_ERR, "can't open {0}: {1}")
MSG_DEF(JSMSG_USER_DEFINED_ERROR, 0, JSEXN_ERR, "JS_ReportError was called")
@@ -169,11 +166,10 @@
// Internal errors
MSG_DEF(JSMSG_ALLOC_OVERFLOW, 0, JSEXN_INTERNALERR, "allocation size overflow")
MSG_DEF(JSMSG_BAD_BYTECODE, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
-MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 0, JSEXN_INTERNALERR, "buffer too small")
+MSG_DEF(JSMSG_BUILD_ID_NOT_AVAILABLE, 0, JSEXN_INTERNALERR, "build ID is not available")
MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
-MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties")
-MSG_DEF(JSMSG_INACTIVE, 0, JSEXN_INTERNALERR, "nothing active on context")
+MSG_DEF(JSMSG_ERR_DURING_THROW, 0, JSEXN_INTERNALERR, "an internal error occurred while throwing an exception")
MSG_DEF(JSMSG_NEED_DIET, 1, JSEXN_INTERNALERR, "{0} too large")
MSG_DEF(JSMSG_OUT_OF_MEMORY, 0, JSEXN_INTERNALERR, "out of memory")
MSG_DEF(JSMSG_OVER_RECURSED, 0, JSEXN_INTERNALERR, "too much recursion")
@@ -185,9 +181,11 @@
// Frontend
MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}")
MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
-MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initialiser too large")
+MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initializer too large")
MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'as' after import *")
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
+MSG_DEF(JSMSG_ASYNC_GENERATOR, 0, JSEXN_SYNTAXERR, "generator function or method can't be async")
+MSG_DEF(JSMSG_AWAIT_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "await can't be used in default expression")
MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
@@ -199,18 +197,19 @@
MSG_DEF(JSMSG_BAD_DESTRUCT_DECL, 0, JSEXN_SYNTAXERR, "missing = in destructuring declaration")
MSG_DEF(JSMSG_BAD_DUP_ARGS, 0, JSEXN_SYNTAXERR, "duplicate argument names not allowed in this context")
MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 0, JSEXN_SYNTAXERR, "invalid for each loop")
-MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side")
-MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
-MSG_DEF(JSMSG_BAD_YIELD_SYNTAX, 0, JSEXN_SYNTAXERR, "yield expression must be parenthesized")
-MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 0, JSEXN_SYNTAXERR, "generator expression must be parenthesized")
+MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for-in/of left-hand side")
+MSG_DEF(JSMSG_LEXICAL_DECL_DEFINES_LET,0, JSEXN_SYNTAXERR, "a lexical declaration can't define a 'let' binding")
+MSG_DEF(JSMSG_LET_STARTING_FOROF_LHS, 0, JSEXN_SYNTAXERR, "an expression X in 'for (X of Y)' must not start with 'let'")
+MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
MSG_DEF(JSMSG_BAD_GENEXP_BODY, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression")
MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_REFERENCEERR, "invalid increment/decrement operand")
MSG_DEF(JSMSG_BAD_METHOD_DEF, 0, JSEXN_SYNTAXERR, "bad method definition")
MSG_DEF(JSMSG_BAD_OCTAL, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant")
MSG_DEF(JSMSG_BAD_OPERAND, 1, JSEXN_SYNTAXERR, "invalid {0} operand")
+MSG_DEF(JSMSG_BAD_POW_LEFTSIDE, 0, JSEXN_SYNTAXERR, "unparenthesized unary expression can't appear on the left-hand side of '**'")
MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id")
MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 1, JSEXN_SYNTAXERR, "{0} not in function")
-MSG_DEF(JSMSG_BAD_STRICT_ASSIGN, 1, JSEXN_SYNTAXERR, "can't assign to {0} in strict mode")
+MSG_DEF(JSMSG_BAD_STRICT_ASSIGN, 1, JSEXN_SYNTAXERR, "'{0}' can't be defined or assigned to in strict mode code")
MSG_DEF(JSMSG_BAD_SWITCH, 0, JSEXN_SYNTAXERR, "invalid switch statement")
MSG_DEF(JSMSG_BAD_SUPER, 0, JSEXN_SYNTAXERR, "invalid use of keyword 'super'")
MSG_DEF(JSMSG_BAD_SUPERPROP, 1, JSEXN_SYNTAXERR, "use of super {0} accesses only valid within methods or eval code within methods")
@@ -230,13 +229,11 @@
MSG_DEF(JSMSG_CURLY_AFTER_BODY, 0, JSEXN_SYNTAXERR, "missing } after function body")
MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 0, JSEXN_SYNTAXERR, "missing } after catch block")
MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 0, JSEXN_SYNTAXERR, "missing } after finally block")
-MSG_DEF(JSMSG_CURLY_AFTER_LET, 0, JSEXN_SYNTAXERR, "missing } after let block")
MSG_DEF(JSMSG_CURLY_AFTER_LIST, 0, JSEXN_SYNTAXERR, "missing } after property list")
MSG_DEF(JSMSG_CURLY_AFTER_TRY, 0, JSEXN_SYNTAXERR, "missing } after try block")
MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 0, JSEXN_SYNTAXERR, "missing { before function body")
MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 0, JSEXN_SYNTAXERR, "missing { before catch block")
MSG_DEF(JSMSG_CURLY_BEFORE_CLASS, 0, JSEXN_SYNTAXERR, "missing { before class body")
-MSG_DEF(JSMSG_CURLY_BEFORE_LET, 0, JSEXN_SYNTAXERR, "missing { before let block")
MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 0, JSEXN_SYNTAXERR, "missing { before finally block")
MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 0, JSEXN_SYNTAXERR, "missing { before switch body")
MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 0, JSEXN_SYNTAXERR, "missing { before try block")
@@ -244,32 +241,37 @@
MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword")
MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword")
MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 0, JSEXN_SYNTAXERR, "applying the 'delete' operator to an unqualified name is deprecated")
-MSG_DEF(JSMSG_DEPRECATED_EXPR_CLOSURE, 0, JSEXN_NONE, "expression closures are deprecated")
-MSG_DEF(JSMSG_DEPRECATED_FLAGS_ARG, 0, JSEXN_NONE, "flags argument of String.prototype.{search,match,replace} is deprecated")
-MSG_DEF(JSMSG_DEPRECATED_FOR_EACH, 0, JSEXN_NONE, "JavaScript 1.6's for-each-in loops are deprecated; consider using ES6 for-of instead")
-MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "octal literals and octal escape sequences are deprecated")
-MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_NONE, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead")
+MSG_DEF(JSMSG_DEPRECATED_EXPR_CLOSURE, 0, JSEXN_WARN, "expression closures are deprecated")
+MSG_DEF(JSMSG_DEPRECATED_FOR_EACH, 0, JSEXN_WARN, "JavaScript 1.6's for-each-in loops are deprecated; consider using ES6 for-of instead")
+MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal literals and octal escape sequences are deprecated; for octal literals use the \"0o\" prefix instead")
+MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_WARN, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead")
+MSG_DEF(JSMSG_DEPRECATED_BLOCK_SCOPE_FUN_REDECL, 1, JSEXN_WARN, "redeclaration of block-scoped function `{0}' is deprecated")
MSG_DEF(JSMSG_DUPLICATE_EXPORT_NAME, 1, JSEXN_SYNTAXERR, "duplicate export name '{0}'")
MSG_DEF(JSMSG_DUPLICATE_FORMAL, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}")
MSG_DEF(JSMSG_DUPLICATE_LABEL, 0, JSEXN_SYNTAXERR, "duplicate label")
MSG_DEF(JSMSG_DUPLICATE_PROPERTY, 1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal")
+MSG_DEF(JSMSG_DUPLICATE_PROTO_PROPERTY, 0, JSEXN_SYNTAXERR, "property name __proto__ appears more than once in object literal")
MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 0, JSEXN_SYNTAXERR, "mistyped ; after conditional?")
MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?")
MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL,0, JSEXN_SYNTAXERR, "export declarations may only appear at top level of a module")
MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 0, JSEXN_SYNTAXERR, "finally without try")
+MSG_DEF(JSMSG_FORBIDDEN_AS_STATEMENT, 1, JSEXN_SYNTAXERR, "{0} can't appear in single-statement context")
MSG_DEF(JSMSG_FROM_AFTER_IMPORT_CLAUSE, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import clause")
MSG_DEF(JSMSG_FROM_AFTER_EXPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after export *")
MSG_DEF(JSMSG_GARBAGE_AFTER_INPUT, 2, JSEXN_SYNTAXERR, "unexpected garbage after {0}, starting with {1}")
MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal")
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 0, JSEXN_SYNTAXERR, "illegal character")
MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level of a module")
-MSG_DEF(JSMSG_INVALID_FOR_INOF_DECL_WITH_INIT,1,JSEXN_SYNTAXERR,"for-{0} loop head declarations may not have initializers")
-MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for")
+MSG_DEF(JSMSG_INVALID_FOR_IN_DECL_WITH_INIT,0,JSEXN_SYNTAXERR,"for-in loop head declarations may not have initializers")
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 0, JSEXN_SYNTAXERR, "label not found")
-MSG_DEF(JSMSG_LET_CLASS_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a class")
MSG_DEF(JSMSG_LET_COMP_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a comprehension variable")
MSG_DEF(JSMSG_LEXICAL_DECL_NOT_IN_BLOCK, 1, JSEXN_SYNTAXERR, "{0} declaration not directly within block")
+MSG_DEF(JSMSG_LEXICAL_DECL_LABEL, 1, JSEXN_SYNTAXERR, "{0} declarations cannot be labelled")
+MSG_DEF(JSMSG_GENERATOR_LABEL, 0, JSEXN_SYNTAXERR, "generator functions cannot be labelled")
+MSG_DEF(JSMSG_FUNCTION_LABEL, 0, JSEXN_SYNTAXERR, "functions cannot be labelled")
+MSG_DEF(JSMSG_SLOPPY_FUNCTION_LABEL, 0, JSEXN_SYNTAXERR, "functions can only be labelled inside blocks")
MSG_DEF(JSMSG_LINE_BREAK_AFTER_THROW, 0, JSEXN_SYNTAXERR, "no line break is allowed between 'throw' and its expression")
+MSG_DEF(JSMSG_LINE_BREAK_BEFORE_ARROW, 0, JSEXN_SYNTAXERR, "no line break is allowed before '=>'")
MSG_DEF(JSMSG_MALFORMED_ESCAPE, 1, JSEXN_SYNTAXERR, "malformed {0} character escape sequence")
MSG_DEF(JSMSG_MISSING_BINARY_DIGITS, 0, JSEXN_SYNTAXERR, "missing binary digits after '0b'")
MSG_DEF(JSMSG_MISSING_EXPONENT, 0, JSEXN_SYNTAXERR, "missing exponent")
@@ -279,11 +281,8 @@
MSG_DEF(JSMSG_MISSING_OCTAL_DIGITS, 0, JSEXN_SYNTAXERR, "missing octal digits after '0o'")
MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword")
MSG_DEF(JSMSG_NAME_AFTER_DOT, 0, JSEXN_SYNTAXERR, "missing name after . operator")
-MSG_DEF(JSMSG_NAME_AFTER_IMPORT_STAR_AS, 0, JSEXN_SYNTAXERR, "missing name after import * as")
MSG_DEF(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT, 0, JSEXN_SYNTAXERR, "expected named imports or namespace import after comma")
-MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
MSG_DEF(JSMSG_NO_BINDING_NAME, 0, JSEXN_SYNTAXERR, "missing binding name")
-MSG_DEF(JSMSG_NO_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class default constructors not yet implemented")
MSG_DEF(JSMSG_NO_EXPORT_NAME, 0, JSEXN_SYNTAXERR, "missing export name")
MSG_DEF(JSMSG_NO_IMPORT_NAME, 0, JSEXN_SYNTAXERR, "missing import name")
MSG_DEF(JSMSG_NO_VARIABLE_NAME, 0, JSEXN_SYNTAXERR, "missing variable name")
@@ -295,32 +294,30 @@
MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control")
MSG_DEF(JSMSG_PAREN_AFTER_FOR_OF_ITERABLE, 0, JSEXN_SYNTAXERR, "missing ) after for-of iterable")
-MSG_DEF(JSMSG_PAREN_AFTER_LET, 0, JSEXN_SYNTAXERR, "missing ) after let head")
MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 0, JSEXN_SYNTAXERR, "missing ) after switch expression")
MSG_DEF(JSMSG_PAREN_AFTER_WITH, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object")
MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 0, JSEXN_SYNTAXERR, "missing ( before catch")
MSG_DEF(JSMSG_PAREN_BEFORE_COND, 0, JSEXN_SYNTAXERR, "missing ( before condition")
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
-MSG_DEF(JSMSG_PAREN_BEFORE_LET, 0, JSEXN_SYNTAXERR, "missing ( before let head")
MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 0, JSEXN_SYNTAXERR, "missing ( before switch expression")
MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object")
MSG_DEF(JSMSG_PAREN_IN_PAREN, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical")
MSG_DEF(JSMSG_RC_AFTER_EXPORT_SPEC_LIST, 0, JSEXN_SYNTAXERR, "missing '}' after export specifier list")
MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list")
-MSG_DEF(JSMSG_REDECLARED_CATCH_IDENTIFIER, 1, JSEXN_TYPEERR, "redeclaration of identifier '{0}' in catch")
-MSG_DEF(JSMSG_REDECLARED_PARAM, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}")
+MSG_DEF(JSMSG_REDECLARED_CATCH_IDENTIFIER, 1, JSEXN_SYNTAXERR, "redeclaration of identifier '{0}' in catch")
MSG_DEF(JSMSG_RESERVED_ID, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
+MSG_DEF(JSMSG_REST_WITH_COMMA, 0, JSEXN_SYNTAXERR, "rest element may not have a trailing comma")
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LEXICAL, 1, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level {0} declarations")
+MSG_DEF(JSMSG_SELFHOSTED_METHOD_CALL, 0, JSEXN_SYNTAXERR, "self-hosted code may not contain direct method calls. Use callFunction() or callContentFunction()")
MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups")
-MSG_DEF(JSMSG_SELFHOSTED_METHOD_CALL, 0, JSEXN_SYNTAXERR, "self-hosted code may not contain direct method calls")
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 0, JSEXN_SYNTAXERR, "missing ; before statement")
MSG_DEF(JSMSG_SOURCE_TOO_LONG, 0, JSEXN_RANGEERR, "source is too long")
-MSG_DEF(JSMSG_STMT_AFTER_RETURN, 0, JSEXN_NONE, "unreachable code after return statement")
+MSG_DEF(JSMSG_STMT_AFTER_RETURN, 0, JSEXN_WARN, "unreachable code after return statement")
MSG_DEF(JSMSG_STRICT_CODE_WITH, 0, JSEXN_SYNTAXERR, "strict mode code may not contain 'with' statements")
-MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function")
+MSG_DEF(JSMSG_STRICT_NON_SIMPLE_PARAMS, 1, JSEXN_SYNTAXERR, "\"use strict\" not allowed in function with {0} parameter")
MSG_DEF(JSMSG_TEMPLSTR_UNTERM_EXPR, 0, JSEXN_SYNTAXERR, "missing } in template string")
MSG_DEF(JSMSG_SIMD_NOT_A_VECTOR, 2, JSEXN_TYPEERR, "expecting a SIMD {0} object as argument {1}")
MSG_DEF(JSMSG_TOO_MANY_CASES, 0, JSEXN_INTERNALERR, "too many switch cases")
@@ -343,19 +340,53 @@
MSG_DEF(JSMSG_WHILE_AFTER_DO, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
MSG_DEF(JSMSG_YIELD_IN_ARROW, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield")
MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "yield in default expression")
+MSG_DEF(JSMSG_YIELD_IN_METHOD, 0, JSEXN_SYNTAXERR, "non-generator method definitions may not contain yield")
MSG_DEF(JSMSG_BAD_COLUMN_NUMBER, 0, JSEXN_RANGEERR, "column number out of range")
MSG_DEF(JSMSG_COMPUTED_NAME_IN_PATTERN,0, JSEXN_SYNTAXERR, "computed property names aren't supported in this destructuring declaration")
MSG_DEF(JSMSG_DEFAULT_IN_PATTERN, 0, JSEXN_SYNTAXERR, "destructuring defaults aren't supported in this destructuring declaration")
-MSG_DEF(JSMSG_BAD_NEWTARGET, 0, JSEXN_SYNTAXERR, "new.target only allowed in non-exotic functions")
+MSG_DEF(JSMSG_BAD_NEWTARGET, 0, JSEXN_SYNTAXERR, "new.target only allowed within functions")
MSG_DEF(JSMSG_ESCAPED_KEYWORD, 0, JSEXN_SYNTAXERR, "keywords must be written literally, without embedded escapes")
// asm.js
MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}")
MSG_DEF(JSMSG_USE_ASM_LINK_FAIL, 1, JSEXN_TYPEERR, "asm.js link error: {0}")
-MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 1, JSEXN_NONE, "Successfully compiled asm.js code ({0})")
+MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 1, JSEXN_WARN, "Successfully compiled asm.js code ({0})")
+
+// wasm
+MSG_DEF(JSMSG_WASM_COMPILE_ERROR, 1, JSEXN_WASMCOMPILEERROR, "{0}")
+MSG_DEF(JSMSG_WASM_IND_CALL_TO_NULL, 0, JSEXN_WASMRUNTIMEERROR, "indirect call to null")
+MSG_DEF(JSMSG_WASM_IND_CALL_BAD_SIG, 0, JSEXN_WASMRUNTIMEERROR, "indirect call signature mismatch")
+MSG_DEF(JSMSG_WASM_UNREACHABLE, 0, JSEXN_WASMRUNTIMEERROR, "unreachable executed")
+MSG_DEF(JSMSG_WASM_INTEGER_OVERFLOW, 0, JSEXN_WASMRUNTIMEERROR, "integer overflow")
+MSG_DEF(JSMSG_WASM_INVALID_CONVERSION, 0, JSEXN_WASMRUNTIMEERROR, "invalid conversion to integer")
+MSG_DEF(JSMSG_WASM_INT_DIVIDE_BY_ZERO, 0, JSEXN_WASMRUNTIMEERROR, "integer divide by zero")
+MSG_DEF(JSMSG_WASM_OUT_OF_BOUNDS, 0, JSEXN_WASMRUNTIMEERROR, "index out of bounds")
+MSG_DEF(JSMSG_WASM_UNALIGNED_ACCESS, 0, JSEXN_WASMRUNTIMEERROR, "unaligned memory access")
+MSG_DEF(JSMSG_WASM_BAD_UINT32, 2, JSEXN_RANGEERR, "bad {0} {1}")
+MSG_DEF(JSMSG_WASM_BAD_GROW, 1, JSEXN_RANGEERR, "failed to grow {0}")
+MSG_DEF(JSMSG_WASM_BAD_FIT, 2, JSEXN_RANGEERR, "{0} segment does not fit in {1}")
+MSG_DEF(JSMSG_WASM_BAD_BUF_ARG, 0, JSEXN_TYPEERR, "first argument must be an ArrayBuffer or typed array object")
+MSG_DEF(JSMSG_WASM_BAD_MOD_ARG, 0, JSEXN_TYPEERR, "first argument must be a WebAssembly.Module")
+MSG_DEF(JSMSG_WASM_BAD_BUF_MOD_ARG, 0, JSEXN_TYPEERR, "first argument must be a WebAssembly.Module, ArrayBuffer or typed array object")
+MSG_DEF(JSMSG_WASM_BAD_DESC_ARG, 1, JSEXN_TYPEERR, "first argument must be a {0} descriptor")
+MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE, 1, JSEXN_TYPEERR, "imported {0} with incompatible size")
+MSG_DEF(JSMSG_WASM_BAD_IMP_MAX, 1, JSEXN_TYPEERR, "imported {0} with incompatible maximum size")
+MSG_DEF(JSMSG_WASM_BAD_ELEMENT, 0, JSEXN_TYPEERR, "\"element\" property of table descriptor must be \"anyfunc\"")
+MSG_DEF(JSMSG_WASM_BAD_IMPORT_ARG, 0, JSEXN_TYPEERR, "second argument must be an object")
+MSG_DEF(JSMSG_WASM_BAD_IMPORT_FIELD, 2, JSEXN_TYPEERR, "import object field '{0}' is not {1}")
+MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG, 0, JSEXN_TYPEERR, "imported function signature mismatch")
+MSG_DEF(JSMSG_WASM_BAD_TABLE_VALUE, 0, JSEXN_TYPEERR, "can only assign WebAssembly exported functions to Table")
+MSG_DEF(JSMSG_WASM_BAD_I64, 0, JSEXN_TYPEERR, "cannot pass i64 to or from JS")
+MSG_DEF(JSMSG_WASM_NO_TRANSFER, 0, JSEXN_TYPEERR, "cannot transfer WebAssembly/asm.js ArrayBuffer")
+MSG_DEF(JSMSG_WASM_TEXT_FAIL, 1, JSEXN_SYNTAXERR, "wasm text error: {0}")
// Proxy
MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
+MSG_DEF(JSMSG_BAD_GETPROTOTYPEOF_TRAP_RETURN,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler returned a non-object, non-null value")
+MSG_DEF(JSMSG_INCONSISTENT_GETPROTOTYPEOF_TRAP,0,JSEXN_TYPEERR,"proxy getPrototypeOf handler didn't return the target object's prototype")
+MSG_DEF(JSMSG_PROXY_SETPROTOTYPEOF_RETURNED_FALSE, 0, JSEXN_TYPEERR, "proxy setPrototypeOf handler returned false")
+MSG_DEF(JSMSG_PROXY_ISEXTENSIBLE_RETURNED_FALSE,0,JSEXN_TYPEERR,"proxy isExtensible handler must return the same extensibility as target")
+MSG_DEF(JSMSG_INCONSISTENT_SETPROTOTYPEOF_TRAP,0,JSEXN_TYPEERR,"proxy setPrototypeOf handler returned true, even though the target's prototype is immutable because the target is non-extensible")
MSG_DEF(JSMSG_CANT_CHANGE_EXTENSIBILITY, 0, JSEXN_TYPEERR, "can't change object's extensibility")
MSG_DEF(JSMSG_CANT_DEFINE_INVALID, 0, JSEXN_TYPEERR, "proxy can't define an incompatible property descriptor")
MSG_DEF(JSMSG_CANT_DEFINE_NEW, 0, JSEXN_TYPEERR, "proxy can't define a new property on a non-extensible object")
@@ -374,7 +405,6 @@
MSG_DEF(JSMSG_CANT_SET_NW_NC, 0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property")
MSG_DEF(JSMSG_CANT_SET_WO_SETTER, 0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter")
MSG_DEF(JSMSG_CANT_SKIP_NC, 0, JSEXN_TYPEERR, "proxy can't skip a non-configurable property")
-MSG_DEF(JSMSG_INVALID_TRAP_RESULT, 2, JSEXN_TYPEERR, "trap {1} for {0} returned an invalid result")
MSG_DEF(JSMSG_ONWKEYS_STR_SYM, 0, JSEXN_TYPEERR, "proxy [[OwnPropertyKeys]] must return an array with only string and symbol elements")
MSG_DEF(JSMSG_MUST_REPORT_SAME_VALUE, 0, JSEXN_TYPEERR, "proxy must report the same value for a non-writable, non-configurable property")
MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 0, JSEXN_TYPEERR, "proxy must report undefined for a non-configurable accessor property without a getter")
@@ -385,6 +415,7 @@
MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined")
MSG_DEF(JSMSG_PROXY_REVOKED, 0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy")
MSG_DEF(JSMSG_PROXY_ARG_REVOKED, 1, JSEXN_TYPEERR, "argument {0} cannot be a revoked proxy")
+MSG_DEF(JSMSG_BAD_TRAP, 1, JSEXN_TYPEERR, "proxy handler's {0} trap wasn't undefined, null, or callable")
// Structured cloning
MSG_DEF(JSMSG_SC_BAD_CLONE_VERSION, 0, JSEXN_ERR, "unsupported structured clone version")
@@ -392,14 +423,18 @@
MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE, 0, JSEXN_TYPEERR, "duplicate transferable for structured clone")
MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE, 0, JSEXN_TYPEERR, "invalid transferable array for structured clone")
MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 0, JSEXN_TYPEERR, "unsupported type for structured data")
-MSG_DEF(JSMSG_SC_SHMEM_MUST_TRANSFER, 0, JSEXN_TYPEERR, "SharedArrayBuffer must be explicitly transfered during structured cloning")
+MSG_DEF(JSMSG_SC_NOT_CLONABLE, 1, JSEXN_TYPEERR, "{0} cannot be cloned in this context")
+MSG_DEF(JSMSG_SC_SAB_TRANSFER, 0, JSEXN_WARN, "SharedArrayBuffer must not be in the transfer list")
+MSG_DEF(JSMSG_SC_SAB_DISABLED, 0, JSEXN_TYPEERR, "SharedArrayBuffer not cloned - shared memory disabled in receiver")
// Debugger
MSG_DEF(JSMSG_ASSIGN_FUNCTION_OR_NULL, 1, JSEXN_TYPEERR, "value assigned to {0} must be a function or null")
+MSG_DEF(JSMSG_DEBUG_BAD_AWAIT, 0, JSEXN_TYPEERR, "await expression received invalid value")
MSG_DEF(JSMSG_DEBUG_BAD_LINE, 0, JSEXN_TYPEERR, "invalid line number")
MSG_DEF(JSMSG_DEBUG_BAD_OFFSET, 0, JSEXN_TYPEERR, "invalid script offset")
MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 2, JSEXN_TYPEERR, "{0} does not refer to {1}")
MSG_DEF(JSMSG_DEBUG_BAD_RESUMPTION, 0, JSEXN_TYPEERR, "debugger resumption value must be undefined, {throw: val}, {return: val}, or null")
+MSG_DEF(JSMSG_DEBUG_BAD_YIELD, 0, JSEXN_TYPEERR, "generator yielded invalid value")
MSG_DEF(JSMSG_DEBUG_CANT_DEBUG_GLOBAL, 0, JSEXN_TYPEERR, "passing non-debuggable global to addDebuggee")
MSG_DEF(JSMSG_DEBUG_CCW_REQUIRED, 1, JSEXN_TYPEERR, "{0}: argument must be an object from a different compartment")
MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object")
@@ -408,22 +443,25 @@
MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING, 0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee")
MSG_DEF(JSMSG_DEBUG_NOT_IDLE, 0, JSEXN_ERR, "can't start debugging: a debuggee script is on the stack")
MSG_DEF(JSMSG_DEBUG_NOT_LIVE, 1, JSEXN_ERR, "{0} is not live")
-MSG_DEF(JSMSG_DEBUG_NO_SCOPE_OBJECT, 0, JSEXN_TYPEERR, "declarative Environments don't have binding objects")
-MSG_DEF(JSMSG_DEBUG_OBJECT_PROTO, 0, JSEXN_TYPEERR, "Debugger.Object.prototype is not a valid Debugger.Object")
-MSG_DEF(JSMSG_DEBUG_OBJECT_WRONG_OWNER,0, JSEXN_TYPEERR, "Debugger.Object belongs to a different Debugger")
-MSG_DEF(JSMSG_DEBUG_OPTIMIZED_OUT, 0, JSEXN_ERR, "variable has been optimized out")
+MSG_DEF(JSMSG_DEBUG_NO_ENV_OBJECT, 0, JSEXN_TYPEERR, "declarative Environments don't have binding objects")
+MSG_DEF(JSMSG_DEBUG_PROTO, 2, JSEXN_TYPEERR, "{0}.prototype is not a valid {1} instance")
+MSG_DEF(JSMSG_DEBUG_WRONG_OWNER, 1, JSEXN_TYPEERR, "{0} belongs to a different Debugger")
+MSG_DEF(JSMSG_DEBUG_OPTIMIZED_OUT, 1, JSEXN_ERR, "variable `{0}' has been optimized out")
MSG_DEF(JSMSG_DEBUG_RESUMPTION_VALUE_DISALLOWED, 0, JSEXN_TYPEERR, "resumption values are disallowed in this hook")
MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND,0, JSEXN_TYPEERR, "variable not found in environment")
MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY, 3, JSEXN_TYPEERR, "{0} is {1}{2}a global object, but a direct reference is required")
+MSG_DEF(JSMSG_DEBUGGEE_WOULD_RUN, 2, JSEXN_DEBUGGEEWOULDRUN, "debuggee `{0}:{1}' would run")
MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 0, JSEXN_TYPEERR, "value is not a function or undefined")
MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true")
-MSG_DEF(JSMSG_NOT_TRACKING_TENURINGS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingTenurePromotions to true")
MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so")
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line' and either 'displayURL', 'url', or 'source'")
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'displayURL', 'url', or 'source' property")
MSG_DEF(JSMSG_DEBUG_CANT_SET_OPT_ENV, 1, JSEXN_REFERENCEERR, "can't set `{0}' in an optimized-out environment")
MSG_DEF(JSMSG_DEBUG_INVISIBLE_COMPARTMENT, 0, JSEXN_TYPEERR, "object in compartment marked as invisible to Debugger")
MSG_DEF(JSMSG_DEBUG_CENSUS_BREAKDOWN, 1, JSEXN_TYPEERR, "unrecognized 'by' value in takeCensus breakdown: {0}")
+MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_RESOLVED, 0, JSEXN_TYPEERR, "Promise hasn't been resolved")
+MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_FULFILLED, 0, JSEXN_TYPEERR, "Promise hasn't been fulfilled")
+MSG_DEF(JSMSG_DEBUG_PROMISE_NOT_REJECTED, 0, JSEXN_TYPEERR, "Promise hasn't been rejected")
// Tracelogger
MSG_DEF(JSMSG_TRACELOGGER_ENABLE_FAIL, 1, JSEXN_ERR, "enabling tracelogger failed: {0}")
@@ -443,14 +481,23 @@
MSG_DEF(JSMSG_UNDEFINED_CURRENCY, 0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style")
// RegExp
+MSG_DEF(JSMSG_BACK_REF_OUT_OF_RANGE, 0, JSEXN_SYNTAXERR, "back reference out of range in regular expression")
MSG_DEF(JSMSG_BAD_CLASS_RANGE, 0, JSEXN_SYNTAXERR, "invalid range in character class")
MSG_DEF(JSMSG_ESCAPE_AT_END_OF_REGEXP, 0, JSEXN_SYNTAXERR, "\\ at end of pattern")
+MSG_DEF(JSMSG_EXEC_NOT_OBJORNULL, 0, JSEXN_TYPEERR, "RegExp exec method should return object or null")
+MSG_DEF(JSMSG_INVALID_DECIMAL_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid decimal escape in regular expression")
MSG_DEF(JSMSG_INVALID_GROUP, 0, JSEXN_SYNTAXERR, "invalid regexp group")
+MSG_DEF(JSMSG_INVALID_IDENTITY_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid identity escape in regular expression")
+MSG_DEF(JSMSG_INVALID_UNICODE_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid unicode escape in regular expression")
MSG_DEF(JSMSG_MISSING_PAREN, 0, JSEXN_SYNTAXERR, "unterminated parenthetical")
MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another")
MSG_DEF(JSMSG_NOTHING_TO_REPEAT, 0, JSEXN_SYNTAXERR, "nothing to repeat")
MSG_DEF(JSMSG_NUMBERS_OUT_OF_ORDER, 0, JSEXN_SYNTAXERR, "numbers out of order in {} quantifier.")
+MSG_DEF(JSMSG_RANGE_WITH_CLASS_ESCAPE, 0, JSEXN_SYNTAXERR, "character class escape cannot be used in class range in regular expression")
+MSG_DEF(JSMSG_RAW_BRACE_IN_REGEP, 0, JSEXN_SYNTAXERR, "raw brace is not allowed in regular expression with unicode flag")
+MSG_DEF(JSMSG_RAW_BRACKET_IN_REGEP, 0, JSEXN_SYNTAXERR, "raw bracket is not allowed in regular expression with unicode flag")
MSG_DEF(JSMSG_TOO_MANY_PARENS, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression")
+MSG_DEF(JSMSG_UNICODE_OVERFLOW, 0, JSEXN_SYNTAXERR, "unicode codepoint should not be greater than 0x10FFFF in regular expression")
MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
MSG_DEF(JSMSG_UNTERM_CLASS, 0, JSEXN_SYNTAXERR, "unterminated character class")
@@ -466,30 +513,34 @@
MSG_DEF(JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS, 0, JSEXN_RANGEERR, "invalid field descriptor")
MSG_DEF(JSMSG_TYPEDOBJECT_TOO_BIG, 0, JSEXN_ERR, "Type is too large to allocate")
MSG_DEF(JSMSG_SIMD_FAILED_CONVERSION, 0, JSEXN_RANGEERR, "SIMD conversion loses precision")
+MSG_DEF(JSMSG_SIMD_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert SIMD value to number")
+
+// Array
+MSG_DEF(JSMSG_TOO_LONG_ARRAY, 0, JSEXN_TYPEERR, "Too long array")
// Typed array
MSG_DEF(JSMSG_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
+MSG_DEF(JSMSG_NON_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected ArrayBuffer, but species constructor returned non-ArrayBuffer")
+MSG_DEF(JSMSG_SAME_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different ArrayBuffer, but species constructor returned same ArrayBuffer")
+MSG_DEF(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected ArrayBuffer with at least {0} bytes, but species constructor returns ArrayBuffer with {1} bytes")
MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
-MSG_DEF(JSMSG_TYPED_ARRAY_BAD_OBJECT, 0, JSEXN_TYPEERR, "invalid object argument")
-MSG_DEF(JSMSG_TYPED_ARRAY_BAD_INDEX, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
MSG_DEF(JSMSG_TYPED_ARRAY_NEGATIVE_ARG,1, JSEXN_RANGEERR, "argument {0} must be >= 0")
MSG_DEF(JSMSG_TYPED_ARRAY_DETACHED, 0, JSEXN_TYPEERR, "attempting to access detached ArrayBuffer")
+MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS, 0, JSEXN_RANGEERR, "attempting to construct out-of-bounds TypedArray on ArrayBuffer")
+MSG_DEF(JSMSG_TYPED_ARRAY_CALL_OR_CONSTRUCT, 1, JSEXN_TYPEERR, "cannot directly {0} builtin %TypedArray%")
+MSG_DEF(JSMSG_NON_TYPED_ARRAY_RETURNED, 0, JSEXN_TYPEERR, "constructor didn't return TypedArray object")
+MSG_DEF(JSMSG_SHORT_TYPED_ARRAY_RETURNED, 2, JSEXN_TYPEERR, "expected TypedArray of at least length {0}, but constructor returned TypedArray of length {1}")
// Shared array buffer
-MSG_DEF(JSMSG_SHARED_ARRAY_BAD_OBJECT, 0, JSEXN_TYPEERR, "invalid object argument")
MSG_DEF(JSMSG_SHARED_ARRAY_BAD_LENGTH, 0, JSEXN_RANGEERR, "length argument out of range")
-
-// Shared typed array
-MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_OBJECT, 0, JSEXN_TYPEERR, "invalid object argument")
-MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_RANGEERR, "bad combination of offset, length, and element size")
-MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_ARG_RANGE, 1, JSEXN_RANGEERR, "argument {0} out of range")
-MSG_DEF(JSMSG_SHARED_TYPED_ARRAY_BAD_LENGTH, 0, JSEXN_TYPEERR, "length argument must not be an object")
+MSG_DEF(JSMSG_NON_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected SharedArrayBuffer, but species constructor returned non-SharedArrayBuffer")
+MSG_DEF(JSMSG_SAME_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different SharedArrayBuffer, but species constructor returned same SharedArrayBuffer")
+MSG_DEF(JSMSG_SHORT_SHARED_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected SharedArrayBuffer with at least {0} bytes, but species constructor returns SharedArrayBuffer with {1} bytes")
// Reflect
MSG_DEF(JSMSG_BAD_PARSE_NODE, 0, JSEXN_INTERNALERR, "bad parse node")
// Symbol
-MSG_DEF(JSMSG_BAD_SYMBOL, 1, JSEXN_TYPEERR, "{0} is not a well-known @@-symbol")
MSG_DEF(JSMSG_SYMBOL_TO_STRING, 0, JSEXN_TYPEERR, "can't convert symbol to string")
MSG_DEF(JSMSG_SYMBOL_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert symbol to number")
@@ -497,7 +548,6 @@
MSG_DEF(JSMSG_ATOMICS_BAD_ARRAY, 0, JSEXN_TYPEERR, "invalid array type for the operation")
MSG_DEF(JSMSG_ATOMICS_TOO_LONG, 0, JSEXN_RANGEERR, "timeout value too large")
MSG_DEF(JSMSG_ATOMICS_WAIT_NOT_ALLOWED, 0, JSEXN_ERR, "waiting is not allowed on this thread")
-MSG_DEF(JSMSG_ATOMICS_BAD_INDEX, 0, JSEXN_RANGEERR, "out-of-range index for atomic access")
// XPConnect wrappers and DOM bindings
MSG_DEF(JSMSG_CANT_SET_INTERPOSED, 1, JSEXN_TYPEERR, "unable to set interposed data property '{0}'")
@@ -520,3 +570,12 @@
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 1, JSEXN_SYNTAXERR, "ambiguous import '{0}'")
MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT, 0, JSEXN_SYNTAXERR, "export not found for namespace")
MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
+MSG_DEF(JSMSG_MODULE_INSTANTIATE_FAILED, 0, JSEXN_INTERNALERR, "attempt to re-instantiate module after failure")
+MSG_DEF(JSMSG_BAD_MODULE_STATE, 0, JSEXN_INTERNALERR, "module record in unexpected state")
+
+// Promise
+MSG_DEF(JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF, 0, JSEXN_TYPEERR, "A promise cannot be resolved with itself.")
+MSG_DEF(JSMSG_PROMISE_CAPABILITY_HAS_SOMETHING_ALREADY, 0, JSEXN_TYPEERR, "GetCapabilitiesExecutor function already invoked with non-undefined values.")
+MSG_DEF(JSMSG_PROMISE_RESOLVE_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the resolve function.")
+MSG_DEF(JSMSG_PROMISE_REJECT_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the reject function.")
+MSG_DEF(JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON,0, JSEXN_INTERNALERR, "Promise rejection value is a non-unwrappable cross-compartment wrapper.")
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/CallArgs.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/CallArgs.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/CallArgs.h
@@ -6,16 +6,51 @@
/*
* Helper classes encapsulating access to the callee, |this| value, arguments,
- * and argument count for a function call.
+ * and argument count for a call/construct operation.
*
- * The intent of JS::CallArgs and JS::CallReceiver is that they be used to
- * encapsulate access to the un-abstracted |unsigned argc, Value* vp| arguments
- * to a function. It's possible (albeit deprecated) to manually index into
- * |vp| to access the callee, |this|, and arguments of a function, and to set
- * its return value. It's also possible to use the supported API of JS_CALLEE,
- * JS_THIS, JS_ARGV, JS_RVAL and JS_SET_RVAL to the same ends. But neither API
- * has the error-handling or moving-GC correctness of CallArgs or CallReceiver.
- * New code should use CallArgs and CallReceiver instead whenever possible.
+ * JS::CallArgs encapsulates access to a JSNative's un-abstracted
+ * |unsigned argc, Value* vp| arguments. The principal way to create a
+ * JS::CallArgs is using JS::CallArgsFromVp:
+ *
+ * // If provided no arguments or a non-numeric first argument, return zero.
+ * // Otherwise return |this| exactly as given, without boxing.
+ * static bool
+ * Func(JSContext* cx, unsigned argc, JS::Value* vp)
+ * {
+ * JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ *
+ * // Guard against no arguments or a non-numeric arg0.
+ * if (args.length() == 0 || !args[0].isNumber()) {
+ * args.rval().setInt32(0);
+ * return true;
+ * }
+ *
+ * // Access to the callee must occur before accessing/setting
+ * // the return value.
+ * JSObject& callee = args.callee();
+ * args.rval().setObject(callee);
+ *
+ * // callee() and calleev() will now assert.
+ *
+ * // It's always fine to access thisv().
+ * HandleValue thisv = args.thisv();
+ * args.rval().set(thisv);
+ *
+ * // As the return value was last set to |this|, returns |this|.
+ * return true;
+ * }
+ *
+ * CallArgs is exposed publicly and used internally. Not all parts of its
+ * public interface are meant to be used by embedders! See inline comments to
+ * for details.
+ *
+ * It's possible (albeit deprecated) to manually index into |vp| to access the
+ * callee, |this|, and arguments of a function, and to set its return value.
+ * It's also possible to use the supported API of JS_CALLEE, JS_THIS, JS_ARGV,
+ * JS_RVAL, and JS_SET_RVAL to the same ends.
+ *
+ * But neither API has the error-handling or moving-GC correctness of CallArgs.
+ * New code should use CallArgs instead whenever possible.
*
* The eventual plan is to change JSNative to take |const CallArgs&| directly,
* for automatic assertion of correct use and to make calling functions more
@@ -42,118 +77,99 @@
typedef bool
(* JSNative)(JSContext* cx, unsigned argc, JS::Value* vp);
-/*
- * Compute |this| for the |vp| inside a JSNative, either boxing primitives or
- * replacing with the global object as necessary.
- *
- * This method will go away at some point: instead use |args.thisv()|. If the
- * value is an object, no further work is required. If that value is |null| or
- * |undefined|, use |JS_GetGlobalForObject| to compute the global object. If
- * the value is some other primitive, use |JS_ValueToObject| to box it.
- */
-extern JS_PUBLIC_API(JS::Value)
-JS_ComputeThis(JSContext* cx, JS::Value* vp);
-
namespace JS {
extern JS_PUBLIC_DATA(const HandleValue) UndefinedHandleValue;
+namespace detail {
+
/*
- * JS::CallReceiver encapsulates access to the callee, |this|, and eventual
- * return value for a function call. The principal way to create a
- * CallReceiver is using JS::CallReceiverFromVp:
- *
- * static bool
- * FunctionReturningThis(JSContext* cx, unsigned argc, JS::Value* vp)
- * {
- * JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
- *
- * // Access to the callee must occur before accessing/setting
- * // the return value.
- * JSObject& callee = rec.callee();
- * rec.rval().set(JS::ObjectValue(callee));
- *
- * // callee() and calleev() will now assert.
- *
- * // It's always fine to access thisv().
- * HandleValue thisv = rec.thisv();
- * rec.rval().set(thisv);
- *
- * // As the return value was last set to |this|, returns |this|.
- * return true;
- * }
- *
- * A note on JS_ComputeThis and JS_THIS_OBJECT: these methods currently aren't
- * part of the CallReceiver interface. We will likely add them at some point.
- * Until then, you should probably continue using |vp| directly for these two
- * cases.
- *
- * CallReceiver is exposed publicly and used internally. Not all parts of its
- * public interface are meant to be used by embedders! See inline comments to
- * for details.
+ * Compute |this| for the |vp| inside a JSNative, either boxing primitives or
+ * replacing with the global object as necessary.
*/
-
-namespace detail {
+extern JS_PUBLIC_API(Value)
+ComputeThis(JSContext* cx, JS::Value* vp);
#ifdef JS_DEBUG
extern JS_PUBLIC_API(void)
-CheckIsValidConstructible(Value v);
+CheckIsValidConstructible(const Value& v);
#endif
-enum UsedRval { IncludeUsedRval, NoUsedRval };
-
-template<UsedRval WantUsedRval>
-class MOZ_STACK_CLASS UsedRvalBase;
-
-template<>
-class MOZ_STACK_CLASS UsedRvalBase<IncludeUsedRval>
+class MOZ_STACK_CLASS IncludeUsedRval
{
protected:
+#ifdef JS_DEBUG
mutable bool usedRval_;
void setUsedRval() const { usedRval_ = true; }
void clearUsedRval() const { usedRval_ = false; }
+ void assertUnusedRval() const { MOZ_ASSERT(!usedRval_); }
+#else
+ void setUsedRval() const {}
+ void clearUsedRval() const {}
+ void assertUnusedRval() const {}
+#endif
};
-template<>
-class MOZ_STACK_CLASS UsedRvalBase<NoUsedRval>
+class MOZ_STACK_CLASS NoUsedRval
{
protected:
void setUsedRval() const {}
void clearUsedRval() const {}
+ void assertUnusedRval() const {}
};
-template<UsedRval WantUsedRval>
-class MOZ_STACK_CLASS CallReceiverBase : public UsedRvalBase<
-#ifdef JS_DEBUG
- WantUsedRval
-#else
- NoUsedRval
-#endif
- >
+template<class WantUsedRval>
+class MOZ_STACK_CLASS CallArgsBase : public WantUsedRval
{
+ static_assert(mozilla::IsSame<WantUsedRval, IncludeUsedRval>::value ||
+ mozilla::IsSame<WantUsedRval, NoUsedRval>::value,
+ "WantUsedRval can only be IncludeUsedRval or NoUsedRval");
+
protected:
Value* argv_;
+ unsigned argc_;
+ bool constructing_;
public:
- /*
- * Returns the function being called, as an object. Must not be called
- * after rval() has been used!
- */
- JSObject& callee() const {
- MOZ_ASSERT(!this->usedRval_);
- return argv_[-2].toObject();
- }
+ // CALLEE ACCESS
/*
* Returns the function being called, as a value. Must not be called after
* rval() has been used!
*/
HandleValue calleev() const {
- MOZ_ASSERT(!this->usedRval_);
+ this->assertUnusedRval();
return HandleValue::fromMarkedLocation(&argv_[-2]);
}
/*
+ * Returns the function being called, as an object. Must not be called
+ * after rval() has been used!
+ */
+ JSObject& callee() const {
+ return calleev().toObject();
+ }
+
+ // CALLING/CONSTRUCTING-DIFFERENTIATIONS
+
+ bool isConstructing() const {
+ if (!argv_[-1].isMagic())
+ return false;
+
+#ifdef JS_DEBUG
+ if (!this->usedRval_)
+ CheckIsValidConstructible(calleev());
+#endif
+
+ return true;
+ }
+
+ MutableHandleValue newTarget() const {
+ MOZ_ASSERT(constructing_);
+ return MutableHandleValue::fromMarkedLocation(&this->argv_[argc_]);
+ }
+
+ /*
* Returns the |this| value passed to the function. This method must not
* be called when the function is being called as a constructor via |new|.
* The value may or may not be an object: it is the individual function's
@@ -170,17 +186,40 @@
if (thisv().isObject())
return thisv();
- return JS_ComputeThis(cx, base());
+ return ComputeThis(cx, base());
}
- bool isConstructing() const {
-#ifdef JS_DEBUG
- if (this->usedRval_)
- CheckIsValidConstructible(calleev());
-#endif
- return argv_[-1].isMagic();
+ // ARGUMENTS
+
+ /* Returns the number of arguments. */
+ unsigned length() const { return argc_; }
+
+ /* Returns the i-th zero-indexed argument. */
+ MutableHandleValue operator[](unsigned i) const {
+ MOZ_ASSERT(i < argc_);
+ return MutableHandleValue::fromMarkedLocation(&this->argv_[i]);
+ }
+
+ /*
+ * Returns the i-th zero-indexed argument, or |undefined| if there's no
+ * such argument.
+ */
+ HandleValue get(unsigned i) const {
+ return i < length()
+ ? HandleValue::fromMarkedLocation(&this->argv_[i])
+ : UndefinedHandleValue;
+ }
+
+ /*
+ * Returns true if the i-th zero-indexed argument is present and is not
+ * |undefined|.
+ */
+ bool hasDefined(unsigned i) const {
+ return i < argc_ && !this->argv_[i].isUndefined();
}
+ // RETURN VALUE
+
/*
* Returns the currently-set return value. The initial contents of this
* value are unspecified. Once this method has been called, callee() and
@@ -198,135 +237,41 @@
}
public:
- // These methods are only intended for internal use. Embedders shouldn't
- // use them!
-
- Value* base() const { return argv_ - 2; }
-
- Value* spAfterCall() const {
- this->setUsedRval();
- return argv_ - 1;
- }
-
- public:
// These methods are publicly exposed, but they are *not* to be used when
// implementing a JSNative method and encapsulating access to |vp| within
// it. You probably don't want to use these!
- void setCallee(Value aCalleev) const {
+ void setCallee(const Value& aCalleev) const {
this->clearUsedRval();
argv_[-2] = aCalleev;
}
- void setThis(Value aThisv) const {
+ void setThis(const Value& aThisv) const {
argv_[-1] = aThisv;
}
MutableHandleValue mutableThisv() const {
return MutableHandleValue::fromMarkedLocation(&argv_[-1]);
}
-};
-
-} // namespace detail
-
-class MOZ_STACK_CLASS CallReceiver : public detail::CallReceiverBase<detail::IncludeUsedRval>
-{
- private:
- friend CallReceiver CallReceiverFromVp(Value* vp);
- friend CallReceiver CallReceiverFromArgv(Value* argv);
-};
-
-MOZ_ALWAYS_INLINE CallReceiver
-CallReceiverFromArgv(Value* argv)
-{
- CallReceiver receiver;
- receiver.clearUsedRval();
- receiver.argv_ = argv;
- return receiver;
-}
-
-MOZ_ALWAYS_INLINE CallReceiver
-CallReceiverFromVp(Value* vp)
-{
- return CallReceiverFromArgv(vp + 2);
-}
-
-/*
- * JS::CallArgs encapsulates everything JS::CallReceiver does, plus access to
- * the function call's arguments. The principal way to create a CallArgs is
- * like so, using JS::CallArgsFromVp:
- *
- * static bool
- * FunctionReturningArgcTimesArg0(JSContext* cx, unsigned argc, JS::Value* vp)
- * {
- * JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
- *
- * // Guard against no arguments or a non-numeric arg0.
- * if (args.length() == 0 || !args[0].isNumber()) {
- * args.rval().setInt32(0);
- * return true;
- * }
- *
- * args.rval().set(JS::NumberValue(args.length() * args[0].toNumber()));
- * return true;
- * }
- *
- * CallArgs is exposed publicly and used internally. Not all parts of its
- * public interface are meant to be used by embedders! See inline comments to
- * for details.
- */
-namespace detail {
-
-template<UsedRval WantUsedRval>
-class MOZ_STACK_CLASS CallArgsBase :
- public mozilla::Conditional<WantUsedRval == detail::IncludeUsedRval,
- CallReceiver,
- CallReceiverBase<NoUsedRval> >::Type
-{
- protected:
- unsigned argc_;
- bool constructing_;
public:
- /* Returns the number of arguments. */
- unsigned length() const { return argc_; }
+ // These methods are publicly exposed, but we're unsure of the interfaces
+ // (because they're hackish and drop assertions). Avoid using these if you
+ // can.
- /* Returns the i-th zero-indexed argument. */
- MutableHandleValue operator[](unsigned i) const {
- MOZ_ASSERT(i < argc_);
- return MutableHandleValue::fromMarkedLocation(&this->argv_[i]);
- }
+ Value* array() const { return argv_; }
+ Value* end() const { return argv_ + argc_ + constructing_; }
- /*
- * Returns the i-th zero-indexed argument, or |undefined| if there's no
- * such argument.
- */
- HandleValue get(unsigned i) const {
- return i < length()
- ? HandleValue::fromMarkedLocation(&this->argv_[i])
- : UndefinedHandleValue;
- }
+ public:
+ // These methods are only intended for internal use. Embedders shouldn't
+ // use them!
- /*
- * Returns true if the i-th zero-indexed argument is present and is not
- * |undefined|.
- */
- bool hasDefined(unsigned i) const {
- return i < argc_ && !this->argv_[i].isUndefined();
- }
+ Value* base() const { return argv_ - 2; }
- MutableHandleValue newTarget() const {
- MOZ_ASSERT(constructing_);
- return MutableHandleValue::fromMarkedLocation(&this->argv_[argc_]);
+ Value* spAfterCall() const {
+ this->setUsedRval();
+ return argv_ - 1;
}
-
- public:
- // These methods are publicly exposed, but we're less sure of the interface
- // here than we'd like (because they're hackish and drop assertions). Try
- // to avoid using these if you can.
-
- Value* array() const { return this->argv_; }
- Value* end() const { return this->argv_ + argc_ + constructing_; }
};
} // namespace detail
@@ -343,6 +288,10 @@
args.argv_ = argv;
args.argc_ = argc;
args.constructing_ = constructing;
+#ifdef DEBUG
+ for (unsigned i = 0; i < argc; ++i)
+ MOZ_ASSERT_IF(argv[i].isMarkable(), !GCThingIsMarkedGray(GCCellPtr(argv[i])));
+#endif
return args;
}
@@ -351,7 +300,7 @@
* Returns true if there are at least |required| arguments passed in. If
* false, it reports an error message on the context.
*/
- bool requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const;
+ JS_PUBLIC_API(bool) requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const;
};
@@ -379,19 +328,30 @@
* take a const JS::CallArgs&.
*/
-#define JS_THIS_OBJECT(cx,vp) (JS_THIS(cx,vp).toObjectOrNull())
-
/*
+ * Return |this| if |this| is an object. Otherwise, return the global object
+ * if |this| is null or undefined, and finally return a boxed version of any
+ * other primitive.
+ *
* Note: if this method returns null, an error has occurred and must be
* propagated or caught.
*/
MOZ_ALWAYS_INLINE JS::Value
JS_THIS(JSContext* cx, JS::Value* vp)
{
- return vp[1].isPrimitive() ? JS_ComputeThis(cx, vp) : vp[1];
+ return vp[1].isPrimitive() ? JS::detail::ComputeThis(cx, vp) : vp[1];
}
/*
+ * A note on JS_THIS_OBJECT: no equivalent method is part of the CallArgs
+ * interface, and we're unlikely to add one (functions shouldn't be implicitly
+ * exposing the global object to arbitrary callers). Continue using |vp|
+ * directly for this case, but be aware this API will eventually be replaced
+ * with a function that operates directly upon |args.thisv()|.
+ */
+#define JS_THIS_OBJECT(cx,vp) (JS_THIS(cx,vp).toObjectOrNull())
+
+/*
* |this| is passed to functions in ES5 without change. Functions themselves
* do any post-processing they desire to box |this|, compute the global object,
* &c. This macro retrieves a function's unboxed |this| value.
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/CharacterEncoding.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/CharacterEncoding.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/CharacterEncoding.h
@@ -31,6 +31,8 @@
typedef mozilla::Range<Latin1Char> Base;
public:
+ using CharT = Latin1Char;
+
Latin1Chars() : Base() {}
Latin1Chars(char* aBytes, size_t aLength) : Base(reinterpret_cast<Latin1Char*>(aBytes), aLength) {}
Latin1Chars(const Latin1Char* aBytes, size_t aLength)
@@ -49,6 +51,8 @@
typedef mozilla::RangedPtr<Latin1Char> Base;
public:
+ using CharT = Latin1Char;
+
Latin1CharsZ() : Base(nullptr, 0) {}
Latin1CharsZ(char* aBytes, size_t aLength)
@@ -73,6 +77,8 @@
typedef mozilla::Range<unsigned char> Base;
public:
+ using CharT = unsigned char;
+
UTF8Chars() : Base() {}
UTF8Chars(char* aBytes, size_t aLength)
: Base(reinterpret_cast<unsigned char*>(aBytes), aLength)
@@ -90,6 +96,8 @@
typedef mozilla::RangedPtr<unsigned char> Base;
public:
+ using CharT = unsigned char;
+
UTF8CharsZ() : Base(nullptr, 0) {}
UTF8CharsZ(char* aBytes, size_t aLength)
@@ -110,6 +118,43 @@
};
/*
+ * A wrapper for a "const char*" that is encoded using UTF-8.
+ * This class does not manage ownership of the data; that is left
+ * to others. This differs from UTF8CharsZ in that the chars are
+ * const and it allows assignment.
+ */
+class JS_PUBLIC_API(ConstUTF8CharsZ)
+{
+ const char* data_;
+
+ public:
+ using CharT = unsigned char;
+
+ ConstUTF8CharsZ() : data_(nullptr)
+ {}
+
+ ConstUTF8CharsZ(const char* aBytes, size_t aLength)
+ : data_(aBytes)
+ {
+ MOZ_ASSERT(aBytes[aLength] == '\0');
+#ifdef DEBUG
+ validate(aLength);
+#endif
+ }
+
+ const void* get() const { return data_; }
+
+ const char* c_str() const { return data_; }
+
+ explicit operator bool() const { return data_ != nullptr; }
+
+ private:
+#ifdef DEBUG
+ void validate(size_t aLength);
+#endif
+};
+
+/*
* SpiderMonkey uses a 2-byte character representation: it is a
* 2-byte-at-a-time view of a UTF-16 byte stream. This is similar to UCS-2,
* but unlike UCS-2, we do not strip UTF-16 extension bytes. This allows a
@@ -122,6 +167,8 @@
typedef mozilla::Range<char16_t> Base;
public:
+ using CharT = char16_t;
+
TwoByteChars() : Base() {}
TwoByteChars(char16_t* aChars, size_t aLength) : Base(aChars, aLength) {}
TwoByteChars(const char16_t* aChars, size_t aLength) : Base(const_cast<char16_t*>(aChars), aLength) {}
@@ -135,6 +182,8 @@
typedef mozilla::RangedPtr<char16_t> Base;
public:
+ using CharT = char16_t;
+
TwoByteCharsZ() : Base(nullptr, 0) {}
TwoByteCharsZ(char16_t* chars, size_t length)
@@ -156,6 +205,8 @@
typedef mozilla::Range<const char16_t> Base;
public:
+ using CharT = char16_t;
+
ConstTwoByteChars() : Base() {}
ConstTwoByteChars(const char16_t* aChars, size_t aLength) : Base(aChars, aLength) {}
};
@@ -174,11 +225,18 @@
LossyTwoByteCharsToNewLatin1CharsZ(js::ExclusiveContext* cx,
const mozilla::Range<const char16_t> tbchars);
+inline Latin1CharsZ
+LossyTwoByteCharsToNewLatin1CharsZ(js::ExclusiveContext* cx, const char16_t* begin, size_t length)
+{
+ const mozilla::Range<const char16_t> tbchars(begin, length);
+ return JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars);
+}
+
template <typename CharT>
extern UTF8CharsZ
-CharsToNewUTF8CharsZ(js::ExclusiveContext* maybeCx, const mozilla::Range<const CharT> chars);
+CharsToNewUTF8CharsZ(js::ExclusiveContext* maybeCx, const mozilla::Range<CharT> chars);
-uint32_t
+JS_PUBLIC_API(uint32_t)
Utf8ToOneUcs4Char(const uint8_t* utf8Buffer, int utf8Length);
/*
@@ -187,17 +245,26 @@
* - On success, returns a malloc'd TwoByteCharsZ, and updates |outlen| to hold
* its length; the length value excludes the trailing null.
*/
-extern TwoByteCharsZ
+extern JS_PUBLIC_API(TwoByteCharsZ)
UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
/*
+ * Like UTF8CharsToNewTwoByteCharsZ, but for ConstUTF8CharsZ.
+ */
+extern JS_PUBLIC_API(TwoByteCharsZ)
+UTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, size_t* outlen);
+
+/*
* The same as UTF8CharsToNewTwoByteCharsZ(), except that any malformed UTF-8 characters
* will be replaced by \uFFFD. No exception will be thrown for malformed UTF-8
* input.
*/
-extern TwoByteCharsZ
+extern JS_PUBLIC_API(TwoByteCharsZ)
LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
+extern JS_PUBLIC_API(TwoByteCharsZ)
+LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const ConstUTF8CharsZ& utf8, size_t* outlen);
+
/*
* Returns the length of the char buffer required to encode |s| as UTF8.
* Does not include the null-terminator.
@@ -206,11 +273,62 @@
GetDeflatedUTF8StringLength(JSFlatString* s);
/*
- * Encode |src| as UTF8. The caller must ensure |dst| has enough space.
- * Does not write the null terminator.
+ * Encode |src| as UTF8. The caller must either ensure |dst| has enough space
+ * to encode the entire string or pass the length of the buffer as |dstlenp|,
+ * in which case the function will encode characters from the string until
+ * the buffer is exhausted. Does not write the null terminator.
+ *
+ * If |dstlenp| is provided, it will be updated to hold the number of bytes
+ * written to the buffer. If |numcharsp| is provided, it will be updated to hold
+ * the number of Unicode characters written to the buffer (which can be less
+ * than the length of the string, if the buffer is exhausted before the string
+ * is fully encoded).
*/
JS_PUBLIC_API(void)
-DeflateStringToUTF8Buffer(JSFlatString* src, mozilla::RangedPtr<char> dst);
+DeflateStringToUTF8Buffer(JSFlatString* src, mozilla::RangedPtr<char> dst,
+ size_t* dstlenp = nullptr, size_t* numcharsp = nullptr);
+
+/*
+ * The smallest character encoding capable of fully representing a particular
+ * string.
+ */
+enum class SmallestEncoding {
+ ASCII,
+ Latin1,
+ UTF16
+};
+
+/*
+ * Returns the smallest encoding possible for the given string: if all
+ * codepoints are <128 then ASCII, otherwise if all codepoints are <256
+ * Latin-1, else UTF16.
+ */
+JS_PUBLIC_API(SmallestEncoding)
+FindSmallestEncoding(UTF8Chars utf8);
+
+/*
+ * Return a null-terminated Latin-1 string copied from the input string,
+ * storing its length (excluding null terminator) in |*outlen|. Fail and
+ * report an error if the string contains non-Latin-1 codepoints. Returns
+ * Latin1CharsZ() on failure.
+ */
+extern JS_PUBLIC_API(Latin1CharsZ)
+UTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
+
+/*
+ * Return a null-terminated Latin-1 string copied from the input string,
+ * storing its length (excluding null terminator) in |*outlen|. Non-Latin-1
+ * codepoints are replaced by '?'. Returns Latin1CharsZ() on failure.
+ */
+extern JS_PUBLIC_API(Latin1CharsZ)
+LossyUTF8CharsToNewLatin1CharsZ(JSContext* cx, const UTF8Chars utf8, size_t* outlen);
+
+/*
+ * Returns true if all characters in the given null-terminated string are
+ * ASCII, i.e. < 0x80, false otherwise.
+ */
+extern JS_PUBLIC_API(bool)
+StringIsASCII(const char* s);
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Class.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Class.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Class.h
@@ -9,8 +9,6 @@
#ifndef js_Class_h
#define js_Class_h
-#include "mozilla/DebugOnly.h"
-
#include "jstypes.h"
#include "js/CallArgs.h"
@@ -42,9 +40,7 @@
namespace JS {
-template <typename T>
-class AutoVectorRooter;
-typedef AutoVectorRooter<jsid> AutoIdVector;
+class AutoIdVector;
/**
* The answer to a successful query as to whether an object is an Array per
@@ -337,8 +333,8 @@
* (e.g., the DOM attributes for a given node reflected as obj) on demand.
*
* JS looks for a property in an object, and if not found, tries to resolve
- * the given id. *resolvedp should be set to true iff the property was
- * was defined on |obj|.
+ * the given id. *resolvedp should be set to true iff the property was defined
+ * on |obj|.
*/
typedef bool
(* JSResolveOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
@@ -368,7 +364,7 @@
/** Finalizes external strings created by JS_NewExternalString. */
struct JSStringFinalizer {
- void (*finalize)(const JSStringFinalizer* fin, char16_t* chars);
+ void (*finalize)(JS::Zone* zone, const JSStringFinalizer* fin, char16_t* chars);
};
/**
@@ -383,8 +379,8 @@
/**
* Function type for trace operation of the class called to enumerate all
* traceable things reachable from obj's private data structure. For each such
- * thing, a trace implementation must call one of the JS_Call*Tracer variants
- * on the thing.
+ * thing, a trace implementation must call JS::TraceEdge on the thing's
+ * location.
*
* JSTraceOp implementation can assume that no other threads mutates object
* state. It must not change state of the object or corresponding native
@@ -412,7 +408,7 @@
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* DefinePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::Handle<JSPropertyDescriptor> desc,
+ JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
typedef bool
(* HasPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
@@ -424,7 +420,7 @@
JS::HandleValue receiver, JS::ObjectOpResult& result);
typedef bool
(* GetOwnPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
typedef bool
(* DeletePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::ObjectOpResult& result);
@@ -453,15 +449,25 @@
JS::Value* vp_;
uint32_t index_;
- mozilla::DebugOnly<uint32_t> length_;
+#ifdef DEBUG
+ uint32_t length_;
+#endif
GetBehavior getBehavior_;
public:
ElementAdder(JSContext* cx, JSObject* obj, uint32_t length, GetBehavior behavior)
- : resObj_(cx, obj), vp_(nullptr), index_(0), length_(length), getBehavior_(behavior)
+ : resObj_(cx, obj), vp_(nullptr), index_(0),
+#ifdef DEBUG
+ length_(length),
+#endif
+ getBehavior_(behavior)
{}
ElementAdder(JSContext* cx, JS::Value* vp, uint32_t length, GetBehavior behavior)
- : resObj_(cx), vp_(vp), index_(0), length_(length), getBehavior_(behavior)
+ : resObj_(cx), vp_(vp), index_(0),
+#ifdef DEBUG
+ length_(length),
+#endif
+ getBehavior_(behavior)
{}
GetBehavior getBehavior() const { return getBehavior_; }
@@ -477,23 +483,55 @@
typedef void
(* FinalizeOp)(FreeOp* fop, JSObject* obj);
-#define JS_CLASS_MEMBERS(FinalizeOpType) \
- const char* name; \
- uint32_t flags; \
- \
- /* Function pointer members (may be null). */ \
- JSAddPropertyOp addProperty; \
- JSDeletePropertyOp delProperty; \
- JSGetterOp getProperty; \
- JSSetterOp setProperty; \
- JSEnumerateOp enumerate; \
- JSResolveOp resolve; \
- JSMayResolveOp mayResolve; \
- FinalizeOpType finalize; \
- JSNative call; \
- JSHasInstanceOp hasInstance; \
- JSNative construct; \
- JSTraceOp trace
+// The special treatment of |finalize| and |trace| is necessary because if we
+// assign either of those hooks to a local variable and then call it -- as is
+// done with the other hooks -- the GC hazard analysis gets confused.
+#define JS_CLASS_MEMBERS(ClassOpsType, FreeOpType) \
+ const char* name; \
+ uint32_t flags; \
+ const ClassOpsType* cOps; \
+ \
+ JSAddPropertyOp getAddProperty() const { return cOps ? cOps->addProperty : nullptr; } \
+ JSDeletePropertyOp getDelProperty() const { return cOps ? cOps->delProperty : nullptr; } \
+ JSGetterOp getGetProperty() const { return cOps ? cOps->getProperty : nullptr; } \
+ JSSetterOp getSetProperty() const { return cOps ? cOps->setProperty : nullptr; } \
+ JSEnumerateOp getEnumerate() const { return cOps ? cOps->enumerate : nullptr; } \
+ JSResolveOp getResolve() const { return cOps ? cOps->resolve : nullptr; } \
+ JSMayResolveOp getMayResolve() const { return cOps ? cOps->mayResolve : nullptr; } \
+ JSNative getCall() const { return cOps ? cOps->call : nullptr; } \
+ JSHasInstanceOp getHasInstance() const { return cOps ? cOps->hasInstance : nullptr; } \
+ JSNative getConstruct() const { return cOps ? cOps->construct : nullptr; } \
+ \
+ bool hasFinalize() const { return cOps && cOps->finalize; } \
+ bool hasTrace() const { return cOps && cOps->trace; } \
+ \
+ bool isTrace(JSTraceOp trace) const { return cOps && cOps->trace == trace; } \
+ \
+ void doFinalize(FreeOpType* fop, JSObject* obj) const { \
+ MOZ_ASSERT(cOps && cOps->finalize); \
+ cOps->finalize(fop, obj); \
+ } \
+ void doTrace(JSTracer* trc, JSObject* obj) const { \
+ MOZ_ASSERT(cOps && cOps->trace); \
+ cOps->trace(trc, obj); \
+ }
+
+struct ClassOps
+{
+ /* Function pointer members (may be null). */
+ JSAddPropertyOp addProperty;
+ JSDeletePropertyOp delProperty;
+ JSGetterOp getProperty;
+ JSSetterOp setProperty;
+ JSEnumerateOp enumerate;
+ JSResolveOp resolve;
+ JSMayResolveOp mayResolve;
+ FinalizeOp finalize;
+ JSNative call;
+ JSHasInstanceOp hasInstance;
+ JSNative construct;
+ JSTraceOp trace;
+};
/** Callback for the creation of constructor and prototype objects. */
typedef JSObject* (*ClassObjectCreationOp)(JSContext* cx, JSProtoKey key);
@@ -516,11 +554,11 @@
FinishClassInitOp finishInit_;
uintptr_t flags;
- static const size_t ParentKeyWidth = JSCLASS_CACHED_PROTO_WIDTH;
+ static const size_t ProtoKeyWidth = JSCLASS_CACHED_PROTO_WIDTH;
- static const uintptr_t ParentKeyMask = (1 << ParentKeyWidth) - 1;
- static const uintptr_t DontDefineConstructor = 1 << ParentKeyWidth;
- static const uintptr_t IsDelegated = 1 << (ParentKeyWidth + 1);
+ static const uintptr_t ProtoKeyMask = (1 << ProtoKeyWidth) - 1;
+ static const uintptr_t DontDefineConstructor = 1 << ProtoKeyWidth;
+ static const uintptr_t IsDelegated = 1 << (ProtoKeyWidth + 1);
bool defined() const { return !!createConstructor_; }
@@ -528,14 +566,16 @@
return (flags & IsDelegated);
}
- bool dependent() const {
+ // The ProtoKey this class inherits from.
+ JSProtoKey inheritanceProtoKey() const {
MOZ_ASSERT(defined());
- return (flags & ParentKeyMask);
- }
-
- JSProtoKey parentKey() const {
static_assert(JSProto_Null == 0, "zeroed key must be null");
- return JSProtoKey(flags & ParentKeyMask);
+
+ // Default: Inherit from Object.
+ if (!(flags & ProtoKeyMask))
+ return JSProto_Object;
+
+ return JSProtoKey(flags & ProtoKeyMask);
}
bool shouldDefineConstructor() const {
@@ -588,12 +628,6 @@
struct ClassExtension
{
/**
- * isWrappedNative is true only if the class is an XPCWrappedNative.
- * WeakMaps use this to override the wrapper disposal optimization.
- */
- bool isWrappedNative;
-
- /**
* If an object is used as a key in a weakmap, it may be desirable for the
* garbage collector to keep that object around longer than it otherwise
* would. A common case is when the key is a wrapper around an object in
@@ -624,28 +658,26 @@
return reinterpret_cast<ClassObjectCreationOp>(const_cast<ClassSpec*>(spec));
}
-#define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
-#define JS_NULL_CLASS_EXT {false,nullptr}
+#define JS_NULL_CLASS_SPEC nullptr
+#define JS_NULL_CLASS_EXT nullptr
struct ObjectOps
{
- LookupPropertyOp lookupProperty;
- DefinePropertyOp defineProperty;
- HasPropertyOp hasProperty;
- GetPropertyOp getProperty;
- SetPropertyOp setProperty;
- GetOwnPropertyOp getOwnPropertyDescriptor;
- DeletePropertyOp deleteProperty;
- WatchOp watch;
- UnwatchOp unwatch;
- GetElementsOp getElements;
- JSNewEnumerateOp enumerate;
- JSFunToStringOp funToString;
-};
-
-#define JS_NULL_OBJECT_OPS \
- {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, \
- nullptr, nullptr, nullptr, nullptr}
+ LookupPropertyOp lookupProperty;
+ DefinePropertyOp defineProperty;
+ HasPropertyOp hasProperty;
+ GetPropertyOp getProperty;
+ SetPropertyOp setProperty;
+ GetOwnPropertyOp getOwnPropertyDescriptor;
+ DeletePropertyOp deleteProperty;
+ WatchOp watch;
+ UnwatchOp unwatch;
+ GetElementsOp getElements;
+ JSNewEnumerateOp enumerate;
+ JSFunToStringOp funToString;
+};
+
+#define JS_NULL_OBJECT_OPS nullptr
} // namespace js
@@ -653,19 +685,54 @@
typedef void (*JSClassInternal)();
+struct JSClassOps
+{
+ /* Function pointer members (may be null). */
+ JSAddPropertyOp addProperty;
+ JSDeletePropertyOp delProperty;
+ JSGetterOp getProperty;
+ JSSetterOp setProperty;
+ JSEnumerateOp enumerate;
+ JSResolveOp resolve;
+ JSMayResolveOp mayResolve;
+ JSFinalizeOp finalize;
+ JSNative call;
+ JSHasInstanceOp hasInstance;
+ JSNative construct;
+ JSTraceOp trace;
+};
+
+#define JS_NULL_CLASS_OPS nullptr
+
struct JSClass {
- JS_CLASS_MEMBERS(JSFinalizeOp);
+ JS_CLASS_MEMBERS(JSClassOps, JSFreeOp);
- void* reserved[23];
+ void* reserved[3];
};
#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot
-#define JSCLASS_DELAY_METADATA_CALLBACK (1<<1) // class's initialization code
+#define JSCLASS_DELAY_METADATA_BUILDER (1<<1) // class's initialization code
// will call
// SetNewObjectMetadata itself
+#define JSCLASS_IS_WRAPPED_NATIVE (1<<2) // class is an XPCWrappedNative.
+ // WeakMaps use this to override
+ // the wrapper disposal
+ // mechanism.
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) // private is (nsISupports*)
#define JSCLASS_IS_DOMJSCLASS (1<<4) // objects are DOM
-// Bit 5 is unused.
+#define JSCLASS_HAS_XRAYED_CONSTRUCTOR (1<<5) // if wrapped by an xray
+ // wrapper, the builtin
+ // class's constructor won't
+ // be unwrapped and invoked.
+ // Instead, the constructor is
+ // resolved in the caller's
+ // compartment and invoked
+ // with a wrapped newTarget.
+ // The constructor has to
+ // detect and handle this
+ // situation.
+ // See PromiseConstructor for
+ // details.
#define JSCLASS_EMULATES_UNDEFINED (1<<6) // objects of this class act
// like the value undefined,
// in some contexts
@@ -700,6 +767,7 @@
#define JSCLASS_USERBIT3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+7))
#define JSCLASS_BACKGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+8))
+#define JSCLASS_FOREGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+9))
// Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see
// below.
@@ -719,7 +787,7 @@
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
#define JSCLASS_GLOBAL_SLOT_COUNT \
- (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 36)
+ (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 39)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
@@ -745,10 +813,10 @@
struct Class
{
- JS_CLASS_MEMBERS(FinalizeOp);
- ClassSpec spec;
- ClassExtension ext;
- ObjectOps ops;
+ JS_CLASS_MEMBERS(js::ClassOps, FreeOp);
+ const ClassSpec* spec;
+ const ClassExtension* ext;
+ const ObjectOps* oOps;
/*
* Objects of this class aren't native objects. They don't have Shapes that
@@ -777,7 +845,7 @@
bool nonProxyCallable() const {
MOZ_ASSERT(!isProxy());
- return isJSFunction() || call;
+ return isJSFunction() || getCall();
}
bool isProxy() const {
@@ -788,40 +856,89 @@
return flags & JSCLASS_IS_DOMJSCLASS;
}
- bool shouldDelayMetadataCallback() const {
- return flags & JSCLASS_DELAY_METADATA_CALLBACK;
+ bool shouldDelayMetadataBuilder() const {
+ return flags & JSCLASS_DELAY_METADATA_BUILDER;
+ }
+
+ bool isWrappedNative() const {
+ return flags & JSCLASS_IS_WRAPPED_NATIVE;
}
static size_t offsetOfFlags() { return offsetof(Class, flags); }
+
+ bool specDefined() const { return spec ? spec->defined() : false; }
+ JSProtoKey specInheritanceProtoKey()
+ const { return spec ? spec->inheritanceProtoKey() : JSProto_Null; }
+ bool specShouldDefineConstructor()
+ const { return spec ? spec->shouldDefineConstructor() : true; }
+ ClassObjectCreationOp specCreateConstructorHook()
+ const { return spec ? spec->createConstructorHook() : nullptr; }
+ ClassObjectCreationOp specCreatePrototypeHook()
+ const { return spec ? spec->createPrototypeHook() : nullptr; }
+ const JSFunctionSpec* specConstructorFunctions()
+ const { return spec ? spec->constructorFunctions() : nullptr; }
+ const JSPropertySpec* specConstructorProperties()
+ const { return spec ? spec->constructorProperties() : nullptr; }
+ const JSFunctionSpec* specPrototypeFunctions()
+ const { return spec ? spec->prototypeFunctions() : nullptr; }
+ const JSPropertySpec* specPrototypeProperties()
+ const { return spec ? spec->prototypeProperties() : nullptr; }
+ FinishClassInitOp specFinishInitHook()
+ const { return spec ? spec->finishInitHook() : nullptr; }
+
+ JSWeakmapKeyDelegateOp extWeakmapKeyDelegateOp()
+ const { return ext ? ext->weakmapKeyDelegateOp : nullptr; }
+ JSObjectMovedOp extObjectMovedOp()
+ const { return ext ? ext->objectMovedOp : nullptr; }
+
+ LookupPropertyOp getOpsLookupProperty() const { return oOps ? oOps->lookupProperty : nullptr; }
+ DefinePropertyOp getOpsDefineProperty() const { return oOps ? oOps->defineProperty : nullptr; }
+ HasPropertyOp getOpsHasProperty() const { return oOps ? oOps->hasProperty : nullptr; }
+ GetPropertyOp getOpsGetProperty() const { return oOps ? oOps->getProperty : nullptr; }
+ SetPropertyOp getOpsSetProperty() const { return oOps ? oOps->setProperty : nullptr; }
+ GetOwnPropertyOp getOpsGetOwnPropertyDescriptor()
+ const { return oOps ? oOps->getOwnPropertyDescriptor
+ : nullptr; }
+ DeletePropertyOp getOpsDeleteProperty() const { return oOps ? oOps->deleteProperty : nullptr; }
+ WatchOp getOpsWatch() const { return oOps ? oOps->watch : nullptr; }
+ UnwatchOp getOpsUnwatch() const { return oOps ? oOps->unwatch : nullptr; }
+ GetElementsOp getOpsGetElements() const { return oOps ? oOps->getElements : nullptr; }
+ JSNewEnumerateOp getOpsEnumerate() const { return oOps ? oOps->enumerate : nullptr; }
+ JSFunToStringOp getOpsFunToString() const { return oOps ? oOps->funToString : nullptr; }
};
+static_assert(offsetof(JSClassOps, addProperty) == offsetof(ClassOps, addProperty),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, delProperty) == offsetof(ClassOps, delProperty),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, getProperty) == offsetof(ClassOps, getProperty),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, setProperty) == offsetof(ClassOps, setProperty),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, enumerate) == offsetof(ClassOps, enumerate),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, resolve) == offsetof(ClassOps, resolve),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, mayResolve) == offsetof(ClassOps, mayResolve),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, finalize) == offsetof(ClassOps, finalize),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, call) == offsetof(ClassOps, call),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, construct) == offsetof(ClassOps, construct),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, hasInstance) == offsetof(ClassOps, hasInstance),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(offsetof(JSClassOps, trace) == offsetof(ClassOps, trace),
+ "ClassOps and JSClassOps must be consistent");
+static_assert(sizeof(JSClassOps) == sizeof(ClassOps),
+ "ClassOps and JSClassOps must be consistent");
+
static_assert(offsetof(JSClass, name) == offsetof(Class, name),
"Class and JSClass must be consistent");
static_assert(offsetof(JSClass, flags) == offsetof(Class, flags),
"Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, addProperty) == offsetof(Class, addProperty),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, delProperty) == offsetof(Class, delProperty),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, getProperty) == offsetof(Class, getProperty),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, setProperty) == offsetof(Class, setProperty),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, enumerate) == offsetof(Class, enumerate),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, resolve) == offsetof(Class, resolve),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, mayResolve) == offsetof(Class, mayResolve),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, finalize) == offsetof(Class, finalize),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, call) == offsetof(Class, call),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, construct) == offsetof(Class, construct),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance),
- "Class and JSClass must be consistent");
-static_assert(offsetof(JSClass, trace) == offsetof(Class, trace),
+static_assert(offsetof(JSClass, cOps) == offsetof(Class, cOps),
"Class and JSClass must be consistent");
static_assert(sizeof(JSClass) == sizeof(Class),
"Class and JSClass must be consistent");
@@ -842,17 +959,30 @@
* Enumeration describing possible values of the [[Class]] internal property
* value of objects.
*/
-enum ESClassValue {
- ESClass_Object, ESClass_Array, ESClass_Number, ESClass_String,
- ESClass_Boolean, ESClass_RegExp, ESClass_ArrayBuffer, ESClass_SharedArrayBuffer,
- ESClass_Date, ESClass_Set, ESClass_Map,
+enum class ESClass {
+ Object,
+ Array,
+ Number,
+ String,
+ Boolean,
+ RegExp,
+ ArrayBuffer,
+ SharedArrayBuffer,
+ Date,
+ Set,
+ Map,
+ Promise,
+ MapIterator,
+ SetIterator,
+ Arguments,
+ Error,
/** None of the above. */
- ESClass_Other
+ Other
};
/* Fills |vp| with the unboxed value for boxed types, or undefined otherwise. */
-inline bool
+bool
Unbox(JSContext* cx, JS::HandleObject obj, JS::MutableHandleValue vp);
#ifdef DEBUG
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Conversions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Conversions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Conversions.h
@@ -30,12 +30,16 @@
/* DO NOT CALL THIS. Use JS::ToNumber. */
extern JS_PUBLIC_API(bool)
-ToNumberSlow(JSContext* cx, JS::Value v, double* dp);
+ToNumberSlow(JSContext* cx, JS::HandleValue v, double* dp);
/* DO NOT CALL THIS. Use JS::ToInt8. */
extern JS_PUBLIC_API(bool)
ToInt8Slow(JSContext *cx, JS::HandleValue v, int8_t *out);
+/* DO NOT CALL THIS. Use JS::ToUint8. */
+extern JS_PUBLIC_API(bool)
+ToUint8Slow(JSContext *cx, JS::HandleValue v, uint8_t *out);
+
/* DO NOT CALL THIS. Use JS::ToInt16. */
extern JS_PUBLIC_API(bool)
ToInt16Slow(JSContext *cx, JS::HandleValue v, int16_t *out);
@@ -215,6 +219,19 @@
return js::ToInt8Slow(cx, v, out);
}
+/* ES6 ECMA-262, 7.1.10 */
+MOZ_ALWAYS_INLINE bool
+ToUint8(JSContext *cx, JS::HandleValue v, uint8_t *out)
+{
+ detail::AssertArgumentsAreSane(cx, v);
+
+ if (v.isInt32()) {
+ *out = uint8_t(v.toInt32());
+ return true;
+ }
+ return js::ToUint8Slow(cx, v, out);
+}
+
/*
* Non-standard, with behavior similar to that of ToInt32, except in its
* producing an int64_t.
@@ -383,9 +400,9 @@
inline int32_t
ToInt32(double d)
{
- // clang crashes compiling this when targeting arm-darwin:
+ // clang crashes compiling this when targeting arm:
// https://llvm.org/bugs/show_bug.cgi?id=22974
-#if defined (__arm__) && defined (__GNUC__) && !defined(__APPLE__)
+#if defined (__arm__) && defined (__GNUC__) && !defined(__clang__)
int32_t i;
uint32_t tmp0;
uint32_t tmp1;
@@ -525,6 +542,13 @@
return detail::ToIntWidth<int8_t>(d);
}
+/* ECMA-262 7.1.10 ToUInt8() specialized for doubles. */
+inline int8_t
+ToUint8(double d)
+{
+ return detail::ToUintWidth<uint8_t>(d);
+}
+
/* WEBIDL 4.2.6 */
inline int16_t
ToInt16(double d)
@@ -532,6 +556,12 @@
return detail::ToIntWidth<int16_t>(d);
}
+inline uint16_t
+ToUint16(double d)
+{
+ return detail::ToUintWidth<uint16_t>(d);
+}
+
/* WEBIDL 4.2.10 */
inline int64_t
ToInt64(double d)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Date.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Date.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Date.h
@@ -149,6 +149,22 @@
JS_PUBLIC_API(double)
DayFromTime(double time);
+// Takes an integer year and returns the number of days from epoch to the given
+// year.
+// NOTE: The calculation performed by this function is literally that given in
+// the ECMAScript specification. Nonfinite years, years containing fractional
+// components, and years outside ECMAScript's date range are not handled with
+// any particular intelligence. Garbage in, garbage out.
+JS_PUBLIC_API(double)
+DayFromYear(double year);
+
+// Takes an integer number of milliseconds since the epoch and an integer year,
+// returns the number of days in that year. If |time| is nonfinite, returns NaN.
+// Otherwise |time| *must* correspond to a time within the valid year |year|.
+// This should usually be ensured by computing |year| as |JS::DayFromYear(time)|.
+JS_PUBLIC_API(double)
+DayWithinYear(double time, double year);
+
} // namespace JS
#endif /* js_Date_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Debug.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Debug.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Debug.h
@@ -12,7 +12,6 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
-#include "mozilla/UniquePtr.h"
#include "jsapi.h"
#include "jspubtd.h"
@@ -26,9 +25,6 @@
} // namespace js
namespace JS {
-
-using mozilla::UniquePtr;
-
namespace dbg {
// Helping embedding code build objects for Debugger
@@ -154,7 +150,7 @@
// A rooted reference to our value.
PersistentRooted<T> value;
- BuiltThing(JSContext* cx, Builder& owner_, T value_ = js::GCMethods<T>::initial())
+ BuiltThing(JSContext* cx, Builder& owner_, T value_ = GCPolicy<T>::initial())
: owner(owner_), value(cx, value_)
{
owner.assertBuilt(value_);
@@ -261,15 +257,15 @@
// and returns the number of bytes allocated to that block. SpiderMonkey itself
// doesn't know which function is appropriate to use, but the embedding does.
-// Tell Debuggers in |runtime| to use |mallocSizeOf| to find the size of
+// Tell Debuggers in |cx| to use |mallocSizeOf| to find the size of
// malloc'd blocks.
JS_PUBLIC_API(void)
-SetDebuggerMallocSizeOf(JSRuntime* runtime, mozilla::MallocSizeOf mallocSizeOf);
+SetDebuggerMallocSizeOf(JSContext* cx, mozilla::MallocSizeOf mallocSizeOf);
-// Get the MallocSizeOf function that the given runtime is using to find the
+// Get the MallocSizeOf function that the given context is using to find the
// size of malloc'd blocks.
JS_PUBLIC_API(mozilla::MallocSizeOf)
-GetDebuggerMallocSizeOf(JSRuntime* runtime);
+GetDebuggerMallocSizeOf(JSContext* cx);
@@ -344,7 +340,7 @@
// call the appropriate |Entry| member function to indicate where we've begun
// execution.
-class MOZ_STACK_CLASS AutoEntryMonitor {
+class MOZ_STACK_CLASS JS_PUBLIC_API(AutoEntryMonitor) {
JSRuntime* runtime_;
AutoEntryMonitor* savedMonitor_;
@@ -355,20 +351,25 @@
// SpiderMonkey reports the JavaScript entry points occuring within this
// AutoEntryMonitor's scope to the following member functions, which the
// embedding is expected to override.
+ //
+ // It is important to note that |asyncCause| is owned by the caller and its
+ // lifetime must outlive the lifetime of the AutoEntryMonitor object. It is
+ // strongly encouraged that |asyncCause| be a string constant or similar
+ // statically allocated string.
// We have begun executing |function|. Note that |function| may not be the
// actual closure we are running, but only the canonical function object to
// which the script refers.
virtual void Entry(JSContext* cx, JSFunction* function,
HandleValue asyncStack,
- HandleString asyncCause) = 0;
+ const char* asyncCause) = 0;
// Execution has begun at the entry point of |script|, which is not a
// function body. (This is probably being executed by 'eval' or some
// JSAPI equivalent.)
virtual void Entry(JSContext* cx, JSScript* script,
HandleValue asyncStack,
- HandleString asyncCause) = 0;
+ const char* asyncCause) = 0;
// Execution of the function or script has ended.
virtual void Exit(JSContext* cx) { }
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCAPI.h
@@ -7,10 +7,11 @@
#ifndef js_GCAPI_h
#define js_GCAPI_h
-#include "mozilla/UniquePtr.h"
#include "mozilla/Vector.h"
+#include "js/GCAnnotations.h"
#include "js/HeapAPI.h"
+#include "js/UniquePtr.h"
namespace js {
namespace gc {
@@ -25,12 +26,12 @@
/** Perform only global GCs. */
JSGC_MODE_GLOBAL = 0,
- /** Perform per-compartment GCs until too much garbage has accumulated. */
- JSGC_MODE_COMPARTMENT = 1,
+ /** Perform per-zone GCs until too much garbage has accumulated. */
+ JSGC_MODE_ZONE = 1,
/**
* Collect in short time slices rather than all at once. Implies
- * JSGC_MODE_COMPARTMENT.
+ * JSGC_MODE_ZONE.
*/
JSGC_MODE_INCREMENTAL = 2
} JSGCMode;
@@ -48,14 +49,12 @@
namespace JS {
-using mozilla::UniquePtr;
-
#define GCREASONS(D) \
/* Reasons internal to the JS engine */ \
D(API) \
D(EAGER_ALLOC_TRIGGER) \
D(DESTROY_RUNTIME) \
- D(DESTROY_CONTEXT) \
+ D(UNUSED0) \
D(LAST_DITCH) \
D(TOO_MUCH_MALLOC) \
D(ALLOC_TRIGGER) \
@@ -66,7 +65,7 @@
D(EVICT_NURSERY) \
D(FULL_STORE_BUFFER) \
D(SHARED_MEMORY_LIMIT) \
- D(PERIODIC_FULL_GC) \
+ D(UNUSED1) \
D(INCREMENTAL_TOO_SLOW) \
D(ABORT_GC) \
\
@@ -130,6 +129,12 @@
NUM_TELEMETRY_REASONS = 100
};
+/**
+ * Get a statically allocated C string explaining the given GC reason.
+ */
+extern JS_PUBLIC_API(const char*)
+ExplainReason(JS::gcreason::Reason reason);
+
} /* namespace gcreason */
/*
@@ -156,7 +161,7 @@
* Schedule all zones to be collected in the next GC.
*/
extern JS_PUBLIC_API(void)
-PrepareForFullGC(JSRuntime* rt);
+PrepareForFullGC(JSContext* cx);
/**
* When performing an incremental GC, the zones that were selected for the
@@ -164,14 +169,14 @@
* This function selects those slices automatically.
*/
extern JS_PUBLIC_API(void)
-PrepareForIncrementalGC(JSRuntime* rt);
+PrepareForIncrementalGC(JSContext* cx);
/**
* Returns true if any zone in the system has been scheduled for GC with one of
* the functions above or by the JS engine.
*/
extern JS_PUBLIC_API(bool)
-IsGCScheduled(JSRuntime* rt);
+IsGCScheduled(JSContext* cx);
/**
* Undoes the effect of the Prepare methods above. The given zone will not be
@@ -196,7 +201,7 @@
* the system.
*/
extern JS_PUBLIC_API(void)
-GCForReason(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason);
+GCForReason(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason);
/*
* Incremental GC:
@@ -222,43 +227,43 @@
* Begin an incremental collection and perform one slice worth of work. When
* this function returns, the collection may not be complete.
* IncrementalGCSlice() must be called repeatedly until
- * !IsIncrementalGCInProgress(rt).
+ * !IsIncrementalGCInProgress(cx).
*
* Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
* shorter than the requested interval.
*/
extern JS_PUBLIC_API(void)
-StartIncrementalGC(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason,
+StartIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason,
int64_t millis = 0);
/**
* Perform a slice of an ongoing incremental collection. When this function
* returns, the collection may not be complete. It must be called repeatedly
- * until !IsIncrementalGCInProgress(rt).
+ * until !IsIncrementalGCInProgress(cx).
*
* Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
* shorter than the requested interval.
*/
extern JS_PUBLIC_API(void)
-IncrementalGCSlice(JSRuntime* rt, gcreason::Reason reason, int64_t millis = 0);
+IncrementalGCSlice(JSContext* cx, gcreason::Reason reason, int64_t millis = 0);
/**
- * If IsIncrementalGCInProgress(rt), this call finishes the ongoing collection
- * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(rt),
+ * If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
+ * by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
* this is equivalent to GCForReason. When this function returns,
- * IsIncrementalGCInProgress(rt) will always be false.
+ * IsIncrementalGCInProgress(cx) will always be false.
*/
extern JS_PUBLIC_API(void)
-FinishIncrementalGC(JSRuntime* rt, gcreason::Reason reason);
+FinishIncrementalGC(JSContext* cx, gcreason::Reason reason);
/**
- * If IsIncrementalGCInProgress(rt), this call aborts the ongoing collection and
+ * If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
* performs whatever work needs to be done to return the collector to its idle
* state. This may take an arbitrarily long time. When this function returns,
- * IsIncrementalGCInProgress(rt) will always be false.
+ * IsIncrementalGCInProgress(cx) will always be false.
*/
extern JS_PUBLIC_API(void)
-AbortIncrementalGC(JSRuntime* rt);
+AbortIncrementalGC(JSContext* cx);
namespace dbg {
@@ -300,7 +305,7 @@
, collections()
{ }
- using Ptr = UniquePtr<GarbageCollectionEvent, DeletePolicy<GarbageCollectionEvent>>;
+ using Ptr = js::UniquePtr<GarbageCollectionEvent>;
static Ptr Create(JSRuntime* rt, ::js::gcstats::Statistics& stats, uint64_t majorGCNumber);
JSObject* toJSObject(JSContext* cx) const;
@@ -328,22 +333,22 @@
};
struct JS_PUBLIC_API(GCDescription) {
- bool isCompartment_;
+ bool isZone_;
JSGCInvocationKind invocationKind_;
gcreason::Reason reason_;
- GCDescription(bool isCompartment, JSGCInvocationKind kind, gcreason::Reason reason)
- : isCompartment_(isCompartment), invocationKind_(kind), reason_(reason) {}
+ GCDescription(bool isZone, JSGCInvocationKind kind, gcreason::Reason reason)
+ : isZone_(isZone), invocationKind_(kind), reason_(reason) {}
- char16_t* formatSliceMessage(JSRuntime* rt) const;
- char16_t* formatSummaryMessage(JSRuntime* rt) const;
- char16_t* formatJSON(JSRuntime* rt, uint64_t timestamp) const;
+ char16_t* formatSliceMessage(JSContext* cx) const;
+ char16_t* formatSummaryMessage(JSContext* cx) const;
+ char16_t* formatJSON(JSContext* cx, uint64_t timestamp) const;
- JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSRuntime* rt) const;
+ JS::dbg::GarbageCollectionEvent::Ptr toGCEvent(JSContext* cx) const;
};
typedef void
-(* GCSliceCallback)(JSRuntime* rt, GCProgress progress, const GCDescription& desc);
+(* GCSliceCallback)(JSContext* cx, GCProgress progress, const GCDescription& desc);
/**
* The GC slice callback is called at the beginning and end of each slice. This
@@ -351,7 +356,45 @@
* marking.
*/
extern JS_PUBLIC_API(GCSliceCallback)
-SetGCSliceCallback(JSRuntime* rt, GCSliceCallback callback);
+SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
+
+/**
+ * Describes the progress of an observed nursery collection.
+ */
+enum class GCNurseryProgress {
+ /**
+ * The nursery collection is starting.
+ */
+ GC_NURSERY_COLLECTION_START,
+ /**
+ * The nursery collection is ending.
+ */
+ GC_NURSERY_COLLECTION_END
+};
+
+/**
+ * A nursery collection callback receives the progress of the nursery collection
+ * and the reason for the collection.
+ */
+using GCNurseryCollectionCallback = void(*)(JSContext* cx, GCNurseryProgress progress,
+ gcreason::Reason reason);
+
+/**
+ * Set the nursery collection callback for the given runtime. When set, it will
+ * be called at the start and end of every nursery collection.
+ */
+extern JS_PUBLIC_API(GCNurseryCollectionCallback)
+SetGCNurseryCollectionCallback(JSContext* cx, GCNurseryCollectionCallback callback);
+
+typedef void
+(* DoCycleCollectionCallback)(JSContext* cx);
+
+/**
+ * The purge gray callback is called after any COMPARTMENT_REVIVED GC in which
+ * the majority of compartments have been marked gray.
+ */
+extern JS_PUBLIC_API(DoCycleCollectionCallback)
+SetDoCycleCollectionCallback(JSContext* cx, DoCycleCollectionCallback callback);
/**
* Incremental GC defaults to enabled, but may be disabled for testing or in
@@ -360,7 +403,7 @@
* disabled on the runtime.
*/
extern JS_PUBLIC_API(void)
-DisableIncrementalGC(JSRuntime* rt);
+DisableIncrementalGC(JSContext* cx);
/**
* Returns true if incremental GC is enabled. Simply having incremental GC
@@ -371,14 +414,14 @@
* collections are not happening incrementally when expected.
*/
extern JS_PUBLIC_API(bool)
-IsIncrementalGCEnabled(JSRuntime* rt);
+IsIncrementalGCEnabled(JSContext* cx);
/**
* Returns true while an incremental GC is ongoing, both when actively
* collecting and between slices.
*/
extern JS_PUBLIC_API(bool)
-IsIncrementalGCInProgress(JSRuntime* rt);
+IsIncrementalGCInProgress(JSContext* cx);
/*
* Returns true when writes to GC things must call an incremental (pre) barrier.
@@ -386,9 +429,6 @@
* At other times, the barrier may be elided for performance.
*/
extern JS_PUBLIC_API(bool)
-IsIncrementalBarrierNeeded(JSRuntime* rt);
-
-extern JS_PUBLIC_API(bool)
IsIncrementalBarrierNeeded(JSContext* cx);
/*
@@ -408,7 +448,7 @@
* Returns true if the most recent GC ran incrementally.
*/
extern JS_PUBLIC_API(bool)
-WasIncrementalGC(JSRuntime* rt);
+WasIncrementalGC(JSContext* cx);
/*
* Generational GC:
@@ -444,37 +484,35 @@
GetGCNumber();
/**
- * The GC does not immediately return the unused memory freed by a collection
- * back to the system incase it is needed soon afterwards. This call forces the
- * GC to return this memory immediately.
- */
-extern JS_PUBLIC_API(void)
-ShrinkGCBuffers(JSRuntime* rt);
+ * Pass a subclass of this "abstract" class to callees to require that they
+ * never GC. Subclasses can use assertions or the hazard analysis to ensure no
+ * GC happens.
+ */
+class JS_PUBLIC_API(AutoRequireNoGC)
+{
+ protected:
+ AutoRequireNoGC() {}
+ ~AutoRequireNoGC() {}
+};
/**
- * Assert if a GC occurs while this class is live. This class does not disable
- * the static rooting hazard analysis.
+ * Diagnostic assert (see MOZ_DIAGNOSTIC_ASSERT) that GC cannot occur while this
+ * class is live. This class does not disable the static rooting hazard
+ * analysis.
+ *
+ * This works by entering a GC unsafe region, which is checked on allocation and
+ * on GC.
*/
-class JS_PUBLIC_API(AutoAssertOnGC)
+class JS_PUBLIC_API(AutoAssertNoGC) : public AutoRequireNoGC
{
-#ifdef DEBUG
js::gc::GCRuntime* gc;
size_t gcNumber;
public:
- AutoAssertOnGC();
- explicit AutoAssertOnGC(JSRuntime* rt);
- ~AutoAssertOnGC();
-
- static void VerifyIsSafeToGC(JSRuntime* rt);
-#else
- public:
- AutoAssertOnGC() {}
- explicit AutoAssertOnGC(JSRuntime* rt) {}
- ~AutoAssertOnGC() {}
-
- static void VerifyIsSafeToGC(JSRuntime* rt) {}
-#endif
+ AutoAssertNoGC();
+ explicit AutoAssertNoGC(JSRuntime* rt);
+ explicit AutoAssertNoGC(JSContext* cx);
+ ~AutoAssertNoGC();
};
/**
@@ -488,18 +526,32 @@
public:
AutoAssertNoAlloc() : gc(nullptr) {}
- explicit AutoAssertNoAlloc(JSRuntime* rt);
+ explicit AutoAssertNoAlloc(JSContext* cx);
void disallowAlloc(JSRuntime* rt);
~AutoAssertNoAlloc();
#else
public:
AutoAssertNoAlloc() {}
- explicit AutoAssertNoAlloc(JSRuntime* rt) {}
+ explicit AutoAssertNoAlloc(JSContext* cx) {}
void disallowAlloc(JSRuntime* rt) {}
#endif
};
/**
+ * Assert if a GC barrier is invoked while this class is live. This class does
+ * not disable the static rooting hazard analysis.
+ */
+class JS_PUBLIC_API(AutoAssertOnBarrier)
+{
+ JSContext* context;
+ bool prev;
+
+ public:
+ explicit AutoAssertOnBarrier(JSContext* cx);
+ ~AutoAssertOnBarrier();
+};
+
+/**
* Disable the static rooting hazard analysis in the live region and assert if
* any allocation that could potentially trigger a GC occurs while this guard
* object is live. This is most useful to help the exact rooting hazard analysis
@@ -517,8 +569,8 @@
{
public:
AutoSuppressGCAnalysis() : AutoAssertNoAlloc() {}
- explicit AutoSuppressGCAnalysis(JSRuntime* rt) : AutoAssertNoAlloc(rt) {}
-};
+ explicit AutoSuppressGCAnalysis(JSContext* cx) : AutoAssertNoAlloc(cx) {}
+} JS_HAZ_GC_SUPPRESSED;
/**
* Assert that code is only ever called from a GC callback, disable the static
@@ -536,24 +588,36 @@
/**
* Place AutoCheckCannotGC in scopes that you believe can never GC. These
- * annotations will be verified both dynamically via AutoAssertOnGC, and
+ * annotations will be verified both dynamically via AutoAssertNoGC, and
* statically with the rooting hazard analysis (implemented by making the
* analysis consider AutoCheckCannotGC to be a GC pointer, and therefore
* complain if it is live across a GC call.) It is useful when dealing with
* internal pointers to GC things where the GC thing itself may not be present
* for the static analysis: e.g. acquiring inline chars from a JSString* on the
* heap.
+ *
+ * We only do the assertion checking in DEBUG builds.
*/
-class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertOnGC
+#ifdef DEBUG
+class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertNoGC
{
public:
- AutoCheckCannotGC() : AutoAssertOnGC() {}
- explicit AutoCheckCannotGC(JSRuntime* rt) : AutoAssertOnGC(rt) {}
-};
+ AutoCheckCannotGC() : AutoAssertNoGC() {}
+ explicit AutoCheckCannotGC(JSContext* cx) : AutoAssertNoGC(cx) {}
+} JS_HAZ_GC_INVALIDATED;
+#else
+class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoRequireNoGC
+{
+ public:
+ AutoCheckCannotGC() {}
+ explicit AutoCheckCannotGC(JSContext* cx) {}
+} JS_HAZ_GC_INVALIDATED;
+#endif
/**
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
- * JS::TraceKind::Shape. |thing| should be non-null.
+ * JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
+ * if anything was unmarked.
*/
extern JS_FRIEND_API(bool)
UnmarkGrayGCThingRecursively(GCCellPtr thing);
@@ -566,31 +630,42 @@
static MOZ_ALWAYS_INLINE void
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
{
- MOZ_ASSERT(thing.kind() != JS::TraceKind::Shape);
-
- /*
- * GC things residing in the nursery cannot be gray: they have no mark bits.
- * All live objects in the nursery are moved to tenured at the beginning of
- * each GC slice, so the gray marker never sees nursery things.
- */
+ // GC things residing in the nursery cannot be gray: they have no mark bits.
+ // All live objects in the nursery are moved to tenured at the beginning of
+ // each GC slice, so the gray marker never sees nursery things.
if (IsInsideNursery(thing.asCell()))
return;
- JS::shadow::Runtime* rt = detail::GetGCThingRuntime(thing.unsafeAsUIntPtr());
+
+ // There's nothing to do for permanent GC things that might be owned by
+ // another runtime.
+ if (thing.mayBeOwnedByOtherRuntime())
+ return;
+
+ JS::shadow::Runtime* rt = detail::GetCellRuntime(thing.asCell());
+ MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
+
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
JS::IncrementalReferenceBarrier(thing);
- else if (JS::GCThingIsMarkedGray(thing))
+ else if (!thing.mayBeOwnedByOtherRuntime() && js::gc::detail::CellIsMarkedGray(thing.asCell()))
JS::UnmarkGrayGCThingRecursively(thing);
}
static MOZ_ALWAYS_INLINE void
MarkGCThingAsLive(JSRuntime* aRt, JS::GCCellPtr thing)
{
- JS::shadow::Runtime* rt = JS::shadow::Runtime::asShadowRuntime(aRt);
- /*
- * Any object in the nursery will not be freed during any GC running at that time.
- */
+ // Any object in the nursery will not be freed during any GC running at that
+ // time.
if (IsInsideNursery(thing.asCell()))
return;
+
+ // There's nothing to do for permanent GC things that might be owned by
+ // another runtime.
+ if (thing.mayBeOwnedByOtherRuntime())
+ return;
+
+ JS::shadow::Runtime* rt = JS::shadow::Runtime::asShadowRuntime(aRt);
+ MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
+
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
JS::IncrementalReferenceBarrier(thing);
}
@@ -609,6 +684,7 @@
static MOZ_ALWAYS_INLINE void
ExposeObjectToActiveJS(JSObject* obj)
{
+ MOZ_ASSERT(obj);
js::gc::ExposeGCThingToActiveJS(GCCellPtr(obj));
}
@@ -634,13 +710,13 @@
* Note: this is not related to the PokeGC in nsJSEnvironment.
*/
extern JS_FRIEND_API(void)
-PokeGC(JSRuntime* rt);
+PokeGC(JSContext* cx);
/*
* Internal to Firefox.
*/
extern JS_FRIEND_API(void)
-NotifyDidPaint(JSRuntime* rt);
+NotifyDidPaint(JSContext* cx);
} /* namespace JS */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCAnnotations.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCAnnotations.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCAnnotations.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_GCAnnotations_h
+#define js_GCAnnotations_h
+
+// Set of annotations for the rooting hazard analysis, used to categorize types
+// and functions.
+#ifdef XGILL_PLUGIN
+
+// Mark a type as being a GC thing (eg js::gc::Cell has this annotation).
+# define JS_HAZ_GC_THING __attribute__((tag("GC Thing")))
+
+// Mark a type as holding a pointer to a GC thing (eg JS::Value has this
+// annotation.)
+# define JS_HAZ_GC_POINTER __attribute__((tag("GC Pointer")))
+
+// Mark a type as a rooted pointer, suitable for use on the stack (eg all
+// Rooted<T> instantiations should have this.)
+# define JS_HAZ_ROOTED __attribute__((tag("Rooted Pointer")))
+
+// Mark a type as something that should not be held live across a GC, but which
+// is not itself a GC pointer.
+# define JS_HAZ_GC_INVALIDATED __attribute__((tag("Invalidated by GC")))
+
+// Mark a type that would otherwise be considered a GC Pointer (eg because it
+// contains a JS::Value field) as a non-GC pointer. It is handled almost the
+// same in the analysis as a rooted pointer, except it will not be reported as
+// an unnecessary root if used across a GC call. This should rarely be used,
+// but makes sense for something like ErrorResult, which only contains a GC
+// pointer when it holds an exception (and it does its own rooting,
+// conditionally.)
+# define JS_HAZ_NON_GC_POINTER __attribute__((tag("Suppressed GC Pointer")))
+
+// Mark a function as something that runs a garbage collection, potentially
+// invalidating GC pointers.
+# define JS_HAZ_GC_CALL __attribute__((tag("GC Call")))
+
+// Mark an RAII class as suppressing GC within its scope.
+# define JS_HAZ_GC_SUPPRESSED __attribute__((tag("Suppress GC")))
+
+#else
+
+# define JS_HAZ_GC_THING
+# define JS_HAZ_GC_POINTER
+# define JS_HAZ_ROOTED
+# define JS_HAZ_GC_INVALIDATED
+# define JS_HAZ_NON_GC_POINTER
+# define JS_HAZ_GC_CALL
+# define JS_HAZ_GC_SUPPRESSED
+
+#endif
+
+#endif /* js_GCAnnotations_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCHashTable.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCHashTable.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCHashTable.h
@@ -7,54 +7,54 @@
#ifndef GCHashTable_h
#define GCHashTable_h
+#include "js/GCPolicyAPI.h"
#include "js/HashTable.h"
#include "js/RootingAPI.h"
+#include "js/SweepingAPI.h"
#include "js/TracingAPI.h"
-namespace js {
+namespace JS {
// Define a reasonable default GC policy for GC-aware Maps.
template <typename Key, typename Value>
-struct DefaultMapGCPolicy {
- using KeyPolicy = DefaultGCPolicy<Key>;
- using ValuePolicy = DefaultGCPolicy<Value>;
-
+struct DefaultMapSweepPolicy {
static bool needsSweep(Key* key, Value* value) {
- return KeyPolicy::needsSweep(key) || ValuePolicy::needsSweep(value);
+ return GCPolicy<Key>::needsSweep(key) || GCPolicy<Value>::needsSweep(value);
}
};
// A GCHashMap is a GC-aware HashMap, meaning that it has additional trace and
// sweep methods that know how to visit all keys and values in the table.
// HashMaps that contain GC pointers will generally want to use this GCHashMap
-// specialization in lieu of HashMap, either because those pointers must be
-// traced to be kept alive -- in which case, KeyPolicy and/or ValuePolicy
-// should do the appropriate tracing -- or because those pointers are weak and
-// must be swept during a GC -- in which case needsSweep should be set
-// appropriately.
+// specialization instead of HashMap, because this conveniently supports tracing
+// keys and values, and cleaning up weak entries.
//
-// Most types of GC pointers as keys and values can be traced with no extra
-// infrastructure. For structs, the DefaultGCPolicy<T> will call a trace()
-// method on the struct. For other structs and non-gc-pointer members, ensure
-// that there is a specialization of DefaultGCPolicy<T> with an appropriate
-// trace() static method available to handle the custom type. Generic helpers
-// can be found in js/public/TracingAPI.h.
+// GCHashMap::trace applies GCPolicy<T>::trace to each entry's key and value.
+// Most types of GC pointers already have appropriate specializations of
+// GCPolicy, so they should just work as keys and values. Any struct type with a
+// default constructor and trace and sweep functions should work as well. If you
+// need to define your own GCPolicy specialization, generic helpers can be found
+// in js/public/TracingAPI.h.
//
-// Note that this HashMap only knows *how* to trace and sweep (and the tracing
-// can handle keys that move), but it does not itself cause tracing or sweeping
-// to be invoked. For tracing, it must be used with Rooted or PersistentRooted,
-// or barriered and traced manually. For sweeping, currently it requires an
-// explicit call to <map>.sweep().
+// The MapSweepPolicy template parameter controls how the table drops entries
+// when swept. GCHashMap::sweep applies MapSweepPolicy::needsSweep to each table
+// entry; if it returns true, the entry is dropped. The default MapSweepPolicy
+// drops the entry if either the key or value is about to be finalized,
+// according to its GCPolicy<T>::needsSweep method. (This default is almost
+// always fine: it's hard to imagine keeping such an entry around anyway.)
//
+// Note that this HashMap only knows *how* to trace and sweep, but it does not
+// itself cause tracing or sweeping to be invoked. For tracing, it must be used
+// with Rooted or PersistentRooted, or barriered and traced manually. For
+// sweeping, currently it requires an explicit call to <map>.sweep().
template <typename Key,
typename Value,
- typename HashPolicy = DefaultHasher<Key>,
- typename AllocPolicy = TempAllocPolicy,
- typename GCPolicy = DefaultMapGCPolicy<Key, Value>>
-class GCHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>,
- public JS::Traceable
+ typename HashPolicy = js::DefaultHasher<Key>,
+ typename AllocPolicy = js::TempAllocPolicy,
+ typename MapSweepPolicy = DefaultMapSweepPolicy<Key, Value>>
+class GCHashMap : public js::HashMap<Key, Value, HashPolicy, AllocPolicy>
{
- using Base = HashMap<Key, Value, HashPolicy, AllocPolicy>;
+ using Base = js::HashMap<Key, Value, HashPolicy, AllocPolicy>;
public:
explicit GCHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {}
@@ -64,8 +64,8 @@
if (!this->initialized())
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
- GCPolicy::ValuePolicy::trace(trc, &e.front().value(), "hashmap value");
- GCPolicy::KeyPolicy::trace(trc, &e.front().mutableKey(), "hashmap key");
+ GCPolicy<Value>::trace(trc, &e.front().value(), "hashmap value");
+ GCPolicy<Key>::trace(trc, &e.front().mutableKey(), "hashmap key");
}
}
@@ -74,16 +74,16 @@
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
- if (GCPolicy::needsSweep(&e.front().mutableKey(), &e.front().value()))
+ if (MapSweepPolicy::needsSweep(&e.front().mutableKey(), &e.front().value()))
e.removeFront();
}
}
// GCHashMap is movable
- GCHashMap(GCHashMap&& rhs) : Base(mozilla::Forward<GCHashMap>(rhs)) {}
+ GCHashMap(GCHashMap&& rhs) : Base(mozilla::Move(rhs)) {}
void operator=(GCHashMap&& rhs) {
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
- Base::operator=(mozilla::Forward<GCHashMap>(rhs));
+ Base::operator=(mozilla::Move(rhs));
}
private:
@@ -92,19 +92,61 @@
GCHashMap& operator=(const GCHashMap& hm) = delete;
};
+} // namespace JS
+
+namespace js {
+
+// HashMap that supports rekeying.
+//
+// If your keys are pointers to something like JSObject that can be tenured or
+// compacted, prefer to use GCHashMap with MovableCellHasher, which takes
+// advantage of the Zone's stable id table to make rekeying unnecessary.
+template <typename Key,
+ typename Value,
+ typename HashPolicy = DefaultHasher<Key>,
+ typename AllocPolicy = TempAllocPolicy,
+ typename MapSweepPolicy = JS::DefaultMapSweepPolicy<Key, Value>>
+class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>
+{
+ using Base = JS::GCHashMap<Key, Value, HashPolicy, AllocPolicy>;
+
+ public:
+ explicit GCRekeyableHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {}
+
+ void sweep() {
+ if (!this->initialized())
+ return;
+
+ for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
+ Key key(e.front().key());
+ if (MapSweepPolicy::needsSweep(&key, &e.front().value()))
+ e.removeFront();
+ else if (!HashPolicy::match(key, e.front().key()))
+ e.rekeyFront(key);
+ }
+ }
+
+ // GCRekeyableHashMap is movable
+ GCRekeyableHashMap(GCRekeyableHashMap&& rhs) : Base(mozilla::Move(rhs)) {}
+ void operator=(GCRekeyableHashMap&& rhs) {
+ MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
+ Base::operator=(mozilla::Move(rhs));
+ }
+};
+
template <typename Outer, typename... Args>
class GCHashMapOperations
{
- using Map = GCHashMap<Args...>;
+ using Map = JS::GCHashMap<Args...>;
using Lookup = typename Map::Lookup;
- using Ptr = typename Map::Ptr;
- using AddPtr = typename Map::AddPtr;
- using Range = typename Map::Range;
- using Enum = typename Map::Enum;
const Map& map() const { return static_cast<const Outer*>(this)->get(); }
public:
+ using AddPtr = typename Map::AddPtr;
+ using Ptr = typename Map::Ptr;
+ using Range = typename Map::Range;
+
bool initialized() const { return map().initialized(); }
Ptr lookup(const Lookup& l) const { return map().lookup(l); }
AddPtr lookupForAdd(const Lookup& l) const { return map().lookupForAdd(l); }
@@ -113,22 +155,29 @@
uint32_t count() const { return map().count(); }
size_t capacity() const { return map().capacity(); }
bool has(const Lookup& l) const { return map().lookup(l).found(); }
+ size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return map().sizeOfExcludingThis(mallocSizeOf);
+ }
+ size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return mallocSizeOf(this) + map().sizeOfExcludingThis(mallocSizeOf);
+ }
};
template <typename Outer, typename... Args>
class MutableGCHashMapOperations
: public GCHashMapOperations<Outer, Args...>
{
- using Map = GCHashMap<Args...>;
+ using Map = JS::GCHashMap<Args...>;
using Lookup = typename Map::Lookup;
- using Ptr = typename Map::Ptr;
- using AddPtr = typename Map::AddPtr;
- using Range = typename Map::Range;
- using Enum = typename Map::Enum;
Map& map() { return static_cast<Outer*>(this)->get(); }
public:
+ using AddPtr = typename Map::AddPtr;
+ struct Enum : public Map::Enum { explicit Enum(Outer& o) : Map::Enum(o.map()) {} };
+ using Ptr = typename Map::Ptr;
+ using Range = typename Map::Range;
+
bool init(uint32_t len = 16) { return map().init(len); }
void clear() { map().clear(); }
void finish() { map().finish(); }
@@ -163,41 +212,48 @@
};
template <typename A, typename B, typename C, typename D, typename E>
-class RootedBase<GCHashMap<A,B,C,D,E>>
- : public MutableGCHashMapOperations<JS::Rooted<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
+class RootedBase<JS::GCHashMap<A,B,C,D,E>>
+ : public MutableGCHashMapOperations<JS::Rooted<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
+{};
+
+template <typename A, typename B, typename C, typename D, typename E>
+class MutableHandleBase<JS::GCHashMap<A,B,C,D,E>>
+ : public MutableGCHashMapOperations<JS::MutableHandle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
{};
template <typename A, typename B, typename C, typename D, typename E>
-class MutableHandleBase<GCHashMap<A,B,C,D,E>>
- : public MutableGCHashMapOperations<JS::MutableHandle<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
+class HandleBase<JS::GCHashMap<A,B,C,D,E>>
+ : public GCHashMapOperations<JS::Handle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
{};
template <typename A, typename B, typename C, typename D, typename E>
-class HandleBase<GCHashMap<A,B,C,D,E>>
- : public GCHashMapOperations<JS::Handle<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
+class WeakCacheBase<JS::GCHashMap<A,B,C,D,E>>
+ : public MutableGCHashMapOperations<JS::WeakCache<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
{};
+} // namespace js
+
+namespace JS {
+
// A GCHashSet is a HashSet with an additional trace method that knows
// be traced to be kept alive will generally want to use this GCHashSet
-// specializeation in lieu of HashSet.
+// specialization in lieu of HashSet.
//
// Most types of GC pointers can be traced with no extra infrastructure. For
// structs and non-gc-pointer members, ensure that there is a specialization of
-// DefaultGCPolicy<T> with an appropriate trace method available to handle the
-// custom type. Generic helpers can be found in js/public/TracingAPI.h.
+// GCPolicy<T> with an appropriate trace method available to handle the custom
+// type. Generic helpers can be found in js/public/TracingAPI.h.
//
// Note that although this HashSet's trace will deal correctly with moved
// elements, it does not itself know when to barrier or trace elements. To
// function properly it must either be used with Rooted or barriered and traced
// manually.
template <typename T,
- typename HashPolicy = DefaultHasher<T>,
- typename AllocPolicy = TempAllocPolicy,
- typename GCPolicy = DefaultGCPolicy<T>>
-class GCHashSet : public HashSet<T, HashPolicy, AllocPolicy>,
- public JS::Traceable
+ typename HashPolicy = js::DefaultHasher<T>,
+ typename AllocPolicy = js::TempAllocPolicy>
+class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy>
{
- using Base = HashSet<T, HashPolicy, AllocPolicy>;
+ using Base = js::HashSet<T, HashPolicy, AllocPolicy>;
public:
explicit GCHashSet(AllocPolicy a = AllocPolicy()) : Base(a) {}
@@ -207,23 +263,23 @@
if (!this->initialized())
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront())
- GCPolicy::trace(trc, &e.mutableFront(), "hashset element");
+ GCPolicy<T>::trace(trc, &e.mutableFront(), "hashset element");
}
void sweep() {
if (!this->initialized())
return;
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
- if (GCPolicy::needsSweep(&e.mutableFront()))
+ if (GCPolicy<T>::needsSweep(&e.mutableFront()))
e.removeFront();
}
}
// GCHashSet is movable
- GCHashSet(GCHashSet&& rhs) : Base(mozilla::Forward<GCHashSet>(rhs)) {}
+ GCHashSet(GCHashSet&& rhs) : Base(mozilla::Move(rhs)) {}
void operator=(GCHashSet&& rhs) {
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
- Base::operator=(mozilla::Forward<GCHashSet>(rhs));
+ Base::operator=(mozilla::Move(rhs));
}
private:
@@ -232,19 +288,24 @@
GCHashSet& operator=(const GCHashSet& hs) = delete;
};
+} // namespace JS
+
+namespace js {
+
template <typename Outer, typename... Args>
class GCHashSetOperations
{
- using Set = GCHashSet<Args...>;
+ using Set = JS::GCHashSet<Args...>;
using Lookup = typename Set::Lookup;
- using Ptr = typename Set::Ptr;
- using AddPtr = typename Set::AddPtr;
- using Range = typename Set::Range;
- using Enum = typename Set::Enum;
- const Set& set() const { return static_cast<const Outer*>(this)->extract(); }
+ const Set& set() const { return static_cast<const Outer*>(this)->get(); }
public:
+ using AddPtr = typename Set::AddPtr;
+ using Entry = typename Set::Entry;
+ using Ptr = typename Set::Ptr;
+ using Range = typename Set::Range;
+
bool initialized() const { return set().initialized(); }
Ptr lookup(const Lookup& l) const { return set().lookup(l); }
AddPtr lookupForAdd(const Lookup& l) const { return set().lookupForAdd(l); }
@@ -253,25 +314,34 @@
uint32_t count() const { return set().count(); }
size_t capacity() const { return set().capacity(); }
bool has(const Lookup& l) const { return set().lookup(l).found(); }
+ size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return set().sizeOfExcludingThis(mallocSizeOf);
+ }
+ size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return mallocSizeOf(this) + set().sizeOfExcludingThis(mallocSizeOf);
+ }
};
template <typename Outer, typename... Args>
class MutableGCHashSetOperations
: public GCHashSetOperations<Outer, Args...>
{
- using Set = GCHashSet<Args...>;
+ using Set = JS::GCHashSet<Args...>;
using Lookup = typename Set::Lookup;
- using Ptr = typename Set::Ptr;
- using AddPtr = typename Set::AddPtr;
- using Range = typename Set::Range;
- using Enum = typename Set::Enum;
- Set& set() { return static_cast<Outer*>(this)->extract(); }
+ Set& set() { return static_cast<Outer*>(this)->get(); }
public:
+ using AddPtr = typename Set::AddPtr;
+ using Entry = typename Set::Entry;
+ struct Enum : public Set::Enum { explicit Enum(Outer& o) : Set::Enum(o.set()) {} };
+ using Ptr = typename Set::Ptr;
+ using Range = typename Set::Range;
+
bool init(uint32_t len = 16) { return set().init(len); }
void clear() { set().clear(); }
void finish() { set().finish(); }
+ void remove(Ptr p) { set().remove(p); }
void remove(const Lookup& l) { set().remove(l); }
template<typename TInput>
@@ -300,41 +370,28 @@
}
};
-template <typename T, typename HP, typename AP, typename GP>
-class RootedBase<GCHashSet<T, HP, AP, GP>>
- : public MutableGCHashSetOperations<JS::Rooted<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
+template <typename T, typename HP, typename AP>
+class RootedBase<JS::GCHashSet<T, HP, AP>>
+ : public MutableGCHashSetOperations<JS::Rooted<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
- using Set = GCHashSet<T, HP, AP, GP>;
-
- friend class GCHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>;
- const Set& extract() const { return *static_cast<const JS::Rooted<Set>*>(this)->address(); }
-
- friend class MutableGCHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>;
- Set& extract() { return *static_cast<JS::Rooted<Set>*>(this)->address(); }
};
-template <typename T, typename HP, typename AP, typename GP>
-class MutableHandleBase<GCHashSet<T, HP, AP, GP>>
- : public MutableGCHashSetOperations<JS::MutableHandle<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
+template <typename T, typename HP, typename AP>
+class MutableHandleBase<JS::GCHashSet<T, HP, AP>>
+ : public MutableGCHashSetOperations<JS::MutableHandle<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
- using Set = GCHashSet<T, HP, AP, GP>;
-
- friend class GCHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>;
- const Set& extract() const {
- return *static_cast<const JS::MutableHandle<Set>*>(this)->address();
- }
+};
- friend class MutableGCHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>;
- Set& extract() { return *static_cast<JS::MutableHandle<Set>*>(this)->address(); }
+template <typename T, typename HP, typename AP>
+class HandleBase<JS::GCHashSet<T, HP, AP>>
+ : public GCHashSetOperations<JS::Handle<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
+{
};
-template <typename T, typename HP, typename AP, typename GP>
-class HandleBase<GCHashSet<T, HP, AP, GP>>
- : public GCHashSetOperations<JS::Handle<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
+template <typename T, typename HP, typename AP>
+class WeakCacheBase<JS::GCHashSet<T, HP, AP>>
+ : public MutableGCHashSetOperations<JS::WeakCache<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
- using Set = GCHashSet<T, HP, AP, GP>;
- friend class GCHashSetOperations<JS::Handle<Set>, T, HP, AP, GP>;
- const Set& extract() const { return *static_cast<const JS::Handle<Set>*>(this)->address(); }
};
} /* namespace js */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCPolicyAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCPolicyAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCPolicyAPI.h
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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/. */
+
+// GC Policy Mechanism
+
+// A GCPolicy controls how the GC interacts with both direct pointers to GC
+// things (e.g. JSObject* or JSString*), tagged and/or optional pointers to GC
+// things (e.g. Value or jsid), and C++ container types (e.g.
+// JSPropertyDescriptor or GCHashMap).
+//
+// The GCPolicy provides at a minimum:
+//
+// static T initial()
+// - Construct and return an empty T.
+//
+// static void trace(JSTracer, T* tp, const char* name)
+// - Trace the edge |*tp|, calling the edge |name|. Containers like
+// GCHashMap and GCHashSet use this method to trace their children.
+//
+// static bool needsSweep(T* tp)
+// - Return true if |*tp| is about to be finalized. Otherwise, update the
+// edge for moving GC, and return false. Containers like GCHashMap and
+// GCHashSet use this method to decide when to remove an entry: if this
+// function returns true on a key/value/member/etc, its entry is dropped
+// from the container. Specializing this method is the standard way to
+// get custom weak behavior from a container type.
+//
+// The default GCPolicy<T> assumes that T has a default constructor and |trace|
+// and |needsSweep| methods, and forwards to them. GCPolicy has appropriate
+// specializations for pointers to GC things and pointer-like types like
+// JS::Heap<T> and mozilla::UniquePtr<T>.
+//
+// There are some stock structs your specializations can inherit from.
+// IgnoreGCPolicy<T> does nothing. StructGCPolicy<T> forwards the methods to the
+// referent type T.
+
+#ifndef GCPolicyAPI_h
+#define GCPolicyAPI_h
+
+#include "mozilla/UniquePtr.h"
+
+#include "js/TraceKind.h"
+#include "js/TracingAPI.h"
+
+// Expand the given macro D for each public GC pointer.
+#define FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \
+ D(JS::Symbol*) \
+ D(JSAtom*) \
+ D(JSFunction*) \
+ D(JSObject*) \
+ D(JSScript*) \
+ D(JSString*)
+
+// Expand the given macro D for each public tagged GC pointer type.
+#define FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(D) \
+ D(JS::Value) \
+ D(jsid)
+
+#define FOR_EACH_PUBLIC_AGGREGATE_GC_POINTER_TYPE(D) \
+ D(JSPropertyDescriptor)
+
+class JSAtom;
+class JSFunction;
+class JSObject;
+class JSScript;
+class JSString;
+namespace JS {
+class Symbol;
+}
+
+namespace JS {
+
+// Defines a policy for container types with non-GC, i.e. C storage. This
+// policy dispatches to the underlying struct for GC interactions.
+template <typename T>
+struct StructGCPolicy
+{
+ static T initial() {
+ return T();
+ }
+
+ static void trace(JSTracer* trc, T* tp, const char* name) {
+ tp->trace(trc);
+ }
+
+ static void sweep(T* tp) {
+ return tp->sweep();
+ }
+
+ static bool needsSweep(T* tp) {
+ return tp->needsSweep();
+ }
+};
+
+// The default GC policy attempts to defer to methods on the underlying type.
+// Most C++ structures that contain a default constructor, a trace function and
+// a sweep function will work out of the box with Rooted, Handle, GCVector,
+// and GCHash{Set,Map}.
+template <typename T> struct GCPolicy : public StructGCPolicy<T> {};
+
+// This policy ignores any GC interaction, e.g. for non-GC types.
+template <typename T>
+struct IgnoreGCPolicy {
+ static T initial() { return T(); }
+ static void trace(JSTracer* trc, T* t, const char* name) {}
+ static bool needsSweep(T* v) { return false; }
+};
+template <> struct GCPolicy<uint32_t> : public IgnoreGCPolicy<uint32_t> {};
+template <> struct GCPolicy<uint64_t> : public IgnoreGCPolicy<uint64_t> {};
+
+template <typename T>
+struct GCPointerPolicy
+{
+ static T initial() { return nullptr; }
+ static void trace(JSTracer* trc, T* vp, const char* name) {
+ if (*vp)
+ js::UnsafeTraceManuallyBarrieredEdge(trc, vp, name);
+ }
+ static bool needsSweep(T* vp) {
+ if (*vp)
+ return js::gc::IsAboutToBeFinalizedUnbarriered(vp);
+ return false;
+ }
+};
+template <> struct GCPolicy<JS::Symbol*> : public GCPointerPolicy<JS::Symbol*> {};
+template <> struct GCPolicy<JSAtom*> : public GCPointerPolicy<JSAtom*> {};
+template <> struct GCPolicy<JSFunction*> : public GCPointerPolicy<JSFunction*> {};
+template <> struct GCPolicy<JSObject*> : public GCPointerPolicy<JSObject*> {};
+template <> struct GCPolicy<JSScript*> : public GCPointerPolicy<JSScript*> {};
+template <> struct GCPolicy<JSString*> : public GCPointerPolicy<JSString*> {};
+
+template <typename T>
+struct GCPolicy<JS::Heap<T>>
+{
+ static void trace(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
+ TraceEdge(trc, thingp, name);
+ }
+ static bool needsSweep(JS::Heap<T>* thingp) {
+ return js::gc::EdgeNeedsSweep(thingp);
+ }
+};
+
+// GCPolicy<UniquePtr<T>> forwards the contained pointer to GCPolicy<T>.
+template <typename T, typename D>
+struct GCPolicy<mozilla::UniquePtr<T, D>>
+{
+ static mozilla::UniquePtr<T,D> initial() { return mozilla::UniquePtr<T,D>(); }
+ static void trace(JSTracer* trc, mozilla::UniquePtr<T,D>* tp, const char* name) {
+ if (tp->get())
+ GCPolicy<T>::trace(trc, tp->get(), name);
+ }
+ static bool needsSweep(mozilla::UniquePtr<T,D>* tp) {
+ if (tp->get())
+ return GCPolicy<T>::needsSweep(tp->get());
+ return false;
+ }
+};
+
+} // namespace JS
+
+#endif // GCPolicyAPI_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCVariant.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCVariant.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCVariant.h
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_GCVariant_h
+#define js_GCVariant_h
+
+#include "mozilla/Variant.h"
+
+#include "js/GCPolicyAPI.h"
+#include "js/RootingAPI.h"
+#include "js/TracingAPI.h"
+
+namespace JS {
+
+// These template specializations allow Variant to be used inside GC wrappers.
+//
+// When matching on GC wrappers around Variants, matching should be done on
+// the wrapper itself. The matcher class's methods should take Handles or
+// MutableHandles. For example,
+//
+// struct MyMatcher
+// {
+// using ReturnType = const char*;
+// ReturnType match(HandleObject o) { return "object"; }
+// ReturnType match(HandleScript s) { return "script"; }
+// };
+//
+// Rooted<Variant<JSObject*, JSScript*>> v(cx, someScript);
+// MyMatcher mm;
+// v.match(mm);
+//
+// If you get compile errors about inability to upcast subclasses (e.g., from
+// NativeObject* to JSObject*) and are inside js/src, be sure to also include
+// "gc/Policy.h".
+
+namespace detail {
+
+template <typename... Ts>
+struct GCVariantImplementation;
+
+// The base case.
+template <typename T>
+struct GCVariantImplementation<T>
+{
+ template <typename ConcreteVariant>
+ static void trace(JSTracer* trc, ConcreteVariant* v, const char* name) {
+ T& thing = v->template as<T>();
+ if (!mozilla::IsPointer<T>::value || thing)
+ GCPolicy<T>::trace(trc, &thing, name);
+ }
+
+ template <typename Matcher, typename ConcreteVariant>
+ static typename Matcher::ReturnType
+ match(Matcher& matcher, Handle<ConcreteVariant> v) {
+ const T& thing = v.get().template as<T>();
+ return matcher.match(Handle<T>::fromMarkedLocation(&thing));
+ }
+
+ template <typename Matcher, typename ConcreteVariant>
+ static typename Matcher::ReturnType
+ match(Matcher& matcher, MutableHandle<ConcreteVariant> v) {
+ T& thing = v.get().template as<T>();
+ return matcher.match(MutableHandle<T>::fromMarkedLocation(&thing));
+ }
+};
+
+// The inductive case.
+template <typename T, typename... Ts>
+struct GCVariantImplementation<T, Ts...>
+{
+ using Next = GCVariantImplementation<Ts...>;
+
+ template <typename ConcreteVariant>
+ static void trace(JSTracer* trc, ConcreteVariant* v, const char* name) {
+ if (v->template is<T>()) {
+ T& thing = v->template as<T>();
+ if (!mozilla::IsPointer<T>::value || thing)
+ GCPolicy<T>::trace(trc, &thing, name);
+ } else {
+ Next::trace(trc, v, name);
+ }
+ }
+
+ template <typename Matcher, typename ConcreteVariant>
+ static typename Matcher::ReturnType
+ match(Matcher& matcher, Handle<ConcreteVariant> v) {
+ if (v.get().template is<T>()) {
+ const T& thing = v.get().template as<T>();
+ return matcher.match(Handle<T>::fromMarkedLocation(&thing));
+ }
+ return Next::match(matcher, v);
+ }
+
+ template <typename Matcher, typename ConcreteVariant>
+ static typename Matcher::ReturnType
+ match(Matcher& matcher, MutableHandle<ConcreteVariant> v) {
+ if (v.get().template is<T>()) {
+ T& thing = v.get().template as<T>();
+ return matcher.match(MutableHandle<T>::fromMarkedLocation(&thing));
+ }
+ return Next::match(matcher, v);
+ }
+};
+
+} // namespace detail
+
+template <typename... Ts>
+struct GCPolicy<mozilla::Variant<Ts...>>
+{
+ using Impl = detail::GCVariantImplementation<Ts...>;
+
+ // Variants do not provide initial(). They do not have a default initial
+ // value and one must be provided.
+
+ static void trace(JSTracer* trc, mozilla::Variant<Ts...>* v, const char* name) {
+ Impl::trace(trc, v, name);
+ }
+};
+
+} // namespace JS
+
+namespace js {
+
+template <typename Outer, typename... Ts>
+class GCVariantOperations
+{
+ using Impl = JS::detail::GCVariantImplementation<Ts...>;
+ using Variant = mozilla::Variant<Ts...>;
+
+ const Variant& variant() const { return static_cast<const Outer*>(this)->get(); }
+
+ public:
+ template <typename T>
+ bool is() const {
+ return variant().template is<T>();
+ }
+
+ template <typename T>
+ JS::Handle<T> as() const {
+ return Handle<T>::fromMarkedLocation(&variant().template as<T>());
+ }
+
+ template <typename Matcher>
+ typename Matcher::ReturnType
+ match(Matcher& matcher) const {
+ return Impl::match(matcher, JS::Handle<Variant>::fromMarkedLocation(&variant()));
+ }
+};
+
+template <typename Outer, typename... Ts>
+class MutableGCVariantOperations
+ : public GCVariantOperations<Outer, Ts...>
+{
+ using Impl = JS::detail::GCVariantImplementation<Ts...>;
+ using Variant = mozilla::Variant<Ts...>;
+
+ const Variant& variant() const { return static_cast<const Outer*>(this)->get(); }
+ Variant& variant() { return static_cast<Outer*>(this)->get(); }
+
+ public:
+ template <typename T>
+ JS::MutableHandle<T> as() {
+ return JS::MutableHandle<T>::fromMarkedLocation(&variant().template as<T>());
+ }
+
+ template <typename Matcher>
+ typename Matcher::ReturnType
+ match(Matcher& matcher) {
+ return Impl::match(matcher, JS::MutableHandle<Variant>::fromMarkedLocation(&variant()));
+ }
+};
+
+template <typename... Ts>
+class RootedBase<mozilla::Variant<Ts...>>
+ : public MutableGCVariantOperations<JS::Rooted<mozilla::Variant<Ts...>>, Ts...>
+{ };
+
+template <typename... Ts>
+class MutableHandleBase<mozilla::Variant<Ts...>>
+ : public MutableGCVariantOperations<JS::MutableHandle<mozilla::Variant<Ts...>>, Ts...>
+{ };
+
+template <typename... Ts>
+class HandleBase<mozilla::Variant<Ts...>>
+ : public GCVariantOperations<JS::Handle<mozilla::Variant<Ts...>>, Ts...>
+{ };
+
+template <typename... Ts>
+class PersistentRootedBase<mozilla::Variant<Ts...>>
+ : public MutableGCVariantOperations<JS::PersistentRooted<mozilla::Variant<Ts...>>, Ts...>
+{ };
+
+} // namespace js
+
+#endif // js_GCVariant_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCVector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCVector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/GCVector.h
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_GCVector_h
+#define js_GCVector_h
+
+#include "mozilla/Vector.h"
+
+#include "js/GCPolicyAPI.h"
+#include "js/RootingAPI.h"
+#include "js/TracingAPI.h"
+#include "js/Vector.h"
+
+namespace JS {
+
+// A GCVector is a Vector with an additional trace method that knows how
+// to visit all of the items stored in the Vector. For vectors that contain GC
+// things, this is usually more convenient than manually iterating and marking
+// the contents.
+//
+// Most types of GC pointers as keys and values can be traced with no extra
+// infrastructure. For structs and non-gc-pointer members, ensure that there is
+// a specialization of GCPolicy<T> with an appropriate trace method available
+// to handle the custom type. Generic helpers can be found in
+// js/public/TracingAPI.h.
+//
+// Note that although this Vector's trace will deal correctly with moved items,
+// it does not itself know when to barrier or trace items. To function properly
+// it must either be used with Rooted, or barriered and traced manually.
+template <typename T,
+ size_t MinInlineCapacity = 0,
+ typename AllocPolicy = js::TempAllocPolicy>
+class GCVector
+{
+ mozilla::Vector<T, MinInlineCapacity, AllocPolicy> vector;
+
+ public:
+ explicit GCVector(AllocPolicy alloc = AllocPolicy())
+ : vector(alloc)
+ {}
+
+ GCVector(GCVector&& vec)
+ : vector(mozilla::Move(vec.vector))
+ {}
+
+ GCVector& operator=(GCVector&& vec) {
+ vector = mozilla::Move(vec.vector);
+ return *this;
+ }
+
+ size_t length() const { return vector.length(); }
+ bool empty() const { return vector.empty(); }
+ size_t capacity() const { return vector.capacity(); }
+
+ T* begin() { return vector.begin(); }
+ const T* begin() const { return vector.begin(); }
+
+ T* end() { return vector.end(); }
+ const T* end() const { return vector.end(); }
+
+ T& operator[](size_t i) { return vector[i]; }
+ const T& operator[](size_t i) const { return vector[i]; }
+
+ T& back() { return vector.back(); }
+ const T& back() const { return vector.back(); }
+
+ bool initCapacity(size_t cap) { return vector.initCapacity(cap); }
+ bool reserve(size_t req) { return vector.reserve(req); }
+ void shrinkBy(size_t amount) { return vector.shrinkBy(amount); }
+ bool growBy(size_t amount) { return vector.growBy(amount); }
+ bool resize(size_t newLen) { return vector.resize(newLen); }
+
+ void clear() { return vector.clear(); }
+
+ template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }
+
+ template<typename... Args>
+ bool
+ emplaceBack(Args&&... args) {
+ return vector.emplaceBack(mozilla::Forward<Args>(args)...);
+ }
+
+ template<typename U>
+ void infallibleAppend(U&& aU) {
+ return vector.infallibleAppend(mozilla::Forward<U>(aU));
+ }
+ void infallibleAppendN(const T& aT, size_t aN) {
+ return vector.infallibleAppendN(aT, aN);
+ }
+ template<typename U> void
+ infallibleAppend(const U* aBegin, const U* aEnd) {
+ return vector.infallibleAppend(aBegin, aEnd);
+ }
+ template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
+ return vector.infallibleAppend(aBegin, aLength);
+ }
+
+ template<typename U, size_t O, class BP>
+ bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vector.appendAll(aU); }
+ template<typename U, size_t O, class BP>
+ bool appendAll(const GCVector<U, O, BP>& aU) { return vector.append(aU.begin(), aU.length()); }
+
+ bool appendN(const T& val, size_t count) { return vector.appendN(val, count); }
+
+ template<typename U> bool append(const U* aBegin, const U* aEnd) {
+ return vector.append(aBegin, aEnd);
+ }
+ template<typename U> bool append(const U* aBegin, size_t aLength) {
+ return vector.append(aBegin, aLength);
+ }
+
+ void popBack() { return vector.popBack(); }
+ T popCopy() { return vector.popCopy(); }
+
+ size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return vector.sizeOfExcludingThis(mallocSizeOf);
+ }
+
+ size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return vector.sizeOfIncludingThis(mallocSizeOf);
+ }
+
+ static void trace(GCVector* vec, JSTracer* trc) { vec->trace(trc); }
+
+ void trace(JSTracer* trc) {
+ for (auto& elem : vector)
+ GCPolicy<T>::trace(trc, &elem, "vector element");
+ }
+};
+
+} // namespace JS
+
+namespace js {
+
+template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
+class GCVectorOperations
+{
+ using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
+ const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
+
+ public:
+ const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
+ size_t length() const { return vec().length(); }
+ bool empty() const { return vec().empty(); }
+ size_t capacity() const { return vec().capacity(); }
+ const T* begin() const { return vec().begin(); }
+ const T* end() const { return vec().end(); }
+ const T& back() const { return vec().back(); }
+
+ JS::Handle<T> operator[](size_t aIndex) const {
+ return JS::Handle<T>::fromMarkedLocation(&vec().operator[](aIndex));
+ }
+};
+
+template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
+class MutableGCVectorOperations
+ : public GCVectorOperations<Outer, T, Capacity, AllocPolicy>
+{
+ using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
+ const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
+ Vec& vec() { return static_cast<Outer*>(this)->get(); }
+
+ public:
+ const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
+ AllocPolicy& allocPolicy() { return vec().allocPolicy(); }
+ const T* begin() const { return vec().begin(); }
+ T* begin() { return vec().begin(); }
+ const T* end() const { return vec().end(); }
+ T* end() { return vec().end(); }
+ const T& back() const { return vec().back(); }
+ T& back() { return vec().back(); }
+
+ JS::Handle<T> operator[](size_t aIndex) const {
+ return JS::Handle<T>::fromMarkedLocation(&vec().operator[](aIndex));
+ }
+ JS::MutableHandle<T> operator[](size_t aIndex) {
+ return JS::MutableHandle<T>::fromMarkedLocation(&vec().operator[](aIndex));
+ }
+
+ bool initCapacity(size_t aRequest) { return vec().initCapacity(aRequest); }
+ bool reserve(size_t aRequest) { return vec().reserve(aRequest); }
+ void shrinkBy(size_t aIncr) { vec().shrinkBy(aIncr); }
+ bool growBy(size_t aIncr) { return vec().growBy(aIncr); }
+ bool resize(size_t aNewLength) { return vec().resize(aNewLength); }
+ bool growByUninitialized(size_t aIncr) { return vec().growByUninitialized(aIncr); }
+ void infallibleGrowByUninitialized(size_t aIncr) { vec().infallibleGrowByUninitialized(aIncr); }
+ bool resizeUninitialized(size_t aNewLength) { return vec().resizeUninitialized(aNewLength); }
+ void clear() { vec().clear(); }
+ void clearAndFree() { vec().clearAndFree(); }
+ template<typename U> bool append(U&& aU) { return vec().append(mozilla::Forward<U>(aU)); }
+ template<typename... Args> bool emplaceBack(Args&&... aArgs) {
+ return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
+ }
+ template<typename U, size_t O, class BP>
+ bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vec().appendAll(aU); }
+ template<typename U, size_t O, class BP>
+ bool appendAll(const JS::GCVector<U, O, BP>& aU) { return vec().appendAll(aU); }
+ bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
+ template<typename U> bool append(const U* aBegin, const U* aEnd) {
+ return vec().append(aBegin, aEnd);
+ }
+ template<typename U> bool append(const U* aBegin, size_t aLength) {
+ return vec().append(aBegin, aLength);
+ }
+ template<typename U> void infallibleAppend(U&& aU) {
+ vec().infallibleAppend(mozilla::Forward<U>(aU));
+ }
+ void infallibleAppendN(const T& aT, size_t aN) { vec().infallibleAppendN(aT, aN); }
+ template<typename U> void infallibleAppend(const U* aBegin, const U* aEnd) {
+ vec().infallibleAppend(aBegin, aEnd);
+ }
+ template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
+ vec().infallibleAppend(aBegin, aLength);
+ }
+ void popBack() { vec().popBack(); }
+ T popCopy() { return vec().popCopy(); }
+ template<typename U> T* insert(T* aP, U&& aVal) {
+ return vec().insert(aP, mozilla::Forward<U>(aVal));
+ }
+ void erase(T* aT) { vec().erase(aT); }
+ void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
+};
+
+template <typename T, size_t N, typename AP>
+class RootedBase<JS::GCVector<T,N,AP>>
+ : public MutableGCVectorOperations<JS::Rooted<JS::GCVector<T,N,AP>>, T,N,AP>
+{};
+
+template <typename T, size_t N, typename AP>
+class MutableHandleBase<JS::GCVector<T,N,AP>>
+ : public MutableGCVectorOperations<JS::MutableHandle<JS::GCVector<T,N,AP>>, T,N,AP>
+{};
+
+template <typename T, size_t N, typename AP>
+class HandleBase<JS::GCVector<T,N,AP>>
+ : public GCVectorOperations<JS::Handle<JS::GCVector<T,N,AP>>, T,N,AP>
+{};
+
+template <typename T, size_t N, typename AP>
+class PersistentRootedBase<JS::GCVector<T,N,AP>>
+ : public MutableGCVectorOperations<JS::PersistentRooted<JS::GCVector<T,N,AP>>, T,N,AP>
+{};
+
+} // namespace js
+
+#endif // js_GCVector_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/HashTable.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/HashTable.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/HashTable.h
@@ -11,6 +11,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Casting.h"
+#include "mozilla/HashFunctions.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
#include "mozilla/Opaque.h"
@@ -34,6 +35,16 @@
/*****************************************************************************/
+// The "generation" of a hash table is an opaque value indicating the state of
+// modification of the hash table through its lifetime. If the generation of
+// a hash table compares equal at times T1 and T2, then lookups in the hash
+// table, pointers to (or into) hash table entries, etc. at time T1 are valid
+// at time T2. If the generation compares unequal, these computations are all
+// invalid and must be performed again to be used.
+//
+// Generations are meaningfully comparable only with respect to a single hash
+// table. It's always nonsensical to compare the generation of distinct hash
+// tables H1 and H2.
using Generation = mozilla::Opaque<uint64_t>;
// A JS-friendly, STL-like container providing a hash-based map from keys to
@@ -61,6 +72,7 @@
struct MapHashPolicy : HashPolicy
{
+ using Base = HashPolicy;
typedef Key KeyType;
static const Key& getKey(TableEntry& e) { return e.key(); }
static void setKey(TableEntry& e, Key& k) { HashPolicy::rekey(e.mutableKey(), k); }
@@ -76,8 +88,8 @@
// HashMap construction is fallible (due to OOM); thus the user must call
// init after constructing a HashMap and check the return value.
explicit HashMap(AllocPolicy a = AllocPolicy()) : impl(a) {}
- bool init(uint32_t len = 16) { return impl.init(len); }
- bool initialized() const { return impl.initialized(); }
+ MOZ_MUST_USE bool init(uint32_t len = 16) { return impl.init(len); }
+ bool initialized() const { return impl.initialized(); }
// Return whether the given lookup value is present in the map. E.g.:
//
@@ -139,19 +151,19 @@
}
template<typename KeyInput, typename ValueInput>
- bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) {
+ MOZ_MUST_USE bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) {
return impl.add(p,
mozilla::Forward<KeyInput>(k),
mozilla::Forward<ValueInput>(v));
}
template<typename KeyInput>
- bool add(AddPtr& p, KeyInput&& k) {
+ MOZ_MUST_USE bool add(AddPtr& p, KeyInput&& k) {
return impl.add(p, mozilla::Forward<KeyInput>(k), Value());
}
template<typename KeyInput, typename ValueInput>
- bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) {
+ MOZ_MUST_USE bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) {
return impl.relookupOrAdd(p, k,
mozilla::Forward<KeyInput>(k),
mozilla::Forward<ValueInput>(v));
@@ -208,8 +220,6 @@
return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
}
- // If |generation()| is the same before and after a HashMap operation,
- // pointers into the table remain valid.
Generation generation() const {
return impl.generation();
}
@@ -222,7 +232,7 @@
// Overwrite existing value with v. Return false on oom.
template<typename KeyInput, typename ValueInput>
- bool put(KeyInput&& k, ValueInput&& v) {
+ MOZ_MUST_USE bool put(KeyInput&& k, ValueInput&& v) {
AddPtr p = lookupForAdd(k);
if (p) {
p->value() = mozilla::Forward<ValueInput>(v);
@@ -233,7 +243,7 @@
// Like put, but assert that the given key is not already present.
template<typename KeyInput, typename ValueInput>
- bool putNew(KeyInput&& k, ValueInput&& v) {
+ MOZ_MUST_USE bool putNew(KeyInput&& k, ValueInput&& v) {
return impl.putNew(k, mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v));
}
@@ -248,7 +258,9 @@
AddPtr p = lookupForAdd(k);
if (p)
return p;
- (void)add(p, k, defaultValue); // p is left false-y on oom.
+ bool ok = add(p, k, defaultValue);
+ MOZ_ASSERT_IF(!ok, !p); // p is left false-y on oom.
+ (void)ok;
return p;
}
@@ -313,6 +325,7 @@
{
struct SetOps : HashPolicy
{
+ using Base = HashPolicy;
typedef T KeyType;
static const KeyType& getKey(const T& t) { return t; }
static void setKey(T& t, KeyType& k) { HashPolicy::rekey(t, k); }
@@ -328,8 +341,8 @@
// HashSet construction is fallible (due to OOM); thus the user must call
// init after constructing a HashSet and check the return value.
explicit HashSet(AllocPolicy a = AllocPolicy()) : impl(a) {}
- bool init(uint32_t len = 16) { return impl.init(len); }
- bool initialized() const { return impl.initialized(); }
+ MOZ_MUST_USE bool init(uint32_t len = 16) { return impl.init(len); }
+ bool initialized() const { return impl.initialized(); }
// Return whether the given lookup value is present in the map. E.g.:
//
@@ -386,12 +399,12 @@
AddPtr lookupForAdd(const Lookup& l) const { return impl.lookupForAdd(l); }
template <typename U>
- bool add(AddPtr& p, U&& u) {
+ MOZ_MUST_USE bool add(AddPtr& p, U&& u) {
return impl.add(p, mozilla::Forward<U>(u));
}
template <typename U>
- bool relookupOrAdd(AddPtr& p, const Lookup& l, U&& u) {
+ MOZ_MUST_USE bool relookupOrAdd(AddPtr& p, const Lookup& l, U&& u) {
return impl.relookupOrAdd(p, l, mozilla::Forward<U>(u));
}
@@ -446,8 +459,6 @@
return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
}
- // If |generation()| is the same before and after a HashSet operation,
- // pointers into the table remain valid.
Generation generation() const {
return impl.generation();
}
@@ -460,19 +471,19 @@
// Add |u| if it is not present already. Return false on oom.
template <typename U>
- bool put(U&& u) {
+ MOZ_MUST_USE bool put(U&& u) {
AddPtr p = lookupForAdd(u);
return p ? true : add(p, mozilla::Forward<U>(u));
}
// Like put, but assert that the given key is not already present.
template <typename U>
- bool putNew(U&& u) {
+ MOZ_MUST_USE bool putNew(U&& u) {
return impl.putNew(u, mozilla::Forward<U>(u));
}
template <typename U>
- bool putNew(const Lookup& l, U&& u) {
+ MOZ_MUST_USE bool putNew(const Lookup& l, U&& u) {
return impl.putNew(l, mozilla::Forward<U>(u));
}
@@ -503,11 +514,16 @@
return false;
}
- // Infallibly rekey one entry with a new key that is equivalent.
- void rekeyInPlace(Ptr p, const T& new_value)
- {
+ // Infallibly replace the current key at |p| with an equivalent key.
+ // Specifically, both HashPolicy::hash and HashPolicy::match must return
+ // identical results for the new and old key when applied against all
+ // possible matching values.
+ void replaceKey(Ptr p, const T& new_value) {
+ MOZ_ASSERT(p.found());
+ MOZ_ASSERT(*p != new_value);
+ MOZ_ASSERT(HashPolicy::hash(*p) == HashPolicy::hash(new_value));
MOZ_ASSERT(HashPolicy::match(*p, new_value));
- impl.rekeyInPlace(p, new_value);
+ const_cast<T&>(*p) = new_value;
}
// HashSet is movable
@@ -606,21 +622,21 @@
struct DefaultHasher<T*> : PointerHasher<T*, mozilla::tl::FloorLog2<sizeof(void*)>::value>
{};
-// Specialize hashing policy for mozilla::UniquePtr<T> to proxy the UniquePtr's
+// Specialize hashing policy for mozilla::UniquePtr to proxy the UniquePtr's
// raw pointer to PointerHasher.
-template <class T>
-struct DefaultHasher<mozilla::UniquePtr<T>>
+template <class T, class D>
+struct DefaultHasher<mozilla::UniquePtr<T, D>>
{
- using Lookup = mozilla::UniquePtr<T>;
+ using Lookup = mozilla::UniquePtr<T, D>;
using PtrHasher = PointerHasher<T*, mozilla::tl::FloorLog2<sizeof(void*)>::value>;
static HashNumber hash(const Lookup& l) {
return PtrHasher::hash(l.get());
}
- static bool match(const mozilla::UniquePtr<T>& k, const Lookup& l) {
+ static bool match(const mozilla::UniquePtr<T, D>& k, const Lookup& l) {
return PtrHasher::match(k.get(), l.get());
}
- static void rekey(mozilla::UniquePtr<T>& k, mozilla::UniquePtr<T>&& newKey) {
+ static void rekey(mozilla::UniquePtr<T, D>& k, mozilla::UniquePtr<T, D>&& newKey) {
k = mozilla::Move(newKey);
}
};
@@ -655,6 +671,50 @@
}
};
+// A hash policy that compares C strings.
+struct CStringHasher
+{
+ typedef const char* Lookup;
+ static js::HashNumber hash(Lookup l) {
+ return mozilla::HashString(l);
+ }
+ static bool match(const char* key, Lookup lookup) {
+ return strcmp(key, lookup) == 0;
+ }
+};
+
+// Fallible hashing interface.
+//
+// Most of the time generating a hash code is infallible so this class provides
+// default methods that always succeed. Specialize this class for your own hash
+// policy to provide fallible hashing.
+//
+// This is used by MovableCellHasher to handle the fact that generating a unique
+// ID for cell pointer may fail due to OOM.
+template <typename HashPolicy>
+struct FallibleHashMethods
+{
+ // Return true if a hashcode is already available for its argument. Once
+ // this returns true for a specific argument it must continue to do so.
+ template <typename Lookup> static bool hasHash(Lookup&& l) { return true; }
+
+ // Fallible method to ensure a hashcode exists for its argument and create
+ // one if not. Returns false on error, e.g. out of memory.
+ template <typename Lookup> static bool ensureHash(Lookup&& l) { return true; }
+};
+
+template <typename HashPolicy, typename Lookup>
+static bool
+HasHash(Lookup&& l) {
+ return FallibleHashMethods<typename HashPolicy::Base>::hasHash(mozilla::Forward<Lookup>(l));
+}
+
+template <typename HashPolicy, typename Lookup>
+static bool
+EnsureHash(Lookup&& l) {
+ return FallibleHashMethods<typename HashPolicy::Base>::ensureHash(mozilla::Forward<Lookup>(l));
+}
+
/*****************************************************************************/
// Both HashMap and HashSet are implemented by a single HashTable that is even
@@ -684,6 +744,11 @@
value_(mozilla::Move(rhs.value_))
{}
+ void operator=(HashMapEntry&& rhs) {
+ key_ = mozilla::Move(rhs.key_);
+ value_ = mozilla::Move(rhs.value_);
+ }
+
typedef Key KeyType;
typedef Value ValueType;
@@ -754,8 +819,16 @@
}
void swap(HashTableEntry* other) {
+ if (this == other)
+ return;
+ MOZ_ASSERT(isLive());
+ if (other->isLive()) {
+ mozilla::Swap(*mem.addr(), *other->mem.addr());
+ } else {
+ *other->mem.addr() = mozilla::Move(*mem.addr());
+ destroy();
+ }
mozilla::Swap(keyHash, other->keyHash);
- mozilla::Swap(mem, other->mem);
}
T& get() { MOZ_ASSERT(isLive()); return *mem.addr(); }
@@ -819,14 +892,21 @@
{}
public:
- // Leaves Ptr uninitialized.
- Ptr() {
+ Ptr()
+ : entry_(nullptr)
#ifdef JS_DEBUG
- entry_ = (Entry*)0xbad;
+ , table_(nullptr)
+ , generation(0)
#endif
+ {}
+
+ bool isValid() const {
+ return !entry_;
}
bool found() const {
+ if (isValid())
+ return false;
#ifdef JS_DEBUG
MOZ_ASSERT(generation == table_->generation());
#endif
@@ -851,6 +931,7 @@
T& operator*() const {
#ifdef JS_DEBUG
+ MOZ_ASSERT(found());
MOZ_ASSERT(generation == table_->generation());
#endif
return entry_->get();
@@ -858,6 +939,7 @@
T* operator->() const {
#ifdef JS_DEBUG
+ MOZ_ASSERT(found());
MOZ_ASSERT(generation == table_->generation());
#endif
return &entry_->get();
@@ -882,8 +964,7 @@
{}
public:
- // Leaves AddPtr uninitialized.
- AddPtr() {}
+ AddPtr() : keyHash(0) {}
};
// A collection of hash table entries. The collection is enumerated by
@@ -1173,7 +1254,7 @@
#endif
{}
- MOZ_WARN_UNUSED_RESULT bool init(uint32_t length)
+ MOZ_MUST_USE bool init(uint32_t length)
{
MOZ_ASSERT(!initialized());
@@ -1543,6 +1624,33 @@
// which approach is best.
}
+ // Note: |l| may be a reference to a piece of |u|, so this function
+ // must take care not to use |l| after moving |u|.
+ //
+ // Prefer to use putNewInfallible; this function does not check
+ // invariants.
+ template <typename... Args>
+ void putNewInfallibleInternal(const Lookup& l, Args&&... args)
+ {
+ MOZ_ASSERT(table);
+
+ HashNumber keyHash = prepareHash(l);
+ Entry* entry = &findFreeEntry(keyHash);
+ MOZ_ASSERT(entry);
+
+ if (entry->isRemoved()) {
+ METER(stats.addOverRemoved++);
+ removedCount--;
+ keyHash |= sCollisionBit;
+ }
+
+ entry->setLive(keyHash, mozilla::Forward<Args>(args)...);
+ entryCount++;
+#ifdef JS_DEBUG
+ mutationCount++;
+#endif
+ }
+
public:
void clear()
{
@@ -1622,12 +1730,16 @@
Ptr lookup(const Lookup& l) const
{
mozilla::ReentrancyGuard g(*this);
+ if (!HasHash<HashPolicy>(l))
+ return Ptr();
HashNumber keyHash = prepareHash(l);
return Ptr(lookup(l, keyHash, 0), *this);
}
Ptr readonlyThreadsafeLookup(const Lookup& l) const
{
+ if (!HasHash<HashPolicy>(l))
+ return Ptr();
HashNumber keyHash = prepareHash(l);
return Ptr(lookup(l, keyHash, 0), *this);
}
@@ -1635,6 +1747,8 @@
AddPtr lookupForAdd(const Lookup& l) const
{
mozilla::ReentrancyGuard g(*this);
+ if (!EnsureHash<HashPolicy>(l))
+ return AddPtr();
HashNumber keyHash = prepareHash(l);
Entry& entry = lookup(l, keyHash, sCollisionBit);
AddPtr p(entry, *this, keyHash);
@@ -1642,13 +1756,17 @@
}
template <typename... Args>
- bool add(AddPtr& p, Args&&... args)
+ MOZ_MUST_USE bool add(AddPtr& p, Args&&... args)
{
mozilla::ReentrancyGuard g(*this);
MOZ_ASSERT(table);
MOZ_ASSERT(!p.found());
MOZ_ASSERT(!(p.keyHash & sCollisionBit));
+ // Check for error from ensureHash() here.
+ if (p.isValid())
+ return false;
+
// Changing an entry from removed to live does not affect whether we
// are overloaded and can be handled separately.
if (p.entry_->isRemoved()) {
@@ -1662,7 +1780,7 @@
RebuildStatus status = checkOverloaded();
if (status == RehashFailed)
return false;
- if (!this->checkSimulatedOOM())
+ if (status == NotOverloaded && !this->checkSimulatedOOM())
return false;
if (status == Rehashed)
p.entry_ = &findFreeEntry(p.keyHash);
@@ -1683,33 +1801,22 @@
template <typename... Args>
void putNewInfallible(const Lookup& l, Args&&... args)
{
- MOZ_ASSERT(table);
-
- HashNumber keyHash = prepareHash(l);
- Entry* entry = &findFreeEntry(keyHash);
- MOZ_ASSERT(entry);
-
- if (entry->isRemoved()) {
- METER(stats.addOverRemoved++);
- removedCount--;
- keyHash |= sCollisionBit;
- }
-
- entry->setLive(keyHash, mozilla::Forward<Args>(args)...);
- entryCount++;
-#ifdef JS_DEBUG
- mutationCount++;
-#endif
+ MOZ_ASSERT(!lookup(l).found());
+ mozilla::ReentrancyGuard g(*this);
+ putNewInfallibleInternal(l, mozilla::Forward<Args>(args)...);
}
// Note: |l| may be alias arguments in |args|, so this function must take
// care not to use |l| after moving |args|.
template <typename... Args>
- bool putNew(const Lookup& l, Args&&... args)
+ MOZ_MUST_USE bool putNew(const Lookup& l, Args&&... args)
{
if (!this->checkSimulatedOOM())
return false;
+ if (!EnsureHash<HashPolicy>(l))
+ return false;
+
if (checkOverloaded() == RehashFailed)
return false;
@@ -1720,8 +1827,12 @@
// Note: |l| may be a reference to a piece of |u|, so this function
// must take care not to use |l| after moving |u|.
template <typename... Args>
- bool relookupOrAdd(AddPtr& p, const Lookup& l, Args&&... args)
+ MOZ_MUST_USE bool relookupOrAdd(AddPtr& p, const Lookup& l, Args&&... args)
{
+ // Check for error from ensureHash() here.
+ if (p.isValid())
+ return false;
+
#ifdef JS_DEBUG
p.generation = generation();
p.mutationCount = mutationCount;
@@ -1751,7 +1862,7 @@
typename HashTableEntry<T>::NonConstT t(mozilla::Move(*p));
HashPolicy::setKey(t, const_cast<Key&>(k));
remove(*p.entry_);
- putNewInfallible(l, mozilla::Move(t));
+ putNewInfallibleInternal(l, mozilla::Move(t));
}
void rekeyAndMaybeRehash(Ptr p, const Lookup& l, const Key& k)
@@ -1760,14 +1871,6 @@
checkOverRemoved();
}
- void rekeyInPlace(Ptr p, const Key& k)
- {
- MOZ_ASSERT(table);
- mozilla::ReentrancyGuard g(*this);
- MOZ_ASSERT(p.found());
- HashPolicy::rekey(const_cast<Key&>(*p), const_cast<Key&>(k));
- }
-
#undef METER
};
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/HeapAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/HeapAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/HeapAPI.h
@@ -17,11 +17,6 @@
/* These values are private to the JS engine. */
namespace js {
-// Whether the current thread is permitted access to any part of the specified
-// runtime or zone.
-JS_FRIEND_API(bool)
-CurrentThreadCanAccessRuntime(JSRuntime* rt);
-
JS_FRIEND_API(bool)
CurrentThreadCanAccessZone(JS::Zone* zone);
@@ -56,7 +51,9 @@
const size_t ChunkRuntimeOffset = ChunkSize - sizeof(void*);
const size_t ChunkTrailerSize = 2 * sizeof(uintptr_t) + sizeof(uint64_t);
const size_t ChunkLocationOffset = ChunkSize - ChunkTrailerSize;
-const size_t ArenaZoneOffset = 0;
+const size_t ArenaZoneOffset = sizeof(size_t);
+const size_t ArenaHeaderSize = sizeof(size_t) + 2 * sizeof(uintptr_t) +
+ sizeof(size_t) + sizeof(uintptr_t);
/*
* Live objects are marked black. How many other additional colors are available
@@ -67,19 +64,15 @@
static const uint32_t GRAY = 1;
/*
- * The "location" field in the Chunk trailer is a bit vector indicting various
- * roles of the chunk.
- *
- * The value 0 for the "location" field is invalid, at least one bit must be
- * set.
- *
- * Some bits preclude others, for example, any "nursery" bit precludes any
- * "tenured" or "middle generation" bit.
+ * The "location" field in the Chunk trailer is a enum indicating various roles
+ * of the chunk.
*/
-const uintptr_t ChunkLocationBitNursery = 1; // Standard GGC nursery
-const uintptr_t ChunkLocationBitTenuredHeap = 2; // Standard GGC tenured generation
-
-const uintptr_t ChunkLocationAnyNursery = ChunkLocationBitNursery;
+enum class ChunkLocation : uint32_t
+{
+ Invalid = 0,
+ Nursery = 1,
+ TenuredHeap = 2
+};
#ifdef JS_DEBUG
/* When downcasting, ensure we are actually the right type. */
@@ -113,13 +106,20 @@
JSTracer* const barrierTracer_; // A pointer to the JSRuntime's |gcMarker|.
public:
+ // Stack GC roots for Rooted GC pointers.
+ js::RootedListHeads stackRoots_;
+ template <typename T> friend class JS::Rooted;
+
bool needsIncrementalBarrier_;
Zone(JSRuntime* runtime, JSTracer* barrierTracerArg)
: runtime_(runtime),
barrierTracer_(barrierTracerArg),
needsIncrementalBarrier_(false)
- {}
+ {
+ for (auto& stackRootPtr : stackRoots_)
+ stackRootPtr = nullptr;
+ }
bool needsIncrementalBarrier() const {
return needsIncrementalBarrier_;
@@ -142,7 +142,7 @@
return runtime_;
}
- static JS::shadow::Zone* asShadowZone(JS::Zone* zone) {
+ static MOZ_ALWAYS_INLINE JS::shadow::Zone* asShadowZone(JS::Zone* zone) {
return reinterpret_cast<JS::shadow::Zone*>(zone);
}
};
@@ -280,14 +280,6 @@
return reinterpret_cast<uintptr_t*>(bmap_addr);
}
-static MOZ_ALWAYS_INLINE JS::shadow::Runtime*
-GetGCThingRuntime(const uintptr_t addr)
-{
- MOZ_ASSERT(addr);
- const uintptr_t rt_addr = (addr & ~ChunkMask) | ChunkRuntimeOffset;
- return *reinterpret_cast<JS::shadow::Runtime**>(rt_addr);
-}
-
static MOZ_ALWAYS_INLINE void
GetGCThingMarkWordAndMask(const uintptr_t addr, uint32_t color,
uintptr_t** wordp, uintptr_t* maskp)
@@ -310,16 +302,30 @@
}
+static MOZ_ALWAYS_INLINE JS::shadow::Runtime*
+GetCellRuntime(const Cell* cell)
+{
+ MOZ_ASSERT(cell);
+ const uintptr_t addr = uintptr_t(cell);
+ const uintptr_t rt_addr = (addr & ~ChunkMask) | ChunkRuntimeOffset;
+ return *reinterpret_cast<JS::shadow::Runtime**>(rt_addr);
+}
+
static MOZ_ALWAYS_INLINE bool
CellIsMarkedGray(const Cell* cell)
{
MOZ_ASSERT(cell);
- MOZ_ASSERT(!js::gc::IsInsideNursery(cell));
+ if (js::gc::IsInsideNursery(cell))
+ return false;
+
uintptr_t* word, mask;
js::gc::detail::GetGCThingMarkWordAndMask(uintptr_t(cell), js::gc::GRAY, &word, &mask);
return *word & mask;
}
+extern JS_PUBLIC_API(bool)
+CellIsMarkedGrayIfKnown(const Cell* cell);
+
} /* namespace detail */
MOZ_ALWAYS_INLINE bool
@@ -330,9 +336,9 @@
uintptr_t addr = uintptr_t(cell);
addr &= ~js::gc::ChunkMask;
addr |= js::gc::ChunkLocationOffset;
- uint32_t location = *reinterpret_cast<uint32_t*>(addr);
- MOZ_ASSERT(location != 0);
- return location & ChunkLocationAnyNursery;
+ auto location = *reinterpret_cast<ChunkLocation*>(addr);
+ MOZ_ASSERT(location == ChunkLocation::Nursery || location == ChunkLocation::TenuredHeap);
+ return location == ChunkLocation::Nursery;
}
} /* namespace gc */
@@ -357,40 +363,16 @@
GetObjectZone(JSObject* obj);
static MOZ_ALWAYS_INLINE bool
-ObjectIsTenured(JSObject* obj)
-{
- return !js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(obj));
-}
-
-static MOZ_ALWAYS_INLINE bool
-ObjectIsMarkedGray(JSObject* obj)
-{
- /*
- * GC things residing in the nursery cannot be gray: they have no mark bits.
- * All live objects in the nursery are moved to tenured at the beginning of
- * each GC slice, so the gray marker never sees nursery things.
- */
- if (js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(obj)))
- return false;
- return js::gc::detail::CellIsMarkedGray(reinterpret_cast<js::gc::Cell*>(obj));
-}
-
-static MOZ_ALWAYS_INLINE bool
-ScriptIsMarkedGray(JSScript* script)
-{
- return js::gc::detail::CellIsMarkedGray(reinterpret_cast<js::gc::Cell*>(script));
-}
-
-static MOZ_ALWAYS_INLINE bool
GCThingIsMarkedGray(GCCellPtr thing)
{
- if (js::gc::IsInsideNursery(thing.asCell()))
- return false;
if (thing.mayBeOwnedByOtherRuntime())
return false;
- return js::gc::detail::CellIsMarkedGray(thing.asCell());
+ return js::gc::detail::CellIsMarkedGrayIfKnown(thing.asCell());
}
+extern JS_PUBLIC_API(JS::TraceKind)
+GCThingTraceKind(void* thing);
+
} /* namespace JS */
namespace js {
@@ -401,8 +383,11 @@
{
MOZ_ASSERT(thing);
MOZ_ASSERT(!js::gc::IsInsideNursery(thing.asCell()));
- if (rt->isHeapBusy())
- return false;
+
+ // TODO: I'd like to assert !isHeapBusy() here but this gets called while we
+ // are tracing the heap, e.g. during memory reporting (see bug 1313318).
+ MOZ_ASSERT(!rt->isHeapCollecting());
+
JS::Zone* zone = JS::GetTenuredGCThingZone(thing);
return JS::shadow::Zone::asShadowZone(zone)->needsIncrementalBarrier();
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Id.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Id.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Id.h
@@ -30,9 +30,9 @@
struct jsid
{
size_t asBits;
- bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
- bool operator!=(jsid rhs) const { return asBits != rhs.asBits; }
-};
+ bool operator==(const jsid& rhs) const { return asBits == rhs.asBits; }
+ bool operator!=(const jsid& rhs) const { return asBits != rhs.asBits; }
+} JS_HAZ_GC_POINTER;
#define JSID_BITS(id) (id.asBits)
#define JSID_TYPE_STRING 0x0
@@ -69,12 +69,6 @@
INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str);
static MOZ_ALWAYS_INLINE bool
-JSID_IS_ZERO(jsid id)
-{
- return JSID_BITS(id) == 0;
-}
-
-static MOZ_ALWAYS_INLINE bool
JSID_IS_INT(jsid id)
{
return !!(JSID_BITS(id) & JSID_TYPE_INT);
@@ -166,20 +160,36 @@
extern JS_PUBLIC_DATA(const JS::HandleId) JSID_VOIDHANDLE;
extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
-namespace js {
+namespace JS {
template <>
-struct GCMethods<jsid>
+struct GCPolicy<jsid>
{
static jsid initial() { return JSID_VOID; }
+ static void trace(JSTracer* trc, jsid* idp, const char* name) {
+ js::UnsafeTraceManuallyBarrieredEdge(trc, idp, name);
+ }
+};
+
+} // namespace JS
+
+namespace js {
+
+template <>
+struct BarrierMethods<jsid>
+{
static void postBarrier(jsid* idp, jsid prev, jsid next) {}
+ static void exposeToJS(jsid id) {
+ if (JSID_IS_GCTHING(id))
+ js::gc::ExposeGCThingToActiveJS(JSID_TO_GCTHING(id));
+ }
};
// If the jsid is a GC pointer type, convert to that type and call |f| with
// the pointer. If the jsid is not a GC type, calls F::defaultValue.
template <typename F, typename... Args>
auto
-DispatchTyped(F f, jsid& id, Args&&... args)
+DispatchTyped(F f, const jsid& id, Args&&... args)
-> decltype(f(static_cast<JSString*>(nullptr), mozilla::Forward<Args>(args)...))
{
if (JSID_IS_STRING(id))
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Initialization.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Initialization.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Initialization.h
@@ -25,6 +25,9 @@
extern JS_PUBLIC_DATA(InitState)
libraryInitState;
+extern JS_PUBLIC_API(const char*)
+InitWithFailureDiagnostic(bool isDebugBuild);
+
} // namespace detail
} // namespace JS
@@ -58,8 +61,46 @@
* is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
* again). This restriction may eventually be lifted.
*/
-extern JS_PUBLIC_API(bool)
-JS_Init(void);
+inline bool
+JS_Init(void)
+{
+#ifdef DEBUG
+ return !JS::detail::InitWithFailureDiagnostic(true);
+#else
+ return !JS::detail::InitWithFailureDiagnostic(false);
+#endif
+}
+
+/**
+ * A variant of JS_Init. On success it returns nullptr. On failure it returns a
+ * pointer to a string literal that describes how initialization failed, which
+ * can be useful for debugging purposes.
+ */
+inline const char*
+JS_InitWithFailureDiagnostic(void)
+{
+#ifdef DEBUG
+ return JS::detail::InitWithFailureDiagnostic(true);
+#else
+ return JS::detail::InitWithFailureDiagnostic(false);
+#endif
+}
+
+/*
+ * Returns true if SpiderMonkey has been initialized successfully, even if it has
+ * possibly been shut down.
+ *
+ * Note that it is the responsibility of the embedder to call JS_Init() and
+ * JS_ShutDown() at the correct times, and therefore this API should ideally not
+ * be necessary to use. This is only intended to be used in cases where the
+ * embedder isn't in full control of deciding whether to initialize SpiderMonkey
+ * or hand off the task to another consumer.
+ */
+inline bool
+JS_IsInitialized(void)
+{
+ return JS::detail::libraryInitState != JS::detail::InitState::Uninitialized;
+}
/**
* Destroy free-standing resources allocated by SpiderMonkey, not associated
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/MemoryMetrics.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/MemoryMetrics.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/MemoryMetrics.h
@@ -166,23 +166,17 @@
#define FOR_EACH_SIZE(macro) \
macro(Objects, GCHeapUsed, objectsGCHeap) \
macro(Objects, MallocHeap, objectsMallocHeapSlots) \
- macro(Objects, MallocHeap, objectsMallocHeapElementsNonAsmJS) \
+ macro(Objects, MallocHeap, objectsMallocHeapElementsNormal) \
macro(Objects, MallocHeap, objectsMallocHeapElementsAsmJS) \
- macro(Objects, NonHeap, objectsNonHeapElementsAsmJS) \
- macro(Objects, NonHeap, objectsNonHeapElementsMapped) \
- macro(Objects, NonHeap, objectsNonHeapCodeAsmJS) \
macro(Objects, MallocHeap, objectsMallocHeapMisc) \
- \
- macro(Other, GCHeapUsed, shapesGCHeapTree) \
- macro(Other, GCHeapUsed, shapesGCHeapDict) \
- macro(Other, GCHeapUsed, shapesGCHeapBase) \
- macro(Other, MallocHeap, shapesMallocHeapTreeTables) \
- macro(Other, MallocHeap, shapesMallocHeapDictTables) \
- macro(Other, MallocHeap, shapesMallocHeapTreeKids)
+ macro(Objects, NonHeap, objectsNonHeapElementsNormal) \
+ macro(Objects, NonHeap, objectsNonHeapElementsShared) \
+ macro(Objects, NonHeap, objectsNonHeapElementsWasm) \
+ macro(Objects, NonHeap, objectsNonHeapCodeWasm)
ClassInfo()
: FOR_EACH_SIZE(ZERO_SIZE)
- dummy()
+ wasmGuardPages(0)
{}
void add(const ClassInfo& other) {
@@ -219,6 +213,55 @@
}
FOR_EACH_SIZE(DECL_SIZE)
+ size_t wasmGuardPages;
+
+#undef FOR_EACH_SIZE
+};
+
+struct ShapeInfo
+{
+#define FOR_EACH_SIZE(macro) \
+ macro(Other, GCHeapUsed, shapesGCHeapTree) \
+ macro(Other, GCHeapUsed, shapesGCHeapDict) \
+ macro(Other, GCHeapUsed, shapesGCHeapBase) \
+ macro(Other, MallocHeap, shapesMallocHeapTreeTables) \
+ macro(Other, MallocHeap, shapesMallocHeapDictTables) \
+ macro(Other, MallocHeap, shapesMallocHeapTreeKids)
+
+ ShapeInfo()
+ : FOR_EACH_SIZE(ZERO_SIZE)
+ dummy()
+ {}
+
+ void add(const ShapeInfo& other) {
+ FOR_EACH_SIZE(ADD_OTHER_SIZE)
+ }
+
+ void subtract(const ShapeInfo& other) {
+ FOR_EACH_SIZE(SUB_OTHER_SIZE)
+ }
+
+ size_t sizeOfAllThings() const {
+ size_t n = 0;
+ FOR_EACH_SIZE(ADD_SIZE_TO_N)
+ return n;
+ }
+
+ size_t sizeOfLiveGCThings() const {
+ size_t n = 0;
+ FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
+ return n;
+ }
+
+ void addToTabSizes(TabSizes* sizes) const {
+ FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
+ }
+
+ void addToServoSizes(ServoSizes *sizes) const {
+ FOR_EACH_SIZE(ADD_TO_SERVO_SIZES)
+ }
+
+ FOR_EACH_SIZE(DECL_SIZE)
int dummy; // present just to absorb the trailing comma from FOR_EACH_SIZE(ZERO_SIZE)
#undef FOR_EACH_SIZE
@@ -282,7 +325,6 @@
#define FOR_EACH_SIZE(macro) \
macro(_, MallocHeap, marker) \
macro(_, NonHeap, nurseryCommitted) \
- macro(_, NonHeap, nurseryDecommitted) \
macro(_, MallocHeap, nurseryMallocedBuffers) \
macro(_, MallocHeap, storeBufferVals) \
macro(_, MallocHeap, storeBufferCells) \
@@ -396,8 +438,6 @@
struct ScriptSourceInfo
{
#define FOR_EACH_SIZE(macro) \
- macro(_, MallocHeap, compressed) \
- macro(_, MallocHeap, uncompressed) \
macro(_, MallocHeap, misc)
ScriptSourceInfo()
@@ -468,12 +508,12 @@
macro(_, MallocHeap, object) \
macro(_, MallocHeap, atomsTable) \
macro(_, MallocHeap, contexts) \
- macro(_, MallocHeap, dtoa) \
macro(_, MallocHeap, temporary) \
macro(_, MallocHeap, interpreterStack) \
macro(_, MallocHeap, mathCache) \
+ macro(_, MallocHeap, sharedImmutableStringsCache) \
+ macro(_, MallocHeap, sharedIntlData) \
macro(_, MallocHeap, uncompressedSourceCache) \
- macro(_, MallocHeap, compressedSourceSet) \
macro(_, MallocHeap, scriptData)
RuntimeSizes()
@@ -537,6 +577,7 @@
macro(Other, GCHeapUnused, string) \
macro(Other, GCHeapUnused, symbol) \
macro(Other, GCHeapUnused, jitcode) \
+ macro(Other, GCHeapUnused, scope)
UnusedGCThingSizes()
: FOR_EACH_SIZE(ZERO_SIZE)
@@ -559,6 +600,7 @@
case JS::TraceKind::JitCode: jitcode += n; break;
case JS::TraceKind::LazyScript: lazyScript += n; break;
case JS::TraceKind::ObjectGroup: objectGroup += n; break;
+ case JS::TraceKind::Scope: scope += n; break;
default:
MOZ_CRASH("Bad trace kind for UnusedGCThingSizes");
}
@@ -598,14 +640,18 @@
macro(Other, GCHeapUsed, jitCodesGCHeap) \
macro(Other, GCHeapUsed, objectGroupsGCHeap) \
macro(Other, MallocHeap, objectGroupsMallocHeap) \
+ macro(Other, GCHeapUsed, scopesGCHeap) \
+ macro(Other, MallocHeap, scopesMallocHeap) \
macro(Other, MallocHeap, typePool) \
macro(Other, MallocHeap, baselineStubsOptimized) \
- macro(Other, MallocHeap, uniqueIdMap)
+ macro(Other, MallocHeap, uniqueIdMap) \
+ macro(Other, MallocHeap, shapeTables)
ZoneStats()
: FOR_EACH_SIZE(ZERO_SIZE)
unusedGCThings(),
stringInfo(),
+ shapeInfo(),
extra(),
allStrings(nullptr),
notableStrings(),
@@ -616,6 +662,7 @@
: FOR_EACH_SIZE(COPY_OTHER_SIZE)
unusedGCThings(mozilla::Move(other.unusedGCThings)),
stringInfo(mozilla::Move(other.stringInfo)),
+ shapeInfo(mozilla::Move(other.shapeInfo)),
extra(other.extra),
allStrings(other.allStrings),
notableStrings(mozilla::Move(other.notableStrings)),
@@ -639,6 +686,7 @@
FOR_EACH_SIZE(ADD_OTHER_SIZE)
unusedGCThings.addSizes(other.unusedGCThings);
stringInfo.add(other.stringInfo);
+ shapeInfo.add(other.shapeInfo);
}
size_t sizeOfLiveGCThings() const {
@@ -646,6 +694,7 @@
size_t n = 0;
FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
n += stringInfo.sizeOfLiveGCThings();
+ n += shapeInfo.sizeOfLiveGCThings();
return n;
}
@@ -654,6 +703,7 @@
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
unusedGCThings.addToTabSizes(sizes);
stringInfo.addToTabSizes(sizes);
+ shapeInfo.addToTabSizes(sizes);
}
void addToServoSizes(JS::ServoSizes *sizes) const {
@@ -661,6 +711,7 @@
FOR_EACH_SIZE(ADD_TO_SERVO_SIZES)
unusedGCThings.addToServoSizes(sizes);
stringInfo.addToServoSizes(sizes);
+ shapeInfo.addToServoSizes(sizes);
}
// These string measurements are initially for all strings. At the end,
@@ -670,6 +721,7 @@
FOR_EACH_SIZE(DECL_SIZE)
UnusedGCThingSizes unusedGCThings;
StringInfo stringInfo;
+ ShapeInfo shapeInfo;
void* extra; // This field can be used by embedders.
typedef js::HashMap<JSString*, StringInfo,
@@ -712,7 +764,10 @@
macro(Other, MallocHeap, crossCompartmentWrappersTable) \
macro(Other, MallocHeap, regexpCompartment) \
macro(Other, MallocHeap, savedStacksSet) \
- macro(Other, MallocHeap, nonSyntacticLexicalScopesTable)
+ macro(Other, MallocHeap, varNamesSet) \
+ macro(Other, MallocHeap, nonSyntacticLexicalScopesTable) \
+ macro(Other, MallocHeap, jitCompartment) \
+ macro(Other, MallocHeap, privateData)
CompartmentStats()
: FOR_EACH_SIZE(ZERO_SIZE)
@@ -735,6 +790,8 @@
MOZ_ASSERT(!other.isTotals);
}
+ CompartmentStats(const CompartmentStats&) = delete; // disallow copying
+
~CompartmentStats() {
// |allClasses| is usually deleted and set to nullptr before this
// destructor runs. But there are failure cases due to OOMs that may
@@ -881,23 +938,23 @@
};
extern JS_PUBLIC_API(bool)
-CollectRuntimeStats(JSRuntime* rt, RuntimeStats* rtStats, ObjectPrivateVisitor* opv, bool anonymize);
+CollectRuntimeStats(JSContext* cx, RuntimeStats* rtStats, ObjectPrivateVisitor* opv, bool anonymize);
extern JS_PUBLIC_API(size_t)
-SystemCompartmentCount(JSRuntime* rt);
+SystemCompartmentCount(JSContext* cx);
extern JS_PUBLIC_API(size_t)
-UserCompartmentCount(JSRuntime* rt);
+UserCompartmentCount(JSContext* cx);
extern JS_PUBLIC_API(size_t)
-PeakSizeOfTemporary(const JSRuntime* rt);
+PeakSizeOfTemporary(const JSContext* cx);
extern JS_PUBLIC_API(bool)
-AddSizeOfTab(JSRuntime* rt, JS::HandleObject obj, mozilla::MallocSizeOf mallocSizeOf,
+AddSizeOfTab(JSContext* cx, JS::HandleObject obj, mozilla::MallocSizeOf mallocSizeOf,
ObjectPrivateVisitor* opv, TabSizes* sizes);
extern JS_PUBLIC_API(bool)
-AddServoSizeOf(JSRuntime *rt, mozilla::MallocSizeOf mallocSizeOf,
+AddServoSizeOf(JSContext* cx, mozilla::MallocSizeOf mallocSizeOf,
ObjectPrivateVisitor *opv, ServoSizes *sizes);
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Principals.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Principals.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Principals.h
@@ -18,7 +18,7 @@
#include "js/StructuredClone.h"
namespace js {
- struct PerformanceGroup;
+ struct JS_PUBLIC_API(PerformanceGroup);
} // namespace js
struct JSPrincipals {
@@ -55,7 +55,7 @@
JS_HoldPrincipals(JSPrincipals* principals);
extern JS_PUBLIC_API(void)
-JS_DropPrincipals(JSRuntime* rt, JSPrincipals* principals);
+JS_DropPrincipals(JSContext* cx, JSPrincipals* principals);
// Return whether the first principal subsumes the second. The exact meaning of
// 'subsumes' is left up to the browser. Subsumption is checked inside the JS
@@ -76,10 +76,10 @@
};
extern JS_PUBLIC_API(void)
-JS_SetSecurityCallbacks(JSRuntime* rt, const JSSecurityCallbacks* callbacks);
+JS_SetSecurityCallbacks(JSContext* cx, const JSSecurityCallbacks* callbacks);
extern JS_PUBLIC_API(const JSSecurityCallbacks*)
-JS_GetSecurityCallbacks(JSRuntime* rt);
+JS_GetSecurityCallbacks(JSContext* cx);
/*
* Code running with "trusted" principals will be given a deeper stack
@@ -87,14 +87,14 @@
* untrusted script has exhausted the stack. This function sets the
* runtime-wide trusted principal.
*
- * This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals) since
- * there is no available JSContext. Instead, the caller must ensure that the
- * given principals stays valid for as long as 'rt' may point to it. If the
- * principals would be destroyed before 'rt', JS_SetTrustedPrincipals must be
- * called again, passing nullptr for 'prin'.
+ * This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals).
+ * Instead, the caller must ensure that the given principals stays valid for as
+ * long as 'cx' may point to it. If the principals would be destroyed before
+ * 'cx', JS_SetTrustedPrincipals must be called again, passing nullptr for
+ * 'prin'.
*/
extern JS_PUBLIC_API(void)
-JS_SetTrustedPrincipals(JSRuntime* rt, JSPrincipals* prin);
+JS_SetTrustedPrincipals(JSContext* cx, JSPrincipals* prin);
typedef void
(* JSDestroyPrincipalsOp)(JSPrincipals* principals);
@@ -105,7 +105,7 @@
* only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
-JS_InitDestroyPrincipalsCallback(JSRuntime* rt, JSDestroyPrincipalsOp destroyPrincipals);
+JS_InitDestroyPrincipalsCallback(JSContext* cx, JSDestroyPrincipalsOp destroyPrincipals);
/*
* Read a JSPrincipals instance from the given |reader| and initialize the out
@@ -126,7 +126,7 @@
* buffer. The initialization can be done only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
-JS_InitReadPrincipalsCallback(JSRuntime* rt, JSReadPrincipalsOp read);
+JS_InitReadPrincipalsCallback(JSContext* cx, JSReadPrincipalsOp read);
#endif /* js_Principals_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/ProfilingFrameIterator.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/ProfilingFrameIterator.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/ProfilingFrameIterator.h
@@ -11,20 +11,24 @@
#include "mozilla/Maybe.h"
#include "jsbytecode.h"
+#include "js/GCAPI.h"
#include "js/TypeDecls.h"
#include "js/Utility.h"
+struct JSContext;
struct JSRuntime;
class JSScript;
namespace js {
class Activation;
- class AsmJSProfilingFrameIterator;
namespace jit {
class JitActivation;
class JitProfilingFrameIterator;
class JitcodeGlobalEntry;
} // namespace jit
+ namespace wasm {
+ class ProfilingFrameIterator;
+ } // namespace wasm
} // namespace js
namespace JS {
@@ -36,6 +40,10 @@
// arbitrary pc. To provide acurate results, profiling must have been enabled
// (via EnableRuntimeProfilingStack) before executing the callstack being
// unwound.
+//
+// Note that the caller must not do anything that could cause GC to happen while
+// the iterator is alive, since this could invalidate Ion code and cause its
+// contents to become out of date.
class JS_PUBLIC_API(ProfilingFrameIterator)
{
JSRuntime* rt_;
@@ -47,17 +55,19 @@
// activation (if any) comes around.
void* savedPrevJitTop_;
+ JS::AutoCheckCannotGC nogc_;
+
static const unsigned StorageSpace = 8 * sizeof(void*);
mozilla::AlignedStorage<StorageSpace> storage_;
- js::AsmJSProfilingFrameIterator& asmJSIter() {
+ js::wasm::ProfilingFrameIterator& wasmIter() {
MOZ_ASSERT(!done());
- MOZ_ASSERT(isAsmJS());
- return *reinterpret_cast<js::AsmJSProfilingFrameIterator*>(storage_.addr());
+ MOZ_ASSERT(isWasm());
+ return *reinterpret_cast<js::wasm::ProfilingFrameIterator*>(storage_.addr());
}
- const js::AsmJSProfilingFrameIterator& asmJSIter() const {
+ const js::wasm::ProfilingFrameIterator& wasmIter() const {
MOZ_ASSERT(!done());
- MOZ_ASSERT(isAsmJS());
- return *reinterpret_cast<const js::AsmJSProfilingFrameIterator*>(storage_.addr());
+ MOZ_ASSERT(isWasm());
+ return *reinterpret_cast<const js::wasm::ProfilingFrameIterator*>(storage_.addr());
}
js::jit::JitProfilingFrameIterator& jitIter() {
@@ -87,7 +97,7 @@
void* lr;
};
- ProfilingFrameIterator(JSRuntime* rt, const RegisterState& state,
+ ProfilingFrameIterator(JSContext* cx, const RegisterState& state,
uint32_t sampleBufferGen = UINT32_MAX);
~ProfilingFrameIterator();
void operator++();
@@ -104,7 +114,7 @@
{
Frame_Baseline,
Frame_Ion,
- Frame_AsmJS
+ Frame_Wasm
};
struct Frame
@@ -113,10 +123,10 @@
void* stackAddress;
void* returnAddress;
void* activation;
- const char* label;
+ UniqueChars label;
};
- bool isAsmJS() const;
+ bool isWasm() const;
bool isJit() const;
uint32_t extractStack(Frame* frames, uint32_t offset, uint32_t end) const;
@@ -133,7 +143,7 @@
};
JS_FRIEND_API(bool)
-IsProfilingEnabledForRuntime(JSRuntime* runtime);
+IsProfilingEnabledForContext(JSContext* cx);
/**
* After each sample run, this method should be called with the latest sample
@@ -144,7 +154,7 @@
* JSRuntime for documentation about what these values are used for.
*/
JS_FRIEND_API(void)
-UpdateJSRuntimeProfilerSampleBufferGen(JSRuntime* runtime, uint32_t generation,
+UpdateJSContextProfilerSampleBufferGen(JSContext* cx, uint32_t generation,
uint32_t lapCount);
struct ForEachProfiledFrameOp
@@ -153,7 +163,7 @@
// lookups on JitcodeGlobalTable.
class MOZ_STACK_CLASS FrameHandle
{
- friend JS_PUBLIC_API(void) ForEachProfiledFrame(JSRuntime* rt, void* addr,
+ friend JS_PUBLIC_API(void) ForEachProfiledFrame(JSContext* cx, void* addr,
ForEachProfiledFrameOp& op);
JSRuntime* rt_;
@@ -175,10 +185,13 @@
bool hasTrackedOptimizations() const { return optsIndex_.isSome(); }
void* canonicalAddress() const { return canonicalAddr_; }
- ProfilingFrameIterator::FrameKind frameKind() const;
- void forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op,
- JSScript** scriptOut, jsbytecode** pcOut) const;
- void forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const;
+ JS_PUBLIC_API(ProfilingFrameIterator::FrameKind) frameKind() const;
+ JS_PUBLIC_API(void) forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op,
+ JSScript** scriptOut,
+ jsbytecode** pcOut) const;
+
+ JS_PUBLIC_API(void)
+ forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const;
};
// Called once per frame.
@@ -186,7 +199,7 @@
};
JS_PUBLIC_API(void)
-ForEachProfiledFrame(JSRuntime* rt, void* addr, ForEachProfiledFrameOp& op);
+ForEachProfiledFrame(JSContext* cx, void* addr, ForEachProfiledFrameOp& op);
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/ProfilingStack.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/ProfilingStack.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/ProfilingStack.h
@@ -14,6 +14,7 @@
#include "js/Utility.h"
struct JSRuntime;
+class JSTracer;
namespace js {
@@ -42,14 +43,14 @@
void * volatile spOrScript;
// Line number for non-JS entries, the bytecode offset otherwise.
- int32_t volatile lineOrPc;
+ int32_t volatile lineOrPcOffset;
// General purpose storage describing this frame.
uint32_t volatile flags_;
public:
// These traits are bit masks. Make sure they're powers of 2.
- enum Flags {
+ enum Flags : uint32_t {
// Indicate whether a profile entry represents a CPP frame. If not set,
// a JS frame is assumed by default. You're not allowed to publicly
// change the frame type. Instead, initialize the ProfileEntry as either
@@ -75,7 +76,7 @@
CATEGORY_MASK = ~ALL
};
- // Keep these in sync with devtools/client/performance/modules/global.js
+ // Keep these in sync with devtools/client/performance/modules/categories.js
enum class Category : uint32_t {
OTHER = 0x10,
CSS = 0x20,
@@ -115,7 +116,7 @@
void initCppFrame(void* aSp, uint32_t aLine) volatile {
flags_ = IS_CPP_ENTRY;
spOrScript = aSp;
- lineOrPc = static_cast<int32_t>(aLine);
+ lineOrPcOffset = static_cast<int32_t>(aLine);
}
void setFlag(uint32_t flag) volatile {
@@ -160,19 +161,24 @@
MOZ_ASSERT(!isJs());
return spOrScript;
}
- JSScript* script() const volatile {
- MOZ_ASSERT(isJs());
- return (JSScript*)spOrScript;
- }
+ JS_PUBLIC_API(JSScript*) script() const volatile;
uint32_t line() const volatile {
MOZ_ASSERT(!isJs());
- return static_cast<uint32_t>(lineOrPc);
+ return static_cast<uint32_t>(lineOrPcOffset);
+ }
+
+ // Note that the pointer returned might be invalid.
+ JSScript* rawScript() const volatile {
+ MOZ_ASSERT(isJs());
+ return (JSScript*)spOrScript;
}
// We can't know the layout of JSScript, so look in vm/SPSProfiler.cpp.
JS_FRIEND_API(jsbytecode*) pc() const volatile;
JS_FRIEND_API(void) setPC(jsbytecode* pc) volatile;
+ void trace(JSTracer* trc);
+
// The offset of a pc into a script's code can actually be 0, so to
// signify a nullptr pc, use a -1 index. This is checked against in
// pc() and setPC() to set/get the right pc.
@@ -180,22 +186,22 @@
static size_t offsetOfLabel() { return offsetof(ProfileEntry, string); }
static size_t offsetOfSpOrScript() { return offsetof(ProfileEntry, spOrScript); }
- static size_t offsetOfLineOrPc() { return offsetof(ProfileEntry, lineOrPc); }
+ static size_t offsetOfLineOrPcOffset() { return offsetof(ProfileEntry, lineOrPcOffset); }
static size_t offsetOfFlags() { return offsetof(ProfileEntry, flags_); }
};
JS_FRIEND_API(void)
-SetRuntimeProfilingStack(JSRuntime* rt, ProfileEntry* stack, uint32_t* size,
+SetContextProfilingStack(JSContext* cx, ProfileEntry* stack, uint32_t* size,
uint32_t max);
JS_FRIEND_API(void)
-EnableRuntimeProfilingStack(JSRuntime* rt, bool enabled);
+EnableContextProfilingStack(JSContext* cx, bool enabled);
JS_FRIEND_API(void)
-RegisterRuntimeProfilingEventMarker(JSRuntime* rt, void (*fn)(const char*));
+RegisterContextProfilingEventMarker(JSContext* cx, void (*fn)(const char*));
JS_FRIEND_API(jsbytecode*)
-ProfilingGetPC(JSRuntime* rt, JSScript* script, void* ip);
+ProfilingGetPC(JSContext* cx, JSScript* script, void* ip);
} // namespace js
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Proxy.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Proxy.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Proxy.h
@@ -29,6 +29,7 @@
using JS::NativeImpl;
using JS::ObjectOpResult;
using JS::PrivateValue;
+using JS::PropertyDescriptor;
using JS::Value;
class RegExpGuard;
@@ -58,16 +59,15 @@
*
* ### Proxies and internal methods
*
- * ES6 draft rev 27 (24 August 2014) specifies 14 internal methods. The runtime
- * semantics of just about everything a script can do to an object is specified
- * in terms of these internal methods. For example:
+ * ES2016 specifies 13 internal methods. The runtime semantics of just
+ * about everything a script can do to an object is specified in terms
+ * of these internal methods. For example:
*
* JS code ES6 internal method that gets called
* --------------------------- --------------------------------
* obj.prop obj.[[Get]](obj, "prop")
* "prop" in obj obj.[[HasProperty]]("prop")
* new obj() obj.[[Construct]](<empty argument List>)
- * for (k in obj) {} obj.[[Enumerate]]()
*
* With regard to the implementation of these internal methods, there are three
* very different kinds of object in SpiderMonkey.
@@ -101,10 +101,8 @@
*
* BaseProxyHandler
* |
- * DirectProxyHandler // has a target
- * |
- * Wrapper // can be unwrapped, revealing target
- * | // (see js::CheckedUnwrap)
+ * Wrapper // has a target, can be unwrapped to reveal
+ * | // target (see js::CheckedUnwrap)
* |
* CrossCompartmentWrapper // target is in another compartment;
* // implements membrane between compartments
@@ -191,7 +189,7 @@
bool mHasSecurityPolicy;
public:
- explicit MOZ_CONSTEXPR BaseProxyHandler(const void* aFamily, bool aHasPrototype = false,
+ explicit constexpr BaseProxyHandler(const void* aFamily, bool aHasPrototype = false,
bool aHasSecurityPolicy = false)
: mFamily(aFamily),
mHasPrototype(aHasPrototype),
@@ -213,7 +211,7 @@
return offsetof(BaseProxyHandler, mFamily);
}
- virtual bool finalizeInBackground(Value priv) const {
+ virtual bool finalizeInBackground(const Value& priv) const {
/*
* Called on creation of a proxy to determine whether its finalize
* method can be finalized on the background thread.
@@ -221,6 +219,14 @@
return true;
}
+ virtual bool canNurseryAllocate() const {
+ /*
+ * Nursery allocation is allowed if and only if it is safe to not
+ * run |finalize| when the ProxyObject dies.
+ */
+ return false;
+ }
+
/* Policy enforcement methods.
*
* enter() allows the policy to specify whether the caller may perform |act|
@@ -251,9 +257,9 @@
/* Standard internal methods. */
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const = 0;
+ MutableHandle<PropertyDescriptor> desc) const = 0;
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
- Handle<JSPropertyDescriptor> desc,
+ Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const = 0;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const = 0;
@@ -261,14 +267,6 @@
ObjectOpResult& result) const = 0;
/*
- * Because [[Enumerate]] is one of the standard traps it should be overridden.
- * However for convenience BaseProxyHandler includes a pure virtual implementation,
- * that turns the properties returned by getOwnEnumerablePropertyKeys (and proto walking)
- * into an Iterator object.
- */
- virtual bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const = 0;
-
- /*
* These methods are standard, but the engine does not normally call them.
* They're opt-in. See "Proxy prototype chains" above.
*
@@ -278,7 +276,9 @@
virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
ObjectOpResult& result) const;
- /* Non-standard but conceptual kin to {g,s}etPrototype, so lives here. */
+ /* Non-standard but conceptual kin to {g,s}etPrototype, so these live here. */
+ virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
+ MutableHandleObject protop) const = 0;
virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy, bool* succeeded) const;
virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
@@ -314,8 +314,9 @@
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const;
/* SpiderMonkey extensions. */
+ virtual bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const;
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const;
+ MutableHandle<PropertyDescriptor> desc) const;
virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const;
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const;
@@ -323,7 +324,7 @@
const CallArgs& args) const;
virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v, bool* bp) const;
virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy,
- ESClassValue* classValue) const;
+ ESClass* cls) const;
virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const;
virtual const char* className(JSContext* cx, HandleObject proxy) const;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const;
@@ -354,79 +355,6 @@
virtual bool isScripted() const { return false; }
};
-/*
- * DirectProxyHandler includes a notion of a target object. All methods are
- * reimplemented such that they forward their behavior to the target. This
- * allows consumers of this class to forward to another object as transparently
- * and efficiently as possible.
- *
- * Important: If you add a method implementation here, you probably also need
- * to add an override in CrossCompartmentWrapper. If you don't, you risk
- * compartment mismatches. See bug 945826 comment 0.
- */
-class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
-{
- public:
- explicit MOZ_CONSTEXPR DirectProxyHandler(const void* aFamily, bool aHasPrototype = false,
- bool aHasSecurityPolicy = false)
- : BaseProxyHandler(aFamily, aHasPrototype, aHasSecurityPolicy)
- { }
-
- /* Standard internal methods. */
- virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
- virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
- Handle<JSPropertyDescriptor> desc,
- ObjectOpResult& result) const override;
- virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
- AutoIdVector& props) const override;
- virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
- ObjectOpResult& result) const override;
- virtual bool enumerate(JSContext* cx, HandleObject proxy,
- MutableHandleObject objp) const override;
- virtual bool getPrototype(JSContext* cx, HandleObject proxy,
- MutableHandleObject protop) const override;
- virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
- ObjectOpResult& result) const override;
- virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
- bool* succeeded) const override;
- virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
- ObjectOpResult& result) const override;
- virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
- virtual bool has(JSContext* cx, HandleObject proxy, HandleId id,
- bool* bp) const override;
- virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
- HandleId id, MutableHandleValue vp) const override;
- virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
- HandleValue receiver, ObjectOpResult& result) const override;
- virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
- virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
-
- /* SpiderMonkey extensions. */
- virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
- virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id,
- bool* bp) const override;
- virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
- AutoIdVector& props) const override;
- virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
- const CallArgs& args) const override;
- virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
- bool* bp) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy,
- ESClassValue* classValue) const override;
- virtual bool isArray(JSContext* cx, HandleObject proxy,
- JS::IsArrayAnswer* answer) const override;
- virtual const char* className(JSContext* cx, HandleObject proxy) const override;
- virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
- unsigned indent) const override;
- virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
- RegExpGuard* g) const override;
- virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
- virtual bool isCallable(JSObject* obj) const override;
- virtual JSObject* weakmapKeyDelegate(JSObject* proxy) const override;
-};
-
extern JS_FRIEND_DATA(const js::Class* const) ProxyClassPtr;
inline bool IsProxy(const JSObject* obj)
@@ -434,6 +362,7 @@
return GetObjectClass(obj)->isProxy();
}
+namespace detail {
const uint32_t PROXY_EXTRA_SLOTS = 2;
// Layout of the values stored by a proxy. Note that API clients require the
@@ -470,7 +399,6 @@
const uint32_t ProxyDataOffset = 2 * sizeof(void*);
-// This method should only be used internally and by the accessors below.
inline ProxyDataLayout*
GetProxyDataLayout(JSObject* obj)
{
@@ -478,16 +406,25 @@
return reinterpret_cast<ProxyDataLayout*>(reinterpret_cast<uint8_t*>(obj) + ProxyDataOffset);
}
+inline const ProxyDataLayout*
+GetProxyDataLayout(const JSObject* obj)
+{
+ MOZ_ASSERT(IsProxy(obj));
+ return reinterpret_cast<const ProxyDataLayout*>(reinterpret_cast<const uint8_t*>(obj) +
+ ProxyDataOffset);
+}
+} // namespace detail
+
inline const BaseProxyHandler*
-GetProxyHandler(JSObject* obj)
+GetProxyHandler(const JSObject* obj)
{
- return GetProxyDataLayout(obj)->handler;
+ return detail::GetProxyDataLayout(obj)->handler;
}
inline const Value&
-GetProxyPrivate(JSObject* obj)
+GetProxyPrivate(const JSObject* obj)
{
- return GetProxyDataLayout(obj)->values->privateSlot;
+ return detail::GetProxyDataLayout(obj)->values->privateSlot;
}
inline JSObject*
@@ -497,16 +434,16 @@
}
inline const Value&
-GetProxyExtra(JSObject* obj, size_t n)
+GetProxyExtra(const JSObject* obj, size_t n)
{
- MOZ_ASSERT(n < PROXY_EXTRA_SLOTS);
- return GetProxyDataLayout(obj)->values->extraSlots[n];
+ MOZ_ASSERT(n < detail::PROXY_EXTRA_SLOTS);
+ return detail::GetProxyDataLayout(obj)->values->extraSlots[n];
}
inline void
SetProxyHandler(JSObject* obj, const BaseProxyHandler* handler)
{
- GetProxyDataLayout(obj)->handler = handler;
+ detail::GetProxyDataLayout(obj)->handler = handler;
}
JS_FRIEND_API(void)
@@ -515,8 +452,8 @@
inline void
SetProxyExtra(JSObject* obj, size_t n, const Value& extra)
{
- MOZ_ASSERT(n < PROXY_EXTRA_SLOTS);
- Value* vp = &GetProxyDataLayout(obj)->values->extraSlots[n];
+ MOZ_ASSERT(n < detail::PROXY_EXTRA_SLOTS);
+ Value* vp = &detail::GetProxyDataLayout(obj)->values->extraSlots[n];
// Trigger a barrier before writing the slot.
if (vp->isMarkable() || extra.isMarkable())
@@ -526,13 +463,13 @@
}
inline bool
-IsScriptedProxy(JSObject* obj)
+IsScriptedProxy(const JSObject* obj)
{
return IsProxy(obj) && GetProxyHandler(obj)->isScripted();
}
inline const Value&
-GetReservedOrProxyPrivateSlot(JSObject* obj, size_t slot)
+GetReservedOrProxyPrivateSlot(const JSObject* obj, size_t slot)
{
MOZ_ASSERT(slot == 0);
MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)) || IsProxy(obj));
@@ -597,7 +534,7 @@
JSObject* proto, const ProxyOptions& options = ProxyOptions());
JSObject*
-RenewProxyObject(JSContext* cx, JSObject* obj, BaseProxyHandler* handler, Value priv);
+RenewProxyObject(JSContext* cx, JSObject* obj, BaseProxyHandler* handler, const Value& priv);
class JS_FRIEND_API(AutoEnterPolicy)
{
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Realm.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Realm.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Realm.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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/. */
+
+/*
+ * Ways to get various per-Realm objects. All the getters declared in this
+ * header operate on the Realm corresponding to the current compartment on the
+ * JSContext.
+ */
+
+#ifndef js_Realm_h
+#define js_Realm_h
+
+#include "jstypes.h"
+
+struct JSContext;
+class JSObject;
+
+namespace JS {
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmObjectPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmFunctionPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmArrayPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmErrorPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+GetRealmIteratorPrototype(JSContext* cx);
+
+} // namespace JS
+
+#endif // js_Realm_h
+
+
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/RootingAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/RootingAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/RootingAPI.h
@@ -14,11 +14,16 @@
#include "mozilla/Move.h"
#include "mozilla/TypeTraits.h"
+#include <type_traits>
+
#include "jspubtd.h"
+#include "js/GCAnnotations.h"
#include "js/GCAPI.h"
+#include "js/GCPolicyAPI.h"
#include "js/HeapAPI.h"
#include "js/TypeDecls.h"
+#include "js/UniquePtr.h"
#include "js/Utility.h"
/*
@@ -105,8 +110,7 @@
namespace js {
template <typename T>
-struct GCMethods {
- static T initial() { return T(); }
+struct BarrierMethods {
};
template <typename T>
@@ -121,6 +125,14 @@
template <typename T>
class HeapBase {};
+// Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many macros into scope
+template <typename T> struct IsHeapConstructibleType { static constexpr bool value = false; };
+#define DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE(T) \
+ template <> struct IsHeapConstructibleType<T> { static constexpr bool value = true; };
+FOR_EACH_PUBLIC_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
+FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
+#undef DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
+
template <typename T>
class PersistentRootedBase {};
@@ -132,14 +144,14 @@
struct PersistentRootedMarker;
} /* namespace gc */
-#define DECLARE_POINTER_COMPARISON_OPS(T) \
+#define DECLARE_POINTER_COMPARISON_OPS(T) \
bool operator==(const T& other) const { return get() == other; } \
bool operator!=(const T& other) const { return get() != other; }
// Important: Return a reference so passing a Rooted<T>, etc. to
// something that takes a |const T&| is not a GC hazard.
-#define DECLARE_POINTER_CONSTREF_OPS(T) \
- operator const T&() const { return get(); } \
+#define DECLARE_POINTER_CONSTREF_OPS(T) \
+ operator const T&() const { return get(); } \
const T& operator->() const { return get(); }
// Assignment operators on a base class are hidden by the implicitly defined
@@ -150,12 +162,16 @@
set(p); \
return *this; \
} \
+ Wrapper<T>& operator=(T&& p) { \
+ set(mozilla::Move(p)); \
+ return *this; \
+ } \
Wrapper<T>& operator=(const Wrapper<T>& other) { \
set(other.get()); \
return *this; \
} \
-#define DELETE_ASSIGNMENT_OPS(Wrapper, T) \
+#define DELETE_ASSIGNMENT_OPS(Wrapper, T) \
template <typename S> Wrapper<T>& operator=(S) = delete; \
Wrapper<T>& operator=(const Wrapper<T>&) = delete;
@@ -212,18 +228,21 @@
* Heap<T> objects should only be used on the heap. GC references stored on the
* C/C++ stack must use Rooted/Handle/MutableHandle instead.
*
- * Type T must be one of: JS::Value, jsid, JSObject*, JSString*, JSScript*
+ * Type T must be a public GC pointer type.
*/
template <typename T>
-class Heap : public js::HeapBase<T>
+class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T>
{
+ // Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for legacy reasons.
+ static_assert(js::IsHeapConstructibleType<T>::value,
+ "Type T must be a public GC pointer type");
public:
Heap() {
static_assert(sizeof(T) == sizeof(Heap<T>),
"Heap<T> must be binary compatible with T.");
- init(js::GCMethods<T>::initial());
+ init(GCPolicy<T>::initial());
}
- explicit Heap(T p) { init(p); }
+ explicit Heap(const T& p) { init(p); }
/*
* For Heap, move semantics are equivalent to copy semantics. In C++, a
@@ -234,50 +253,91 @@
explicit Heap(const Heap<T>& p) { init(p.ptr); }
~Heap() {
- post(ptr, js::GCMethods<T>::initial());
+ post(ptr, GCPolicy<T>::initial());
}
DECLARE_POINTER_CONSTREF_OPS(T);
DECLARE_POINTER_ASSIGN_OPS(Heap, T);
- DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr);
- T* unsafeGet() { return &ptr; }
+ const T* address() const { return &ptr; }
- /*
- * Set the pointer to a value which will cause a crash if it is
- * dereferenced.
- */
- void setToCrashOnTouch() {
- ptr = reinterpret_cast<T>(crashOnTouchPointer);
+ void exposeToActiveJS() const {
+ js::BarrierMethods<T>::exposeToJS(ptr);
+ }
+ const T& get() const {
+ exposeToActiveJS();
+ return ptr;
+ }
+ const T& unbarrieredGet() const {
+ return ptr;
}
- bool isSetToCrashOnTouch() {
- return ptr == crashOnTouchPointer;
+ T* unsafeGet() { return &ptr; }
+
+ explicit operator bool() const {
+ return bool(js::BarrierMethods<T>::asGCThingOrNull(ptr));
+ }
+ explicit operator bool() {
+ return bool(js::BarrierMethods<T>::asGCThingOrNull(ptr));
}
private:
- void init(T newPtr) {
+ void init(const T& newPtr) {
ptr = newPtr;
- post(js::GCMethods<T>::initial(), ptr);
+ post(GCPolicy<T>::initial(), ptr);
}
- void set(T newPtr) {
+ void set(const T& newPtr) {
T tmp = ptr;
ptr = newPtr;
post(tmp, ptr);
}
void post(const T& prev, const T& next) {
- js::GCMethods<T>::postBarrier(&ptr, prev, next);
+ js::BarrierMethods<T>::postBarrier(&ptr, prev, next);
}
- enum {
- crashOnTouchPointer = 1
- };
-
T ptr;
};
+static MOZ_ALWAYS_INLINE bool
+ObjectIsTenured(JSObject* obj)
+{
+ return !js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(obj));
+}
+
+static MOZ_ALWAYS_INLINE bool
+ObjectIsTenured(const Heap<JSObject*>& obj)
+{
+ return ObjectIsTenured(obj.unbarrieredGet());
+}
+
+static MOZ_ALWAYS_INLINE bool
+ObjectIsMarkedGray(JSObject* obj)
+{
+ auto cell = reinterpret_cast<js::gc::Cell*>(obj);
+ return js::gc::detail::CellIsMarkedGrayIfKnown(cell);
+}
+
+static MOZ_ALWAYS_INLINE bool
+ObjectIsMarkedGray(const JS::Heap<JSObject*>& obj)
+{
+ return ObjectIsMarkedGray(obj.unbarrieredGet());
+}
+
+static MOZ_ALWAYS_INLINE bool
+ScriptIsMarkedGray(JSScript* script)
+{
+ auto cell = reinterpret_cast<js::gc::Cell*>(script);
+ return js::gc::detail::CellIsMarkedGrayIfKnown(cell);
+}
+
+static MOZ_ALWAYS_INLINE bool
+ScriptIsMarkedGray(const Heap<JSScript*>& script)
+{
+ return ScriptIsMarkedGray(script.unbarrieredGet());
+}
+
/**
* The TenuredHeap<T> class is similar to the Heap<T> class above in that it
* encapsulates the GC concerns of an on-heap reference to a JS object. However,
@@ -343,12 +403,27 @@
return (bits & flag) != 0;
}
- T getPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
+ T unbarrieredGetPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
uintptr_t getFlags() const { return bits & flagsMask; }
+ void exposeToActiveJS() const {
+ js::BarrierMethods<T>::exposeToJS(unbarrieredGetPtr());
+ }
+ T getPtr() const {
+ exposeToActiveJS();
+ return unbarrieredGetPtr();
+ }
+
operator T() const { return getPtr(); }
T operator->() const { return getPtr(); }
+ explicit operator bool() const {
+ return bool(js::BarrierMethods<T>::asGCThingOrNull(unbarrieredGetPtr()));
+ }
+ explicit operator bool() {
+ return bool(js::BarrierMethods<T>::asGCThingOrNull(unbarrieredGetPtr()));
+ }
+
TenuredHeap<T>& operator=(T p) {
setPtr(p);
return *this;
@@ -417,7 +492,7 @@
* for the lifetime of the handle, as its users may not expect its value
* to change underneath them.
*/
- static MOZ_CONSTEXPR Handle fromMarkedLocation(const T* p) {
+ static constexpr Handle fromMarkedLocation(const T* p) {
return Handle(p, DeliberatelyChoosingThisOverload,
ImUsingThisOnlyInFromFromMarkedLocation);
}
@@ -452,7 +527,7 @@
enum Disambiguator { DeliberatelyChoosingThisOverload = 42 };
enum CallerIdentity { ImUsingThisOnlyInFromFromMarkedLocation = 17 };
- MOZ_CONSTEXPR Handle(const T* p, Disambiguator, CallerIdentity) : ptr(p) {}
+ constexpr Handle(const T* p, Disambiguator, CallerIdentity) : ptr(p) {}
const T* ptr;
};
@@ -477,9 +552,12 @@
MutableHandle(decltype(nullptr)) = delete;
public:
- void set(T v) {
+ void set(const T& v) {
*ptr = v;
}
+ void set(T&& v) {
+ *ptr = mozilla::Move(v);
+ }
/*
* This may be called only if the location of the T is guaranteed
@@ -509,36 +587,28 @@
namespace js {
-/**
- * By default, things should use the inheritance hierarchy to find their
- * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
- * Rooted<T> may be used without the class definition being available.
- */
-template <typename T>
-struct RootKind
-{
- static ThingRootKind rootKind() { return T::rootKind(); }
-};
-
-template <typename T>
-struct RootKind<T*>
-{
- static ThingRootKind rootKind() { return T::rootKind(); }
-};
-
template <typename T>
-struct GCMethods<T*>
+struct BarrierMethods<T*>
{
static T* initial() { return nullptr; }
+ static gc::Cell* asGCThingOrNull(T* v) {
+ if (!v)
+ return nullptr;
+ MOZ_ASSERT(uintptr_t(v) > 32);
+ return reinterpret_cast<gc::Cell*>(v);
+ }
static void postBarrier(T** vp, T* prev, T* next) {
if (next)
JS::AssertGCThingIsNotAnObjectSubclass(reinterpret_cast<js::gc::Cell*>(next));
}
- static void relocate(T** vp) {}
+ static void exposeToJS(T* t) {
+ if (t)
+ js::gc::ExposeGCThingToActiveJS(JS::GCCellPtr(t));
+ }
};
template <>
-struct GCMethods<JSObject*>
+struct BarrierMethods<JSObject*>
{
static JSObject* initial() { return nullptr; }
static gc::Cell* asGCThingOrNull(JSObject* v) {
@@ -550,17 +620,31 @@
static void postBarrier(JSObject** vp, JSObject* prev, JSObject* next) {
JS::HeapObjectPostBarrier(vp, prev, next);
}
+ static void exposeToJS(JSObject* obj) {
+ if (obj)
+ JS::ExposeObjectToActiveJS(obj);
+ }
};
template <>
-struct GCMethods<JSFunction*>
+struct BarrierMethods<JSFunction*>
{
static JSFunction* initial() { return nullptr; }
+ static gc::Cell* asGCThingOrNull(JSFunction* v) {
+ if (!v)
+ return nullptr;
+ MOZ_ASSERT(uintptr_t(v) > 32);
+ return reinterpret_cast<gc::Cell*>(v);
+ }
static void postBarrier(JSFunction** vp, JSFunction* prev, JSFunction* next) {
JS::HeapObjectPostBarrier(reinterpret_cast<JSObject**>(vp),
reinterpret_cast<JSObject*>(prev),
reinterpret_cast<JSObject*>(next));
}
+ static void exposeToJS(JSFunction* fun) {
+ if (fun)
+ JS::ExposeObjectToActiveJS(reinterpret_cast<JSObject*>(fun));
+ }
};
// Provide hash codes for Cell kinds that may be relocated and, thus, not have
@@ -580,6 +664,8 @@
using Key = T;
using Lookup = T;
+ static bool hasHash(const Lookup& l);
+ static bool ensureHash(const Lookup& l);
static HashNumber hash(const Lookup& l);
static bool match(const Key& k, const Lookup& l);
static void rekey(Key& k, const Key& newKey) { k = newKey; }
@@ -591,47 +677,52 @@
using Key = JS::Heap<T>;
using Lookup = T;
+ static bool hasHash(const Lookup& l) { return MovableCellHasher<T>::hasHash(l); }
+ static bool ensureHash(const Lookup& l) { return MovableCellHasher<T>::ensureHash(l); }
static HashNumber hash(const Lookup& l) { return MovableCellHasher<T>::hash(l); }
- static bool match(const Key& k, const Lookup& l) { return MovableCellHasher<T>::match(k, l); }
+ static bool match(const Key& k, const Lookup& l) {
+ return MovableCellHasher<T>::match(k.unbarrieredGet(), l);
+ }
static void rekey(Key& k, const Key& newKey) { k.unsafeSet(newKey); }
};
-} /* namespace js */
-
-namespace JS {
-
-// Non pointer types -- structs or classes that contain GC pointers, either as
-// a member or in a more complex container layout -- can also be stored in a
-// [Persistent]Rooted if it derives from JS::Traceable. A JS::Traceable stored
-// in a [Persistent]Rooted must implement the method:
-// |static void trace(T*, JSTracer*)|
-class Traceable
+template <typename T>
+struct FallibleHashMethods<MovableCellHasher<T>>
{
- public:
- static js::ThingRootKind rootKind() { return js::THING_ROOT_TRACEABLE; }
+ template <typename Lookup> static bool hasHash(Lookup&& l) {
+ return MovableCellHasher<T>::hasHash(mozilla::Forward<Lookup>(l));
+ }
+ template <typename Lookup> static bool ensureHash(Lookup&& l) {
+ return MovableCellHasher<T>::ensureHash(mozilla::Forward<Lookup>(l));
+ }
};
-} /* namespace JS */
+} /* namespace js */
namespace js {
+// The alignment must be set because the Rooted and PersistentRooted ptr fields
+// may be accessed through reinterpret_cast<Rooted<ConcreteTraceable>*>, and
+// the compiler may choose a different alignment for the ptr field when it
+// knows the actual type stored in DispatchWrapper<T>.
+//
+// It would make more sense to align only those specific fields of type
+// DispatchWrapper, rather than DispatchWrapper itself, but that causes MSVC to
+// fail when Rooted is used in an IsConvertible test.
template <typename T>
-class DispatchWrapper
+class alignas(8) DispatchWrapper
{
- static_assert(mozilla::IsBaseOf<JS::Traceable, T>::value,
+ static_assert(JS::MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
"DispatchWrapper is intended only for usage with a Traceable");
- using TraceFn = void (*)(T*, JSTracer*);
+ using TraceFn = void (*)(JSTracer*, T*, const char*);
TraceFn tracer;
-#if JS_BITS_PER_WORD == 32
- uint32_t padding; // Ensure the storage fields have CellSize alignment.
-#endif
- T storage;
+ alignas(gc::CellSize) T storage;
public:
template <typename U>
MOZ_IMPLICIT DispatchWrapper(U&& initial)
- : tracer(&T::trace),
+ : tracer(&JS::GCPolicy<T>::trace),
storage(mozilla::Forward<U>(initial))
{ }
@@ -643,37 +734,13 @@
// Trace the contained storage (of unknown type) using the trace function
// we set aside when we did know the type.
- static void TraceWrapped(JSTracer* trc, JS::Traceable* thingp, const char* name) {
+ static void TraceWrapped(JSTracer* trc, T* thingp, const char* name) {
auto wrapper = reinterpret_cast<DispatchWrapper*>(
uintptr_t(thingp) - offsetof(DispatchWrapper, storage));
- wrapper->tracer(&wrapper->storage, trc);
+ wrapper->tracer(trc, &wrapper->storage, name);
}
};
-inline RootLists&
-RootListsForRootingContext(JSContext* cx)
-{
- return ContextFriendFields::get(cx)->roots;
-}
-
-inline RootLists&
-RootListsForRootingContext(js::ContextFriendFields* cx)
-{
- return cx->roots;
-}
-
-inline RootLists&
-RootListsForRootingContext(JSRuntime* rt)
-{
- return PerThreadDataFriendFields::getMainThread(rt)->roots;
-}
-
-inline RootLists&
-RootListsForRootingContext(js::PerThreadDataFriendFields* pt)
-{
- return pt->roots;
-}
-
} /* namespace js */
namespace JS {
@@ -689,30 +756,38 @@
template <typename T>
class MOZ_RAII Rooted : public js::RootedBase<T>
{
- static_assert(!mozilla::IsConvertible<T, Traceable*>::value,
- "Rooted takes pointer or Traceable types but not Traceable* type");
-
- /* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */
- void registerWithRootLists(js::RootLists& roots) {
- js::ThingRootKind kind = js::RootKind<T>::rootKind();
- this->stack = &roots.stackRoots_[kind];
+ inline void registerWithRootLists(js::RootedListHeads& roots) {
+ this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
this->prev = *stack;
*stack = reinterpret_cast<Rooted<void*>*>(this);
}
+ inline js::RootedListHeads& rootLists(JS::RootingContext* cx) {
+ return rootLists(static_cast<js::ContextFriendFields*>(cx));
+ }
+ inline js::RootedListHeads& rootLists(js::ContextFriendFields* cx) {
+ if (JS::Zone* zone = cx->zone_)
+ return JS::shadow::Zone::asShadowZone(zone)->stackRoots_;
+ MOZ_ASSERT(cx->isJSContext);
+ return cx->roots.stackRoots_;
+ }
+ inline js::RootedListHeads& rootLists(JSContext* cx) {
+ return rootLists(js::ContextFriendFields::get(cx));
+ }
+
public:
template <typename RootingContext>
explicit Rooted(const RootingContext& cx)
- : ptr(js::GCMethods<T>::initial())
+ : ptr(GCPolicy<T>::initial())
{
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
template <typename RootingContext, typename S>
Rooted(const RootingContext& cx, S&& initial)
: ptr(mozilla::Forward<S>(initial))
{
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
~Rooted() {
@@ -726,9 +801,12 @@
* This method is public for Rooted so that Codegen.py can use a Rooted
* interchangeably with a MutableHandleValue.
*/
- void set(T value) {
+ void set(const T& value) {
ptr = value;
}
+ void set(T&& value) {
+ ptr = mozilla::Move(value);
+ }
DECLARE_POINTER_COMPARISON_OPS(T);
DECLARE_POINTER_CONSTREF_OPS(T);
@@ -747,20 +825,20 @@
/*
* For pointer types, the TraceKind for tracing is based on the list it is
- * in (selected via rootKind), so no additional storage is required here.
- * All Traceable, however, share the same list, so the function to
- * call for tracing is stored adjacent to the struct. Since C++ cannot
- * templatize on storage class, this is implemented via the wrapper class
- * DispatchWrapper.
+ * in (selected via MapTypeToRootKind), so no additional storage is
+ * required here. Non-pointer types, however, share the same list, so the
+ * function to call for tracing is stored adjacent to the struct. Since C++
+ * cannot templatize on storage class, this is implemented via the wrapper
+ * class DispatchWrapper.
*/
using MaybeWrapped = typename mozilla::Conditional<
- mozilla::IsBaseOf<Traceable, T>::value,
+ MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
js::DispatchWrapper<T>,
T>::Type;
MaybeWrapped ptr;
Rooted(const Rooted&) = delete;
-};
+} JS_HAZ_ROOTED;
} /* namespace JS */
@@ -808,7 +886,7 @@
{
public:
template <typename CX>
- explicit FakeRooted(CX* cx) : ptr(GCMethods<T>::initial()) {}
+ explicit FakeRooted(CX* cx) : ptr(JS::GCPolicy<T>::initial()) {}
template <typename CX>
FakeRooted(CX* cx, T initial) : ptr(initial) {}
@@ -842,7 +920,7 @@
ptr = root->address();
}
- void set(T v) {
+ void set(const T& v) {
*ptr = v;
}
@@ -899,7 +977,7 @@
template <typename T> class MaybeRooted<T, NoGC>
{
public:
- typedef T HandleType;
+ typedef const T& HandleType;
typedef FakeRooted<T> RootType;
typedef FakeMutableHandle<T> MutableHandleType;
@@ -970,7 +1048,7 @@
* These roots can be used in heap-allocated data structures, so they are not
* associated with any particular JSContext or stack. They are registered with
* the JSRuntime itself, without locking, so they require a full JSContext to be
- * initialized, not one of its more restricted superclasses. Initialization may
+ * initialized, not one of its more restricted superclasses. Initialization may
* take place on construction, or in two phases if the no-argument constructor
* is called followed by init().
*
@@ -1001,45 +1079,43 @@
class PersistentRooted : public js::PersistentRootedBase<T>,
private mozilla::LinkedListElement<PersistentRooted<T>>
{
- typedef mozilla::LinkedListElement<PersistentRooted<T>> ListBase;
+ using ListBase = mozilla::LinkedListElement<PersistentRooted<T>>;
friend class mozilla::LinkedList<PersistentRooted>;
friend class mozilla::LinkedListElement<PersistentRooted>;
- friend struct js::gc::PersistentRootedMarker<T>;
-
- friend void js::gc::FinishPersistentRootedChains(js::RootLists&);
-
void registerWithRootLists(js::RootLists& roots) {
MOZ_ASSERT(!initialized());
- js::ThingRootKind kind = js::RootKind<T>::rootKind();
+ JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
roots.heapRoots_[kind].insertBack(reinterpret_cast<JS::PersistentRooted<void*>*>(this));
- // Until marking and destruction support the full set, we assert that
- // we don't try to add any unsupported types.
- MOZ_ASSERT(kind == js::THING_ROOT_OBJECT ||
- kind == js::THING_ROOT_SCRIPT ||
- kind == js::THING_ROOT_STRING ||
- kind == js::THING_ROOT_SYMBOL ||
- kind == js::THING_ROOT_ID ||
- kind == js::THING_ROOT_VALUE ||
- kind == js::THING_ROOT_TRACEABLE);
}
+ js::RootLists& rootLists(JSContext* cx) {
+ return rootLists(JS::RootingContext::get(cx));
+ }
+ js::RootLists& rootLists(JS::RootingContext* cx) {
+ MOZ_ASSERT(cx->isJSContext);
+ return cx->roots;
+ }
+
+ // Disallow ExclusiveContext*.
+ js::RootLists& rootLists(js::ContextFriendFields* cx) = delete;
+
public:
- PersistentRooted() : ptr(js::GCMethods<T>::initial()) {}
+ PersistentRooted() : ptr(GCPolicy<T>::initial()) {}
template <typename RootingContext>
explicit PersistentRooted(const RootingContext& cx)
- : ptr(js::GCMethods<T>::initial())
+ : ptr(GCPolicy<T>::initial())
{
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
template <typename RootingContext, typename U>
PersistentRooted(const RootingContext& cx, U&& initial)
: ptr(mozilla::Forward<U>(initial))
{
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
PersistentRooted(const PersistentRooted& rhs)
@@ -1063,18 +1139,18 @@
template <typename RootingContext>
void init(const RootingContext& cx) {
- init(cx, js::GCMethods<T>::initial());
+ init(cx, GCPolicy<T>::initial());
}
template <typename RootingContext, typename U>
void init(const RootingContext& cx, U&& initial) {
ptr = mozilla::Forward<U>(initial);
- registerWithRootLists(js::RootListsForRootingContext(cx));
+ registerWithRootLists(rootLists(cx));
}
void reset() {
if (initialized()) {
- set(js::GCMethods<T>::initial());
+ set(GCPolicy<T>::initial());
ListBase::remove();
}
}
@@ -1097,19 +1173,19 @@
}
private:
- void set(T value) {
+ template <typename U>
+ void set(U&& value) {
MOZ_ASSERT(initialized());
- ptr = value;
+ ptr = mozilla::Forward<U>(value);
}
// See the comment above Rooted::ptr.
using MaybeWrapped = typename mozilla::Conditional<
- mozilla::IsBaseOf<Traceable, T>::value,
+ MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
js::DispatchWrapper<T>,
T>::Type;
-
MaybeWrapped ptr;
-};
+} JS_HAZ_ROOTED;
class JS_PUBLIC_API(ObjectPtr)
{
@@ -1120,20 +1196,26 @@
explicit ObjectPtr(JSObject* obj) : value(obj) {}
+ ObjectPtr(const ObjectPtr& other) : value(other.value) {}
+
+ ObjectPtr(ObjectPtr&& other)
+ : value(other.value)
+ {
+ other.value = nullptr;
+ }
+
/* Always call finalize before the destructor. */
~ObjectPtr() { MOZ_ASSERT(!value); }
- void finalize(JSRuntime* rt) {
- if (IsIncrementalBarrierNeeded(rt))
- IncrementalObjectBarrier(value);
- value = nullptr;
- }
+ void finalize(JSRuntime* rt);
+ void finalize(JSContext* cx);
void init(JSObject* obj) { value = obj; }
JSObject* get() const { return value; }
+ JSObject* unbarrieredGet() const { return value.unbarrieredGet(); }
- void writeBarrierPre(JSRuntime* rt) {
+ void writeBarrierPre(JSContext* cx) {
IncrementalObjectBarrier(value);
}
@@ -1150,11 +1232,57 @@
JSObject& operator*() const { return *value; }
JSObject* operator->() const { return value; }
operator JSObject*() const { return value; }
+
+ explicit operator bool() const { return value.unbarrieredGet(); }
+ explicit operator bool() { return value.unbarrieredGet(); }
};
} /* namespace JS */
namespace js {
+
+template <typename Outer, typename T, typename D>
+class UniquePtrOperations
+{
+ const UniquePtr<T, D>& uniquePtr() const { return static_cast<const Outer*>(this)->get(); }
+
+ public:
+ explicit operator bool() const { return !!uniquePtr(); }
+ T* get() const { return uniquePtr().get(); }
+ T* operator->() const { return get(); }
+ T& operator*() const { return *uniquePtr(); }
+};
+
+template <typename Outer, typename T, typename D>
+class MutableUniquePtrOperations : public UniquePtrOperations<Outer, T, D>
+{
+ UniquePtr<T, D>& uniquePtr() { return static_cast<Outer*>(this)->get(); }
+
+ public:
+ MOZ_MUST_USE typename UniquePtr<T, D>::Pointer release() { return uniquePtr().release(); }
+ void reset(T* ptr = T()) { uniquePtr().reset(ptr); }
+};
+
+template <typename T, typename D>
+class RootedBase<UniquePtr<T, D>>
+ : public MutableUniquePtrOperations<JS::Rooted<UniquePtr<T, D>>, T, D>
+{ };
+
+template <typename T, typename D>
+class MutableHandleBase<UniquePtr<T, D>>
+ : public MutableUniquePtrOperations<JS::MutableHandle<UniquePtr<T, D>>, T, D>
+{ };
+
+template <typename T, typename D>
+class HandleBase<UniquePtr<T, D>>
+ : public UniquePtrOperations<JS::Handle<UniquePtr<T, D>>, T, D>
+{ };
+
+template <typename T, typename D>
+class PersistentRootedBase<UniquePtr<T, D>>
+ : public MutableUniquePtrOperations<JS::PersistentRooted<UniquePtr<T, D>>, T, D>
+{ };
+
namespace gc {
template <typename T, typename TraceCallbacks>
@@ -1163,7 +1291,7 @@
{
static_assert(sizeof(T) == sizeof(JS::Heap<T>), "T and Heap<T> must be compatible.");
MOZ_ASSERT(v);
- mozilla::DebugOnly<Cell*> cell = GCMethods<T>::asGCThingOrNull(*v);
+ mozilla::DebugOnly<Cell*> cell = BarrierMethods<T>::asGCThingOrNull(*v);
MOZ_ASSERT(cell);
MOZ_ASSERT(!IsInsideNursery(cell));
JS::Heap<T>* asHeapT = reinterpret_cast<JS::Heap<T>*>(v);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/StructuredClone.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/StructuredClone.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/StructuredClone.h
@@ -7,6 +7,10 @@
#ifndef js_StructuredClone_h
#define js_StructuredClone_h
+#include "mozilla/Attributes.h"
+#include "mozilla/BufferList.h"
+#include "mozilla/Move.h"
+
#include <stdint.h>
#include "jstypes.h"
@@ -22,6 +26,41 @@
// API for the HTML5 internal structured cloning algorithm.
namespace JS {
+
+enum class StructuredCloneScope : uint32_t {
+ SameProcessSameThread,
+ SameProcessDifferentThread,
+
+ /**
+ * When writing, this means we're writing for an audience in a different
+ * process. Produce serialized data that can be sent to other processes,
+ * bitwise copied, or even stored as bytes in a database and read by later
+ * versions of Firefox years from now. The HTML5 spec refers to this as
+ * "ForStorage" as in StructuredSerializeForStorage, though we use
+ * DifferentProcess for IPC as well as storage.
+ *
+ * Transferable objects are limited to ArrayBuffers, whose contents are
+ * copied into the serialized data (rather than just writing a pointer).
+ */
+ DifferentProcess,
+
+ /**
+ * Handle a backwards-compatibility case with IndexedDB (bug 1434308): when
+ * reading, this means to treat legacy SameProcessSameThread data as if it
+ * were DifferentProcess.
+ *
+ * Do not use this for writing; use DifferentProcess instead.
+ */
+ DifferentProcessForIndexedDB,
+
+ /**
+ * Existing code wants to be able to create an uninitialized
+ * JSStructuredCloneData without knowing the scope, then populate it with
+ * data (at which point the scope *is* known.)
+ */
+ Unassigned
+};
+
enum TransferableOwnership {
/** Transferable data has not been filled in yet */
SCTAG_TMO_UNFILLED = 0,
@@ -35,23 +74,54 @@
/** Data is a pointer that can be freed */
SCTAG_TMO_ALLOC_DATA = 2,
- /** Data is a SharedArrayBufferObject's buffer */
- SCTAG_TMO_SHARED_BUFFER = 3,
-
/** Data is a memory mapped pointer */
- SCTAG_TMO_MAPPED_DATA = 4,
+ SCTAG_TMO_MAPPED_DATA = 3,
/**
* Data is embedding-specific. The engine can free it by calling the
* freeTransfer op. The embedding can also use SCTAG_TMO_USER_MIN and
* greater, up to 32 bits, to distinguish specific ownership variants.
*/
- SCTAG_TMO_CUSTOM = 5,
+ SCTAG_TMO_CUSTOM = 4,
SCTAG_TMO_USER_MIN
};
+
+class CloneDataPolicy
+{
+ bool sharedArrayBuffer_;
+
+ public:
+ // The default is to allow all policy-controlled aspects.
+
+ CloneDataPolicy() :
+ sharedArrayBuffer_(true)
+ {}
+
+ // In the JS engine, SharedArrayBuffers can only be cloned intra-process
+ // because the shared memory areas are allocated in process-private memory.
+ // Clients should therefore deny SharedArrayBuffers when cloning data that
+ // are to be transmitted inter-process.
+ //
+ // Clients should also deny SharedArrayBuffers when cloning data that are to
+ // be transmitted intra-process if policy needs dictate such denial.
+
+ CloneDataPolicy& denySharedArrayBuffer() {
+ sharedArrayBuffer_ = false;
+ return *this;
+ }
+
+ bool isSharedArrayBufferAllowed() const {
+ return sharedArrayBuffer_;
+ }
+};
+
} /* namespace JS */
+namespace js {
+template <typename T, typename AllocPolicy> struct BufferIterator;
+}
+
/**
* Read structured data from the reader r. This hook is used to read a value
* previously serialized by a call to the WriteStructuredCloneOp hook.
@@ -123,9 +193,9 @@
uint64_t* extraData);
/**
- * Called when JS_ClearStructuredClone has to free an unknown transferable
- * object. Note that it should never trigger a garbage collection (and will
- * assert in a debug build if it does.)
+ * Called when freeing an unknown transferable object. Note that it
+ * should never trigger a garbage collection (and will assert in a
+ * debug build if it does.)
*/
typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwnership ownership,
void* content, uint64_t extraData, void* closure);
@@ -134,7 +204,7 @@
// Increment this when anything at all changes in the serialization format.
// (Note that this does not need to be bumped for Transferable-only changes,
// since they are never saved to persistent storage.)
-#define JS_STRUCTURED_CLONE_VERSION 6
+#define JS_STRUCTURED_CLONE_VERSION 8
struct JSStructuredCloneCallbacks {
ReadStructuredCloneOp read;
@@ -145,97 +215,239 @@
FreeTransferStructuredCloneOp freeTransfer;
};
+enum OwnTransferablePolicy {
+ OwnsTransferablesIfAny,
+ IgnoreTransferablesIfAny,
+ NoTransferables
+};
+
+/**
+ * JSStructuredCloneData represents structured clone data together with the
+ * information needed to read/write/transfer/free the records within it, in the
+ * form of a set of callbacks.
+ */
+class MOZ_NON_MEMMOVABLE JS_PUBLIC_API(JSStructuredCloneData) {
+ public:
+ using BufferList = mozilla::BufferList<js::SystemAllocPolicy>;
+ using Iterator = BufferList::IterImpl;
+
+ private:
+ static const size_t kStandardCapacity = 4096;
+
+ BufferList bufList_;
+
+ // The (address space, thread) scope within which this clone is valid. Note
+ // that this must be either set during construction, or start out as
+ // Unassigned and transition once to something else.
+ JS::StructuredCloneScope scope_;
+
+ const JSStructuredCloneCallbacks* callbacks_;
+ void* closure_;
+ OwnTransferablePolicy ownTransferables_;
+
+ friend struct JSStructuredCloneWriter;
+ friend class JS_PUBLIC_API(JSAutoStructuredCloneBuffer);
+ template <typename T, typename AllocPolicy> friend struct js::BufferIterator;
+
+ public:
+ // The constructor must be infallible but SystemAllocPolicy is not, so both
+ // the initial size and initial capacity of the BufferList must be zero.
+ explicit JSStructuredCloneData(JS::StructuredCloneScope aScope)
+ : bufList_(0, 0, kStandardCapacity, js::SystemAllocPolicy())
+ , scope_(aScope)
+ , callbacks_(nullptr)
+ , closure_(nullptr)
+ , ownTransferables_(OwnTransferablePolicy::NoTransferables)
+ {}
+
+ // Steal the raw data from a BufferList. In this case, we don't know the
+ // scope and none of the callback info is assigned yet.
+ JSStructuredCloneData(BufferList&& buffers, JS::StructuredCloneScope aScope)
+ : bufList_(mozilla::Move(buffers))
+ , scope_(aScope)
+ , callbacks_(nullptr)
+ , closure_(nullptr)
+ , ownTransferables_(OwnTransferablePolicy::NoTransferables)
+ {}
+ MOZ_IMPLICIT JSStructuredCloneData(BufferList&& buffers)
+ : JSStructuredCloneData(mozilla::Move(buffers), JS::StructuredCloneScope::Unassigned)
+ {}
+ JSStructuredCloneData(JSStructuredCloneData&& other) = default;
+ JSStructuredCloneData& operator=(JSStructuredCloneData&& other) = default;
+ ~JSStructuredCloneData() { discardTransferables(); }
+
+ void setCallbacks(const JSStructuredCloneCallbacks* callbacks,
+ void* closure,
+ OwnTransferablePolicy policy)
+ {
+ callbacks_ = callbacks;
+ closure_ = closure;
+ ownTransferables_ = policy;
+ }
+
+ JS::StructuredCloneScope scope() const { return scope_; }
+
+ void initScope(JS::StructuredCloneScope aScope) {
+ MOZ_ASSERT(Size() == 0, "initScope() of nonempty JSStructuredCloneData");
+ if (scope_ != JS::StructuredCloneScope::Unassigned)
+ MOZ_ASSERT(scope_ == aScope, "Cannot change scope after it has been initialized");
+ scope_ = aScope;
+ }
+
+ size_t Size() const { return bufList_.Size(); }
+
+ const Iterator Start() const { return bufList_.Iter(); }
+
+ bool Advance(Iterator& iter, size_t distance) const {
+ return iter.AdvanceAcrossSegments(bufList_, distance);
+ }
+
+ bool ReadBytes(Iterator& iter, char* buffer, size_t size) const {
+ return bufList_.ReadBytes(iter, buffer, size);
+ }
+
+ // Append new data to the end of the buffer.
+ bool AppendBytes(const char* data, size_t size) {
+ MOZ_ASSERT(scope_ != JS::StructuredCloneScope::Unassigned);
+ return bufList_.WriteBytes(data, size);
+ }
+
+ // Update data stored within the existing buffer. There must be at least
+ // 'size' bytes between the position of 'iter' and the end of the buffer.
+ bool UpdateBytes(Iterator& iter, const char* data, size_t size) const {
+ MOZ_ASSERT(scope_ != JS::StructuredCloneScope::Unassigned);
+ while (size > 0) {
+ size_t remaining = iter.RemainingInSegment();
+ size_t nbytes = std::min(remaining, size);
+ memcpy(iter.Data(), data, nbytes);
+ data += nbytes;
+ size -= nbytes;
+ iter.Advance(bufList_, nbytes);
+ }
+ return true;
+ }
+
+ void Clear() {
+ discardTransferables();
+ bufList_.Clear();
+ }
+
+ // Return a new read-only JSStructuredCloneData that "borrows" the contents
+ // of |this|. Its lifetime should not exceed the donor's. This is only
+ // allowed for DifferentProcess clones, so finalization of the borrowing
+ // clone will do nothing.
+ JSStructuredCloneData Borrow(Iterator& iter, size_t size, bool* success) const
+ {
+ MOZ_ASSERT(scope_ == JS::StructuredCloneScope::DifferentProcess);
+ return JSStructuredCloneData(bufList_.Borrow<js::SystemAllocPolicy>(iter, size, success),
+ scope_);
+ }
+
+ // Iterate over all contained data, one BufferList segment's worth at a
+ // time, and invoke the given FunctionToApply with the data pointer and
+ // size. The function should return a bool value, and this loop will exit
+ // with false if the function ever returns false.
+ template <typename FunctionToApply>
+ bool ForEachDataChunk(FunctionToApply&& function) const {
+ Iterator iter = bufList_.Iter();
+ while (!iter.Done()) {
+ if (!function(iter.Data(), iter.RemainingInSegment()))
+ return false;
+ iter.Advance(bufList_, iter.RemainingInSegment());
+ }
+ return true;
+ }
+
+ // Append the entire contents of other's bufList_ to our own.
+ bool Append(const JSStructuredCloneData& other) {
+ MOZ_ASSERT(scope_ == other.scope_);
+ return other.ForEachDataChunk([&](const char* data, size_t size) {
+ return AppendBytes(data, size);
+ });
+ }
+
+ void discardTransferables();
+};
+
/** Note: if the *data contains transferable objects, it can be read only once. */
JS_PUBLIC_API(bool)
-JS_ReadStructuredClone(JSContext* cx, uint64_t* data, size_t nbytes, uint32_t version,
+JS_ReadStructuredClone(JSContext* cx, JSStructuredCloneData& data, uint32_t version,
+ JS::StructuredCloneScope scope,
JS::MutableHandleValue vp,
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure);
-/**
- * Note: On success, the caller is responsible for calling
- * JS_ClearStructuredClone(*datap, nbytes, optionalCallbacks, closure).
- */
JS_PUBLIC_API(bool)
-JS_WriteStructuredClone(JSContext* cx, JS::HandleValue v, uint64_t** datap, size_t* nbytesp,
+JS_WriteStructuredClone(JSContext* cx, JS::HandleValue v, JSStructuredCloneData* data,
+ JS::StructuredCloneScope scope,
+ JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* optionalCallbacks,
void* closure, JS::HandleValue transferable);
JS_PUBLIC_API(bool)
-JS_ClearStructuredClone(uint64_t* data, size_t nbytes,
- const JSStructuredCloneCallbacks* optionalCallbacks,
- void *closure, bool freeData = true);
-
-JS_PUBLIC_API(bool)
-JS_StructuredCloneHasTransferables(const uint64_t* data, size_t nbytes, bool* hasTransferable);
+JS_StructuredCloneHasTransferables(JSStructuredCloneData& data, bool* hasTransferable);
JS_PUBLIC_API(bool)
JS_StructuredClone(JSContext* cx, JS::HandleValue v, JS::MutableHandleValue vp,
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure);
-/** RAII sugar for JS_WriteStructuredClone. */
+/**
+ * The C-style API calls to read and write structured clones are fragile --
+ * they rely on the caller to properly handle ownership of the clone data, and
+ * the handling of the input data as well as the interpretation of the contents
+ * of the clone buffer are dependent on the callbacks passed in. If you
+ * serialize and deserialize with different callbacks, the results are
+ * questionable.
+ *
+ * JSAutoStructuredCloneBuffer wraps things up in an RAII class for data
+ * management, and uses the same callbacks for both writing and reading
+ * (serializing and deserializing).
+ */
class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
- uint64_t* data_;
- size_t nbytes_;
+ const JS::StructuredCloneScope scope_;
+ JSStructuredCloneData data_;
uint32_t version_;
- enum {
- OwnsTransferablesIfAny,
- IgnoreTransferablesIfAny,
- NoTransferables
- } ownTransferables_;
-
- const JSStructuredCloneCallbacks* callbacks_;
- void* closure_;
public:
- JSAutoStructuredCloneBuffer()
- : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
- ownTransferables_(NoTransferables),
- callbacks_(nullptr), closure_(nullptr)
- {}
-
- JSAutoStructuredCloneBuffer(const JSStructuredCloneCallbacks* callbacks, void* closure)
- : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
- ownTransferables_(NoTransferables),
- callbacks_(callbacks), closure_(closure)
- {}
+ JSAutoStructuredCloneBuffer(JS::StructuredCloneScope aScope,
+ const JSStructuredCloneCallbacks* callbacks, void* closure)
+ : scope_(aScope), data_(aScope), version_(JS_STRUCTURED_CLONE_VERSION)
+ {
+ data_.setCallbacks(callbacks, closure, OwnTransferablePolicy::NoTransferables);
+ }
JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other);
JSAutoStructuredCloneBuffer& operator=(JSAutoStructuredCloneBuffer&& other);
~JSAutoStructuredCloneBuffer() { clear(); }
- uint64_t* data() const { return data_; }
- size_t nbytes() const { return nbytes_; }
+ JSStructuredCloneData& data() { return data_; }
+ bool empty() const { return !data_.Size(); }
- void clear(const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
+ void clear();
- /** Copy some memory. It will be automatically freed by the destructor. */
- bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
- const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
+ JS::StructuredCloneScope scope() const { return scope_; }
/**
* Adopt some memory. It will be automatically freed by the destructor.
* data must have been allocated by the JS engine (e.g., extracted via
* JSAutoStructuredCloneBuffer::steal).
*/
- void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
+ void adopt(JSStructuredCloneData&& data, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
/**
- * Release the buffer and transfer ownership to the caller. The caller is
- * responsible for calling JS_ClearStructuredClone or feeding the memory
- * back to JSAutoStructuredCloneBuffer::adopt.
+ * Release the buffer and transfer ownership to the caller.
*/
- void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr,
+ void steal(JSStructuredCloneData* data, uint32_t* versionp=nullptr,
const JSStructuredCloneCallbacks** callbacks=nullptr, void** closure=nullptr);
/**
* Abandon ownership of any transferable objects stored in the buffer,
* without freeing the buffer itself. Useful when copying the data out into
- * an external container, though note that you will need to use adopt() or
- * JS_ClearStructuredClone to properly release that data eventually.
+ * an external container, though note that you will need to use adopt() to
+ * properly release that data eventually.
*/
- void abandon() { ownTransferables_ = IgnoreTransferablesIfAny; }
+ void abandon() { data_.ownTransferables_ = OwnTransferablePolicy::IgnoreTransferablesIfAny; }
bool read(JSContext* cx, JS::MutableHandleValue vp,
const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
@@ -244,6 +456,7 @@
const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
bool write(JSContext* cx, JS::HandleValue v, JS::HandleValue transferable,
+ JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
private:
@@ -259,6 +472,7 @@
#define JS_SCERR_RECURSION 0
#define JS_SCERR_TRANSFERABLE 1
#define JS_SCERR_DUP_TRANSFERABLE 2
+#define JS_SCERR_UNSUPPORTED_TYPE 3
JS_PUBLIC_API(bool)
JS_ReadUint32Pair(JSStructuredCloneReader* r, uint32_t* p1, uint32_t* p2);
@@ -281,4 +495,10 @@
JS_PUBLIC_API(bool)
JS_WriteTypedArray(JSStructuredCloneWriter* w, JS::HandleValue v);
+JS_PUBLIC_API(bool)
+JS_ObjectNotWritten(JSStructuredCloneWriter* w, JS::HandleObject obj);
+
+JS_PUBLIC_API(JS::StructuredCloneScope)
+JS_GetStructuredCloneScope(JSStructuredCloneWriter* w);
+
#endif /* js_StructuredClone_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/SweepingAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/SweepingAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/SweepingAPI.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_SweepingAPI_h
+#define js_SweepingAPI_h
+
+#include "js/HeapAPI.h"
+
+namespace js {
+template <typename T>
+class WeakCacheBase {};
+} // namespace js
+
+namespace JS {
+template <typename T> class WeakCache;
+
+namespace shadow {
+JS_PUBLIC_API(void)
+RegisterWeakCache(JS::Zone* zone, JS::WeakCache<void*>* cachep);
+} // namespace shadow
+
+// A WeakCache stores the given Sweepable container and links itself into a
+// list of such caches that are swept during each GC.
+template <typename T>
+class WeakCache : public js::WeakCacheBase<T>,
+ private mozilla::LinkedListElement<WeakCache<T>>
+{
+ friend class mozilla::LinkedListElement<WeakCache<T>>;
+ friend class mozilla::LinkedList<WeakCache<T>>;
+
+ WeakCache() = delete;
+ WeakCache(const WeakCache&) = delete;
+
+ using SweepFn = void (*)(T*);
+ SweepFn sweeper;
+ T cache;
+
+ public:
+ using Type = T;
+
+ template <typename U>
+ WeakCache(Zone* zone, U&& initial)
+ : cache(mozilla::Forward<U>(initial))
+ {
+ sweeper = GCPolicy<T>::sweep;
+ shadow::RegisterWeakCache(zone, reinterpret_cast<WeakCache<void*>*>(this));
+ }
+ WeakCache(WeakCache&& other)
+ : sweeper(other.sweeper),
+ cache(mozilla::Move(other.cache))
+ {
+ }
+
+ const T& get() const { return cache; }
+ T& get() { return cache; }
+
+ void sweep() { sweeper(&cache); }
+};
+
+} // namespace JS
+
+#endif // js_SweepingAPI_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TraceKind.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TraceKind.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TraceKind.h
@@ -7,6 +7,8 @@
#ifndef js_TraceKind_h
#define js_TraceKind_h
+#include "mozilla/UniquePtr.h"
+
#include "js/TypeDecls.h"
// Forward declarations of all the types a TraceKind can denote.
@@ -15,6 +17,7 @@
class LazyScript;
class ObjectGroup;
class Shape;
+class Scope;
namespace jit {
class JitCode;
} // namespace jit
@@ -53,18 +56,31 @@
// The following kinds do not have an exposed C++ idiom.
BaseShape = 0x0F,
JitCode = 0x1F,
- LazyScript = 0x2F
+ LazyScript = 0x2F,
+ Scope = 0x3F
};
const static uintptr_t OutOfLineTraceKindMask = 0x07;
static_assert(uintptr_t(JS::TraceKind::BaseShape) & OutOfLineTraceKindMask, "mask bits are set");
static_assert(uintptr_t(JS::TraceKind::JitCode) & OutOfLineTraceKindMask, "mask bits are set");
static_assert(uintptr_t(JS::TraceKind::LazyScript) & OutOfLineTraceKindMask, "mask bits are set");
+static_assert(uintptr_t(JS::TraceKind::Scope) & OutOfLineTraceKindMask, "mask bits are set");
+
+// When this header is imported inside SpiderMonkey, the class definitions are
+// available and we can query those definitions to find the correct kind
+// directly from the class hierarchy.
+template <typename T>
+struct MapTypeToTraceKind {
+ static const JS::TraceKind kind = T::TraceKind;
+};
+// When this header is used outside SpiderMonkey, the class definitions are not
+// available, so the following table containing all public GC types is used.
#define JS_FOR_EACH_TRACEKIND(D) \
/* PrettyName TypeName AddToCCKind */ \
D(BaseShape, js::BaseShape, true) \
D(JitCode, js::jit::JitCode, true) \
D(LazyScript, js::LazyScript, true) \
+ D(Scope, js::Scope, true) \
D(Object, JSObject, true) \
D(ObjectGroup, js::ObjectGroup, true) \
D(Script, JSScript, true) \
@@ -72,8 +88,7 @@
D(String, JSString, false) \
D(Symbol, JS::Symbol, false)
-// Map from base trace type to the trace kind.
-template <typename T> struct MapTypeToTraceKind {};
+// Map from all public types to their trace kind.
#define JS_EXPAND_DEF(name, type, _) \
template <> struct MapTypeToTraceKind<type> { \
static const JS::TraceKind kind = JS::TraceKind::name; \
@@ -81,6 +96,60 @@
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
#undef JS_EXPAND_DEF
+// RootKind is closely related to TraceKind. Whereas TraceKind's indices are
+// laid out for convenient embedding as a pointer tag, the indicies of RootKind
+// are designed for use as array keys via EnumeratedArray.
+enum class RootKind : int8_t
+{
+ // These map 1:1 with trace kinds.
+#define EXPAND_ROOT_KIND(name, _0, _1) \
+ name,
+JS_FOR_EACH_TRACEKIND(EXPAND_ROOT_KIND)
+#undef EXPAND_ROOT_KIND
+
+ // These tagged pointers are special-cased for performance.
+ Id,
+ Value,
+
+ // Everything else.
+ Traceable,
+
+ Limit
+};
+
+// Most RootKind correspond directly to a trace kind.
+template <TraceKind traceKind> struct MapTraceKindToRootKind {};
+#define JS_EXPAND_DEF(name, _0, _1) \
+ template <> struct MapTraceKindToRootKind<JS::TraceKind::name> { \
+ static const JS::RootKind kind = JS::RootKind::name; \
+ };
+JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF)
+#undef JS_EXPAND_DEF
+
+// Specify the RootKind for all types. Value and jsid map to special cases;
+// pointer types we can derive directly from the TraceKind; everything else
+// should go in the Traceable list and use GCPolicy<T>::trace for tracing.
+template <typename T>
+struct MapTypeToRootKind {
+ static const JS::RootKind kind = JS::RootKind::Traceable;
+};
+template <typename T>
+struct MapTypeToRootKind<T*> {
+ static const JS::RootKind kind =
+ JS::MapTraceKindToRootKind<JS::MapTypeToTraceKind<T>::kind>::kind;
+};
+template <typename T>
+struct MapTypeToRootKind<mozilla::UniquePtr<T>> {
+ static const JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
+};
+template <> struct MapTypeToRootKind<JS::Value> {
+ static const JS::RootKind kind = JS::RootKind::Value;
+};
+template <> struct MapTypeToRootKind<jsid> {
+ static const JS::RootKind kind = JS::RootKind::Id;
+};
+template <> struct MapTypeToRootKind<JSFunction*> : public MapTypeToRootKind<JSObject*> {};
+
// Fortunately, few places in the system need to deal with fully abstract
// cells. In those places that do, we generally want to move to a layout
// templated function as soon as possible. This template wraps the upcast
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TraceableVector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TraceableVector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TraceableVector.h
@@ -1,239 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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 js_TraceableVector_h
-#define js_TraceableVector_h
-
-#include "mozilla/Vector.h"
-
-#include "js/RootingAPI.h"
-#include "js/TracingAPI.h"
-#include "js/Vector.h"
-
-namespace js {
-
-// A TraceableVector is a Vector with an additional trace method that knows how
-// to visit all of the items stored in the Vector. For vectors that contain GC
-// things, this is usually more convenient than manually iterating and marking
-// the contents.
-//
-// Most types of GC pointers as keys and values can be traced with no extra
-// infrastructure. For structs and non-gc-pointer members, ensure that there
-// is a specialization of DefaultGCPolicy<T> with an appropriate trace method
-// available to handle the custom type. Generic helpers can be found in
-// js/public/TracingAPI.h.
-//
-// Note that although this Vector's trace will deal correctly with moved items,
-// it does not itself know when to barrier or trace items. To function properly
-// it must either be used with Rooted, or barriered and traced manually.
-template <typename T,
- size_t MinInlineCapacity = 0,
- typename AllocPolicy = TempAllocPolicy,
- typename GCPolicy = DefaultGCPolicy<T>>
-class TraceableVector : public JS::Traceable
-{
- mozilla::Vector<T, MinInlineCapacity, AllocPolicy> vector;
-
- public:
- explicit TraceableVector(AllocPolicy alloc = AllocPolicy())
- : vector(alloc)
- {}
-
- TraceableVector(TraceableVector&& vec)
- : vector(mozilla::Move(vec.vector))
- {}
-
- TraceableVector& operator=(TraceableVector&& vec) {
- vector = mozilla::Move(vec.vector);
- return *this;
- }
-
- size_t length() const { return vector.length(); }
- bool empty() const { return vector.empty(); }
- size_t capacity() const { return vector.capacity(); }
-
- T* begin() { return vector.begin(); }
- const T* begin() const { return vector.begin(); }
-
- T* end() { return vector.end(); }
- const T* end() const { return vector.end(); }
-
- T& operator[](size_t i) { return vector[i]; }
- const T& operator[](size_t i) const { return vector[i]; }
-
- T& back() { return vector.back(); }
- const T& back() const { return vector.back(); }
-
- bool initCapacity(size_t cap) { return vector.initCapacity(cap); }
- bool reserve(size_t req) { return vector.reserve(req); }
- void shrinkBy(size_t amount) { return vector.shrinkBy(amount); }
- bool growBy(size_t amount) { return vector.growBy(amount); }
- bool resize(size_t newLen) { return vector.resize(newLen); }
-
- void clear() { return vector.clear(); }
-
- template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }
-
- template<typename... Args>
- bool
- emplaceBack(Args&&... args) {
- return vector.emplaceBack(mozilla::Forward<Args>(args)...);
- }
-
- template<typename U>
- void infallibleAppend(U&& aU) {
- return vector.infallibleAppend(mozilla::Forward<U>(aU));
- }
- void infallibleAppendN(const T& aT, size_t aN) {
- return vector.infallibleAppendN(aT, aN);
- }
- template<typename U> void
- infallibleAppend(const U* aBegin, const U* aEnd) {
- return vector.infallibleAppend(aBegin, aEnd);
- }
- template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
- return vector.infallibleAppend(aBegin, aLength);
- }
-
- bool appendN(const T& val, size_t count) { return vector.appendN(val, count); }
-
- template<typename U> bool append(const U* aBegin, const U* aEnd) {
- return vector.append(aBegin, aEnd);
- }
- template<typename U> bool append(const U* aBegin, size_t aLength) {
- return vector.append(aBegin, aLength);
- }
-
- void popBack() { return vector.popBack(); }
- T popCopy() { return vector.popCopy(); }
-
- size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
- return vector.sizeOfExcludingThis(mallocSizeOf);
- }
-
- size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
- return vector.sizeOfIncludingThis(mallocSizeOf);
- }
-
- static void trace(TraceableVector* vec, JSTracer* trc) { vec->trace(trc); }
-
- void trace(JSTracer* trc) {
- for (auto& elem : vector)
- GCPolicy::trace(trc, &elem, "vector element");
- }
-};
-
-template <typename Outer, typename T, size_t Capacity, typename AllocPolicy, typename GCPolicy>
-class TraceableVectorOperations
-{
- using Vec = TraceableVector<T, Capacity, AllocPolicy, GCPolicy>;
- const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
-
- public:
- const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
- size_t length() const { return vec().length(); }
- bool empty() const { return vec().empty(); }
- size_t capacity() const { return vec().capacity(); }
- const T* begin() const { return vec().begin(); }
- const T* end() const { return vec().end(); }
- const T& back() const { return vec().back(); }
- bool canAppendWithoutRealloc(size_t aNeeded) const { return vec().canAppendWithoutRealloc(); }
-
- JS::Handle<T> operator[](size_t aIndex) const {
- return JS::Handle<T>::fromMarkedLocation(&vec().operator[](aIndex));
- }
-};
-
-template <typename Outer, typename T, size_t Capacity, typename AllocPolicy, typename GCPolicy>
-class MutableTraceableVectorOperations
- : public TraceableVectorOperations<Outer, T, Capacity, AllocPolicy, GCPolicy>
-{
- using Vec = TraceableVector<T, Capacity, AllocPolicy, GCPolicy>;
- const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
- Vec& vec() { return static_cast<Outer*>(this)->get(); }
-
- public:
- const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
- AllocPolicy& allocPolicy() { return vec().allocPolicy(); }
- const T* begin() const { return vec().begin(); }
- T* begin() { return vec().begin(); }
- const T* end() const { return vec().end(); }
- T* end() { return vec().end(); }
- const T& operator[](size_t aIndex) const { return vec().operator[](aIndex); }
- const T& back() const { return vec().back(); }
- T& back() { return vec().back(); }
-
- JS::MutableHandle<T> operator[](size_t aIndex) {
- return JS::MutableHandle<T>::fromMarkedLocation(&vec().operator[](aIndex));
- }
-
- bool initCapacity(size_t aRequest) { return vec().initCapacity(aRequest); }
- bool reserve(size_t aRequest) { return vec().reserve(aRequest); }
- void shrinkBy(size_t aIncr) { vec().shrinkBy(aIncr); }
- bool growBy(size_t aIncr) { return vec().growBy(aIncr); }
- bool resize(size_t aNewLength) { return vec().resize(aNewLength); }
- bool growByUninitialized(size_t aIncr) { return vec().growByUninitialized(aIncr); }
- void infallibleGrowByUninitialized(size_t aIncr) { vec().infallibleGrowByUninitialized(aIncr); }
- bool resizeUninitialized(size_t aNewLength) { return vec().resizeUninitialized(aNewLength); }
- void clear() { vec().clear(); }
- void clearAndFree() { vec().clearAndFree(); }
- template<typename U> bool append(U&& aU) { return vec().append(mozilla::Forward<U>(aU)); }
- template<typename... Args> bool emplaceBack(Args&&... aArgs) {
- return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
- }
- template<typename U, size_t O, class BP>
- bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vec().appendAll(aU); }
- bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
- template<typename U> bool append(const U* aBegin, const U* aEnd) {
- return vec().append(aBegin, aEnd);
- }
- template<typename U> bool append(const U* aBegin, size_t aLength) {
- return vec().append(aBegin, aLength);
- }
- template<typename U> void infallibleAppend(U&& aU) {
- vec().infallibleAppend(mozilla::Forward<U>(aU));
- }
- void infallibleAppendN(const T& aT, size_t aN) { vec().infallibleAppendN(aT, aN); }
- template<typename U> void infallibleAppend(const U* aBegin, const U* aEnd) {
- vec().infallibleAppend(aBegin, aEnd);
- }
- template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
- vec().infallibleAppend(aBegin, aLength);
- }
- void popBack() { vec().popBack(); }
- T popCopy() { return vec().popCopy(); }
- template<typename U> T* insert(T* aP, U&& aVal) {
- return vec().insert(aP, mozilla::Forward<U>(aVal));
- }
- void erase(T* aT) { vec().erase(aT); }
- void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
-};
-
-template <typename T, size_t N, typename AP, typename GP>
-class RootedBase<TraceableVector<T,N,AP,GP>>
- : public MutableTraceableVectorOperations<JS::Rooted<TraceableVector<T,N,AP,GP>>, T,N,AP,GP>
-{};
-
-template <typename T, size_t N, typename AP, typename GP>
-class MutableHandleBase<TraceableVector<T,N,AP,GP>>
- : public MutableTraceableVectorOperations<JS::MutableHandle<TraceableVector<T,N,AP,GP>>,
- T,N,AP,GP>
-{};
-
-template <typename T, size_t N, typename AP, typename GP>
-class HandleBase<TraceableVector<T,N,AP,GP>>
- : public TraceableVectorOperations<JS::Handle<TraceableVector<T,N,AP,GP>>, T,N,AP,GP>
-{};
-
-template <typename T, size_t N, typename AP, typename GP>
-class PersistentRootedBase<TraceableVector<T,N,AP,GP>>
- : public MutableTraceableVectorOperations<JS::PersistentRooted<TraceableVector<T,N,AP,GP>>,
- T,N,AP,GP>
-{};
-
-} // namespace js
-
-#endif // js_TraceableVector_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TracingAPI.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TracingAPI.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TracingAPI.h
@@ -27,13 +27,15 @@
} // namespace JS
enum WeakMapTraceKind {
- /** Do true ephemeron marking with an iterative weak marking phase. */
+ /**
+ * Do not trace into weak map keys or values during traversal. Users must
+ * handle weak maps manually.
+ */
DoNotTraceWeakMaps,
/**
* Do true ephemeron marking with a weak key lookup marking phase. This is
- * expected to be constant for the lifetime of a JSTracer; it does not
- * change when switching from "plain" marking to weak marking.
+ * the default for GCMarker.
*/
ExpandWeakMaps,
@@ -59,11 +61,24 @@
// Return the weak map tracing behavior currently set on this tracer.
WeakMapTraceKind weakMapAction() const { return weakMapAction_; }
- // An intermediate state on the road from C to C++ style dispatch.
enum class TracerKindTag {
+ // Marking path: a tracer used only for marking liveness of cells, not
+ // for moving them. The kind will transition to WeakMarking after
+ // everything reachable by regular edges has been marked.
Marking,
- WeakMarking, // In weak marking phase: looking up every marked obj/script.
+
+ // Same as Marking, except we have now moved on to the "weak marking
+ // phase", in which every marked obj/script is immediately looked up to
+ // see if it is a weak map key (and therefore might require marking its
+ // weak map value).
+ WeakMarking,
+
+ // A tracer that traverses the graph for the purposes of moving objects
+ // from the nursery to the tenured area.
Tenuring,
+
+ // General-purpose traversal that invokes a callback on each cell.
+ // Traversing children is the responsibility of the callback.
Callback
};
bool isMarkingTracer() const { return tag_ == TracerKindTag::Marking || tag_ == TracerKindTag::WeakMarking; }
@@ -71,19 +86,37 @@
bool isTenuringTracer() const { return tag_ == TracerKindTag::Tenuring; }
bool isCallbackTracer() const { return tag_ == TracerKindTag::Callback; }
inline JS::CallbackTracer* asCallbackTracer();
+#ifdef DEBUG
+ bool checkEdges() { return checkEdges_; }
+#endif
protected:
JSTracer(JSRuntime* rt, TracerKindTag tag,
WeakMapTraceKind weakTraceKind = TraceWeakMapValues)
- : runtime_(rt), weakMapAction_(weakTraceKind), tag_(tag)
+ : runtime_(rt)
+ , weakMapAction_(weakTraceKind)
+#ifdef DEBUG
+ , checkEdges_(true)
+#endif
+ , tag_(tag)
{}
+#ifdef DEBUG
+ // Set whether to check edges are valid in debug builds.
+ void setCheckEdges(bool check) {
+ checkEdges_ = check;
+ }
+#endif
+
private:
- JSRuntime* runtime_;
- WeakMapTraceKind weakMapAction_;
+ JSRuntime* runtime_;
+ WeakMapTraceKind weakMapAction_;
+#ifdef DEBUG
+ bool checkEdges_;
+#endif
protected:
- TracerKindTag tag_;
+ TracerKindTag tag_;
};
namespace JS {
@@ -99,6 +132,7 @@
: JSTracer(rt, JSTracer::TracerKindTag::Callback, weakTraceKind),
contextName_(nullptr), contextIndex_(InvalidIndex), contextFunctor_(nullptr)
{}
+ CallbackTracer(JSContext* cx, WeakMapTraceKind weakTraceKind = TraceWeakMapValues);
// Override these methods to receive notification when an edge is visited
// with the type contained in the callback. The default implementation
@@ -124,6 +158,9 @@
virtual void onLazyScriptEdge(js::LazyScript** lazyp) {
onChild(JS::GCCellPtr(*lazyp, JS::TraceKind::LazyScript));
}
+ virtual void onScopeEdge(js::Scope** scopep) {
+ onChild(JS::GCCellPtr(*scopep, JS::TraceKind::Scope));
+ }
// Override this method to receive notification when a node in the GC
// heap graph is visited.
@@ -193,6 +230,7 @@
void dispatchToOnEdge(js::BaseShape** basep) { onBaseShapeEdge(basep); }
void dispatchToOnEdge(js::jit::JitCode** codep) { onJitCodeEdge(codep); }
void dispatchToOnEdge(js::LazyScript** lazyp) { onLazyScriptEdge(lazyp); }
+ void dispatchToOnEdge(js::Scope** scopep) { onScopeEdge(scopep); }
private:
friend class AutoTracingName;
@@ -281,151 +319,85 @@
return static_cast<JS::CallbackTracer*>(this);
}
-// The JS_Call*Tracer family of functions traces the given GC thing reference.
-// This performs the tracing action configured on the given JSTracer:
-// typically calling the JSTracer::callback or marking the thing as live.
+namespace JS {
+
+// The JS::TraceEdge family of functions traces the given GC thing reference.
+// This performs the tracing action configured on the given JSTracer: typically
+// calling the JSTracer::callback or marking the thing as live.
//
-// The argument to JS_Call*Tracer is an in-out param: when the function
-// returns, the garbage collector might have moved the GC thing. In this case,
-// the reference passed to JS_Call*Tracer will be updated to the object's new
-// location. Callers of this method are responsible for updating any state
-// that is dependent on the object's address. For example, if the object's
-// address is used as a key in a hashtable, then the object must be removed
-// and re-inserted with the correct hash.
+// The argument to JS::TraceEdge is an in-out param: when the function returns,
+// the garbage collector might have moved the GC thing. In this case, the
+// reference passed to JS::TraceEdge will be updated to the thing's new
+// location. Callers of this method are responsible for updating any state that
+// is dependent on the object's address. For example, if the object's address
+// is used as a key in a hashtable, then the object must be removed and
+// re-inserted with the correct hash.
//
-extern JS_PUBLIC_API(void)
-JS_CallValueTracer(JSTracer* trc, JS::Heap<JS::Value>* valuep, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallIdTracer(JSTracer* trc, JS::Heap<jsid>* idp, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallObjectTracer(JSTracer* trc, JS::Heap<JSObject*>* objp, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallStringTracer(JSTracer* trc, JS::Heap<JSString*>* strp, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallScriptTracer(JSTracer* trc, JS::Heap<JSScript*>* scriptp, const char* name);
-
-extern JS_PUBLIC_API(void)
-JS_CallFunctionTracer(JSTracer* trc, JS::Heap<JSFunction*>* funp, const char* name);
-
-namespace JS {
+// Note that while |edgep| must never be null, it is fine for |*edgep| to be
+// nullptr.
template <typename T>
extern JS_PUBLIC_API(void)
TraceEdge(JSTracer* trc, JS::Heap<T>* edgep, const char* name);
-} // namespace JS
-
-// The following JS_CallUnbarriered*Tracer functions should only be called where
-// you know for sure that a heap post barrier is not required. Use with extreme
-// caution!
-extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredValueTracer(JSTracer* trc, JS::Value* valuep, const char* name);
extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredIdTracer(JSTracer* trc, jsid* idp, const char* name);
+TraceEdge(JSTracer* trc, JS::TenuredHeap<JSObject*>* edgep, const char* name);
+// Edges that are always traced as part of root marking do not require
+// incremental barriers. This function allows for marking non-barriered
+// pointers, but asserts that this happens during root marking.
+//
+// Note that while |edgep| must never be null, it is fine for |*edgep| to be
+// nullptr.
+template <typename T>
extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredObjectTracer(JSTracer* trc, JSObject** objp, const char* name);
+UnsafeTraceRoot(JSTracer* trc, T* edgep, const char* name);
extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredStringTracer(JSTracer* trc, JSString** strp, const char* name);
+TraceChildren(JSTracer* trc, GCCellPtr thing);
-extern JS_PUBLIC_API(void)
-JS_CallUnbarrieredScriptTracer(JSTracer* trc, JSScript** scriptp, const char* name);
+using ZoneSet = js::HashSet<Zone*, js::DefaultHasher<Zone*>, js::SystemAllocPolicy>;
+using CompartmentSet = js::HashSet<JSCompartment*, js::DefaultHasher<JSCompartment*>,
+ js::SystemAllocPolicy>;
/**
- * Trace an object that is known to always be tenured. No post barriers are
- * required in this case.
+ * Trace every value within |compartments| that is wrapped by a
+ * cross-compartment wrapper from a compartment that is not an element of
+ * |compartments|.
*/
extern JS_PUBLIC_API(void)
-JS_CallTenuredObjectTracer(JSTracer* trc, JS::TenuredHeap<JSObject*>* objp, const char* name);
+TraceIncomingCCWs(JSTracer* trc, const JS::CompartmentSet& compartments);
-extern JS_PUBLIC_API(void)
-JS_TraceRuntime(JSTracer* trc);
-
-namespace JS {
-extern JS_PUBLIC_API(void)
-TraceChildren(JSTracer* trc, GCCellPtr thing);
-
-typedef js::HashSet<Zone*, js::DefaultHasher<Zone*>, js::SystemAllocPolicy> ZoneSet;
} // namespace JS
-/**
- * Trace every value within |zones| that is wrapped by a cross-compartment
- * wrapper from a zone that is not an element of |zones|.
- */
-extern JS_PUBLIC_API(void)
-JS_TraceIncomingCCWs(JSTracer* trc, const JS::ZoneSet& zones);
-
extern JS_PUBLIC_API(void)
JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc,
void* thing, JS::TraceKind kind, bool includeDetails);
namespace js {
-namespace gc {
-template <typename T>
-extern JS_PUBLIC_API(bool)
-EdgeNeedsSweep(JS::Heap<T>* edgep);
-} // namespace gc
-// Automates static dispatch for GC interaction with TraceableContainers.
-template <typename>
-struct DefaultGCPolicy;
-
-// This policy dispatches GC methods to a method on the type.
+// Trace an edge that is not a GC root and is not wrapped in a barriered
+// wrapper for some reason.
+//
+// This method does not check if |*edgep| is non-null before tracing through
+// it, so callers must check any nullable pointer before calling this method.
template <typename T>
-struct StructGCPolicy {
- static void trace(JSTracer* trc, T* t, const char* name) {
- // This is the default GC policy for storing GC things in containers.
- // If your build is failing here, it means you either need an
- // implementation of DefaultGCPolicy<T> for your type or, if this is
- // the right policy for you, your struct or container is missing a
- // trace method.
- t->trace(trc);
- }
-
- static bool needsSweep(T* t) {
- return t->needsSweep();
- }
-};
+extern JS_PUBLIC_API(void)
+UnsafeTraceManuallyBarrieredEdge(JSTracer* trc, T* edgep, const char* name);
-// This policy ignores any GC interaction, e.g. for non-GC types.
-template <typename T>
-struct IgnoreGCPolicy {
- static void trace(JSTracer* trc, T* t, const char* name) {}
- static bool needsSweep(T* v) { return false; }
-};
+namespace gc {
-// The default policy when no other more specific policy fits (e.g. for a
-// direct GC pointer), is to assume a struct type that implements the needed
-// methods.
+// Return true if the given edge is not live and is about to be swept.
template <typename T>
-struct DefaultGCPolicy : public StructGCPolicy<T> {};
-
-template <>
-struct DefaultGCPolicy<jsid>
-{
- static void trace(JSTracer* trc, jsid* id, const char* name) {
- JS_CallUnbarrieredIdTracer(trc, id, name);
- }
-};
-
-template <> struct DefaultGCPolicy<uint32_t> : public IgnoreGCPolicy<uint32_t> {};
-template <> struct DefaultGCPolicy<uint64_t> : public IgnoreGCPolicy<uint64_t> {};
+extern JS_PUBLIC_API(bool)
+EdgeNeedsSweep(JS::Heap<T>* edgep);
+// Not part of the public API, but declared here so we can use it in GCPolicy
+// which is.
template <typename T>
-struct DefaultGCPolicy<JS::Heap<T>>
-{
- static void trace(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
- JS::TraceEdge(trc, thingp, name);
- }
- static bool needsSweep(JS::Heap<T>* thingp) {
- return gc::EdgeNeedsSweep(thingp);
- }
-};
+bool
+IsAboutToBeFinalizedUnbarriered(T* thingp);
+} // namespace gc
} // namespace js
#endif /* js_TracingAPI_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TrackedOptimizationInfo.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TrackedOptimizationInfo.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/TrackedOptimizationInfo.h
@@ -16,6 +16,7 @@
_(GetProp_ArgumentsCallee) \
_(GetProp_InferredConstant) \
_(GetProp_Constant) \
+ _(GetProp_NotDefined) \
_(GetProp_StaticName) \
_(GetProp_SimdGetter) \
_(GetProp_TypedObject) \
@@ -51,6 +52,12 @@
_(SetElem_Arguments) \
_(SetElem_InlineCache) \
\
+ _(BinaryArith_Concat) \
+ _(BinaryArith_SpecializedTypes) \
+ _(BinaryArith_SpecializedOnBaselineTypes) \
+ _(BinaryArith_SharedCache) \
+ _(BinaryArith_Call) \
+ \
_(InlineCache_OptimizedStub) \
\
_(Call_Inline)
@@ -74,6 +81,7 @@
_(NotObject) \
_(NotStruct) \
_(NotUnboxed) \
+ _(NotUndefined) \
_(UnboxedConvertedToNative) \
_(StructNoField) \
_(InconsistentFieldType) \
@@ -88,13 +96,17 @@
_(ArrayDoubleConversion) \
_(ArrayRange) \
_(ArraySeenNegativeIndex) \
- _(TypedObjectNeutered) \
+ _(TypedObjectHasDetachedBuffer) \
_(TypedObjectArrayRange) \
_(AccessNotDense) \
_(AccessNotSimdObject) \
_(AccessNotTypedObject) \
_(AccessNotTypedArray) \
_(AccessNotString) \
+ _(OperandNotString) \
+ _(OperandNotNumber) \
+ _(OperandNotStringOrNumber) \
+ _(OperandNotSimpleArith) \
_(StaticTypedArrayUint32) \
_(StaticTypedArrayCantComputeMask) \
_(OutOfBounds) \
@@ -144,6 +156,7 @@
\
_(ICNameStub_ReadSlot) \
_(ICNameStub_CallGetter) \
+ _(ICNameStub_TypeOfNoProperty) \
\
_(CantInlineGeneric) \
_(CantInlineNoTarget) \
@@ -180,6 +193,7 @@
#define TRACKED_TYPESITE_LIST(_) \
_(Receiver) \
+ _(Operand) \
_(Index) \
_(Value) \
_(Call_Target) \
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNode.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNode.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNode.h
@@ -15,7 +15,6 @@
#include "mozilla/Move.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/TypeTraits.h"
-#include "mozilla/UniquePtr.h"
#include "mozilla/Variant.h"
#include "jspubtd.h"
@@ -25,6 +24,7 @@
#include "js/RootingAPI.h"
#include "js/TracingAPI.h"
#include "js/TypeDecls.h"
+#include "js/UniquePtr.h"
#include "js/Value.h"
#include "js/Vector.h"
@@ -71,7 +71,7 @@
// One can construct a ubi::Node value given a pointer to a type that ubi::Node
// supports. In the other direction, one can convert a ubi::Node back to a
// pointer; these downcasts are checked dynamically. In particular, one can
-// convert a 'JSRuntime*' to a ubi::Node, yielding a node with an outgoing edge
+// convert a 'JSContext*' to a ubi::Node, yielding a node with an outgoing edge
// for every root registered with the runtime; starting from this, one can walk
// the entire heap. (Of course, one could also start traversal at any other kind
// of type to which one has a pointer.)
@@ -174,16 +174,6 @@
} // namespace ubi
} // namespace JS
-namespace mozilla {
-
-template<>
-class DefaultDelete<JS::ubi::EdgeRange> : public JS::DeletePolicy<JS::ubi::EdgeRange> { };
-
-template<>
-class DefaultDelete<JS::ubi::StackFrame> : public JS::DeletePolicy<JS::ubi::StackFrame> { };
-
-} // namespace mozilla
-
namespace JS {
namespace ubi {
@@ -191,9 +181,11 @@
using mozilla::Maybe;
using mozilla::Move;
using mozilla::RangedPtr;
-using mozilla::UniquePtr;
using mozilla::Variant;
+template <typename T>
+using Vector = mozilla::Vector<T, 0, js::SystemAllocPolicy>;
+
/*** ubi::StackFrame ******************************************************************************/
// Concrete JS::ubi::StackFrame instances backed by a live SavedFrame object
@@ -201,7 +193,7 @@
// heap snapshots store their strings as const char16_t*. In order to provide
// zero-cost accessors to these strings in a single interface that works with
// both cases, we use this variant type.
-class AtomOrTwoByteChars : public Variant<JSAtom*, const char16_t*> {
+class JS_PUBLIC_API(AtomOrTwoByteChars) : public Variant<JSAtom*, const char16_t*> {
using Base = Variant<JSAtom*, const char16_t*>;
public:
@@ -267,7 +259,7 @@
// Return true if this frame's function is a self-hosted JavaScript builtin,
// false otherwise.
- virtual bool isSelfHosted() const = 0;
+ virtual bool isSelfHosted(JSContext* cx) const = 0;
// Construct a SavedFrame stack for the stack starting with this frame and
// containing all of its parents. The SavedFrame objects will be placed into
@@ -294,8 +286,9 @@
// simplifies the principals check into the boolean isSystem() state. This
// is fine because we only expose JS::ubi::Stack to devtools and chrome
// code, and not to the web platform.
- virtual bool constructSavedFrameStack(JSContext* cx,
- MutableHandleObject outSavedFrameStack) const = 0;
+ virtual MOZ_MUST_USE bool constructSavedFrameStack(JSContext* cx,
+ MutableHandleObject outSavedFrameStack)
+ const = 0;
// Trace the concrete implementation of JS::ubi::StackFrame.
virtual void trace(JSTracer* trc) = 0;
@@ -319,7 +312,7 @@
// valid within the scope of an AutoCheckCannotGC; if the graph being analyzed
// is an offline heap snapshot, the JS::ubi::StackFrame is valid as long as the
// offline heap snapshot is alive.
-class StackFrame : public JS::Traceable {
+class StackFrame {
// Storage in which we allocate BaseStackFrame subclasses.
mozilla::AlignedStorage2<BaseStackFrame> storage;
@@ -409,12 +402,6 @@
size_t sourceLength();
size_t functionDisplayNameLength();
- // JS::Traceable implementation just forwards to our virtual trace method.
- static void trace(StackFrame* frame, JSTracer* trc) {
- if (frame)
- frame->trace(trc);
- }
-
// Methods that forward to virtual calls through BaseStackFrame.
void trace(JSTracer* trc) { base()->trace(trc); }
@@ -429,9 +416,9 @@
AtomOrTwoByteChars functionDisplayName() const { return base()->functionDisplayName(); }
StackFrame parent() const { return base()->parent(); }
bool isSystem() const { return base()->isSystem(); }
- bool isSelfHosted() const { return base()->isSelfHosted(); }
- bool constructSavedFrameStack(JSContext* cx,
- MutableHandleObject outSavedFrameStack) const {
+ bool isSelfHosted(JSContext* cx) const { return base()->isSelfHosted(cx); }
+ MOZ_MUST_USE bool constructSavedFrameStack(JSContext* cx,
+ MutableHandleObject outSavedFrameStack) const {
return base()->constructSavedFrameStack(cx, outSavedFrameStack);
}
@@ -463,7 +450,9 @@
uint64_t identifier() const override { return 0; }
void trace(JSTracer* trc) override { }
- bool constructSavedFrameStack(JSContext* cx, MutableHandleObject out) const override {
+ MOZ_MUST_USE bool constructSavedFrameStack(JSContext* cx, MutableHandleObject out)
+ const override
+ {
out.set(nullptr);
return true;
}
@@ -474,11 +463,13 @@
AtomOrTwoByteChars functionDisplayName() const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
StackFrame parent() const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
bool isSystem() const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
- bool isSelfHosted() const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
+ bool isSelfHosted(JSContext* cx) const override { MOZ_CRASH("null JS::ubi::StackFrame"); }
};
-bool ConstructSavedFrameStackSlow(JSContext* cx, JS::ubi::StackFrame& frame,
- MutableHandleObject outSavedFrameStack);
+MOZ_MUST_USE JS_PUBLIC_API(bool)
+ConstructSavedFrameStackSlow(JSContext* cx,
+ JS::ubi::StackFrame& frame,
+ MutableHandleObject outSavedFrameStack);
/*** ubi::Node ************************************************************************************/
@@ -529,7 +520,7 @@
// The base class implemented by each ubi::Node referent type. Subclasses must
// not add data members to this class.
-class Base {
+class JS_PUBLIC_API(Base) {
friend class Node;
// For performance's sake, we'd prefer to avoid a virtual destructor; and
@@ -579,7 +570,7 @@
virtual CoarseType coarseType() const { return CoarseType::Other; }
// Return a human-readable name for the referent's type. The result should
- // be statically allocated. (You can use MOZ_UTF16("strings") for this.)
+ // be statically allocated. (You can use u"strings" for this.)
//
// This must always return Concrete<T>::concreteTypeName; we use that
// pointer as a tag for this particular referent type.
@@ -589,6 +580,11 @@
// node owns exclusively that are not exposed as their own ubi::Nodes.
// |mallocSizeOf| should be a malloc block sizing function; see
// |mfbt/MemoryReporting.h|.
+ //
+ // Because we can use |JS::ubi::Node|s backed by a snapshot that was taken
+ // on a 64-bit platform when we are currently on a 32-bit platform, we
+ // cannot rely on |size_t| for node sizes. Instead, |Size| is uint64_t on
+ // all platforms.
using Size = uint64_t;
virtual Size size(mozilla::MallocSizeOf mallocSizeof) const { return 1; }
@@ -597,7 +593,7 @@
//
// If wantNames is true, compute names for edges. Doing so can be expensive
// in time and memory.
- virtual UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const = 0;
+ virtual js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const = 0;
// Return the Zone to which this node's referent belongs, or nullptr if the
// referent is not of a type allocated in SpiderMonkey Zones.
@@ -633,8 +629,9 @@
// Otherwise, place nullptr in the out parameter. Caller maintains ownership
// of the out parameter. True is returned on success, false is returned on
// OOM.
- virtual bool jsObjectConstructorName(JSContext* cx,
- UniquePtr<char16_t[], JS::FreePolicy>& outName) const {
+ virtual MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& outName)
+ const
+ {
outName.reset(nullptr);
return true;
}
@@ -651,28 +648,28 @@
};
// A traits template with a specialization for each referent type that
-// ubi::Node supports. The specialization must be the concrete subclass of
-// Base that represents a pointer to the referent type. It must also
-// include the members described here.
+// ubi::Node supports. The specialization must be the concrete subclass of Base
+// that represents a pointer to the referent type. It must include these
+// members:
+//
+// // The specific char16_t array returned by Concrete<T>::typeName().
+// static const char16_t concreteTypeName[];
+//
+// // Construct an instance of this concrete class in |storage| referring
+// // to |referent|. Implementations typically use a placement 'new'.
+// //
+// // In some cases, |referent| will contain dynamic type information that
+// // identifies it a some more specific subclass of |Referent|. For
+// // example, when |Referent| is |JSObject|, then |referent->getClass()|
+// // could tell us that it's actually a JSFunction. Similarly, if
+// // |Referent| is |nsISupports|, we would like a ubi::Node that knows its
+// // final implementation type.
+// //
+// // So we delegate the actual construction to this specialization, which
+// // knows Referent's details.
+// static void construct(void* storage, Referent* referent);
template<typename Referent>
-struct Concrete {
- // The specific char16_t array returned by Concrete<T>::typeName.
- static const char16_t concreteTypeName[];
-
- // Construct an instance of this concrete class in |storage| referring
- // to |referent|. Implementations typically use a placement 'new'.
- //
- // In some cases, |referent| will contain dynamic type information that
- // identifies it a some more specific subclass of |Referent|. For example,
- // when |Referent| is |JSObject|, then |referent->getClass()| could tell us
- // that it's actually a JSFunction. Similarly, if |Referent| is
- // |nsISupports|, we would like a ubi::Node that knows its final
- // implementation type.
- //
- // So, we delegate the actual construction to this specialization, which
- // knows Referent's details.
- static void construct(void* storage, Referent* referent);
-};
+class Concrete;
// A container for a Base instance; all members simply forward to the contained
// instance. This container allows us to pass ubi::Node instances by value.
@@ -686,6 +683,8 @@
void construct(T* ptr) {
static_assert(sizeof(Concrete<T>) == sizeof(*base()),
"ubi::Base specializations must be the same size as ubi::Base");
+ static_assert(mozilla::IsBaseOf<Base, Concrete<T>>::value,
+ "ubi::Concrete<T> must inherit from ubi::Base");
Concrete<T>::construct(base(), ptr);
}
struct ConstructFunctor;
@@ -780,8 +779,7 @@
JS::Zone* zone() const { return base()->zone(); }
JSCompartment* compartment() const { return base()->compartment(); }
const char* jsObjectClassName() const { return base()->jsObjectClassName(); }
- bool jsObjectConstructorName(JSContext* cx,
- UniquePtr<char16_t[], JS::FreePolicy>& outName) const {
+ MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& outName) const {
return base()->jsObjectConstructorName(cx, outName);
}
@@ -796,8 +794,8 @@
return size;
}
- UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames = true) const {
- return base()->edges(rt, wantNames);
+ js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames = true) const {
+ return base()->edges(cx, wantNames);
}
bool hasAllocationStack() const { return base()->hasAllocationStack(); }
@@ -827,10 +825,12 @@
};
};
+using NodeSet = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
+using NodeSetPtr = mozilla::UniquePtr<NodeSet, JS::DeletePolicy<NodeSet>>;
/*** Edge and EdgeRange ***************************************************************************/
-using EdgeName = UniquePtr<const char16_t[], JS::FreePolicy>;
+using EdgeName = UniqueTwoByteChars;
// An outgoing edge to a referent node.
class Edge {
@@ -863,7 +863,8 @@
// false as the wantNames parameter.
//
// The storage is owned by this Edge, and will be freed when this Edge is
- // destructed.
+ // destructed. You may take ownership of the name by `mozilla::Move`ing it
+ // out of the edge; it is just a UniquePtr.
//
// (In real life we'll want a better representation for names, to avoid
// creating tons of strings when the names follow a pattern; and we'll need
@@ -959,7 +960,7 @@
//
// {
// mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC;
-// JS::ubi::RootList rootList(rt, maybeNoGC);
+// JS::ubi::RootList rootList(cx, maybeNoGC);
// if (!rootList.init())
// return false;
//
@@ -970,22 +971,23 @@
//
// ...
// }
-class MOZ_STACK_CLASS RootList {
+class MOZ_STACK_CLASS JS_PUBLIC_API(RootList) {
Maybe<AutoCheckCannotGC>& noGC;
public:
- JSRuntime* rt;
+ JSContext* cx;
EdgeVector edges;
bool wantNames;
- RootList(JSRuntime* rt, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
+ RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
// Find all GC roots.
- bool init();
- // Find only GC roots in the provided set of |Zone|s.
- bool init(ZoneSet& debuggees);
- // Find only GC roots in the given Debugger object's set of debuggee zones.
- bool init(HandleObject debuggees);
+ MOZ_MUST_USE bool init();
+ // Find only GC roots in the provided set of |JSCompartment|s.
+ MOZ_MUST_USE bool init(CompartmentSet& debuggees);
+ // Find only GC roots in the given Debugger object's set of debuggee
+ // compartments.
+ MOZ_MUST_USE bool init(HandleObject debuggees);
// Returns true if the RootList has been initialized successfully, false
// otherwise.
@@ -994,64 +996,53 @@
// Explicitly add the given Node as a root in this RootList. If wantNames is
// true, you must pass an edgeName. The RootList does not take ownership of
// edgeName.
- bool addRoot(Node node, const char16_t* edgeName = nullptr);
+ MOZ_MUST_USE bool addRoot(Node node, const char16_t* edgeName = nullptr);
};
/*** Concrete classes for ubi::Node referent types ************************************************/
template<>
-struct Concrete<RootList> : public Base {
- UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
- const char16_t* typeName() const override { return concreteTypeName; }
-
+class JS_PUBLIC_API(Concrete<RootList>) : public Base {
protected:
explicit Concrete(RootList* ptr) : Base(ptr) { }
RootList& get() const { return *static_cast<RootList*>(ptr); }
public:
- static const char16_t concreteTypeName[];
static void construct(void* storage, RootList* ptr) { new (storage) Concrete(ptr); }
+
+ js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
+
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
};
// A reusable ubi::Concrete specialization base class for types supported by
// JS::TraceChildren.
template<typename Referent>
-class TracerConcrete : public Base {
- const char16_t* typeName() const override { return concreteTypeName; }
- UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
+class JS_PUBLIC_API(TracerConcrete) : public Base {
+ js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
JS::Zone* zone() const override;
protected:
explicit TracerConcrete(Referent* ptr) : Base(ptr) { }
Referent& get() const { return *static_cast<Referent*>(ptr); }
-
- public:
- static const char16_t concreteTypeName[];
- static void construct(void* storage, Referent* ptr) { new (storage) TracerConcrete(ptr); }
};
// For JS::TraceChildren-based types that have a 'compartment' method.
template<typename Referent>
-class TracerConcreteWithCompartment : public TracerConcrete<Referent> {
+class JS_PUBLIC_API(TracerConcreteWithCompartment) : public TracerConcrete<Referent> {
typedef TracerConcrete<Referent> TracerBase;
JSCompartment* compartment() const override;
protected:
explicit TracerConcreteWithCompartment(Referent* ptr) : TracerBase(ptr) { }
-
- public:
- static void construct(void* storage, Referent* ptr) {
- new (storage) TracerConcreteWithCompartment(ptr);
- }
};
// Define specializations for some commonly-used public JSAPI types.
// These can use the generic templates above.
template<>
-struct Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> {
- Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
-
+class JS_PUBLIC_API(Concrete<JS::Symbol>) : TracerConcrete<JS::Symbol> {
protected:
explicit Concrete(JS::Symbol* ptr) : TracerConcrete(ptr) { }
@@ -1059,33 +1050,32 @@
static void construct(void* storage, JS::Symbol* ptr) {
new (storage) Concrete(ptr);
}
-};
-template<> struct Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> {
- CoarseType coarseType() const final { return CoarseType::Script; }
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
- const char* scriptFilename() const final;
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
+};
+
+template<>
+class JS_PUBLIC_API(Concrete<JSScript>) : TracerConcreteWithCompartment<JSScript> {
protected:
explicit Concrete(JSScript *ptr) : TracerConcreteWithCompartment<JSScript>(ptr) { }
public:
static void construct(void *storage, JSScript *ptr) { new (storage) Concrete(ptr); }
-};
-// The JSObject specialization.
-template<>
-class Concrete<JSObject> : public TracerConcreteWithCompartment<JSObject> {
- const char* jsObjectClassName() const override;
- bool jsObjectConstructorName(JSContext* cx,
- UniquePtr<char16_t[], JS::FreePolicy>& outName) const override;
+ CoarseType coarseType() const final { return CoarseType::Script; }
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
+ const char* scriptFilename() const final;
- bool hasAllocationStack() const override;
- StackFrame allocationStack() const override;
-
- CoarseType coarseType() const final { return CoarseType::Object; }
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
+};
+// The JSObject specialization.
+template<>
+class JS_PUBLIC_API(Concrete<JSObject>) : public TracerConcreteWithCompartment<JSObject> {
protected:
explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { }
@@ -1093,27 +1083,44 @@
static void construct(void* storage, JSObject* ptr) {
new (storage) Concrete(ptr);
}
-};
-// For JSString, we extend the generic template with a 'size' implementation.
-template<> struct Concrete<JSString> : TracerConcrete<JSString> {
+ const char* jsObjectClassName() const override;
+ MOZ_MUST_USE bool jsObjectConstructorName(JSContext* cx, UniqueTwoByteChars& outName)
+ const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
- CoarseType coarseType() const final { return CoarseType::String; }
+ bool hasAllocationStack() const override;
+ StackFrame allocationStack() const override;
+
+ CoarseType coarseType() const final { return CoarseType::Object; }
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
+};
+
+// For JSString, we extend the generic template with a 'size' implementation.
+template<>
+class JS_PUBLIC_API(Concrete<JSString>) : TracerConcrete<JSString> {
protected:
explicit Concrete(JSString *ptr) : TracerConcrete<JSString>(ptr) { }
public:
static void construct(void *storage, JSString *ptr) { new (storage) Concrete(ptr); }
+
+ Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
+
+ CoarseType coarseType() const final { return CoarseType::String; }
+
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
};
// The ubi::Node null pointer. Any attempt to operate on a null ubi::Node asserts.
template<>
-class Concrete<void> : public Base {
+class JS_PUBLIC_API(Concrete<void>) : public Base {
const char16_t* typeName() const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
- UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
+ js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
JS::Zone* zone() const override;
JSCompartment* compartment() const override;
CoarseType coarseType() const final;
@@ -1122,7 +1129,6 @@
public:
static void construct(void* storage, void* ptr) { new (storage) Concrete(ptr); }
- static const char16_t concreteTypeName[];
};
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeBreadthFirst.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeBreadthFirst.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeBreadthFirst.h
@@ -83,8 +83,8 @@
//
// We do nothing with noGC, other than require it to exist, with a lifetime
// that encloses our own.
- BreadthFirst(JSRuntime* rt, Handler& handler, const JS::AutoCheckCannotGC& noGC)
- : wantNames(true), rt(rt), visited(), handler(handler), pending(),
+ BreadthFirst(JSContext* cx, Handler& handler, const JS::AutoCheckCannotGC& noGC)
+ : wantNames(true), cx(cx), visited(), handler(handler), pending(),
traversalBegun(false), stopRequested(false), abandonRequested(false)
{ }
@@ -126,7 +126,7 @@
pending.popFront();
// Get a range containing all origin's outgoing edges.
- auto range = origin.edges(rt, wantNames);
+ auto range = origin.edges(cx, wantNames);
if (!range)
return false;
@@ -134,7 +134,7 @@
for (; !range->empty(); range->popFront()) {
MOZ_ASSERT(!stopRequested);
- const Edge& edge = range->front();
+ Edge& edge = range->front();
typename NodeMap::AddPtr a = visited.lookupForAdd(edge.referent);
bool first = !a;
@@ -181,8 +181,8 @@
// Other edges *to* that referent will still be traversed.
void abandonReferent() { abandonRequested = true; }
- // The runtime with which we were constructed.
- JSRuntime* rt;
+ // The context with which we were constructed.
+ JSContext* cx;
// A map associating each node N that we have reached with a
// Handler::NodeData, for |handler|'s use. This is public, so that
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeCensus.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeCensus.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeCensus.h
@@ -7,8 +7,11 @@
#ifndef js_UbiNodeCensus_h
#define js_UbiNodeCensus_h
+#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
+#include <algorithm>
+
#include "jsapi.h"
#include "js/UbiNode.h"
@@ -80,14 +83,14 @@
class CountBase;
struct CountDeleter {
- void operator()(CountBase*);
+ JS_PUBLIC_API(void) operator()(CountBase*);
};
-using CountBasePtr = UniquePtr<CountBase, CountDeleter>;
+using CountBasePtr = js::UniquePtr<CountBase, CountDeleter>;
// Abstract base class for CountType nodes.
struct CountType {
- explicit CountType(Census& census) : census(census) { }
+ explicit CountType() { }
virtual ~CountType() { }
// Destruct a count tree node that this type instance constructed.
@@ -102,17 +105,17 @@
// Implement the 'count' method for counts returned by this CountType
// instance's 'newCount' method.
- virtual bool count(CountBase& count, const Node& node) = 0;
+ virtual MOZ_MUST_USE bool count(CountBase& count,
+ mozilla::MallocSizeOf mallocSizeOf,
+ const Node& node) = 0;
// Implement the 'report' method for counts returned by this CountType
// instance's 'newCount' method.
- virtual bool report(CountBase& count, MutableHandleValue report) = 0;
-
- protected:
- Census& census;
+ virtual MOZ_MUST_USE bool report(JSContext* cx, CountBase& count,
+ MutableHandleValue report) = 0;
};
-using CountTypePtr = UniquePtr<CountType, JS::DeletePolicy<CountType>>;
+using CountTypePtr = js::UniquePtr<CountType>;
// An abstract base class for count tree nodes.
class CountBase {
@@ -126,15 +129,39 @@
~CountBase() { }
public:
- explicit CountBase(CountType& type) : type(type), total_(0) { }
+ explicit CountBase(CountType& type)
+ : type(type)
+ , total_(0)
+ , smallestNodeIdCounted_(SIZE_MAX)
+ { }
// Categorize and count |node| as appropriate for this count's type.
- bool count(const Node& node) { return type.count(*this, node); }
+ MOZ_MUST_USE bool count(mozilla::MallocSizeOf mallocSizeOf, const Node& node) {
+ total_++;
+
+ auto id = node.identifier();
+ if (id < smallestNodeIdCounted_) {
+ smallestNodeIdCounted_ = id;
+ }
+
+#ifdef DEBUG
+ size_t oldTotal = total_;
+#endif
+
+ bool ret = type.count(*this, mallocSizeOf, node);
+
+ MOZ_ASSERT(total_ == oldTotal,
+ "CountType::count should not increment total_, CountBase::count handles that");
+
+ return ret;
+ }
// Construct a JavaScript object reporting the counts recorded in this
// count, and store it in |report|. Return true on success, or false on
// failure.
- bool report(MutableHandleValue report) { return type.report(*this, report); }
+ MOZ_MUST_USE bool report(JSContext* cx, MutableHandleValue report) {
+ return type.report(cx, *this, report);
+ }
// Down-cast this CountBase to its true type, based on its 'type' member,
// and run its destructor.
@@ -144,6 +171,10 @@
void trace(JSTracer* trc) { type.traceCount(*this, trc); }
size_t total_;
+
+ // The smallest JS::ubi::Node::identifier() passed to this instance's
+ // count() method. This provides a stable way to sort sets.
+ Node::Id smallestNodeIdCounted_;
};
class RootedCount : JS::CustomAutoRooter {
@@ -172,19 +203,7 @@
explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
- bool init();
-
- // A 'new' work-alike that behaves like TempAllocPolicy: report OOM on this
- // census's context, but don't charge the memory allocated to our context's
- // GC pressure counters.
- template<typename T, typename... Args>
- T* new_(Args&&... args) MOZ_HEAP_ALLOCATOR {
- void* memory = js_malloc(sizeof(T));
- if (MOZ_UNLIKELY(!memory)) {
- return nullptr;
- }
- return new(memory) T(mozilla::Forward<Args>(args)...);
- }
+ MOZ_MUST_USE JS_PUBLIC_API(bool) init();
};
// A BreadthFirst handler type that conducts a census, using a CountBase to
@@ -192,31 +211,40 @@
class CensusHandler {
Census& census;
CountBasePtr& rootCount;
+ mozilla::MallocSizeOf mallocSizeOf;
public:
- CensusHandler(Census& census, CountBasePtr& rootCount)
+ CensusHandler(Census& census, CountBasePtr& rootCount, mozilla::MallocSizeOf mallocSizeOf)
: census(census),
- rootCount(rootCount)
+ rootCount(rootCount),
+ mallocSizeOf(mallocSizeOf)
{ }
- bool report(MutableHandleValue report) {
- return rootCount->report(report);
+ MOZ_MUST_USE bool report(JSContext* cx, MutableHandleValue report) {
+ return rootCount->report(cx, report);
}
// This class needs to retain no per-node data.
class NodeData { };
- bool operator() (BreadthFirst<CensusHandler>& traversal,
- Node origin, const Edge& edge,
- NodeData* referentData, bool first);
+ MOZ_MUST_USE JS_PUBLIC_API(bool) operator() (BreadthFirst<CensusHandler>& traversal,
+ Node origin, const Edge& edge,
+ NodeData* referentData, bool first);
};
using CensusTraversal = BreadthFirst<CensusHandler>;
-// Examine the census options supplied by the API consumer, and use that to
-// build a CountType tree.
-bool ParseCensusOptions(JSContext* cx, Census& census, HandleObject options,
- CountTypePtr& outResult);
+// Examine the census options supplied by the API consumer, and (among other
+// things) use that to build a CountType tree.
+MOZ_MUST_USE JS_PUBLIC_API(bool) ParseCensusOptions(JSContext* cx,
+ Census& census, HandleObject options,
+ CountTypePtr& outResult);
+
+// Parse the breakdown language (as described in
+// js/src/doc/Debugger/Debugger.Memory.md) into a CountTypePtr. A null pointer
+// is returned on error and is reported to the cx.
+JS_PUBLIC_API(CountTypePtr) ParseBreakdown(JSContext* cx, HandleValue breakdownValue);
+
} // namespace ubi
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeDominatorTree.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeDominatorTree.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeDominatorTree.h
@@ -7,6 +7,7 @@
#ifndef js_UbiNodeDominatorTree_h
#define js_UbiNodeDominatorTree_h
+#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Maybe.h"
#include "mozilla/Move.h"
@@ -71,8 +72,6 @@
private:
// Types.
- using NodeSet = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
- using NodeSetPtr = mozilla::UniquePtr<NodeSet, JS::DeletePolicy<NodeSet>>;
using PredecessorSets = js::HashMap<Node, NodeSetPtr, js::DefaultHasher<Node>,
js::SystemAllocPolicy>;
using NodeToIndexMap = js::HashMap<Node, uint32_t, js::DefaultHasher<Node>,
@@ -95,10 +94,10 @@
{
friend class DominatedSetRange;
- const mozilla::Vector<Node>& postOrder;
+ const JS::ubi::Vector<Node>& postOrder;
const uint32_t* ptr;
- DominatedNodePtr(const mozilla::Vector<Node>& postOrder, const uint32_t* ptr)
+ DominatedNodePtr(const JS::ubi::Vector<Node>& postOrder, const uint32_t* ptr)
: postOrder(postOrder)
, ptr(ptr)
{ }
@@ -119,11 +118,11 @@
{
friend class DominatedSets;
- const mozilla::Vector<Node>& postOrder;
+ const JS::ubi::Vector<Node>& postOrder;
const uint32_t* beginPtr;
const uint32_t* endPtr;
- DominatedSetRange(mozilla::Vector<Node>& postOrder, const uint32_t* begin, const uint32_t* end)
+ DominatedSetRange(JS::ubi::Vector<Node>& postOrder, const uint32_t* begin, const uint32_t* end)
: postOrder(postOrder)
, beginPtr(begin)
, endPtr(end)
@@ -180,10 +179,10 @@
*/
class DominatedSets
{
- mozilla::Vector<uint32_t> dominated;
- mozilla::Vector<uint32_t> indices;
+ JS::ubi::Vector<uint32_t> dominated;
+ JS::ubi::Vector<uint32_t> indices;
- DominatedSets(mozilla::Vector<uint32_t>&& dominated, mozilla::Vector<uint32_t>&& indices)
+ DominatedSets(JS::ubi::Vector<uint32_t>&& dominated, JS::ubi::Vector<uint32_t>&& indices)
: dominated(mozilla::Move(dominated))
, indices(mozilla::Move(indices))
{ }
@@ -211,7 +210,7 @@
* immediate dominator. Returns `Some` on success, `Nothing` on OOM
* failure.
*/
- static mozilla::Maybe<DominatedSets> Create(const mozilla::Vector<uint32_t>& doms) {
+ static mozilla::Maybe<DominatedSets> Create(const JS::ubi::Vector<uint32_t>& doms) {
auto length = doms.length();
MOZ_ASSERT(length < UINT32_MAX);
@@ -236,8 +235,8 @@
// filled in. After having filled in all of a bucket's entries,
// the index points to the start of the bucket.
- mozilla::Vector<uint32_t> dominated;
- mozilla::Vector<uint32_t> indices;
+ JS::ubi::Vector<uint32_t> dominated;
+ JS::ubi::Vector<uint32_t> indices;
if (!dominated.growBy(length) || !indices.growBy(length))
return mozilla::Nothing();
@@ -279,7 +278,7 @@
* Get the set of nodes immediately dominated by the node at
* `postOrder[nodeIndex]`.
*/
- DominatedSetRange dominatedSet(mozilla::Vector<Node>& postOrder, uint32_t nodeIndex) const {
+ DominatedSetRange dominatedSet(JS::ubi::Vector<Node>& postOrder, uint32_t nodeIndex) const {
MOZ_ASSERT(postOrder.length() == indices.length());
MOZ_ASSERT(nodeIndex < indices.length());
auto end = nodeIndex == indices.length() - 1
@@ -291,11 +290,11 @@
private:
// Data members.
- mozilla::Vector<Node> postOrder;
+ JS::ubi::Vector<Node> postOrder;
NodeToIndexMap nodeToPostOrderIndex;
- mozilla::Vector<uint32_t> doms;
+ JS::ubi::Vector<uint32_t> doms;
DominatedSets dominatedSets;
- mozilla::Maybe<mozilla::Vector<JS::ubi::Node::Size>> retainedSizes;
+ mozilla::Maybe<JS::ubi::Vector<JS::ubi::Node::Size>> retainedSizes;
private:
// We use `UNDEFINED` as a sentinel value in the `doms` vector to signal
@@ -303,8 +302,8 @@
// index in `postOrder` yet.
static const uint32_t UNDEFINED = UINT32_MAX;
- DominatorTree(mozilla::Vector<Node>&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex,
- mozilla::Vector<uint32_t>&& doms, DominatedSets&& dominatedSets)
+ DominatorTree(JS::ubi::Vector<Node>&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex,
+ JS::ubi::Vector<uint32_t>&& doms, DominatedSets&& dominatedSets)
: postOrder(mozilla::Move(postOrder))
, nodeToPostOrderIndex(mozilla::Move(nodeToPostOrderIndex))
, doms(mozilla::Move(doms))
@@ -312,7 +311,7 @@
, retainedSizes(mozilla::Nothing())
{ }
- static uint32_t intersect(mozilla::Vector<uint32_t>& doms, uint32_t finger1, uint32_t finger2) {
+ static uint32_t intersect(JS::ubi::Vector<uint32_t>& doms, uint32_t finger1, uint32_t finger2) {
while (finger1 != finger2) {
if (finger1 < finger2)
finger1 = doms[finger1];
@@ -324,8 +323,9 @@
// Do the post order traversal of the heap graph and populate our
// predecessor sets.
- static bool doTraversal(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root,
- mozilla::Vector<Node>& postOrder, PredecessorSets& predecessorSets) {
+ static MOZ_MUST_USE bool doTraversal(JSContext* cx, AutoCheckCannotGC& noGC, const Node& root,
+ JS::ubi::Vector<Node>& postOrder,
+ PredecessorSets& predecessorSets) {
uint32_t nodeCount = 0;
auto onNode = [&](const Node& node) {
nodeCount++;
@@ -349,7 +349,7 @@
return p->value()->put(origin);
};
- PostOrder traversal(rt, noGC);
+ PostOrder traversal(cx, noGC);
return traversal.init() &&
traversal.addStart(root) &&
traversal.traverse(onNode, onEdge);
@@ -357,7 +357,8 @@
// Populates the given `map` with an entry for each node to its index in
// `postOrder`.
- static bool mapNodesToTheirIndices(mozilla::Vector<Node>& postOrder, NodeToIndexMap& map) {
+ static MOZ_MUST_USE bool mapNodesToTheirIndices(JS::ubi::Vector<Node>& postOrder,
+ NodeToIndexMap& map) {
MOZ_ASSERT(!map.initialized());
MOZ_ASSERT(postOrder.length() < UINT32_MAX);
uint32_t length = postOrder.length();
@@ -370,12 +371,12 @@
// Convert the Node -> NodeSet predecessorSets to a index -> Vector<index>
// form.
- static bool convertPredecessorSetsToVectors(
+ static MOZ_MUST_USE bool convertPredecessorSetsToVectors(
const Node& root,
- mozilla::Vector<Node>& postOrder,
+ JS::ubi::Vector<Node>& postOrder,
PredecessorSets& predecessorSets,
NodeToIndexMap& nodeToPostOrderIndex,
- mozilla::Vector<mozilla::Vector<uint32_t>>& predecessorVectors)
+ JS::ubi::Vector<JS::ubi::Vector<uint32_t>>& predecessorVectors)
{
MOZ_ASSERT(postOrder.length() < UINT32_MAX);
uint32_t length = postOrder.length();
@@ -409,7 +410,8 @@
// Initialize `doms` such that the immediate dominator of the `root` is the
// `root` itself and all others are `UNDEFINED`.
- static bool initializeDominators(mozilla::Vector<uint32_t>& doms, uint32_t length) {
+ static MOZ_MUST_USE bool initializeDominators(JS::ubi::Vector<uint32_t>& doms,
+ uint32_t length) {
MOZ_ASSERT(doms.length() == 0);
if (!doms.growByUninitialized(length))
return false;
@@ -425,7 +427,7 @@
MOZ_ASSERT_IF(retainedSizes.isSome(), postOrder.length() == retainedSizes->length());
}
- bool computeRetainedSizes(mozilla::MallocSizeOf mallocSizeOf) {
+ MOZ_MUST_USE bool computeRetainedSizes(mozilla::MallocSizeOf mallocSizeOf) {
MOZ_ASSERT(retainedSizes.isNothing());
auto length = postOrder.length();
@@ -511,10 +513,10 @@
* responsibility to handle and report the OOM.
*/
static mozilla::Maybe<DominatorTree>
- Create(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root) {
- mozilla::Vector<Node> postOrder;
+ Create(JSContext* cx, AutoCheckCannotGC& noGC, const Node& root) {
+ JS::ubi::Vector<Node> postOrder;
PredecessorSets predecessorSets;
- if (!predecessorSets.init() || !doTraversal(rt, noGC, root, postOrder, predecessorSets))
+ if (!predecessorSets.init() || !doTraversal(cx, noGC, root, postOrder, predecessorSets))
return mozilla::Nothing();
MOZ_ASSERT(postOrder.length() < UINT32_MAX);
@@ -531,12 +533,12 @@
if (!mapNodesToTheirIndices(postOrder, nodeToPostOrderIndex))
return mozilla::Nothing();
- mozilla::Vector<mozilla::Vector<uint32_t>> predecessorVectors;
+ JS::ubi::Vector<JS::ubi::Vector<uint32_t>> predecessorVectors;
if (!convertPredecessorSetsToVectors(root, postOrder, predecessorSets, nodeToPostOrderIndex,
predecessorVectors))
return mozilla::Nothing();
- mozilla::Vector<uint32_t> doms;
+ JS::ubi::Vector<uint32_t> doms;
if (!initializeDominators(doms, length))
return mozilla::Nothing();
@@ -650,8 +652,8 @@
* `outSize`, or 0 if `node` is not a member of the dominator tree. Returns
* false on OOM failure, leaving `outSize` unchanged.
*/
- bool getRetainedSize(const Node& node, mozilla::MallocSizeOf mallocSizeOf,
- Node::Size& outSize) {
+ MOZ_MUST_USE bool getRetainedSize(const Node& node, mozilla::MallocSizeOf mallocSizeOf,
+ Node::Size& outSize) {
assertSanity();
auto ptr = nodeToPostOrderIndex.lookup(node);
if (!ptr) {
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodePostOrder.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodePostOrder.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodePostOrder.h
@@ -7,7 +7,7 @@
#ifndef js_UbiNodePostOrder_h
#define js_UbiNodePostOrder_h
-#include "mozilla/DebugOnly.h"
+#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/Move.h"
@@ -83,13 +83,15 @@
using Stack = js::Vector<OriginAndEdges, 256, js::SystemAllocPolicy>;
using Set = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
- JSRuntime* rt;
+ JSContext* cx;
Set seen;
Stack stack;
- mozilla::DebugOnly<bool> traversed;
+#ifdef DEBUG
+ bool traversed;
+#endif
private:
- bool fillEdgesFromRange(EdgeVector& edges, UniquePtr<EdgeRange>& range) {
+ MOZ_MUST_USE bool fillEdgesFromRange(EdgeVector& edges, js::UniquePtr<EdgeRange>& range) {
MOZ_ASSERT(range);
for ( ; !range->empty(); range->popFront()) {
if (!edges.append(mozilla::Move(range->front())))
@@ -98,9 +100,9 @@
return true;
}
- bool pushForTraversing(const Node& node) {
+ MOZ_MUST_USE bool pushForTraversing(const Node& node) {
EdgeVector edges;
- auto range = node.edges(rt, /* wantNames */ false);
+ auto range = node.edges(cx, /* wantNames */ false);
return range &&
fillEdgesFromRange(edges, range) &&
stack.append(OriginAndEdges(node, mozilla::Move(edges)));
@@ -113,19 +115,21 @@
// The traversal asserts that no GC happens in its runtime during its
// lifetime via the `AutoCheckCannotGC&` parameter. We do nothing with it,
// other than require it to exist with a lifetime that encloses our own.
- PostOrder(JSRuntime* rt, AutoCheckCannotGC&)
- : rt(rt)
+ PostOrder(JSContext* cx, AutoCheckCannotGC&)
+ : cx(cx)
, seen()
, stack()
+#ifdef DEBUG
, traversed(false)
+#endif
{ }
// Initialize this traversal object. Return false on OOM.
- bool init() { return seen.init(); }
+ MOZ_MUST_USE bool init() { return seen.init(); }
// Add `node` as a starting point for the traversal. You may add
// as many starting points as you like. Returns false on OOM.
- bool addStart(const Node& node) {
+ MOZ_MUST_USE bool addStart(const Node& node) {
if (!seen.put(node))
return false;
return pushForTraversing(node);
@@ -141,9 +145,11 @@
// Return false on OOM or error return from `onNode::operator()` or
// `onEdge::operator()`.
template<typename NodeVisitor, typename EdgeVisitor>
- bool traverse(NodeVisitor onNode, EdgeVisitor onEdge) {
+ MOZ_MUST_USE bool traverse(NodeVisitor onNode, EdgeVisitor onEdge) {
+#ifdef DEBUG
MOZ_ASSERT(!traversed, "Can only traverse() once!");
traversed = true;
+#endif
while (!stack.empty()) {
auto& origin = stack.back().origin;
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeShortestPaths.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeShortestPaths.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UbiNodeShortestPaths.h
@@ -0,0 +1,350 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_UbiNodeShortestPaths_h
+#define js_UbiNodeShortestPaths_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Move.h"
+
+#include "jsalloc.h"
+
+#include "js/UbiNodeBreadthFirst.h"
+#include "js/Vector.h"
+
+namespace JS {
+namespace ubi {
+
+/**
+ * A back edge along a path in the heap graph.
+ */
+struct JS_PUBLIC_API(BackEdge)
+{
+ private:
+ Node predecessor_;
+ EdgeName name_;
+
+ public:
+ using Ptr = mozilla::UniquePtr<BackEdge, JS::DeletePolicy<BackEdge>>;
+
+ BackEdge() : predecessor_(), name_(nullptr) { }
+
+ MOZ_MUST_USE bool init(const Node& predecessor, Edge& edge) {
+ MOZ_ASSERT(!predecessor_);
+ MOZ_ASSERT(!name_);
+
+ predecessor_ = predecessor;
+ name_ = mozilla::Move(edge.name);
+ return true;
+ }
+
+ BackEdge(const BackEdge&) = delete;
+ BackEdge& operator=(const BackEdge&) = delete;
+
+ BackEdge(BackEdge&& rhs)
+ : predecessor_(rhs.predecessor_)
+ , name_(mozilla::Move(rhs.name_))
+ {
+ MOZ_ASSERT(&rhs != this);
+ }
+
+ BackEdge& operator=(BackEdge&& rhs) {
+ this->~BackEdge();
+ new(this) BackEdge(Move(rhs));
+ return *this;
+ }
+
+ Ptr clone() const;
+
+ const EdgeName& name() const { return name_; }
+ EdgeName& name() { return name_; }
+
+ const JS::ubi::Node& predecessor() const { return predecessor_; }
+};
+
+/**
+ * A path is a series of back edges from which we discovered a target node.
+ */
+using Path = JS::ubi::Vector<BackEdge*>;
+
+/**
+ * The `JS::ubi::ShortestPaths` type represents a collection of up to N shortest
+ * retaining paths for each of a target set of nodes, starting from the same
+ * root node.
+ */
+struct JS_PUBLIC_API(ShortestPaths)
+{
+ private:
+ // Types, type aliases, and data members.
+
+ using BackEdgeVector = JS::ubi::Vector<BackEdge::Ptr>;
+ using NodeToBackEdgeVectorMap = js::HashMap<Node, BackEdgeVector, js::DefaultHasher<Node>,
+ js::SystemAllocPolicy>;
+
+ struct Handler;
+ using Traversal = BreadthFirst<Handler>;
+
+ /**
+ * A `JS::ubi::BreadthFirst` traversal handler that records back edges for
+ * how we reached each node, allowing us to reconstruct the shortest
+ * retaining paths after the traversal.
+ */
+ struct Handler
+ {
+ using NodeData = BackEdge;
+
+ ShortestPaths& shortestPaths;
+ size_t totalMaxPathsToRecord;
+ size_t totalPathsRecorded;
+
+ explicit Handler(ShortestPaths& shortestPaths)
+ : shortestPaths(shortestPaths)
+ , totalMaxPathsToRecord(shortestPaths.targets_.count() * shortestPaths.maxNumPaths_)
+ , totalPathsRecorded(0)
+ {
+ }
+
+ bool
+ operator()(Traversal& traversal, JS::ubi::Node origin, JS::ubi::Edge& edge,
+ BackEdge* back, bool first)
+ {
+ MOZ_ASSERT(back);
+ MOZ_ASSERT(origin == shortestPaths.root_ || traversal.visited.has(origin));
+ MOZ_ASSERT(totalPathsRecorded < totalMaxPathsToRecord);
+
+ if (first && !back->init(origin, edge))
+ return false;
+
+ if (!shortestPaths.targets_.has(edge.referent))
+ return true;
+
+ // If `first` is true, then we moved the edge's name into `back` in
+ // the above call to `init`. So clone that back edge to get the
+ // correct edge name. If `first` is not true, then our edge name is
+ // still in `edge`. This accounts for the asymmetry between
+ // `back->clone()` in the first branch, and the `init` call in the
+ // second branch.
+
+ if (first) {
+ BackEdgeVector paths;
+ if (!paths.reserve(shortestPaths.maxNumPaths_))
+ return false;
+ auto cloned = back->clone();
+ if (!cloned)
+ return false;
+ paths.infallibleAppend(mozilla::Move(cloned));
+ if (!shortestPaths.paths_.putNew(edge.referent, mozilla::Move(paths)))
+ return false;
+ totalPathsRecorded++;
+ } else {
+ auto ptr = shortestPaths.paths_.lookup(edge.referent);
+ MOZ_ASSERT(ptr,
+ "This isn't the first time we have seen the target node `edge.referent`. "
+ "We should have inserted it into shortestPaths.paths_ the first time we "
+ "saw it.");
+
+ if (ptr->value().length() < shortestPaths.maxNumPaths_) {
+ BackEdge::Ptr thisBackEdge(js_new<BackEdge>());
+ if (!thisBackEdge || !thisBackEdge->init(origin, edge))
+ return false;
+ ptr->value().infallibleAppend(mozilla::Move(thisBackEdge));
+ totalPathsRecorded++;
+ }
+ }
+
+ MOZ_ASSERT(totalPathsRecorded <= totalMaxPathsToRecord);
+ if (totalPathsRecorded == totalMaxPathsToRecord)
+ traversal.stop();
+
+ return true;
+ }
+
+ };
+
+ // The maximum number of paths to record for each node.
+ uint32_t maxNumPaths_;
+
+ // The root node we are starting the search from.
+ Node root_;
+
+ // The set of nodes we are searching for paths to.
+ NodeSet targets_;
+
+ // The resulting paths.
+ NodeToBackEdgeVectorMap paths_;
+
+ // Need to keep alive the traversal's back edges so we can walk them later
+ // when the traversal is over when recreating the shortest paths.
+ Traversal::NodeMap backEdges_;
+
+ private:
+ // Private methods.
+
+ ShortestPaths(uint32_t maxNumPaths, const Node& root, NodeSet&& targets)
+ : maxNumPaths_(maxNumPaths)
+ , root_(root)
+ , targets_(mozilla::Move(targets))
+ , paths_()
+ , backEdges_()
+ {
+ MOZ_ASSERT(maxNumPaths_ > 0);
+ MOZ_ASSERT(root_);
+ MOZ_ASSERT(targets_.initialized());
+ }
+
+ bool initialized() const {
+ return targets_.initialized() &&
+ paths_.initialized() &&
+ backEdges_.initialized();
+ }
+
+ public:
+ // Public methods.
+
+ ShortestPaths(ShortestPaths&& rhs)
+ : maxNumPaths_(rhs.maxNumPaths_)
+ , root_(rhs.root_)
+ , targets_(mozilla::Move(rhs.targets_))
+ , paths_(mozilla::Move(rhs.paths_))
+ , backEdges_(mozilla::Move(rhs.backEdges_))
+ {
+ MOZ_ASSERT(this != &rhs, "self-move is not allowed");
+ }
+
+ ShortestPaths& operator=(ShortestPaths&& rhs) {
+ this->~ShortestPaths();
+ new (this) ShortestPaths(mozilla::Move(rhs));
+ return *this;
+ }
+
+ ShortestPaths(const ShortestPaths&) = delete;
+ ShortestPaths& operator=(const ShortestPaths&) = delete;
+
+ /**
+ * Construct a new `JS::ubi::ShortestPaths`, finding up to `maxNumPaths`
+ * shortest retaining paths for each target node in `targets` starting from
+ * `root`.
+ *
+ * The resulting `ShortestPaths` instance must not outlive the
+ * `JS::ubi::Node` graph it was constructed from.
+ *
+ * - For `JS::ubi::Node` graphs backed by the live heap graph, this means
+ * that the `ShortestPaths`'s lifetime _must_ be contained within the
+ * scope of the provided `AutoCheckCannotGC` reference because a GC will
+ * invalidate the nodes.
+ *
+ * - For `JS::ubi::Node` graphs backed by some other offline structure
+ * provided by the embedder, the resulting `ShortestPaths`'s lifetime is
+ * bounded by that offline structure's lifetime.
+ *
+ * Returns `mozilla::Nothing()` on OOM failure. It is the caller's
+ * responsibility to handle and report the OOM.
+ */
+ static mozilla::Maybe<ShortestPaths>
+ Create(JSContext* cx, AutoCheckCannotGC& noGC, uint32_t maxNumPaths, const Node& root, NodeSet&& targets) {
+ MOZ_ASSERT(targets.count() > 0);
+ MOZ_ASSERT(maxNumPaths > 0);
+
+ size_t count = targets.count();
+ ShortestPaths paths(maxNumPaths, root, mozilla::Move(targets));
+ if (!paths.paths_.init(count))
+ return mozilla::Nothing();
+
+ Handler handler(paths);
+ Traversal traversal(cx, handler, noGC);
+ traversal.wantNames = true;
+ if (!traversal.init() || !traversal.addStart(root) || !traversal.traverse())
+ return mozilla::Nothing();
+
+ // Take ownership of the back edges we created while traversing the
+ // graph so that we can follow them from `paths_` and don't
+ // use-after-free.
+ paths.backEdges_ = mozilla::Move(traversal.visited);
+
+ MOZ_ASSERT(paths.initialized());
+ return mozilla::Some(mozilla::Move(paths));
+ }
+
+ /**
+ * Get a range that iterates over each target node we searched for retaining
+ * paths for. The returned range must not outlive the `ShortestPaths`
+ * instance.
+ */
+ NodeSet::Range eachTarget() const {
+ MOZ_ASSERT(initialized());
+ return targets_.all();
+ }
+
+ /**
+ * Invoke the provided functor/lambda/callable once for each retaining path
+ * discovered for `target`. The `func` is passed a single `JS::ubi::Path&`
+ * argument, which contains each edge along the path ordered starting from
+ * the root and ending at the target, and must not outlive the scope of the
+ * call.
+ *
+ * Note that it is possible that we did not find any paths from the root to
+ * the given target, in which case `func` will not be invoked.
+ */
+ template <class Func>
+ MOZ_MUST_USE bool forEachPath(const Node& target, Func func) {
+ MOZ_ASSERT(initialized());
+ MOZ_ASSERT(targets_.has(target));
+
+ auto ptr = paths_.lookup(target);
+
+ // We didn't find any paths to this target, so nothing to do here.
+ if (!ptr)
+ return true;
+
+ MOZ_ASSERT(ptr->value().length() <= maxNumPaths_);
+
+ Path path;
+ for (const auto& backEdge : ptr->value()) {
+ path.clear();
+
+ if (!path.append(backEdge.get()))
+ return false;
+
+ Node here = backEdge->predecessor();
+ MOZ_ASSERT(here);
+
+ while (here != root_) {
+ auto p = backEdges_.lookup(here);
+ MOZ_ASSERT(p);
+ if (!path.append(&p->value()))
+ return false;
+ here = p->value().predecessor();
+ MOZ_ASSERT(here);
+ }
+
+ path.reverse();
+
+ if (!func(path))
+ return false;
+ }
+
+ return true;
+ }
+};
+
+#ifdef DEBUG
+// A helper function to dump the first `maxNumPaths` shortest retaining paths to
+// `node` from the GC roots. Useful when GC things you expect to have been
+// reclaimed by the collector haven't been!
+//
+// Usage:
+//
+// JSObject* foo = ...;
+// JS::ubi::dumpPaths(rt, JS::ubi::Node(foo));
+JS_PUBLIC_API(void)
+dumpPaths(JSRuntime* rt, Node node, uint32_t maxNumPaths = 10);
+#endif
+
+} // namespace ubi
+} // namespace JS
+
+#endif // js_UbiNodeShortestPaths_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UniquePtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UniquePtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/UniquePtr.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 js_UniquePtr_h
+#define js_UniquePtr_h
+
+#include "mozilla/UniquePtr.h"
+
+#include "js/Utility.h"
+
+namespace js {
+
+// Replacement for mozilla::UniquePtr that defaults to js::DefaultDelete.
+template <typename T, typename D = JS::DeletePolicy<T>>
+using UniquePtr = mozilla::UniquePtr<T, D>;
+
+namespace detail {
+
+template<typename T>
+struct UniqueSelector
+{
+ typedef UniquePtr<T> SingleObject;
+};
+
+template<typename T>
+struct UniqueSelector<T[]>
+{
+ typedef UniquePtr<T[]> UnknownBound;
+};
+
+template<typename T, decltype(sizeof(int)) N>
+struct UniqueSelector<T[N]>
+{
+ typedef UniquePtr<T[N]> KnownBound;
+};
+
+} // namespace detail
+
+// Replacement for mozilla::MakeUnique that correctly calls js_new and produces
+// a js::UniquePtr.
+template<typename T, typename... Args>
+typename detail::UniqueSelector<T>::SingleObject
+MakeUnique(Args&&... aArgs)
+{
+ return UniquePtr<T>(js_new<T>(mozilla::Forward<Args>(aArgs)...));
+}
+
+template<typename T>
+typename detail::UniqueSelector<T>::UnknownBound
+MakeUnique(decltype(sizeof(int)) aN) = delete;
+
+template<typename T, typename... Args>
+typename detail::UniqueSelector<T>::KnownBound
+MakeUnique(Args&&... aArgs) = delete;
+
+} // namespace js
+
+#endif /* js_UniquePtr_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Utility.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Utility.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Utility.h
@@ -8,6 +8,7 @@
#define js_Utility_h
#include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/Compiler.h"
#include "mozilla/Move.h"
@@ -34,22 +35,6 @@
/* The private JS engine namespace. */
namespace js {}
-/*
- * Patterns used by SpiderMonkey to overwrite unused memory. If you are
- * accessing an object with one of these pattern, you probably have a dangling
- * pointer.
- */
-#define JS_FRESH_NURSERY_PATTERN 0x2F
-#define JS_SWEPT_NURSERY_PATTERN 0x2B
-#define JS_ALLOCATED_NURSERY_PATTERN 0x2D
-#define JS_FRESH_TENURED_PATTERN 0x4F
-#define JS_MOVED_TENURED_PATTERN 0x49
-#define JS_SWEPT_TENURED_PATTERN 0x4B
-#define JS_ALLOCATED_TENURED_PATTERN 0x4D
-#define JS_EMPTY_STOREBUFFER_PATTERN 0x1B
-#define JS_SWEPT_CODE_PATTERN 0x3B
-#define JS_SWEPT_FRAME_PATTERN 0x5B
-
#define JS_STATIC_ASSERT(cond) static_assert(cond, "JS_STATIC_ASSERT")
#define JS_STATIC_ASSERT_IF(cond, expr) MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
@@ -81,6 +66,7 @@
THREAD_TYPE_COMPRESS, // 5
THREAD_TYPE_GCHELPER, // 6
THREAD_TYPE_GCPARALLEL, // 7
+ THREAD_TYPE_PROMISE_TASK, // 8
THREAD_TYPE_MAX // Used to check shell function arguments
};
@@ -103,15 +89,6 @@
# if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
-/*
- * In order to test OOM conditions, when the testing function
- * oomAfterAllocations COUNT is passed, we fail continuously after the NUM'th
- * allocation from now.
- */
-extern JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations; /* set in builtin/TestingFunctions.cpp */
-extern JS_PUBLIC_DATA(uint32_t) OOM_counter; /* data race, who cares. */
-extern JS_PUBLIC_DATA(bool) OOM_failAlways;
-
#ifdef JS_OOM_BREAKPOINT
static MOZ_NEVER_INLINE void js_failedAllocBreakpoint() { asm(""); }
#define JS_OOM_CALL_BP_FUNC() js_failedAllocBreakpoint()
@@ -122,28 +99,42 @@
namespace js {
namespace oom {
+/*
+ * Out of memory testing support. We provide various testing functions to
+ * simulate OOM conditions and so we can test that they are handled correctly.
+ */
+
extern JS_PUBLIC_DATA(uint32_t) targetThread;
+extern JS_PUBLIC_DATA(uint64_t) maxAllocations;
+extern JS_PUBLIC_DATA(uint64_t) counter;
+extern JS_PUBLIC_DATA(bool) failAlways;
-static inline bool
+extern void
+SimulateOOMAfter(uint64_t allocations, uint32_t thread, bool always);
+
+extern void
+ResetSimulatedOOM();
+
+inline bool
IsThreadSimulatingOOM()
{
return js::oom::targetThread && js::oom::targetThread == js::oom::GetThreadType();
}
-static inline bool
+inline bool
IsSimulatedOOMAllocation()
{
- return IsThreadSimulatingOOM() && (OOM_counter == OOM_maxAllocations ||
- (OOM_counter > OOM_maxAllocations && OOM_failAlways));
+ return IsThreadSimulatingOOM() &&
+ (counter == maxAllocations || (counter > maxAllocations && failAlways));
}
-static inline bool
+inline bool
ShouldFailWithOOM()
{
if (!IsThreadSimulatingOOM())
return false;
- OOM_counter++;
+ counter++;
if (IsSimulatedOOMAllocation()) {
JS_OOM_CALL_BP_FUNC();
return true;
@@ -151,6 +142,11 @@
return false;
}
+inline bool
+HadSimulatedOOM() {
+ return counter >= maxAllocations;
+}
+
} /* namespace oom */
} /* namespace js */
@@ -182,32 +178,44 @@
namespace js {
/* Disable OOM testing in sections which are not OOM safe. */
-struct MOZ_RAII AutoEnterOOMUnsafeRegion
+struct MOZ_RAII JS_PUBLIC_DATA(AutoEnterOOMUnsafeRegion)
{
MOZ_NORETURN MOZ_COLD void crash(const char* reason);
+ MOZ_NORETURN MOZ_COLD void crash(size_t size, const char* reason);
+
+ using AnnotateOOMAllocationSizeCallback = void(*)(size_t);
+ static AnnotateOOMAllocationSizeCallback annotateOOMSizeCallback;
+ static void setAnnotateOOMAllocationSizeCallback(AnnotateOOMAllocationSizeCallback callback) {
+ annotateOOMSizeCallback = callback;
+ }
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
AutoEnterOOMUnsafeRegion()
- : oomEnabled_(oom::IsThreadSimulatingOOM() && OOM_maxAllocations != UINT32_MAX),
+ : oomEnabled_(oom::IsThreadSimulatingOOM() && oom::maxAllocations != UINT64_MAX),
oomAfter_(0)
{
if (oomEnabled_) {
- oomAfter_ = int64_t(OOM_maxAllocations) - OOM_counter;
- OOM_maxAllocations = UINT32_MAX;
+ MOZ_ALWAYS_TRUE(owner_.compareExchange(nullptr, this));
+ oomAfter_ = int64_t(oom::maxAllocations) - int64_t(oom::counter);
+ oom::maxAllocations = UINT64_MAX;
}
}
~AutoEnterOOMUnsafeRegion() {
if (oomEnabled_) {
- MOZ_ASSERT(OOM_maxAllocations == UINT32_MAX);
- int64_t maxAllocations = OOM_counter + oomAfter_;
- MOZ_ASSERT(maxAllocations >= 0 && maxAllocations < UINT32_MAX,
+ MOZ_ASSERT(oom::maxAllocations == UINT64_MAX);
+ int64_t maxAllocations = int64_t(oom::counter) + oomAfter_;
+ MOZ_ASSERT(maxAllocations >= 0,
"alloc count + oom limit exceeds range, your oom limit is probably too large");
- OOM_maxAllocations = uint32_t(maxAllocations);
+ oom::maxAllocations = uint64_t(maxAllocations);
+ MOZ_ALWAYS_TRUE(owner_.compareExchange(this, nullptr));
}
}
private:
+ // Used to catch concurrent use from other threads.
+ static mozilla::Atomic<AutoEnterOOMUnsafeRegion*> owner_;
+
bool oomEnabled_;
int64_t oomAfter_;
#endif
@@ -235,6 +243,11 @@
static inline void* js_realloc(void* p, size_t bytes)
{
+ // realloc() with zero size is not portable, as some implementations may
+ // return nullptr on success and free |p| for this. We assume nullptr
+ // indicates failure and that |p| is still valid.
+ MOZ_ASSERT(bytes != 0);
+
JS_OOM_POSSIBLY_FAIL();
return realloc(p, bytes);
}
@@ -302,14 +315,14 @@
* Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
* or the build will break.
*/
-#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
+#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS) \
template <class T, typename... Args> \
QUALIFIERS T * \
NEWNAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
void* memory = ALLOCATOR(sizeof(T)); \
- return memory \
- ? new(memory) T(mozilla::Forward<Args>(args)...) \
- : nullptr; \
+ return MOZ_LIKELY(memory) \
+ ? new(memory) T(mozilla::Forward<Args>(args)...) \
+ : nullptr; \
}
/*
@@ -339,7 +352,7 @@
* instances of type |T|. Return false if the calculation overflowed.
*/
template <typename T>
-MOZ_WARN_UNUSED_RESULT inline bool
+MOZ_MUST_USE inline bool
CalculateAllocSize(size_t numElems, size_t* bytesOut)
{
*bytesOut = numElems * sizeof(T);
@@ -352,7 +365,7 @@
* false if the calculation overflowed.
*/
template <typename T, typename Extra>
-MOZ_WARN_UNUSED_RESULT inline bool
+MOZ_MUST_USE inline bool
CalculateAllocSizeWithExtra(size_t numExtra, size_t* bytesOut)
{
*bytesOut = sizeof(T) + numExtra * sizeof(Extra);
@@ -460,6 +473,14 @@
template<typename T>
struct DeletePolicy
{
+ constexpr DeletePolicy() {}
+
+ template<typename U>
+ MOZ_IMPLICIT DeletePolicy(DeletePolicy<U> other,
+ typename mozilla::EnableIf<mozilla::IsConvertible<U*, T*>::value,
+ int>::Type dummy = 0)
+ {}
+
void operator()(const T* ptr) {
js_delete(const_cast<T*>(ptr));
}
@@ -472,6 +493,9 @@
}
};
+typedef mozilla::UniquePtr<char[], JS::FreePolicy> UniqueChars;
+typedef mozilla::UniquePtr<char16_t[], JS::FreePolicy> UniqueTwoByteChars;
+
} // namespace JS
namespace js {
@@ -480,13 +504,6 @@
typedef uint32_t HashNumber;
const unsigned HashNumberSizeBits = 32;
-typedef mozilla::UniquePtr<char, JS::FreePolicy> UniqueChars;
-
-static inline UniqueChars make_string_copy(const char* str)
-{
- return UniqueChars(js_strdup(str));
-}
-
namespace detail {
/*
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Value.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Value.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Value.h
@@ -10,6 +10,7 @@
#define js_Value_h
#include "mozilla/Attributes.h"
+#include "mozilla/Casting.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Likely.h"
@@ -29,34 +30,12 @@
#define JSVAL_INT_MIN ((int32_t)0x80000000)
#define JSVAL_INT_MAX ((int32_t)0x7fffffff)
-/*
- * Try to get jsvals 64-bit aligned. We could almost assert that all values are
- * aligned, but MSVC and GCC occasionally break alignment.
- */
-#if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__)
-# define JSVAL_ALIGNMENT __attribute__((aligned (8)))
-#elif defined(_MSC_VER)
- /*
- * Structs can be aligned with MSVC, but not if they are used as parameters,
- * so we just don't try to align.
- */
-# define JSVAL_ALIGNMENT
-#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-# define JSVAL_ALIGNMENT
-#elif defined(__HP_cc) || defined(__HP_aCC)
-# define JSVAL_ALIGNMENT
-#endif
-
#if defined(JS_PUNBOX64)
# define JSVAL_TAG_SHIFT 47
#endif
-/*
- * We try to use enums so that printing a jsval_layout in the debugger shows
- * nice symbolic type tags, however we can only do this when we can force the
- * underlying type of the enum to be the desired size.
- */
-#if !defined(__SUNPRO_CC) && !defined(__xlC__)
+// Use enums so that printing a JS::Value in the debugger shows nice
+// symbolic type tags.
#if defined(_MSC_VER)
# define JS_ENUM_HEADER(id, type) enum id : type
@@ -76,8 +55,9 @@
JSVAL_TYPE_MAGIC = 0x04,
JSVAL_TYPE_STRING = 0x05,
JSVAL_TYPE_SYMBOL = 0x06,
- JSVAL_TYPE_NULL = 0x07,
- JSVAL_TYPE_OBJECT = 0x08,
+ JSVAL_TYPE_PRIVATE_GCTHING = 0x07,
+ JSVAL_TYPE_NULL = 0x08,
+ JSVAL_TYPE_OBJECT = 0x0c,
/* These never appear in a jsval; they are only provided as an out-of-band value. */
JSVAL_TYPE_UNKNOWN = 0x20,
@@ -100,7 +80,8 @@
JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN,
JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC,
JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL,
- JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT
+ JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT,
+ JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_CLEAR | JSVAL_TYPE_PRIVATE_GCTHING
} JS_ENUM_FOOTER(JSValueTag);
static_assert(sizeof(JSValueTag) == sizeof(uint32_t),
@@ -119,7 +100,8 @@
JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN,
JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC,
JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL,
- JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT
+ JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT,
+ JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_PRIVATE_GCTHING
} JS_ENUM_FOOTER(JSValueTag);
static_assert(sizeof(JSValueTag) == sizeof(uint32_t),
@@ -127,15 +109,16 @@
JS_ENUM_HEADER(JSValueShiftedTag, uint64_t)
{
- JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
- JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
- JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
+ JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
+ JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT),
+ JSVAL_SHIFTED_TAG_PRIVATE_GCTHING = (((uint64_t)JSVAL_TAG_PRIVATE_GCTHING) << JSVAL_TAG_SHIFT)
} JS_ENUM_FOOTER(JSValueShiftedTag);
static_assert(sizeof(JSValueShiftedTag) == sizeof(uint64_t),
@@ -153,64 +136,12 @@
#undef JS_ENUM_HEADER
#undef JS_ENUM_FOOTER
-#else /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
-
-typedef uint8_t JSValueType;
-#define JSVAL_TYPE_DOUBLE ((uint8_t)0x00)
-#define JSVAL_TYPE_INT32 ((uint8_t)0x01)
-#define JSVAL_TYPE_UNDEFINED ((uint8_t)0x02)
-#define JSVAL_TYPE_BOOLEAN ((uint8_t)0x03)
-#define JSVAL_TYPE_MAGIC ((uint8_t)0x04)
-#define JSVAL_TYPE_STRING ((uint8_t)0x05)
-#define JSVAL_TYPE_SYMBOL ((uint8_t)0x06)
-#define JSVAL_TYPE_NULL ((uint8_t)0x07)
-#define JSVAL_TYPE_OBJECT ((uint8_t)0x08)
-#define JSVAL_TYPE_UNKNOWN ((uint8_t)0x20)
-
-#if defined(JS_NUNBOX32)
-
-typedef uint32_t JSValueTag;
-#define JSVAL_TAG_CLEAR ((uint32_t)(0xFFFFFF80))
-#define JSVAL_TAG_INT32 ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32))
-#define JSVAL_TAG_UNDEFINED ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED))
-#define JSVAL_TAG_STRING ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING))
-#define JSVAL_TAG_SYMBOL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_SYMBOL))
-#define JSVAL_TAG_BOOLEAN ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
-#define JSVAL_TAG_MAGIC ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
-#define JSVAL_TAG_NULL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
-#define JSVAL_TAG_OBJECT ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
-
-#elif defined(JS_PUNBOX64)
-
-typedef uint32_t JSValueTag;
-#define JSVAL_TAG_MAX_DOUBLE ((uint32_t)(0x1FFF0))
-#define JSVAL_TAG_INT32 (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32)
-#define JSVAL_TAG_UNDEFINED (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED)
-#define JSVAL_TAG_STRING (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING)
-#define JSVAL_TAG_SYMBOL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_SYMBOL)
-#define JSVAL_TAG_BOOLEAN (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
-#define JSVAL_TAG_MAGIC (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
-#define JSVAL_TAG_NULL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
-#define JSVAL_TAG_OBJECT (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
-
-typedef uint64_t JSValueShiftedTag;
-#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
-#define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_SYMBOL (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
-#define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
-
-#endif /* JS_PUNBOX64 */
-#endif /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
-
#if defined(JS_NUNBOX32)
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
+#define JSVAL_RAW64_UNDEFINED (uint64_t(JSVAL_TAG_UNDEFINED) << 32)
+
#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT
#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
@@ -218,6 +149,8 @@
#elif defined(JS_PUNBOX64)
+#define JSVAL_RAW64_UNDEFINED (uint64_t(JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
+
#define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL
#define JSVAL_TAG_MASK 0xFFFF800000000000LL
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
@@ -267,9 +200,6 @@
/** magic value passed to natives to indicate construction */
JS_IS_CONSTRUCTING,
- /** arguments.callee has been overwritten */
- JS_OVERWRITTEN_CALLEE,
-
/** value of static block object slot */
JS_BLOCK_NEEDS_CLONE,
@@ -294,686 +224,22 @@
JS_WHY_MAGIC_COUNT
} JSWhyMagic;
-#if defined(IS_LITTLE_ENDIAN)
-# if defined(JS_NUNBOX32)
-typedef union jsval_layout
-{
- uint64_t asBits;
- struct {
- union {
- int32_t i32;
- uint32_t u32;
- uint32_t boo; // Don't use |bool| -- it must be four bytes.
- JSString* str;
- JS::Symbol* sym;
- JSObject* obj;
- js::gc::Cell* cell;
- void* ptr;
- JSWhyMagic why;
- size_t word;
- uintptr_t uintptr;
- } payload;
- JSValueTag tag;
- } s;
- double asDouble;
- void* asPtr;
-} JSVAL_ALIGNMENT jsval_layout;
-# elif defined(JS_PUNBOX64)
-typedef union jsval_layout
-{
- uint64_t asBits;
-#if !defined(_WIN64)
- /* MSVC does not pack these correctly :-( */
- struct {
- uint64_t payload47 : 47;
- JSValueTag tag : 17;
- } debugView;
-#endif
- struct {
- union {
- int32_t i32;
- uint32_t u32;
- JSWhyMagic why;
- } payload;
- } s;
- double asDouble;
- void* asPtr;
- size_t asWord;
- uintptr_t asUIntPtr;
-} JSVAL_ALIGNMENT jsval_layout;
-# endif /* JS_PUNBOX64 */
-#else /* defined(IS_LITTLE_ENDIAN) */
-# if defined(JS_NUNBOX32)
-typedef union jsval_layout
-{
- uint64_t asBits;
- struct {
- JSValueTag tag;
- union {
- int32_t i32;
- uint32_t u32;
- uint32_t boo; // Don't use |bool| -- it must be four bytes.
- JSString* str;
- JS::Symbol* sym;
- JSObject* obj;
- js::gc::Cell* cell;
- void* ptr;
- JSWhyMagic why;
- size_t word;
- uintptr_t uintptr;
- } payload;
- } s;
- double asDouble;
- void* asPtr;
-} JSVAL_ALIGNMENT jsval_layout;
-# elif defined(JS_PUNBOX64)
-typedef union jsval_layout
-{
- uint64_t asBits;
- struct {
- JSValueTag tag : 17;
- uint64_t payload47 : 47;
- } debugView;
- struct {
- uint32_t padding;
- union {
- int32_t i32;
- uint32_t u32;
- JSWhyMagic why;
- } payload;
- } s;
- double asDouble;
- void* asPtr;
- size_t asWord;
- uintptr_t asUIntPtr;
-} JSVAL_ALIGNMENT jsval_layout;
-# endif /* JS_PUNBOX64 */
-#endif /* defined(IS_LITTLE_ENDIAN) */
-
-JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
-
-/*
- * For codesize purposes on some platforms, it's important that the
- * compiler know that JS::Values constructed from constant values can be
- * folded to constant bit patterns at compile time, rather than
- * constructed at runtime. Doing this requires a fair amount of C++11
- * features, which are not supported on all of our compilers. Set up
- * some defines and helper macros in an attempt to confine the ugliness
- * here, rather than scattering it all about the file. The important
- * features are:
- *
- * - constexpr;
- * - defaulted functions;
- * - C99-style designated initializers.
- */
-#if defined(__clang__)
-# if __has_feature(cxx_constexpr) && __has_feature(cxx_defaulted_functions)
-# define JS_VALUE_IS_CONSTEXPR
-# endif
-#elif defined(__GNUC__)
-/*
- * We need 4.5 for defaulted functions, 4.6 for constexpr, 4.7 because 4.6
- * doesn't understand |(X) { .field = ... }| syntax, and 4.7.3 because
- * versions prior to that have bugs in the C++ front-end that cause crashes.
- */
-# if MOZ_GCC_VERSION_AT_LEAST(4, 7, 3)
-# define JS_VALUE_IS_CONSTEXPR
-# endif
-#endif
-
-#if defined(JS_VALUE_IS_CONSTEXPR)
-# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
- return (jsval_layout) { .asBits = (BITS) }
-# define JS_VALUE_CONSTEXPR MOZ_CONSTEXPR
-# define JS_VALUE_CONSTEXPR_VAR MOZ_CONSTEXPR_VAR
-#else
-# define JS_RETURN_LAYOUT_FROM_BITS(BITS) \
- jsval_layout l; \
- l.asBits = (BITS); \
- return l;
-# define JS_VALUE_CONSTEXPR
-# define JS_VALUE_CONSTEXPR_VAR const
-#endif
-
-#if defined(JS_NUNBOX32)
-
-/*
- * N.B. GCC, in some but not all cases, chooses to emit signed comparison of
- * JSValueTag even though its underlying type has been forced to be uint32_t.
- * Thus, all comparisons should explicitly cast operands to uint32_t.
- */
-
-static inline JS_VALUE_CONSTEXPR jsval_layout
-BUILD_JSVAL(JSValueTag tag, uint32_t payload)
-{
- JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << 32) | payload);
-}
-
-static inline bool
-JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
-{
- return (uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_CLEAR;
-}
-
-static inline jsval_layout
-DOUBLE_TO_JSVAL_IMPL(double d)
-{
- jsval_layout l;
- l.asDouble = d;
- MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
- return l;
-}
-
-static inline bool
-JSVAL_IS_INT32_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_INT32;
-}
-
-static inline int32_t
-JSVAL_TO_INT32_IMPL(jsval_layout l)
-{
- return l.s.payload.i32;
-}
-
-static inline JS_VALUE_CONSTEXPR jsval_layout
-INT32_TO_JSVAL_IMPL(int32_t i)
-{
-#if defined(JS_VALUE_IS_CONSTEXPR)
- return BUILD_JSVAL(JSVAL_TAG_INT32, i);
-#else
- jsval_layout l;
- l.s.tag = JSVAL_TAG_INT32;
- l.s.payload.i32 = i;
- return l;
-#endif
-}
-
-static inline bool
-JSVAL_IS_NUMBER_IMPL(jsval_layout l)
-{
- JSValueTag tag = l.s.tag;
- MOZ_ASSERT(tag != JSVAL_TAG_CLEAR);
- return (uint32_t)tag <= (uint32_t)JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET;
-}
-
-static inline bool
-JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_UNDEFINED;
-}
-
-static inline bool
-JSVAL_IS_STRING_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_STRING;
-}
-
-static inline jsval_layout
-STRING_TO_JSVAL_IMPL(JSString* str)
-{
- jsval_layout l;
- MOZ_ASSERT(uintptr_t(str) > 0x1000);
- l.s.tag = JSVAL_TAG_STRING;
- l.s.payload.str = str;
- return l;
-}
-
-static inline JSString*
-JSVAL_TO_STRING_IMPL(jsval_layout l)
-{
- return l.s.payload.str;
-}
-
-static inline bool
-JSVAL_IS_SYMBOL_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_SYMBOL;
-}
-
-static inline jsval_layout
-SYMBOL_TO_JSVAL_IMPL(JS::Symbol* sym)
-{
- jsval_layout l;
- MOZ_ASSERT(uintptr_t(sym) > 0x1000);
- l.s.tag = JSVAL_TAG_SYMBOL;
- l.s.payload.sym = sym;
- return l;
-}
-
-static inline JS::Symbol*
-JSVAL_TO_SYMBOL_IMPL(jsval_layout l)
-{
- return l.s.payload.sym;
-}
-
-static inline bool
-JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_BOOLEAN;
-}
-
-static inline bool
-JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
-{
- return l.s.payload.boo;
-}
-
-static inline jsval_layout
-BOOLEAN_TO_JSVAL_IMPL(bool b)
-{
- jsval_layout l;
- l.s.tag = JSVAL_TAG_BOOLEAN;
- l.s.payload.boo = b;
- return l;
-}
-
-static inline bool
-JSVAL_IS_MAGIC_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_MAGIC;
-}
-
-static inline bool
-JSVAL_IS_OBJECT_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_OBJECT;
-}
-
-static inline bool
-JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
-{
- return (uint32_t)l.s.tag < (uint32_t)JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET;
-}
-
-static inline bool
-JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
-{
- MOZ_ASSERT((uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_OBJECT);
- return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET;
-}
-
-static inline JSObject*
-JSVAL_TO_OBJECT_IMPL(jsval_layout l)
-{
- return l.s.payload.obj;
-}
-
-static inline jsval_layout
-OBJECT_TO_JSVAL_IMPL(JSObject* obj)
-{
- jsval_layout l;
- MOZ_ASSERT(uintptr_t(obj) > 0x1000 || uintptr_t(obj) == 0x42);
- l.s.tag = JSVAL_TAG_OBJECT;
- l.s.payload.obj = obj;
- return l;
-}
-
-static inline bool
-JSVAL_IS_NULL_IMPL(jsval_layout l)
-{
- return l.s.tag == JSVAL_TAG_NULL;
-}
-
-static inline jsval_layout
-PRIVATE_PTR_TO_JSVAL_IMPL(void* ptr)
-{
- jsval_layout l;
- MOZ_ASSERT(((uint32_t)ptr & 1) == 0);
- l.s.tag = (JSValueTag)0;
- l.s.payload.ptr = ptr;
- MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
- return l;
-}
-
-static inline void*
-JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
-{
- return l.s.payload.ptr;
-}
-
-static inline bool
-JSVAL_IS_GCTHING_IMPL(jsval_layout l)
-{
- /* gcc sometimes generates signed < without explicit casts. */
- return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET;
-}
-
-static inline js::gc::Cell*
-JSVAL_TO_GCTHING_IMPL(jsval_layout l)
-{
- return l.s.payload.cell;
-}
-
-static inline uint32_t
-JSVAL_TRACE_KIND_IMPL(jsval_layout l)
-{
- static_assert((JSVAL_TAG_STRING & 0x03) == size_t(JS::TraceKind::String),
- "Value type tags must correspond with JS::TraceKinds.");
- static_assert((JSVAL_TAG_SYMBOL & 0x03) == size_t(JS::TraceKind::Symbol),
- "Value type tags must correspond with JS::TraceKinds.");
- static_assert((JSVAL_TAG_OBJECT & 0x03) == size_t(JS::TraceKind::Object),
- "Value type tags must correspond with JS::TraceKinds.");
- return l.s.tag & 0x03;
-}
-
-static inline bool
-JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
-{
- return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
-}
-
-static inline bool
-JSVAL_IS_SPECIFIC_BOOLEAN_IMPL(jsval_layout l, bool b)
-{
- return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == uint32_t(b));
-}
-
-static inline jsval_layout
-MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
-{
- jsval_layout l;
- l.s.tag = JSVAL_TAG_MAGIC;
- l.s.payload.why = why;
- return l;
-}
-
-static inline jsval_layout
-MAGIC_UINT32_TO_JSVAL_IMPL(uint32_t payload)
-{
- jsval_layout l;
- l.s.tag = JSVAL_TAG_MAGIC;
- l.s.payload.u32 = payload;
- return l;
-}
-
-static inline bool
-JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
-{
- JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
- return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
-}
-
-static inline JSValueType
-JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
-{
- uint32_t type = l.s.tag & 0xF;
- MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
- return (JSValueType)type;
-}
-
-#elif defined(JS_PUNBOX64)
-
-static inline JS_VALUE_CONSTEXPR jsval_layout
-BUILD_JSVAL(JSValueTag tag, uint64_t payload)
-{
- JS_RETURN_LAYOUT_FROM_BITS((((uint64_t)(uint32_t)tag) << JSVAL_TAG_SHIFT) | payload);
-}
-
-static inline bool
-JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
-{
- return l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
-}
-
-static inline jsval_layout
-DOUBLE_TO_JSVAL_IMPL(double d)
-{
- jsval_layout l;
- l.asDouble = d;
- MOZ_ASSERT(l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE);
- return l;
-}
-
-static inline bool
-JSVAL_IS_INT32_IMPL(jsval_layout l)
-{
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_INT32;
-}
-
-static inline int32_t
-JSVAL_TO_INT32_IMPL(jsval_layout l)
-{
- return (int32_t)l.asBits;
-}
-
-static inline JS_VALUE_CONSTEXPR jsval_layout
-INT32_TO_JSVAL_IMPL(int32_t i32)
-{
- JS_RETURN_LAYOUT_FROM_BITS(((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
-}
-
-static inline bool
-JSVAL_IS_NUMBER_IMPL(jsval_layout l)
-{
- return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
-}
-
-static inline bool
-JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
-{
- return l.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
-}
-
-static inline bool
-JSVAL_IS_STRING_IMPL(jsval_layout l)
-{
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_STRING;
-}
-
-static inline jsval_layout
-STRING_TO_JSVAL_IMPL(JSString* str)
-{
- jsval_layout l;
- uint64_t strBits = (uint64_t)str;
- MOZ_ASSERT(uintptr_t(str) > 0x1000);
- MOZ_ASSERT((strBits >> JSVAL_TAG_SHIFT) == 0);
- l.asBits = strBits | JSVAL_SHIFTED_TAG_STRING;
- return l;
-}
-
-static inline JSString*
-JSVAL_TO_STRING_IMPL(jsval_layout l)
-{
- return (JSString*)(l.asBits & JSVAL_PAYLOAD_MASK);
-}
-
-static inline bool
-JSVAL_IS_SYMBOL_IMPL(jsval_layout l)
-{
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_SYMBOL;
-}
-
-static inline jsval_layout
-SYMBOL_TO_JSVAL_IMPL(JS::Symbol* sym)
-{
- jsval_layout l;
- uint64_t symBits = (uint64_t)sym;
- MOZ_ASSERT(uintptr_t(sym) > 0x1000);
- MOZ_ASSERT((symBits >> JSVAL_TAG_SHIFT) == 0);
- l.asBits = symBits | JSVAL_SHIFTED_TAG_SYMBOL;
- return l;
-}
-
-static inline JS::Symbol*
-JSVAL_TO_SYMBOL_IMPL(jsval_layout l)
-{
- return (JS::Symbol*)(l.asBits & JSVAL_PAYLOAD_MASK);
-}
-
-static inline bool
-JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
-{
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_BOOLEAN;
-}
-
-static inline bool
-JSVAL_TO_BOOLEAN_IMPL(jsval_layout l)
-{
- return (bool)(l.asBits & JSVAL_PAYLOAD_MASK);
-}
-
-static inline jsval_layout
-BOOLEAN_TO_JSVAL_IMPL(bool b)
-{
- jsval_layout l;
- l.asBits = ((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
- return l;
-}
-
-static inline bool
-JSVAL_IS_MAGIC_IMPL(jsval_layout l)
-{
- return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_MAGIC;
-}
-
-static inline bool
-JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
-{
- return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
-}
-
-static inline bool
-JSVAL_IS_OBJECT_IMPL(jsval_layout l)
-{
- MOZ_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
- return l.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
-}
-
-static inline bool
-JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
-{
- MOZ_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
- return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET;
-}
-
-static inline JSObject*
-JSVAL_TO_OBJECT_IMPL(jsval_layout l)
-{
- uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
- MOZ_ASSERT((ptrBits & 0x7) == 0);
- return (JSObject*)ptrBits;
-}
-
-static inline jsval_layout
-OBJECT_TO_JSVAL_IMPL(JSObject* obj)
-{
- jsval_layout l;
- uint64_t objBits = (uint64_t)obj;
- MOZ_ASSERT(uintptr_t(obj) > 0x1000 || uintptr_t(obj) == 0x42);
- MOZ_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
- l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
- return l;
-}
-
-static inline bool
-JSVAL_IS_NULL_IMPL(jsval_layout l)
-{
- return l.asBits == JSVAL_SHIFTED_TAG_NULL;
-}
-
-static inline bool
-JSVAL_IS_GCTHING_IMPL(jsval_layout l)
-{
- return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
-}
-
-static inline js::gc::Cell*
-JSVAL_TO_GCTHING_IMPL(jsval_layout l)
-{
- uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
- MOZ_ASSERT((ptrBits & 0x7) == 0);
- return reinterpret_cast<js::gc::Cell*>(ptrBits);
-}
-
-static inline uint32_t
-JSVAL_TRACE_KIND_IMPL(jsval_layout l)
-{
- static_assert((JSVAL_TAG_STRING & 0x03) == size_t(JS::TraceKind::String),
- "Value type tags must correspond with JS::TraceKinds.");
- static_assert((JSVAL_TAG_SYMBOL & 0x03) == size_t(JS::TraceKind::Symbol),
- "Value type tags must correspond with JS::TraceKinds.");
- static_assert((JSVAL_TAG_OBJECT & 0x03) == size_t(JS::TraceKind::Object),
- "Value type tags must correspond with JS::TraceKinds.");
- return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) & 0x03;
-}
-
-static inline jsval_layout
-PRIVATE_PTR_TO_JSVAL_IMPL(void* ptr)
-{
- jsval_layout l;
- uint64_t ptrBits = (uint64_t)ptr;
- MOZ_ASSERT((ptrBits & 1) == 0);
- l.asBits = ptrBits >> 1;
- MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
- return l;
-}
-
-static inline void*
-JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
-{
- MOZ_ASSERT((l.asBits & 0x8000000000000000LL) == 0);
- return (void*)(l.asBits << 1);
-}
-
-static inline bool
-JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
-{
- return l.asBits == (((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
-}
-
-static inline bool
-JSVAL_IS_SPECIFIC_BOOLEAN_IMPL(jsval_layout l, bool b)
-{
- return l.asBits == (((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
-}
-
-static inline jsval_layout
-MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
-{
- jsval_layout l;
- l.asBits = ((uint64_t)(uint32_t)why) | JSVAL_SHIFTED_TAG_MAGIC;
- return l;
-}
-
-static inline jsval_layout
-MAGIC_UINT32_TO_JSVAL_IMPL(uint32_t payload)
-{
- jsval_layout l;
- l.asBits = ((uint64_t)payload) | JSVAL_SHIFTED_TAG_MAGIC;
- return l;
-}
-
-static inline bool
-JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
-{
- uint64_t lbits = lhs.asBits, rbits = rhs.asBits;
- return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
- (((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
-}
-
-static inline JSValueType
-JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
-{
- uint64_t type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
- MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
- return (JSValueType)type;
-}
+namespace JS {
-#endif /* JS_PUNBOX64 */
+static inline constexpr JS::Value UndefinedValue();
+static inline JS::Value PoisonedObjectValue(JSObject* obj);
-static inline bool
-JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
-{
- return JSVAL_IS_GCTHING_IMPL(l) && !JSVAL_IS_NULL_IMPL(l);
-}
+namespace detail {
-static inline jsval_layout JSVAL_TO_IMPL(JS::Value v);
-static inline JS_VALUE_CONSTEXPR JS::Value IMPL_TO_JSVAL(jsval_layout l);
+constexpr int CanonicalizedNaNSignBit = 0;
+constexpr uint64_t CanonicalizedNaNSignificand = 0x8000000000000ULL;
-namespace JS {
+constexpr uint64_t CanonicalizedNaNBits =
+ mozilla::SpecificNaNBits<double,
+ detail::CanonicalizedNaNSignBit,
+ detail::CanonicalizedNaNSignificand>::value;
-static inline JS_VALUE_CONSTEXPR JS::Value UndefinedValue();
+} // namespace detail
/**
* Returns a generic quiet NaN value, with all payload bits set to zero.
@@ -984,7 +250,8 @@
static MOZ_ALWAYS_INLINE double
GenericNaN()
{
- return mozilla::SpecificNaN<double>(0, 0x8000000000000ULL);
+ return mozilla::SpecificNaN<double>(detail::CanonicalizedNaNSignBit,
+ detail::CanonicalizedNaNSignificand);
}
/* MSVC with PGO miscompiles this function. */
@@ -1033,17 +300,21 @@
* 32-bit user code should avoid copying jsval/JS::Value as much as possible,
* preferring to pass by const Value&.
*/
-class Value
+class MOZ_NON_PARAM alignas(8) Value
{
public:
+#if defined(JS_NUNBOX32)
+ using PayloadType = uint32_t;
+#elif defined(JS_PUNBOX64)
+ using PayloadType = uint64_t;
+#endif
+
/*
* N.B. the default constructor leaves Value unitialized. Adding a default
* constructor prevents Value from being stored in a union.
*/
-#if defined(JS_VALUE_IS_CONSTEXPR)
Value() = default;
Value(const Value& v) = default;
-#endif
/**
* Returns false if creating a NumberValue containing the given type would
@@ -1057,15 +328,15 @@
/*** Mutators ***/
void setNull() {
- data.asBits = BUILD_JSVAL(JSVAL_TAG_NULL, 0).asBits;
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_NULL, 0);
}
void setUndefined() {
- data.asBits = BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0).asBits;
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_UNDEFINED, 0);
}
void setInt32(int32_t i) {
- data = INT32_TO_JSVAL_IMPL(i);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
}
int32_t& getInt32Ref() {
@@ -1074,7 +345,10 @@
}
void setDouble(double d) {
- data = DOUBLE_TO_JSVAL_IMPL(d);
+ // Don't assign to data.asDouble to fix a miscompilation with
+ // GCC 5.2.1 and 5.3.1. See bug 1312488.
+ data = layout(d);
+ MOZ_ASSERT(isDouble());
}
void setNaN() {
@@ -1087,27 +361,45 @@
}
void setString(JSString* str) {
- data = STRING_TO_JSVAL_IMPL(str);
+ MOZ_ASSERT(uintptr_t(str) > 0x1000);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_STRING, PayloadType(str));
}
void setSymbol(JS::Symbol* sym) {
- data = SYMBOL_TO_JSVAL_IMPL(sym);
+ MOZ_ASSERT(uintptr_t(sym) > 0x1000);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym));
}
void setObject(JSObject& obj) {
- data = OBJECT_TO_JSVAL_IMPL(&obj);
+ MOZ_ASSERT(uintptr_t(&obj) > 0x1000 || uintptr_t(&obj) == 0x48);
+#if defined(JS_PUNBOX64)
+ // VisualStudio cannot contain parenthesized C++ style cast and shift
+ // inside decltype in template parameter:
+ // AssertionConditionType<decltype((uintptr_t(x) >> 1))>
+ // It throws syntax error.
+ MOZ_ASSERT((((uintptr_t)&obj) >> JSVAL_TAG_SHIFT) == 0);
+#endif
+ setObjectNoCheck(&obj);
+ }
+
+ private:
+ void setObjectNoCheck(JSObject* obj) {
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_OBJECT, PayloadType(obj));
}
+ friend inline Value PoisonedObjectValue(JSObject* obj);
+
+ public:
void setBoolean(bool b) {
- data = BOOLEAN_TO_JSVAL_IMPL(b);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(b));
}
void setMagic(JSWhyMagic why) {
- data = MAGIC_TO_JSVAL_IMPL(why);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, uint32_t(why));
}
void setMagicUint32(uint32_t payload) {
- data = MAGIC_UINT32_TO_JSVAL_IMPL(payload);
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, payload);
}
bool setNumber(uint32_t ui) {
@@ -1144,14 +436,54 @@
data.asBits = tmp;
}
+ private:
+ JSValueTag toTag() const {
+#if defined(JS_NUNBOX32)
+ return data.s.tag;
+#elif defined(JS_PUNBOX64)
+ return JSValueTag(data.asBits >> JSVAL_TAG_SHIFT);
+#endif
+ }
+
+ public:
+ /*** JIT-only interfaces to interact with and create raw Values ***/
+#if defined(JS_NUNBOX32)
+ PayloadType toNunboxPayload() const {
+ return data.s.payload.i32;
+ }
+
+ JSValueTag toNunboxTag() const {
+ return data.s.tag;
+ }
+#elif defined(JS_PUNBOX64)
+ const void* bitsAsPunboxPointer() const {
+ return reinterpret_cast<void*>(data.asBits);
+ }
+#endif
+
/*** Value type queries ***/
+ /*
+ * N.B. GCC, in some but not all cases, chooses to emit signed comparison
+ * of JSValueTag even though its underlying type has been forced to be
+ * uint32_t. Thus, all comparisons should explicitly cast operands to
+ * uint32_t.
+ */
+
bool isUndefined() const {
- return JSVAL_IS_UNDEFINED_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return toTag() == JSVAL_TAG_UNDEFINED;
+#elif defined(JS_PUNBOX64)
+ return data.asBits == JSVAL_SHIFTED_TAG_UNDEFINED;
+#endif
}
bool isNull() const {
- return JSVAL_IS_NULL_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return toTag() == JSVAL_TAG_NULL;
+#elif defined(JS_PUNBOX64)
+ return data.asBits == JSVAL_SHIFTED_TAG_NULL;
+#endif
}
bool isNullOrUndefined() const {
@@ -1159,73 +491,109 @@
}
bool isInt32() const {
- return JSVAL_IS_INT32_IMPL(data);
+ return toTag() == JSVAL_TAG_INT32;
}
bool isInt32(int32_t i32) const {
- return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
+ return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i32));
}
bool isDouble() const {
- return JSVAL_IS_DOUBLE_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return uint32_t(toTag()) <= uint32_t(JSVAL_TAG_CLEAR);
+#elif defined(JS_PUNBOX64)
+ return (data.asBits | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
+#endif
}
bool isNumber() const {
- return JSVAL_IS_NUMBER_IMPL(data);
+#if defined(JS_NUNBOX32)
+ MOZ_ASSERT(toTag() != JSVAL_TAG_CLEAR);
+ return uint32_t(toTag()) <= uint32_t(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET);
+#elif defined(JS_PUNBOX64)
+ return data.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET;
+#endif
}
bool isString() const {
- return JSVAL_IS_STRING_IMPL(data);
+ return toTag() == JSVAL_TAG_STRING;
}
bool isSymbol() const {
- return JSVAL_IS_SYMBOL_IMPL(data);
+ return toTag() == JSVAL_TAG_SYMBOL;
}
bool isObject() const {
- return JSVAL_IS_OBJECT_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return toTag() == JSVAL_TAG_OBJECT;
+#elif defined(JS_PUNBOX64)
+ MOZ_ASSERT((data.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
+ return data.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
+#endif
}
bool isPrimitive() const {
- return JSVAL_IS_PRIMITIVE_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return uint32_t(toTag()) < uint32_t(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET);
+#elif defined(JS_PUNBOX64)
+ return data.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
+#endif
}
bool isObjectOrNull() const {
- return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
+ MOZ_ASSERT(uint32_t(toTag()) <= uint32_t(JSVAL_TAG_OBJECT));
+#if defined(JS_NUNBOX32)
+ return uint32_t(toTag()) >= uint32_t(JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET);
+#elif defined(JS_PUNBOX64)
+ return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET;
+#endif
}
bool isGCThing() const {
- return JSVAL_IS_GCTHING_IMPL(data);
+#if defined(JS_NUNBOX32)
+ /* gcc sometimes generates signed < without explicit casts. */
+ return uint32_t(toTag()) >= uint32_t(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET);
+#elif defined(JS_PUNBOX64)
+ return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
+#endif
}
bool isBoolean() const {
- return JSVAL_IS_BOOLEAN_IMPL(data);
+ return toTag() == JSVAL_TAG_BOOLEAN;
}
bool isTrue() const {
- return JSVAL_IS_SPECIFIC_BOOLEAN_IMPL(data, true);
+ return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(true));
}
bool isFalse() const {
- return JSVAL_IS_SPECIFIC_BOOLEAN_IMPL(data, false);
+ return data.asBits == bitsFromTagAndPayload(JSVAL_TAG_BOOLEAN, uint32_t(false));
}
bool isMagic() const {
- return JSVAL_IS_MAGIC_IMPL(data);
+ return toTag() == JSVAL_TAG_MAGIC;
}
bool isMagic(JSWhyMagic why) const {
MOZ_ASSERT_IF(isMagic(), data.s.payload.why == why);
- return JSVAL_IS_MAGIC_IMPL(data);
+ return isMagic();
}
bool isMarkable() const {
- return JSVAL_IS_TRACEABLE_IMPL(data);
+ return isGCThing() && !isNull();
}
JS::TraceKind traceKind() const {
MOZ_ASSERT(isMarkable());
- return JS::TraceKind(JSVAL_TRACE_KIND_IMPL(data));
+ static_assert((JSVAL_TAG_STRING & 0x03) == size_t(JS::TraceKind::String),
+ "Value type tags must correspond with JS::TraceKinds.");
+ static_assert((JSVAL_TAG_SYMBOL & 0x03) == size_t(JS::TraceKind::Symbol),
+ "Value type tags must correspond with JS::TraceKinds.");
+ static_assert((JSVAL_TAG_OBJECT & 0x03) == size_t(JS::TraceKind::Object),
+ "Value type tags must correspond with JS::TraceKinds.");
+ if (MOZ_UNLIKELY(isPrivateGCThing()))
+ return JS::GCThingTraceKind(toGCThing());
+ return JS::TraceKind(toTag() & 0x03);
}
JSWhyMagic whyMagic() const {
@@ -1254,7 +622,11 @@
int32_t toInt32() const {
MOZ_ASSERT(isInt32());
- return JSVAL_TO_INT32_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.i32;
+#elif defined(JS_PUNBOX64)
+ return int32_t(data.asBits);
+#endif
}
double toDouble() const {
@@ -1269,27 +641,56 @@
JSString* toString() const {
MOZ_ASSERT(isString());
- return JSVAL_TO_STRING_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.str;
+#elif defined(JS_PUNBOX64)
+ return reinterpret_cast<JSString*>(data.asBits & JSVAL_PAYLOAD_MASK);
+#endif
}
JS::Symbol* toSymbol() const {
MOZ_ASSERT(isSymbol());
- return JSVAL_TO_SYMBOL_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.sym;
+#elif defined(JS_PUNBOX64)
+ return reinterpret_cast<JS::Symbol*>(data.asBits & JSVAL_PAYLOAD_MASK);
+#endif
}
JSObject& toObject() const {
MOZ_ASSERT(isObject());
- return *JSVAL_TO_OBJECT_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return *data.s.payload.obj;
+#elif defined(JS_PUNBOX64)
+ return *toObjectOrNull();
+#endif
}
JSObject* toObjectOrNull() const {
MOZ_ASSERT(isObjectOrNull());
- return JSVAL_TO_OBJECT_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.obj;
+#elif defined(JS_PUNBOX64)
+ uint64_t ptrBits = data.asBits & JSVAL_PAYLOAD_MASK;
+ MOZ_ASSERT((ptrBits & 0x7) == 0);
+ return reinterpret_cast<JSObject*>(ptrBits);
+#endif
}
js::gc::Cell* toGCThing() const {
MOZ_ASSERT(isGCThing());
- return JSVAL_TO_GCTHING_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return data.s.payload.cell;
+#elif defined(JS_PUNBOX64)
+ uint64_t ptrBits = data.asBits & JSVAL_PAYLOAD_MASK;
+ MOZ_ASSERT((ptrBits & 0x7) == 0);
+ return reinterpret_cast<js::gc::Cell*>(ptrBits);
+#endif
+ }
+
+ js::gc::Cell* toMarkablePointer() const {
+ MOZ_ASSERT(isMarkable());
+ return toGCThing();
}
GCCellPtr toGCCellPtr() const {
@@ -1298,7 +699,11 @@
bool toBoolean() const {
MOZ_ASSERT(isBoolean());
- return JSVAL_TO_BOOLEAN_IMPL(data);
+#if defined(JS_NUNBOX32)
+ return bool(data.s.payload.boo);
+#elif defined(JS_PUNBOX64)
+ return bool(data.asBits & JSVAL_PAYLOAD_MASK);
+#endif
}
uint32_t payloadAsRawUint32() const {
@@ -1311,7 +716,9 @@
}
JSValueType extractNonDoubleType() const {
- return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
+ uint32_t type = toTag() & 0xF;
+ MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
+ return JSValueType(type);
}
/*
@@ -1324,12 +731,24 @@
*/
void setPrivate(void* ptr) {
- data = PRIVATE_PTR_TO_JSVAL_IMPL(ptr);
+ MOZ_ASSERT((uintptr_t(ptr) & 1) == 0);
+#if defined(JS_NUNBOX32)
+ data.s.tag = JSValueTag(0);
+ data.s.payload.ptr = ptr;
+#elif defined(JS_PUNBOX64)
+ data.asBits = uintptr_t(ptr) >> 1;
+#endif
+ MOZ_ASSERT(isDouble());
}
void* toPrivate() const {
- MOZ_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
- return JSVAL_TO_PRIVATE_PTR_IMPL(data);
+ MOZ_ASSERT(isDouble());
+#if defined(JS_NUNBOX32)
+ return data.s.payload.ptr;
+#elif defined(JS_PUNBOX64)
+ MOZ_ASSERT((data.asBits & 0x8000000000000000ULL) == 0);
+ return reinterpret_cast<void*>(data.asBits << 1);
+#endif
}
void setPrivateUint32(uint32_t ui) {
@@ -1342,17 +761,35 @@
}
/*
- * An unmarked value is just a void* cast as a Value. Thus, the Value is
- * not safe for GC and must not be marked. This API avoids raw casts
- * and the ensuing strict-aliasing warnings.
+ * Private GC Thing API
+ *
+ * Non-JSObject, JSString, and JS::Symbol cells may be put into the 64-bit
+ * payload as private GC things. Such Values are considered isMarkable()
+ * and isGCThing(), and as such, automatically marked. Their traceKind()
+ * is gotten via their cells.
*/
- void setUnmarkedPtr(void* ptr) {
- data.asPtr = ptr;
+ void setPrivateGCThing(js::gc::Cell* cell) {
+ MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::String,
+ "Private GC thing Values must not be strings. Make a StringValue instead.");
+ MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Symbol,
+ "Private GC thing Values must not be symbols. Make a SymbolValue instead.");
+ MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Object,
+ "Private GC thing Values must not be objects. Make an ObjectValue instead.");
+
+ MOZ_ASSERT(uintptr_t(cell) > 0x1000);
+#if defined(JS_PUNBOX64)
+ // VisualStudio cannot contain parenthesized C++ style cast and shift
+ // inside decltype in template parameter:
+ // AssertionConditionType<decltype((uintptr_t(x) >> 1))>
+ // It throws syntax error.
+ MOZ_ASSERT((((uintptr_t)cell) >> JSVAL_TAG_SHIFT) == 0);
+#endif
+ data.asBits = bitsFromTagAndPayload(JSVAL_TAG_PRIVATE_GCTHING, PayloadType(cell));
}
- void* toUnmarkedPtr() const {
- return data.asPtr;
+ bool isPrivateGCThing() const {
+ return toTag() == JSVAL_TAG_PRIVATE_GCTHING;
}
const size_t* payloadWord() const {
@@ -1378,12 +815,117 @@
private:
#endif
- jsval_layout data;
+#if MOZ_LITTLE_ENDIAN
+# if defined(JS_NUNBOX32)
+ union layout {
+ uint64_t asBits;
+ struct {
+ union {
+ int32_t i32;
+ uint32_t u32;
+ uint32_t boo; // Don't use |bool| -- it must be four bytes.
+ JSString* str;
+ JS::Symbol* sym;
+ JSObject* obj;
+ js::gc::Cell* cell;
+ void* ptr;
+ JSWhyMagic why;
+ size_t word;
+ uintptr_t uintptr;
+ } payload;
+ JSValueTag tag;
+ } s;
+ double asDouble;
+ void* asPtr;
+
+ layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
+ explicit constexpr layout(uint64_t bits) : asBits(bits) {}
+ explicit constexpr layout(double d) : asDouble(d) {}
+ } data;
+# elif defined(JS_PUNBOX64)
+ union layout {
+ uint64_t asBits;
+#if !defined(_WIN64)
+ /* MSVC does not pack these correctly :-( */
+ struct {
+ uint64_t payload47 : 47;
+ JSValueTag tag : 17;
+ } debugView;
+#endif
+ struct {
+ union {
+ int32_t i32;
+ uint32_t u32;
+ JSWhyMagic why;
+ } payload;
+ } s;
+ double asDouble;
+ void* asPtr;
+ size_t asWord;
+ uintptr_t asUIntPtr;
+
+ layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
+ explicit constexpr layout(uint64_t bits) : asBits(bits) {}
+ explicit constexpr layout(double d) : asDouble(d) {}
+ } data;
+# endif /* JS_PUNBOX64 */
+#else /* MOZ_LITTLE_ENDIAN */
+# if defined(JS_NUNBOX32)
+ union layout {
+ uint64_t asBits;
+ struct {
+ JSValueTag tag;
+ union {
+ int32_t i32;
+ uint32_t u32;
+ uint32_t boo; // Don't use |bool| -- it must be four bytes.
+ JSString* str;
+ JS::Symbol* sym;
+ JSObject* obj;
+ js::gc::Cell* cell;
+ void* ptr;
+ JSWhyMagic why;
+ size_t word;
+ uintptr_t uintptr;
+ } payload;
+ } s;
+ double asDouble;
+ void* asPtr;
+
+ layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
+ explicit constexpr layout(uint64_t bits) : asBits(bits) {}
+ explicit constexpr layout(double d) : asDouble(d) {}
+ } data;
+# elif defined(JS_PUNBOX64)
+ union layout {
+ uint64_t asBits;
+ struct {
+ JSValueTag tag : 17;
+ uint64_t payload47 : 47;
+ } debugView;
+ struct {
+ uint32_t padding;
+ union {
+ int32_t i32;
+ uint32_t u32;
+ JSWhyMagic why;
+ } payload;
+ } s;
+ double asDouble;
+ void* asPtr;
+ size_t asWord;
+ uintptr_t asUIntPtr;
+
+ layout() : asBits(JSVAL_RAW64_UNDEFINED) {}
+ explicit constexpr layout(uint64_t bits) : asBits(bits) {}
+ explicit constexpr layout(double d) : asDouble(d) {}
+ } data;
+# endif /* JS_PUNBOX64 */
+#endif /* MOZ_LITTLE_ENDIAN */
private:
-#if defined(JS_VALUE_IS_CONSTEXPR)
- MOZ_IMPLICIT JS_VALUE_CONSTEXPR Value(jsval_layout layout) : data(layout) {}
-#endif
+ explicit constexpr Value(uint64_t asBits) : data(asBits) {}
+ explicit constexpr Value(double d) : data(d) {}
void staticAssertions() {
JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
@@ -1392,11 +934,86 @@
JS_STATIC_ASSERT(sizeof(Value) == 8);
}
- friend jsval_layout (::JSVAL_TO_IMPL)(Value);
- friend Value JS_VALUE_CONSTEXPR (::IMPL_TO_JSVAL)(jsval_layout l);
- friend Value JS_VALUE_CONSTEXPR (JS::UndefinedValue)();
+ friend constexpr Value JS::UndefinedValue();
+
+ public:
+ static constexpr uint64_t
+ bitsFromTagAndPayload(JSValueTag tag, PayloadType payload)
+ {
+#if defined(JS_NUNBOX32)
+ return (uint64_t(uint32_t(tag)) << 32) | payload;
+#elif defined(JS_PUNBOX64)
+ return (uint64_t(uint32_t(tag)) << JSVAL_TAG_SHIFT) | payload;
+#endif
+ }
+
+ static constexpr Value
+ fromTagAndPayload(JSValueTag tag, PayloadType payload)
+ {
+ return fromRawBits(bitsFromTagAndPayload(tag, payload));
+ }
+
+ static constexpr Value
+ fromRawBits(uint64_t asBits) {
+ return Value(asBits);
+ }
+
+ static constexpr Value
+ fromInt32(int32_t i) {
+ return fromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i));
+ }
+
+ static constexpr Value
+ fromDouble(double d) {
+ return Value(d);
+ }
+} JS_HAZ_GC_POINTER;
+
+/**
+ * This is a null-constructible structure that can convert to and from
+ * a Value, allowing UninitializedValue to be stored in unions.
+ */
+struct MOZ_NON_PARAM alignas(8) UninitializedValue
+{
+ private:
+ uint64_t bits;
+
+ public:
+ UninitializedValue() = default;
+ UninitializedValue(const UninitializedValue&) = default;
+ MOZ_IMPLICIT UninitializedValue(const Value& val) : bits(val.asRawBits()) {}
+
+ inline uint64_t asRawBits() const {
+ return bits;
+ }
+
+ inline Value& asValueRef() {
+ return *reinterpret_cast<Value*>(this);
+ }
+ inline const Value& asValueRef() const {
+ return *reinterpret_cast<const Value*>(this);
+ }
+
+ inline operator Value&() {
+ return asValueRef();
+ }
+ inline operator Value const&() const {
+ return asValueRef();
+ }
+ inline operator Value() const {
+ return asValueRef();
+ }
+
+ inline void operator=(Value const& other) {
+ asValueRef() = other;
+ }
};
+static_assert(sizeof(Value) == 8, "Value size must leave three tag bits, be a binary power, and is ubiquitously depended upon everywhere");
+
+static_assert(sizeof(UninitializedValue) == sizeof(Value), "Value and UninitializedValue must be the same size");
+static_assert(alignof(UninitializedValue) == alignof(Value), "Value and UninitializedValue must have same alignment");
+
inline bool
IsOptimizedPlaceholderMagicValue(const Value& v)
{
@@ -1424,22 +1041,16 @@
return v;
}
-static inline JS_VALUE_CONSTEXPR Value
+static inline constexpr Value
UndefinedValue()
{
-#if defined(JS_VALUE_IS_CONSTEXPR)
- return Value(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
-#else
- JS::Value v;
- v.setUndefined();
- return v;
-#endif
+ return Value::fromTagAndPayload(JSVAL_TAG_UNDEFINED, 0);
}
-static inline JS_VALUE_CONSTEXPR Value
+static inline constexpr Value
Int32Value(int32_t i32)
{
- return IMPL_TO_JSVAL(INT32_TO_JSVAL_IMPL(i32));
+ return Value::fromInt32(i32);
}
static inline Value
@@ -1450,27 +1061,23 @@
return v;
}
-static inline JS_VALUE_CONSTEXPR Value
+static inline Value
CanonicalizedDoubleValue(double d)
{
- /*
- * This is a manually inlined version of:
- * d = JS_CANONICALIZE_NAN(d);
- * return IMPL_TO_JSVAL(DOUBLE_TO_JSVAL_IMPL(d));
- * because GCC from XCode 3.1.4 miscompiles the above code.
- */
-#if defined(JS_VALUE_IS_CONSTEXPR)
- return IMPL_TO_JSVAL(MOZ_UNLIKELY(mozilla::IsNaN(d))
- ? (jsval_layout) { .asBits = 0x7FF8000000000000LL }
- : (jsval_layout) { .asDouble = d });
-#else
- jsval_layout l;
- if (MOZ_UNLIKELY(d != d))
- l.asBits = 0x7FF8000000000000LL;
- else
- l.asDouble = d;
- return IMPL_TO_JSVAL(l);
-#endif
+ return MOZ_UNLIKELY(mozilla::IsNaN(d))
+ ? Value::fromRawBits(detail::CanonicalizedNaNBits)
+ : Value::fromDouble(d);
+}
+
+static inline bool
+IsCanonicalized(double d)
+{
+ if (mozilla::IsInfinite(d) || mozilla::IsFinite(d))
+ return true;
+
+ uint64_t bits;
+ mozilla::BitwiseCast<uint64_t>(d, &bits);
+ return (bits & ~mozilla::DoubleTypeTraits::kSignBit) == detail::CanonicalizedNaNBits;
}
static inline Value
@@ -1541,7 +1148,7 @@
ObjectValueCrashOnTouch()
{
Value v;
- v.setObject(*reinterpret_cast<JSObject*>(0x42));
+ v.setObject(*reinterpret_cast<JSObject*>(0x48));
return v;
}
@@ -1607,12 +1214,12 @@
return Int32Value(i);
}
-static inline JS_VALUE_CONSTEXPR Value
+static inline constexpr Value
NumberValue(uint32_t i)
{
return i <= JSVAL_INT_MAX
? Int32Value(int32_t(i))
- : CanonicalizedDoubleValue(double(i));
+ : Value::fromDouble(double(i));
}
namespace detail {
@@ -1683,10 +1290,32 @@
return v;
}
+static inline Value
+PrivateGCThingValue(js::gc::Cell* cell)
+{
+ Value v;
+ v.setPrivateGCThing(cell);
+ return v;
+}
+
+static inline Value
+PoisonedObjectValue(JSObject* obj)
+{
+ Value v;
+ v.setObjectNoCheck(obj);
+ return v;
+}
+
inline bool
SameType(const Value& lhs, const Value& rhs)
{
- return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
+#if defined(JS_NUNBOX32)
+ JSValueTag ltag = lhs.toTag(), rtag = rhs.toTag();
+ return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
+#elif defined(JS_PUNBOX64)
+ return (lhs.isDouble() && rhs.isDouble()) ||
+ (((lhs.data.asBits ^ rhs.data.asBits) & 0xFFFF800000000000ULL) == 0);
+#endif
}
} // namespace JS
@@ -1695,24 +1324,35 @@
namespace JS {
JS_PUBLIC_API(void) HeapValuePostBarrier(Value* valuep, const Value& prev, const Value& next);
-} // namespace JS
-namespace js {
-
-template <> struct GCMethods<const JS::Value>
+template <>
+struct GCPolicy<JS::Value>
{
- static JS::Value initial() { return JS::UndefinedValue(); }
+ static Value initial() { return UndefinedValue(); }
+ static void trace(JSTracer* trc, Value* v, const char* name) {
+ js::UnsafeTraceManuallyBarrieredEdge(trc, v, name);
+ }
+ static bool isTenured(const Value& thing) {
+ return !thing.isGCThing() || !IsInsideNursery(thing.toGCThing());
+ }
};
-template <> struct GCMethods<JS::Value>
+} // namespace JS
+
+namespace js {
+
+template <>
+struct BarrierMethods<JS::Value>
{
- static JS::Value initial() { return JS::UndefinedValue(); }
static gc::Cell* asGCThingOrNull(const JS::Value& v) {
return v.isMarkable() ? v.toGCThing() : nullptr;
}
static void postBarrier(JS::Value* v, const JS::Value& prev, const JS::Value& next) {
JS::HeapValuePostBarrier(v, prev, next);
}
+ static void exposeToJS(const JS::Value& v) {
+ JS::ExposeValueToActiveJS(v);
+ }
};
template <class Outer> class MutableValueOperations;
@@ -1762,10 +1402,11 @@
JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }
gc::Cell* toGCThing() const { return value().toGCThing(); }
JS::TraceKind traceKind() const { return value().traceKind(); }
- uint64_t asRawBits() const { return value().asRawBits(); }
+ void* toPrivate() const { return value().toPrivate(); }
+ uint32_t toPrivateUint32() const { return value().toPrivateUint32(); }
+ uint64_t asRawBits() const { return value().asRawBits(); }
JSValueType extractNonDoubleType() const { return value().extractNonDoubleType(); }
- uint32_t toPrivateUint32() const { return value().toPrivateUint32(); }
JSWhyMagic whyMagic() const { return value().whyMagic(); }
uint32_t magicUint32() const { return value().magicUint32(); }
@@ -1796,6 +1437,9 @@
void setSymbol(JS::Symbol* sym) { this->value().setSymbol(sym); }
void setObject(JSObject& obj) { this->value().setObject(obj); }
void setObjectOrNull(JSObject* arg) { this->value().setObjectOrNull(arg); }
+ void setPrivate(void* ptr) { this->value().setPrivate(ptr); }
+ void setPrivateUint32(uint32_t ui) { this->value().setPrivateUint32(ui); }
+ void setPrivateGCThing(js::gc::Cell* cell) { this->value().setPrivateGCThing(cell); }
};
/*
@@ -1824,6 +1468,7 @@
void setString(JSString* str) { setBarriered(JS::StringValue(str)); }
void setSymbol(JS::Symbol* sym) { setBarriered(JS::SymbolValue(sym)); }
void setObject(JSObject& obj) { setBarriered(JS::ObjectValue(obj)); }
+ void setPrivateGCThing(js::gc::Cell* cell) { setBarriered(JS::PrivateGCThingValue(cell)); }
bool setNumber(uint32_t ui) {
if (ui > JSVAL_INT_MAX) {
@@ -1885,55 +1530,18 @@
return f(&val.toObject(), mozilla::Forward<Args>(args)...);
if (val.isSymbol())
return f(val.toSymbol(), mozilla::Forward<Args>(args)...);
+ if (MOZ_UNLIKELY(val.isPrivateGCThing()))
+ return DispatchTyped(f, val.toGCCellPtr(), mozilla::Forward<Args>(args)...);
MOZ_ASSERT(!val.isMarkable());
return F::defaultValue(val);
}
-template <class S> struct VoidDefaultAdaptor { static void defaultValue(S) {} };
+template <class S> struct VoidDefaultAdaptor { static void defaultValue(const S&) {} };
template <class S> struct IdentityDefaultAdaptor { static S defaultValue(const S& v) {return v;} };
-template <class S, bool v> struct BoolDefaultAdaptor { static bool defaultValue(S) { return v; } };
+template <class S, bool v> struct BoolDefaultAdaptor { static bool defaultValue(const S&) { return v; } };
} // namespace js
-inline jsval_layout
-JSVAL_TO_IMPL(JS::Value v)
-{
- return v.data;
-}
-
-inline JS_VALUE_CONSTEXPR JS::Value
-IMPL_TO_JSVAL(jsval_layout l)
-{
-#if defined(JS_VALUE_IS_CONSTEXPR)
- return JS::Value(l);
-#else
- JS::Value v;
- v.data = l;
- return v;
-#endif
-}
-
-namespace JS {
-
-#ifdef JS_DEBUG
-namespace detail {
-
-struct ValueAlignmentTester { char c; JS::Value v; };
-static_assert(sizeof(ValueAlignmentTester) == 16,
- "JS::Value must be 16-byte-aligned");
-
-struct LayoutAlignmentTester { char c; jsval_layout l; };
-static_assert(sizeof(LayoutAlignmentTester) == 16,
- "jsval_layout must be 16-byte-aligned");
-
-} // namespace detail
-#endif /* JS_DEBUG */
-
-} // namespace JS
-
-static_assert(sizeof(jsval_layout) == sizeof(JS::Value),
- "jsval_layout and JS::Value must have identical layouts");
-
/************************************************************************/
namespace JS {
@@ -1945,7 +1553,4 @@
} // namespace JS
-#undef JS_VALUE_IS_CONSTEXPR
-#undef JS_RETURN_LAYOUT_FROM_BITS
-
#endif /* js_Value_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Vector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Vector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/js/Vector.h
@@ -34,15 +34,9 @@
template <typename T,
size_t MinInlineCapacity = 0,
- class AllocPolicy = TempAllocPolicy
-// 1800 is MSVC2013. Optimistically assume MSVC2015 (1900) is fixed.
-// If you're porting to MSVC2015 and this doesn't work, extend the
-// condition to encompass that additional version (but *do* keep the
-// version-check so we know when MSVC's fixed).
-#if !defined(_MSC_VER) || (1800 <= _MSC_VER && _MSC_VER <= 1800)
+ class AllocPolicy = TempAllocPolicy,
// Don't use this with JS::Value! Use JS::AutoValueVector instead.
- , typename = typename mozilla::EnableIf<!detail::TypeIsGCThing<T>::value>::Type
-#endif
+ typename = typename mozilla::EnableIf<!detail::TypeIsGCThing<T>::value>::Type
>
using Vector = mozilla::Vector<T, MinInlineCapacity, AllocPolicy>;
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jsalloc.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jsalloc.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jsalloc.h
@@ -51,7 +51,7 @@
};
class ExclusiveContext;
-void ReportOutOfMemory(ExclusiveContext* cxArg);
+JS_FRIEND_API(void) ReportOutOfMemory(ExclusiveContext* cxArg);
/*
* Allocation policy that calls the system memory functions and reports errors
@@ -132,7 +132,7 @@
bool checkSimulatedOOM() const {
if (js::oom::ShouldFailWithOOM()) {
- JS_ReportOutOfMemory(reinterpret_cast<JSContext*>(cx_));
+ js::ReportOutOfMemory(reinterpret_cast<ExclusiveContext*>(cx_));
return false;
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jsapi.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jsapi.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jsapi.h
@@ -14,7 +14,9 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Range.h"
#include "mozilla/RangedPtr.h"
+#include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h"
+#include "mozilla/Variant.h"
#include <stdarg.h>
#include <stddef.h>
@@ -25,12 +27,14 @@
#include "jspubtd.h"
#include "js/CallArgs.h"
+#include "js/CharacterEncoding.h"
#include "js/Class.h"
+#include "js/GCVector.h"
#include "js/HashTable.h"
#include "js/Id.h"
#include "js/Principals.h"
+#include "js/Realm.h"
#include "js/RootingAPI.h"
-#include "js/TraceableVector.h"
#include "js/TracingAPI.h"
#include "js/Utility.h"
#include "js/Value.h"
@@ -123,14 +127,14 @@
size_t length() const { return vector.length(); }
bool empty() const { return vector.empty(); }
- bool append(const T& v) { return vector.append(v); }
- bool appendN(const T& v, size_t len) { return vector.appendN(v, len); }
- bool append(const T* ptr, size_t len) { return vector.append(ptr, len); }
- bool appendAll(const AutoVectorRooterBase<T>& other) {
+ MOZ_MUST_USE bool append(const T& v) { return vector.append(v); }
+ MOZ_MUST_USE bool appendN(const T& v, size_t len) { return vector.appendN(v, len); }
+ MOZ_MUST_USE bool append(const T* ptr, size_t len) { return vector.append(ptr, len); }
+ MOZ_MUST_USE bool appendAll(const AutoVectorRooterBase<T>& other) {
return vector.appendAll(other.vector);
}
- bool insert(T* p, const T& val) { return vector.insert(p, val); }
+ MOZ_MUST_USE bool insert(T* p, const T& val) { return vector.insert(p, val); }
/* For use when space has already been reserved. */
void infallibleAppend(const T& v) { vector.infallibleAppend(v); }
@@ -138,7 +142,7 @@
void popBack() { vector.popBack(); }
T popCopy() { return vector.popCopy(); }
- bool growBy(size_t inc) {
+ MOZ_MUST_USE bool growBy(size_t inc) {
size_t oldLength = vector.length();
if (!vector.growByUninitialized(inc))
return false;
@@ -146,7 +150,7 @@
return true;
}
- bool resize(size_t newLength) {
+ MOZ_MUST_USE bool resize(size_t newLength) {
size_t oldLength = vector.length();
if (newLength <= oldLength) {
vector.shrinkBy(oldLength - newLength);
@@ -160,7 +164,7 @@
void clear() { vector.clear(); }
- bool reserve(size_t newLength) {
+ MOZ_MUST_USE bool reserve(size_t newLength) {
return vector.reserve(newLength);
}
@@ -214,13 +218,36 @@
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
-typedef AutoVectorRooter<Value> AutoValueVector;
-typedef AutoVectorRooter<jsid> AutoIdVector;
-typedef AutoVectorRooter<JSObject*> AutoObjectVector;
-
-using ValueVector = js::TraceableVector<JS::Value>;
-using IdVector = js::TraceableVector<jsid>;
-using ScriptVector = js::TraceableVector<JSScript*>;
+class AutoValueVector : public Rooted<GCVector<Value, 8>> {
+ using Vec = GCVector<Value, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoValueVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoValueVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+};
+
+class AutoIdVector : public Rooted<GCVector<jsid, 8>> {
+ using Vec = GCVector<jsid, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoIdVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoIdVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+
+ bool appendAll(const AutoIdVector& other) { return this->Base::appendAll(other.get()); }
+};
+
+class AutoObjectVector : public Rooted<GCVector<JSObject*, 8>> {
+ using Vec = GCVector<JSObject*, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoObjectVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoObjectVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+};
+
+using ValueVector = JS::GCVector<JS::Value>;
+using IdVector = JS::GCVector<jsid>;
+using ScriptVector = JS::GCVector<JSScript*>;
+using StringVector = JS::GCVector<JSString*>;
template<class Key, class Value>
class MOZ_RAII AutoHashMapRooter : protected AutoGCRooter
@@ -454,7 +481,7 @@
{
public:
template <typename CX>
- explicit CustomAutoRooter(CX* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ explicit CustomAutoRooter(const CX& cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, CUSTOM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
@@ -463,6 +490,8 @@
friend void AutoGCRooter::trace(JSTracer* trc);
protected:
+ virtual ~CustomAutoRooter() {}
+
/** Supplied by derived class to trace roots. */
virtual void trace(JSTracer* trc) = 0;
@@ -518,15 +547,15 @@
/************************************************************************/
struct JSFreeOp {
- private:
+ protected:
JSRuntime* runtime_;
- protected:
explicit JSFreeOp(JSRuntime* rt)
: runtime_(rt) { }
public:
JSRuntime* runtime() const {
+ MOZ_ASSERT(runtime_);
return runtime_;
}
};
@@ -535,46 +564,28 @@
/************************************************************************/
-typedef enum JSContextOp {
- JSCONTEXT_NEW,
- JSCONTEXT_DESTROY
-} JSContextOp;
-
-/**
- * The possible values for contextOp when the runtime calls the callback are:
- * JSCONTEXT_NEW JS_NewContext successfully created a new JSContext
- * instance. The callback can initialize the instance as
- * required. If the callback returns false, the instance
- * will be destroyed and JS_NewContext returns null. In
- * this case the callback is not called again.
- * JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The
- * callback may perform its own cleanup and must always
- * return true.
- * Any other value For future compatibility the callback must do nothing
- * and return true in this case.
- */
-typedef bool
-(* JSContextCallback)(JSContext* cx, unsigned contextOp, void* data);
-
typedef enum JSGCStatus {
JSGC_BEGIN,
JSGC_END
} JSGCStatus;
typedef void
-(* JSGCCallback)(JSRuntime* rt, JSGCStatus status, void* data);
+(* JSGCCallback)(JSContext* cx, JSGCStatus status, void* data);
+
+typedef void
+(* JSObjectsTenuredCallback)(JSContext* cx, void* data);
typedef enum JSFinalizeStatus {
/**
- * Called when preparing to sweep a group of compartments, before anything
- * has been swept. The collector will not yield to the mutator before
- * calling the callback with JSFINALIZE_GROUP_END status.
+ * Called when preparing to sweep a group of zones, before anything has been
+ * swept. The collector will not yield to the mutator before calling the
+ * callback with JSFINALIZE_GROUP_END status.
*/
JSFINALIZE_GROUP_START,
/**
- * Called when preparing to sweep a group of compartments. Weak references
- * to unmarked things have been removed and things that are not swept
+ * Called when preparing to sweep a group of zones. Weak references to
+ * unmarked things have been removed and things that are not swept
* incrementally have been finalized at this point. The collector may yield
* to the mutator after this point.
*/
@@ -587,28 +598,48 @@
} JSFinalizeStatus;
typedef void
-(* JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status, bool isCompartment, void* data);
+(* JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status, bool isZoneGC, void* data);
typedef void
-(* JSWeakPointerZoneGroupCallback)(JSRuntime* rt, void* data);
+(* JSWeakPointerZoneGroupCallback)(JSContext* cx, void* data);
typedef void
-(* JSWeakPointerCompartmentCallback)(JSRuntime* rt, JSCompartment* comp, void* data);
+(* JSWeakPointerCompartmentCallback)(JSContext* cx, JSCompartment* comp, void* data);
typedef bool
(* JSInterruptCallback)(JSContext* cx);
+typedef JSObject*
+(* JSGetIncumbentGlobalCallback)(JSContext* cx);
+
+typedef bool
+(* JSEnqueuePromiseJobCallback)(JSContext* cx, JS::HandleObject job,
+ JS::HandleObject allocationSite, JS::HandleObject incumbentGlobal,
+ void* data);
+
+enum class PromiseRejectionHandlingState {
+ Unhandled,
+ Handled
+};
+
typedef void
-(* JSErrorReporter)(JSContext* cx, const char* message, JSErrorReport* report);
+(* JSPromiseRejectionTrackerCallback)(JSContext* cx, JS::HandleObject promise,
+ PromiseRejectionHandlingState state, void* data);
+
+typedef void
+(* JSProcessPromiseCallback)(JSContext* cx, JS::HandleObject promise);
/**
* Possible exception types. These types are part of a JSErrorFormatString
* structure. They define which error to throw in case of a runtime error.
- * JSEXN_NONE marks an unthrowable error.
+ *
+ * JSEXN_WARN is used for warnings in js.msg files (for instance because we
+ * don't want to prepend 'Error:' to warning messages). This value can go away
+ * if we ever decide to use an entirely separate mechanism for warnings.
*/
typedef enum JSExnType {
- JSEXN_NONE = -1,
- JSEXN_ERR,
+ JSEXN_ERR,
+ JSEXN_FIRST = JSEXN_ERR,
JSEXN_INTERNALERR,
JSEXN_EVALERR,
JSEXN_RANGEERR,
@@ -616,10 +647,17 @@
JSEXN_SYNTAXERR,
JSEXN_TYPEERR,
JSEXN_URIERR,
- JSEXN_LIMIT
+ JSEXN_DEBUGGEEWOULDRUN,
+ JSEXN_WASMCOMPILEERROR,
+ JSEXN_WASMRUNTIMEERROR,
+ JSEXN_WARN,
+ JSEXN_LIMIT
} JSExnType;
typedef struct JSErrorFormatString {
+ /** The error message name in ASCII. */
+ const char* name;
+
/** The error format string in ASCII. */
const char* format;
@@ -663,9 +701,10 @@
* for wrapping in a context. This might include unwrapping other wrappers
* or even finding a more suitable object for the new compartment.
*/
-typedef JSObject*
+typedef void
(* JSPreWrapCallback)(JSContext* cx, JS::HandleObject scope, JS::HandleObject obj,
- JS::HandleObject objectPassedToWrap);
+ JS::HandleObject objectPassedToWrap,
+ JS::MutableHandleObject retObj);
struct JSWrapObjectCallbacks
{
@@ -676,11 +715,15 @@
typedef void
(* JSDestroyCompartmentCallback)(JSFreeOp* fop, JSCompartment* compartment);
+typedef size_t
+(* JSSizeOfIncludingThisCompartmentCallback)(mozilla::MallocSizeOf mallocSizeOf,
+ JSCompartment* compartment);
+
typedef void
(* JSZoneCallback)(JS::Zone* zone);
typedef void
-(* JSCompartmentNameCallback)(JSRuntime* rt, JSCompartment* compartment,
+(* JSCompartmentNameCallback)(JSContext* cx, JSCompartment* compartment,
char* buf, size_t bufsize);
/************************************************************************/
@@ -746,6 +789,16 @@
}
}
+ SourceBufferHolder(SourceBufferHolder&& other)
+ : data_(other.data_),
+ length_(other.length_),
+ ownsChars_(other.ownsChars_)
+ {
+ other.data_ = nullptr;
+ other.length_ = 0;
+ other.ownsChars_ = false;
+ }
+
~SourceBufferHolder() {
if (ownsChars_)
js_free(const_cast<char16_t*>(data_));
@@ -815,29 +868,17 @@
object that delegates to a prototype
containing this property */
#define JSPROP_INTERNAL_USE_BIT 0x80 /* internal JS engine use only */
-#define JSPROP_DEFINE_LATE 0x100 /* Don't define property when initially creating
- the constructor. Some objects like Function/Object
- have self-hosted functions that can only be defined
- after the initialization is already finished. */
#define JSFUN_STUB_GSOPS 0x200 /* use JS_PropertyStub getter/setter
instead of defaulting to class gsops
for property holding function */
#define JSFUN_CONSTRUCTOR 0x400 /* native that can be called as a ctor */
-/*
- * Specify a generic native prototype methods, i.e., methods of a class
- * prototype that are exposed as static methods taking an extra leading
- * argument: the generic |this| parameter.
- *
- * If you set this flag in a JSFunctionSpec struct's flags initializer, then
- * that struct must live at least as long as the native static method object
- * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically
- * JSFunctionSpec structs are allocated in static arrays.
- */
-#define JSFUN_GENERIC_NATIVE 0x800
+// 0x800 /* Unused */
+
+#define JSFUN_HAS_REST 0x1000 /* function has ...rest parameter. */
-#define JSFUN_FLAGS_MASK 0xe00 /* | of all the JSFUN_* flags */
+#define JSFUN_FLAGS_MASK 0x1e00 /* | of all the JSFUN_* flags */
/*
* If set, will allow redefining a non-configurable property, but only on a
@@ -873,17 +914,6 @@
specified when passed to Object.defineProperty
from script. */
-/**
- * The first call to JS_CallOnce by any thread in a process will call 'func'.
- * Later calls to JS_CallOnce with the same JSCallOnceType object will be
- * suppressed.
- *
- * Equivalently: each distinct JSCallOnceType object will allow one JS_CallOnce
- * to invoke its JSInitCallback.
- */
-extern JS_PUBLIC_API(bool)
-JS_CallOnce(JSCallOnceType* once, JSInitCallback func);
-
/** Microseconds since the epoch, midnight, January 1, 1970 UTC. */
extern JS_PUBLIC_API(int64_t)
JS_Now(void);
@@ -902,7 +932,7 @@
JS_GetEmptyStringValue(JSContext* cx);
extern JS_PUBLIC_API(JSString*)
-JS_GetEmptyString(JSRuntime* rt);
+JS_GetEmptyString(JSContext* cx);
extern JS_PUBLIC_API(bool)
JS_ValueToObject(JSContext* cx, JS::HandleValue v, JS::MutableHandleObject objp);
@@ -922,6 +952,13 @@
extern JS_PUBLIC_API(JSType)
JS_TypeOfValue(JSContext* cx, JS::Handle<JS::Value> v);
+namespace JS {
+
+extern JS_PUBLIC_API(const char*)
+InformalValueTypeName(const JS::Value& v);
+
+} /* namespace JS */
+
extern JS_PUBLIC_API(bool)
JS_StrictlyEqual(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* equal);
@@ -944,19 +981,19 @@
/*
* Locking, contexts, and memory allocation.
*
- * It is important that SpiderMonkey be initialized, and the first runtime and
- * first context be created, in a single-threaded fashion. Otherwise the
- * behavior of the library is undefined.
+ * It is important that SpiderMonkey be initialized, and the first context
+ * be created, in a single-threaded fashion. Otherwise the behavior of the
+ * library is undefined.
* See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
*/
-extern JS_PUBLIC_API(JSRuntime*)
-JS_NewRuntime(uint32_t maxbytes,
+extern JS_PUBLIC_API(JSContext*)
+JS_NewContext(uint32_t maxbytes,
uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
- JSRuntime* parentRuntime = nullptr);
+ JSContext* parentContext = nullptr);
extern JS_PUBLIC_API(void)
-JS_DestroyRuntime(JSRuntime* rt);
+JS_DestroyContext(JSContext* cx);
typedef double (*JS_CurrentEmbedderTimeFunction)();
@@ -978,16 +1015,13 @@
JS_GetCurrentEmbedderTime();
JS_PUBLIC_API(void*)
-JS_GetRuntimePrivate(JSRuntime* rt);
-
-extern JS_PUBLIC_API(JSRuntime*)
-JS_GetRuntime(JSContext* cx);
-
-extern JS_PUBLIC_API(JSRuntime*)
-JS_GetParentRuntime(JSContext* cx);
+JS_GetContextPrivate(JSContext* cx);
JS_PUBLIC_API(void)
-JS_SetRuntimePrivate(JSRuntime* rt, void* data);
+JS_SetContextPrivate(JSContext* cx, void* data);
+
+extern JS_PUBLIC_API(JSContext*)
+JS_GetParentContext(JSContext* cx);
extern JS_PUBLIC_API(void)
JS_BeginRequest(JSContext* cx);
@@ -995,14 +1029,14 @@
extern JS_PUBLIC_API(void)
JS_EndRequest(JSContext* cx);
+extern JS_PUBLIC_API(void)
+JS_SetFutexCanWait(JSContext* cx);
+
namespace js {
void
AssertHeapIsIdle(JSRuntime* rt);
-void
-AssertHeapIsIdle(JSContext* cx);
-
} /* namespace js */
class MOZ_RAII JSAutoRequest
@@ -1030,36 +1064,6 @@
#endif
};
-extern JS_PUBLIC_API(void)
-JS_SetContextCallback(JSRuntime* rt, JSContextCallback cxCallback, void* data);
-
-extern JS_PUBLIC_API(JSContext*)
-JS_NewContext(JSRuntime* rt, size_t stackChunkSize);
-
-extern JS_PUBLIC_API(void)
-JS_DestroyContext(JSContext* cx);
-
-extern JS_PUBLIC_API(void)
-JS_DestroyContextNoGC(JSContext* cx);
-
-extern JS_PUBLIC_API(void*)
-JS_GetContextPrivate(JSContext* cx);
-
-extern JS_PUBLIC_API(void)
-JS_SetContextPrivate(JSContext* cx, void* data);
-
-extern JS_PUBLIC_API(void*)
-JS_GetSecondContextPrivate(JSContext* cx);
-
-extern JS_PUBLIC_API(void)
-JS_SetSecondContextPrivate(JSContext* cx, void* data);
-
-extern JS_PUBLIC_API(JSRuntime*)
-JS_GetRuntime(JSContext* cx);
-
-extern JS_PUBLIC_API(JSContext*)
-JS_ContextIterator(JSRuntime* rt, JSContext** iterp);
-
extern JS_PUBLIC_API(JSVersion)
JS_GetVersion(JSContext* cx);
@@ -1082,16 +1086,20 @@
namespace JS {
-class JS_PUBLIC_API(RuntimeOptions) {
+class JS_PUBLIC_API(ContextOptions) {
public:
- RuntimeOptions()
+ ContextOptions()
: baseline_(true),
ion_(true),
asmJS_(true),
+ wasm_(false),
+ wasmAlwaysBaseline_(false),
throwOnAsmJSValidationFailure_(false),
nativeRegExp_(true),
unboxedArrays_(false),
asyncStack_(true),
+ throwOnDebuggeeWouldRun_(true),
+ dumpStackOnDebuggeeWouldRun_(false),
werror_(false),
strictMode_(false),
extraWarnings_(false)
@@ -1099,89 +1107,121 @@
}
bool baseline() const { return baseline_; }
- RuntimeOptions& setBaseline(bool flag) {
+ ContextOptions& setBaseline(bool flag) {
baseline_ = flag;
return *this;
}
- RuntimeOptions& toggleBaseline() {
+ ContextOptions& toggleBaseline() {
baseline_ = !baseline_;
return *this;
}
bool ion() const { return ion_; }
- RuntimeOptions& setIon(bool flag) {
+ ContextOptions& setIon(bool flag) {
ion_ = flag;
return *this;
}
- RuntimeOptions& toggleIon() {
+ ContextOptions& toggleIon() {
ion_ = !ion_;
return *this;
}
bool asmJS() const { return asmJS_; }
- RuntimeOptions& setAsmJS(bool flag) {
+ ContextOptions& setAsmJS(bool flag) {
asmJS_ = flag;
return *this;
}
- RuntimeOptions& toggleAsmJS() {
+ ContextOptions& toggleAsmJS() {
asmJS_ = !asmJS_;
return *this;
}
+ bool wasm() const { return wasm_; }
+ ContextOptions& setWasm(bool flag) {
+ wasm_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleWasm() {
+ wasm_ = !wasm_;
+ return *this;
+ }
+
+ bool wasmAlwaysBaseline() const { return wasmAlwaysBaseline_; }
+ ContextOptions& setWasmAlwaysBaseline(bool flag) {
+ wasmAlwaysBaseline_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleWasmAlwaysBaseline() {
+ wasmAlwaysBaseline_ = !wasmAlwaysBaseline_;
+ return *this;
+ }
+
bool throwOnAsmJSValidationFailure() const { return throwOnAsmJSValidationFailure_; }
- RuntimeOptions& setThrowOnAsmJSValidationFailure(bool flag) {
+ ContextOptions& setThrowOnAsmJSValidationFailure(bool flag) {
throwOnAsmJSValidationFailure_ = flag;
return *this;
}
- RuntimeOptions& toggleThrowOnAsmJSValidationFailure() {
+ ContextOptions& toggleThrowOnAsmJSValidationFailure() {
throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
return *this;
}
bool nativeRegExp() const { return nativeRegExp_; }
- RuntimeOptions& setNativeRegExp(bool flag) {
+ ContextOptions& setNativeRegExp(bool flag) {
nativeRegExp_ = flag;
return *this;
}
bool unboxedArrays() const { return unboxedArrays_; }
- RuntimeOptions& setUnboxedArrays(bool flag) {
+ ContextOptions& setUnboxedArrays(bool flag) {
unboxedArrays_ = flag;
return *this;
}
bool asyncStack() const { return asyncStack_; }
- RuntimeOptions& setAsyncStack(bool flag) {
+ ContextOptions& setAsyncStack(bool flag) {
asyncStack_ = flag;
return *this;
}
+ bool throwOnDebuggeeWouldRun() const { return throwOnDebuggeeWouldRun_; }
+ ContextOptions& setThrowOnDebuggeeWouldRun(bool flag) {
+ throwOnDebuggeeWouldRun_ = flag;
+ return *this;
+ }
+
+ bool dumpStackOnDebuggeeWouldRun() const { return dumpStackOnDebuggeeWouldRun_; }
+ ContextOptions& setDumpStackOnDebuggeeWouldRun(bool flag) {
+ dumpStackOnDebuggeeWouldRun_ = flag;
+ return *this;
+ }
+
bool werror() const { return werror_; }
- RuntimeOptions& setWerror(bool flag) {
+ ContextOptions& setWerror(bool flag) {
werror_ = flag;
return *this;
}
- RuntimeOptions& toggleWerror() {
+ ContextOptions& toggleWerror() {
werror_ = !werror_;
return *this;
}
bool strictMode() const { return strictMode_; }
- RuntimeOptions& setStrictMode(bool flag) {
+ ContextOptions& setStrictMode(bool flag) {
strictMode_ = flag;
return *this;
}
- RuntimeOptions& toggleStrictMode() {
+ ContextOptions& toggleStrictMode() {
strictMode_ = !strictMode_;
return *this;
}
bool extraWarnings() const { return extraWarnings_; }
- RuntimeOptions& setExtraWarnings(bool flag) {
+ ContextOptions& setExtraWarnings(bool flag) {
extraWarnings_ = flag;
return *this;
}
- RuntimeOptions& toggleExtraWarnings() {
+ ContextOptions& toggleExtraWarnings() {
extraWarnings_ = !extraWarnings_;
return *this;
}
@@ -1190,94 +1230,36 @@
bool baseline_ : 1;
bool ion_ : 1;
bool asmJS_ : 1;
+ bool wasm_ : 1;
+ bool wasmAlwaysBaseline_ : 1;
bool throwOnAsmJSValidationFailure_ : 1;
bool nativeRegExp_ : 1;
bool unboxedArrays_ : 1;
bool asyncStack_ : 1;
+ bool throwOnDebuggeeWouldRun_ : 1;
+ bool dumpStackOnDebuggeeWouldRun_ : 1;
bool werror_ : 1;
bool strictMode_ : 1;
bool extraWarnings_ : 1;
};
-JS_PUBLIC_API(RuntimeOptions&)
-RuntimeOptionsRef(JSRuntime* rt);
-
-JS_PUBLIC_API(RuntimeOptions&)
-RuntimeOptionsRef(JSContext* cx);
-
-class JS_PUBLIC_API(ContextOptions) {
- public:
- ContextOptions()
- : privateIsNSISupports_(false),
- dontReportUncaught_(false),
- autoJSAPIOwnsErrorReporting_(false)
- {
- }
-
- bool privateIsNSISupports() const { return privateIsNSISupports_; }
- ContextOptions& setPrivateIsNSISupports(bool flag) {
- privateIsNSISupports_ = flag;
- return *this;
- }
- ContextOptions& togglePrivateIsNSISupports() {
- privateIsNSISupports_ = !privateIsNSISupports_;
- return *this;
- }
-
- bool dontReportUncaught() const { return dontReportUncaught_; }
- ContextOptions& setDontReportUncaught(bool flag) {
- dontReportUncaught_ = flag;
- return *this;
- }
- ContextOptions& toggleDontReportUncaught() {
- dontReportUncaught_ = !dontReportUncaught_;
- return *this;
- }
-
- bool autoJSAPIOwnsErrorReporting() const { return autoJSAPIOwnsErrorReporting_; }
- ContextOptions& setAutoJSAPIOwnsErrorReporting(bool flag) {
- autoJSAPIOwnsErrorReporting_ = flag;
- return *this;
- }
- ContextOptions& toggleAutoJSAPIOwnsErrorReporting() {
- autoJSAPIOwnsErrorReporting_ = !autoJSAPIOwnsErrorReporting_;
- return *this;
- }
-
-
- private:
- bool privateIsNSISupports_ : 1;
- bool dontReportUncaught_ : 1;
- // dontReportUncaught isn't respected by all JSAPI codepaths, particularly the
- // JS_ReportError* functions that eventually report the error even when dontReportUncaught is
- // set, if script is not running. We want a way to indicate that the embedder will always
- // handle any exceptions, and that SpiderMonkey should just leave them on the context. This is
- // the way we want to do all future error handling in Gecko - stealing the exception explicitly
- // from the context and handling it as per the situation. This will eventually become the
- // default and these 2 flags should go away.
- bool autoJSAPIOwnsErrorReporting_ : 1;
-};
-
JS_PUBLIC_API(ContextOptions&)
ContextOptionsRef(JSContext* cx);
-class JS_PUBLIC_API(AutoSaveContextOptions) {
- public:
- explicit AutoSaveContextOptions(JSContext* cx)
- : cx_(cx),
- oldOptions_(ContextOptionsRef(cx_))
- {
- }
-
- ~AutoSaveContextOptions()
- {
- ContextOptionsRef(cx_) = oldOptions_;
- }
+/**
+ * Initialize the runtime's self-hosted code. Embeddings should call this
+ * exactly once per runtime/context, before the first JS_NewGlobalObject
+ * call.
+ */
+JS_PUBLIC_API(bool)
+InitSelfHostedCode(JSContext* cx);
- private:
- JSContext* cx_;
- JS::ContextOptions oldOptions_;
-};
+/**
+ * Asserts (in debug and release builds) that `obj` belongs to the current
+ * thread's context.
+ */
+JS_PUBLIC_API(void)
+AssertObjectBelongsToCurrentThread(JSObject* obj);
} /* namespace JS */
@@ -1285,19 +1267,23 @@
JS_GetImplementationVersion(void);
extern JS_PUBLIC_API(void)
-JS_SetDestroyCompartmentCallback(JSRuntime* rt, JSDestroyCompartmentCallback callback);
+JS_SetDestroyCompartmentCallback(JSContext* cx, JSDestroyCompartmentCallback callback);
+
+extern JS_PUBLIC_API(void)
+JS_SetSizeOfIncludingThisCompartmentCallback(JSContext* cx,
+ JSSizeOfIncludingThisCompartmentCallback callback);
extern JS_PUBLIC_API(void)
-JS_SetDestroyZoneCallback(JSRuntime* rt, JSZoneCallback callback);
+JS_SetDestroyZoneCallback(JSContext* cx, JSZoneCallback callback);
extern JS_PUBLIC_API(void)
-JS_SetSweepZoneCallback(JSRuntime* rt, JSZoneCallback callback);
+JS_SetSweepZoneCallback(JSContext* cx, JSZoneCallback callback);
extern JS_PUBLIC_API(void)
-JS_SetCompartmentNameCallback(JSRuntime* rt, JSCompartmentNameCallback callback);
+JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback);
extern JS_PUBLIC_API(void)
-JS_SetWrapObjectCallbacks(JSRuntime* rt, const JSWrapObjectCallbacks* callbacks);
+JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks);
extern JS_PUBLIC_API(void)
JS_SetCompartmentPrivate(JSCompartment* compartment, void* data);
@@ -1391,7 +1377,7 @@
extern JS_PUBLIC_API(void)
JS_LeaveCompartment(JSContext* cx, JSCompartment* oldCompartment);
-typedef void (*JSIterateCompartmentCallback)(JSRuntime* rt, void* data, JSCompartment* compartment);
+typedef void (*JSIterateCompartmentCallback)(JSContext* cx, void* data, JSCompartment* compartment);
/**
* This function calls |compartmentCallback| on every compartment. Beware that
@@ -1399,7 +1385,7 @@
* returns. Also, barriers are disabled via the TraceSession.
*/
extern JS_PUBLIC_API(void)
-JS_IterateCompartments(JSRuntime* rt, void* data,
+JS_IterateCompartments(JSContext* cx, void* data,
JSIterateCompartmentCallback compartmentCallback);
/**
@@ -1509,13 +1495,13 @@
JS_IsGlobalObject(JSObject* obj);
extern JS_PUBLIC_API(JSObject*)
-JS_GlobalLexicalScope(JSObject* obj);
+JS_GlobalLexicalEnvironment(JSObject* obj);
extern JS_PUBLIC_API(bool)
-JS_HasExtensibleLexicalScope(JSObject* obj);
+JS_HasExtensibleLexicalEnvironment(JSObject* obj);
extern JS_PUBLIC_API(JSObject*)
-JS_ExtensibleLexicalScope(JSObject* obj);
+JS_ExtensibleLexicalEnvironment(JSObject* obj);
/**
* May return nullptr, if |c| never had a global (e.g. the atoms compartment),
@@ -1607,50 +1593,47 @@
extern JS_PUBLIC_API(void)
JS_freeop(JSFreeOp* fop, void* p);
-extern JS_PUBLIC_API(JSFreeOp*)
-JS_GetDefaultFreeOp(JSRuntime* rt);
-
extern JS_PUBLIC_API(void)
JS_updateMallocCounter(JSContext* cx, size_t nbytes);
extern JS_PUBLIC_API(char*)
JS_strdup(JSContext* cx, const char* s);
-/** Duplicate a string. Does not report an error on failure. */
-extern JS_PUBLIC_API(char*)
-JS_strdup(JSRuntime* rt, const char* s);
-
/**
* Register externally maintained GC roots.
*
* traceOp: the trace operation. For each root the implementation should call
- * JS_CallTracer whenever the root contains a traceable thing.
+ * JS::TraceEdge whenever the root contains a traceable thing.
* data: the data argument to pass to each invocation of traceOp.
*/
extern JS_PUBLIC_API(bool)
-JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
+JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
/** Undo a call to JS_AddExtraGCRootsTracer. */
extern JS_PUBLIC_API(void)
-JS_RemoveExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
+JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
/*
* Garbage collector API.
*/
extern JS_PUBLIC_API(void)
-JS_GC(JSRuntime* rt);
+JS_GC(JSContext* cx);
extern JS_PUBLIC_API(void)
JS_MaybeGC(JSContext* cx);
extern JS_PUBLIC_API(void)
-JS_SetGCCallback(JSRuntime* rt, JSGCCallback cb, void* data);
+JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data);
+
+extern JS_PUBLIC_API(void)
+JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb,
+ void* data);
extern JS_PUBLIC_API(bool)
-JS_AddFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb, void* data);
+JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data);
extern JS_PUBLIC_API(void)
-JS_RemoveFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb);
+JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb);
/*
* Weak pointers and garbage collection
@@ -1687,17 +1670,17 @@
*/
extern JS_PUBLIC_API(bool)
-JS_AddWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb, void* data);
+JS_AddWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb, void* data);
extern JS_PUBLIC_API(void)
-JS_RemoveWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb);
+JS_RemoveWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb);
extern JS_PUBLIC_API(bool)
-JS_AddWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb,
+JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb,
void* data);
extern JS_PUBLIC_API(void)
-JS_RemoveWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb);
+JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb);
extern JS_PUBLIC_API(void)
JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp);
@@ -1718,9 +1701,6 @@
/** Number of times GC has been invoked. Includes both major and minor GC. */
JSGC_NUMBER = 4,
- /** Max size of the code cache in bytes. */
- JSGC_MAX_CODE_CACHE_BYTES = 5,
-
/** Select GC mode. */
JSGC_MODE = 6,
@@ -1770,13 +1750,6 @@
JSGC_ALLOCATION_THRESHOLD = 19,
/**
- * We decommit memory lazily. If more than this number of megabytes is
- * available to be decommitted, then JS_MaybeGC will trigger a shrinking GC
- * to decommit it.
- */
- JSGC_DECOMMIT_THRESHOLD = 20,
-
- /**
* We try to keep at least this many unused chunks in the free chunk pool at
* all times, even after a shrinking GC.
*/
@@ -1786,23 +1759,20 @@
JSGC_MAX_EMPTY_CHUNK_COUNT = 22,
/** Whether compacting GC is enabled. */
- JSGC_COMPACTING_ENABLED = 23
-} JSGCParamKey;
-
-extern JS_PUBLIC_API(void)
-JS_SetGCParameter(JSRuntime* rt, JSGCParamKey key, uint32_t value);
+ JSGC_COMPACTING_ENABLED = 23,
-extern JS_PUBLIC_API(uint32_t)
-JS_GetGCParameter(JSRuntime* rt, JSGCParamKey key);
+ /** If true, painting can trigger IGC slices. */
+ JSGC_REFRESH_FRAME_SLICES_ENABLED = 24,
+} JSGCParamKey;
extern JS_PUBLIC_API(void)
-JS_SetGCParameterForThread(JSContext* cx, JSGCParamKey key, uint32_t value);
+JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value);
extern JS_PUBLIC_API(uint32_t)
-JS_GetGCParameterForThread(JSContext* cx, JSGCParamKey key);
+JS_GetGCParameter(JSContext* cx, JSGCParamKey key);
extern JS_PUBLIC_API(void)
-JS_SetGCParametersBasedOnAvailableMemory(JSRuntime* rt, uint32_t availMem);
+JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem);
/**
* Create a new JSString whose chars member refers to external memory, i.e.,
@@ -1844,7 +1814,7 @@
* and before any code is executed and/or interrupts requested.
*/
extern JS_PUBLIC_API(void)
-JS_SetNativeStackQuota(JSRuntime* cx, size_t systemCodeStackSize,
+JS_SetNativeStackQuota(JSContext* cx, size_t systemCodeStackSize,
size_t trustedScriptStackSize = 0,
size_t untrustedScriptStackSize = 0);
@@ -1927,22 +1897,42 @@
*/
struct JSPropertySpec {
struct SelfHostedWrapper {
- void* unused;
+ void* unused;
const char* funname;
};
+ struct ValueWrapper {
+ uintptr_t type;
+ union {
+ const char* string;
+ int32_t int32;
+ };
+ };
+
const char* name;
uint8_t flags;
union {
- JSNativeWrapper native;
- SelfHostedWrapper selfHosted;
- } getter;
- union {
- JSNativeWrapper native;
- SelfHostedWrapper selfHosted;
- } setter;
+ struct {
+ union {
+ JSNativeWrapper native;
+ SelfHostedWrapper selfHosted;
+ } getter;
+ union {
+ JSNativeWrapper native;
+ SelfHostedWrapper selfHosted;
+ } setter;
+ } accessors;
+ ValueWrapper value;
+ };
+
+ bool isAccessor() const {
+ return !(flags & JSPROP_INTERNAL_USE_BIT);
+ }
+ JS_PUBLIC_API(bool) getValue(JSContext* cx, JS::MutableHandleValue value) const;
bool isSelfHosted() const {
+ MOZ_ASSERT(isAccessor());
+
#ifdef DEBUG
// Verify that our accessors match our JSPROP_GETTER flag.
if (flags & JSPROP_GETTER)
@@ -1961,17 +1951,17 @@
"JSNativeWrapper::info");
private:
void checkAccessorsAreNative() const {
- MOZ_ASSERT(getter.native.op);
+ MOZ_ASSERT(accessors.getter.native.op);
// We may not have a setter at all. So all we can assert here, for the
// native case is that if we have a jitinfo for the setter then we have
// a setter op too. This is good enough to make sure we don't have a
// SelfHostedWrapper for the setter.
- MOZ_ASSERT_IF(setter.native.info, setter.native.op);
+ MOZ_ASSERT_IF(accessors.setter.native.info, accessors.setter.native.op);
}
void checkAccessorsAreSelfHosted() const {
- MOZ_ASSERT(!getter.selfHosted.unused);
- MOZ_ASSERT(!setter.selfHosted.unused);
+ MOZ_ASSERT(!accessors.getter.selfHosted.unused);
+ MOZ_ASSERT(!accessors.setter.selfHosted.unused);
}
};
@@ -1986,13 +1976,15 @@
inline int
CheckIsCharacterLiteral(const char (&arr)[N]);
+/* NEVER DEFINED, DON'T USE. For use by JS_CAST_INT32_TO only. */
+inline int CheckIsInt32(int32_t value);
+
/* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_GETTER only. */
inline int CheckIsGetterOp(JSGetterOp op);
/* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_SETTER only. */
inline int CheckIsSetterOp(JSSetterOp op);
-
} // namespace detail
} // namespace JS
@@ -2004,6 +1996,10 @@
(static_cast<void>(sizeof(JS::detail::CheckIsCharacterLiteral(s))), \
reinterpret_cast<To>(s))
+#define JS_CAST_INT32_TO(s, To) \
+ (static_cast<void>(sizeof(JS::detail::CheckIsInt32(s))), \
+ reinterpret_cast<To>(s))
+
#define JS_CHECK_ACCESSOR_FLAGS(flags) \
(static_cast<mozilla::EnableIf<((flags) & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT)) == 0>::Type>(0), \
(flags))
@@ -2020,37 +2016,50 @@
#define JS_STUBSETTER JS_PROPERTYOP_SETTER(JS_StrictPropertyStub)
+#define JS_PS_ACCESSOR_SPEC(name, getter, setter, flags, extraFlags) \
+ { name, uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | extraFlags), \
+ { { getter, setter } } }
+#define JS_PS_VALUE_SPEC(name, value, flags) \
+ { name, uint8_t(flags | JSPROP_INTERNAL_USE_BIT), \
+ { { value, JSNATIVE_WRAPPER(nullptr) } } }
+
+#define SELFHOSTED_WRAPPER(name) \
+ { { nullptr, JS_CAST_STRING_TO(name, const JSJitInfo*) } }
+#define STRINGVALUE_WRAPPER(value) \
+ { { reinterpret_cast<JSNative>(JSVAL_TYPE_STRING), JS_CAST_STRING_TO(value, const JSJitInfo*) } }
+#define INT32VALUE_WRAPPER(value) \
+ { { reinterpret_cast<JSNative>(JSVAL_TYPE_INT32), JS_CAST_INT32_TO(value, const JSJitInfo*) } }
+
/*
* JSPropertySpec uses JSNativeWrapper. These macros encapsulate the definition
* of JSNative-backed JSPropertySpecs, by defining the JSNativeWrappers for
* them.
*/
#define JS_PSG(name, getter, flags) \
- {name, \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
- JSNATIVE_WRAPPER(getter), \
- JSNATIVE_WRAPPER(nullptr)}
+ JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED)
#define JS_PSGS(name, getter, setter, flags) \
- {name, \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \
- JSNATIVE_WRAPPER(getter), \
- JSNATIVE_WRAPPER(setter)}
+ JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(setter), flags, \
+ JSPROP_SHARED)
#define JS_SELF_HOSTED_GET(name, getterName, flags) \
- {name, \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
- { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
- JSNATIVE_WRAPPER(nullptr) }
+ JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED | JSPROP_GETTER)
#define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
- {name, \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER), \
- { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) }, \
- { nullptr, JS_CAST_STRING_TO(setterName, const JSJitInfo*) } }
-#define JS_PS_END { nullptr, 0, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr) }
+ JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), SELFHOSTED_WRAPPER(setterName), \
+ flags, JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER)
#define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \
- {reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
- uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
- { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
- JSNATIVE_WRAPPER(nullptr) }
+ JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
+ SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED | JSPROP_GETTER)
+#define JS_STRING_PS(name, string, flags) \
+ JS_PS_VALUE_SPEC(name, STRINGVALUE_WRAPPER(string), flags)
+#define JS_STRING_SYM_PS(symbol, string, flags) \
+ JS_PS_VALUE_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
+ STRINGVALUE_WRAPPER(string), flags)
+#define JS_INT32_PS(name, value, flags) \
+ JS_PS_VALUE_SPEC(name, INT32VALUE_WRAPPER(value), flags)
+#define JS_PS_END \
+ JS_PS_ACCESSOR_SPEC(nullptr, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr), 0, 0)
/**
* To define a native function, set call to a JSNativeWrapper. To define a
@@ -2128,6 +2137,17 @@
extern JS_PUBLIC_API(bool)
JS_HasInstance(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<JS::Value> v, bool* bp);
+namespace JS {
+
+// Implementation of
+// http://www.ecma-international.org/ecma-262/6.0/#sec-ordinaryhasinstance. If
+// you're looking for the equivalent of "instanceof", you want JS_HasInstance,
+// not this function.
+extern JS_PUBLIC_API(bool)
+OrdinaryHasInstance(JSContext* cx, HandleObject objArg, HandleValue v, bool* bp);
+
+} // namespace JS
+
extern JS_PUBLIC_API(void*)
JS_GetPrivate(JSObject* obj);
@@ -2148,7 +2168,121 @@
SystemZone = 1
};
-class JS_PUBLIC_API(CompartmentOptions)
+/**
+ * CompartmentCreationOptions specifies options relevant to creating a new
+ * compartment, that are either immutable characteristics of that compartment
+ * or that are discarded after the compartment has been created.
+ *
+ * Access to these options on an existing compartment is read-only: if you
+ * need particular selections, make them before you create the compartment.
+ */
+class JS_PUBLIC_API(CompartmentCreationOptions)
+{
+ public:
+ CompartmentCreationOptions()
+ : addonId_(nullptr),
+ traceGlobal_(nullptr),
+ invisibleToDebugger_(false),
+ mergeable_(false),
+ preserveJitCode_(false),
+ cloneSingletons_(false),
+ sharedMemoryAndAtomics_(false),
+ secureContext_(false)
+ {
+ zone_.spec = JS::FreshZone;
+ }
+
+ // A null add-on ID means that the compartment is not associated with an
+ // add-on.
+ JSAddonId* addonIdOrNull() const { return addonId_; }
+ CompartmentCreationOptions& setAddonId(JSAddonId* id) {
+ addonId_ = id;
+ return *this;
+ }
+
+ JSTraceOp getTrace() const {
+ return traceGlobal_;
+ }
+ CompartmentCreationOptions& setTrace(JSTraceOp op) {
+ traceGlobal_ = op;
+ return *this;
+ }
+
+ void* zonePointer() const {
+ MOZ_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
+ return zone_.pointer;
+ }
+ ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
+ CompartmentCreationOptions& setZone(ZoneSpecifier spec);
+ CompartmentCreationOptions& setSameZoneAs(JSObject* obj);
+
+ // Certain scopes (i.e. XBL compilation scopes) are implementation details
+ // of the embedding, and references to them should never leak out to script.
+ // This flag causes the this compartment to skip firing onNewGlobalObject
+ // and makes addDebuggee a no-op for this global.
+ bool invisibleToDebugger() const { return invisibleToDebugger_; }
+ CompartmentCreationOptions& setInvisibleToDebugger(bool flag) {
+ invisibleToDebugger_ = flag;
+ return *this;
+ }
+
+ // Compartments used for off-thread compilation have their contents merged
+ // into a target compartment when the compilation is finished. This is only
+ // allowed if this flag is set. The invisibleToDebugger flag must also be
+ // set for such compartments.
+ bool mergeable() const { return mergeable_; }
+ CompartmentCreationOptions& setMergeable(bool flag) {
+ mergeable_ = flag;
+ return *this;
+ }
+
+ // Determines whether this compartment should preserve JIT code on
+ // non-shrinking GCs.
+ bool preserveJitCode() const { return preserveJitCode_; }
+ CompartmentCreationOptions& setPreserveJitCode(bool flag) {
+ preserveJitCode_ = flag;
+ return *this;
+ }
+
+ bool cloneSingletons() const { return cloneSingletons_; }
+ CompartmentCreationOptions& setCloneSingletons(bool flag) {
+ cloneSingletons_ = flag;
+ return *this;
+ }
+
+ bool getSharedMemoryAndAtomicsEnabled() const;
+ CompartmentCreationOptions& setSharedMemoryAndAtomicsEnabled(bool flag);
+
+ // This flag doesn't affect JS engine behavior. It is used by Gecko to
+ // mark whether content windows and workers are "Secure Context"s. See
+ // https://w3c.github.io/webappsec-secure-contexts/
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1162772#c34
+ bool secureContext() const { return secureContext_; }
+ CompartmentCreationOptions& setSecureContext(bool flag) {
+ secureContext_ = flag;
+ return *this;
+ }
+
+ private:
+ JSAddonId* addonId_;
+ JSTraceOp traceGlobal_;
+ union {
+ ZoneSpecifier spec;
+ void* pointer; // js::Zone* is not exposed in the API.
+ } zone_;
+ bool invisibleToDebugger_;
+ bool mergeable_;
+ bool preserveJitCode_;
+ bool cloneSingletons_;
+ bool sharedMemoryAndAtomics_;
+ bool secureContext_;
+};
+
+/**
+ * CompartmentBehaviors specifies behaviors of a compartment that can be
+ * changed after the compartment's been created.
+ */
+class JS_PUBLIC_API(CompartmentBehaviors)
{
public:
class Override {
@@ -2179,140 +2313,119 @@
Mode mode_;
};
- explicit CompartmentOptions()
+ CompartmentBehaviors()
: version_(JSVERSION_UNKNOWN)
- , invisibleToDebugger_(false)
- , mergeable_(false)
, discardSource_(false)
, disableLazyParsing_(false)
- , cloneSingletons_(false)
- , traceGlobal_(nullptr)
, singletonsAsTemplates_(true)
- , addonId_(nullptr)
- , preserveJitCode_(false)
{
- zone_.spec = JS::FreshZone;
}
JSVersion version() const { return version_; }
- CompartmentOptions& setVersion(JSVersion aVersion) {
+ CompartmentBehaviors& setVersion(JSVersion aVersion) {
MOZ_ASSERT(aVersion != JSVERSION_UNKNOWN);
version_ = aVersion;
return *this;
}
- // Certain scopes (i.e. XBL compilation scopes) are implementation details
- // of the embedding, and references to them should never leak out to script.
- // This flag causes the this compartment to skip firing onNewGlobalObject
- // and makes addDebuggee a no-op for this global.
- bool invisibleToDebugger() const { return invisibleToDebugger_; }
- CompartmentOptions& setInvisibleToDebugger(bool flag) {
- invisibleToDebugger_ = flag;
- return *this;
- }
-
- // Compartments used for off-thread compilation have their contents merged
- // into a target compartment when the compilation is finished. This is only
- // allowed if this flag is set. The invisibleToDebugger flag must also be
- // set for such compartments.
- bool mergeable() const { return mergeable_; }
- CompartmentOptions& setMergeable(bool flag) {
- mergeable_ = flag;
- return *this;
- }
-
// For certain globals, we know enough about the code that will run in them
// that we can discard script source entirely.
bool discardSource() const { return discardSource_; }
- CompartmentOptions& setDiscardSource(bool flag) {
+ CompartmentBehaviors& setDiscardSource(bool flag) {
discardSource_ = flag;
return *this;
}
bool disableLazyParsing() const { return disableLazyParsing_; }
- CompartmentOptions& setDisableLazyParsing(bool flag) {
+ CompartmentBehaviors& setDisableLazyParsing(bool flag) {
disableLazyParsing_ = flag;
return *this;
}
- bool cloneSingletons() const { return cloneSingletons_; }
- CompartmentOptions& setCloneSingletons(bool flag) {
- cloneSingletons_ = flag;
- return *this;
- }
-
- bool extraWarnings(JSRuntime* rt) const;
bool extraWarnings(JSContext* cx) const;
Override& extraWarningsOverride() { return extraWarningsOverride_; }
- void* zonePointer() const {
- MOZ_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
- return zone_.pointer;
- }
- ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
- CompartmentOptions& setZone(ZoneSpecifier spec);
- CompartmentOptions& setSameZoneAs(JSObject* obj);
-
- void setSingletonsAsValues() {
- singletonsAsTemplates_ = false;
- }
bool getSingletonsAsTemplates() const {
return singletonsAsTemplates_;
}
-
- // A null add-on ID means that the compartment is not associated with an
- // add-on.
- JSAddonId* addonIdOrNull() const { return addonId_; }
- CompartmentOptions& setAddonId(JSAddonId* id) {
- addonId_ = id;
- return *this;
- }
-
- CompartmentOptions& setTrace(JSTraceOp op) {
- traceGlobal_ = op;
- return *this;
- }
- JSTraceOp getTrace() const {
- return traceGlobal_;
- }
-
- bool preserveJitCode() const { return preserveJitCode_; }
- CompartmentOptions& setPreserveJitCode(bool flag) {
- preserveJitCode_ = flag;
+ CompartmentBehaviors& setSingletonsAsValues() {
+ singletonsAsTemplates_ = false;
return *this;
}
private:
JSVersion version_;
- bool invisibleToDebugger_;
- bool mergeable_;
bool discardSource_;
bool disableLazyParsing_;
- bool cloneSingletons_;
Override extraWarningsOverride_;
- union {
- ZoneSpecifier spec;
- void* pointer; // js::Zone* is not exposed in the API.
- } zone_;
- JSTraceOp traceGlobal_;
// To XDR singletons, we need to ensure that all singletons are all used as
// templates, by making JSOP_OBJECT return a clone of the JSScript
// singleton, instead of returning the value which is baked in the JSScript.
bool singletonsAsTemplates_;
+};
- JSAddonId* addonId_;
- bool preserveJitCode_;
+/**
+ * CompartmentOptions specifies compartment characteristics: both those that
+ * can't be changed on a compartment once it's been created
+ * (CompartmentCreationOptions), and those that can be changed on an existing
+ * compartment (CompartmentBehaviors).
+ */
+class JS_PUBLIC_API(CompartmentOptions)
+{
+ public:
+ explicit CompartmentOptions()
+ : creationOptions_(),
+ behaviors_()
+ {}
+
+ CompartmentOptions(const CompartmentCreationOptions& compartmentCreation,
+ const CompartmentBehaviors& compartmentBehaviors)
+ : creationOptions_(compartmentCreation),
+ behaviors_(compartmentBehaviors)
+ {}
+
+ // CompartmentCreationOptions specify fundamental compartment
+ // characteristics that must be specified when the compartment is created,
+ // that can't be changed after the compartment is created.
+ CompartmentCreationOptions& creationOptions() {
+ return creationOptions_;
+ }
+ const CompartmentCreationOptions& creationOptions() const {
+ return creationOptions_;
+ }
+
+ // CompartmentBehaviors specify compartment characteristics that can be
+ // changed after the compartment is created.
+ CompartmentBehaviors& behaviors() {
+ return behaviors_;
+ }
+ const CompartmentBehaviors& behaviors() const {
+ return behaviors_;
+ }
+
+ private:
+ CompartmentCreationOptions creationOptions_;
+ CompartmentBehaviors behaviors_;
};
-JS_PUBLIC_API(CompartmentOptions&)
-CompartmentOptionsRef(JSCompartment* compartment);
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSCompartment* compartment);
+
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSObject* obj);
-JS_PUBLIC_API(CompartmentOptions&)
-CompartmentOptionsRef(JSObject* obj);
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSContext* cx);
-JS_PUBLIC_API(CompartmentOptions&)
-CompartmentOptionsRef(JSContext* cx);
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSCompartment* compartment);
+
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSObject* obj);
+
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSContext* cx);
/**
* During global creation, we fire notifications to callbacks registered
@@ -2346,7 +2459,7 @@
extern JS_PUBLIC_API(JSObject*)
JS_NewGlobalObject(JSContext* cx, const JSClass* clasp, JSPrincipals* principals,
JS::OnNewGlobalHookOption hookOption,
- const JS::CompartmentOptions& options = JS::CompartmentOptions());
+ const JS::CompartmentOptions& options);
/**
* Spidermonkey does not have a good way of keeping track of what compartments should be marked on
* their own. We can mark the roots unconditionally, but marking GC things only relevant in live
@@ -2368,9 +2481,6 @@
extern JS_PUBLIC_API(bool)
JS_IsNative(JSObject* obj);
-extern JS_PUBLIC_API(JSRuntime*)
-JS_GetObjectRuntime(JSObject* obj);
-
/**
* Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
* proto. If proto is nullptr, the JS object will have `null` as [[Prototype]].
@@ -2399,27 +2509,27 @@
/*** Property descriptors ************************************************************************/
-struct JS_PUBLIC_API(JSPropertyDescriptor) : public JS::Traceable {
+namespace JS {
+
+struct JS_PUBLIC_API(PropertyDescriptor) {
JSObject* obj;
unsigned attrs;
JSGetterOp getter;
JSSetterOp setter;
JS::Value value;
- JSPropertyDescriptor()
+ PropertyDescriptor()
: obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JS::UndefinedValue())
{}
- static void trace(JSPropertyDescriptor* self, JSTracer* trc) { self->trace(trc); }
+ static void trace(PropertyDescriptor* self, JSTracer* trc) { self->trace(trc); }
void trace(JSTracer* trc);
};
-namespace JS {
-
template <typename Outer>
class PropertyDescriptorOperations
{
- const JSPropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
+ const PropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
bool has(unsigned bit) const {
MOZ_ASSERT(bit != 0);
@@ -2551,7 +2661,7 @@
template <typename Outer>
class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<Outer>
{
- JSPropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
+ PropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
public:
void clear() {
@@ -2574,7 +2684,7 @@
setSetter(setterOp);
}
- void assign(JSPropertyDescriptor& other) {
+ void assign(PropertyDescriptor& other) {
object().set(other.obj);
setAttributes(other.attrs);
setGetter(other.getter);
@@ -2662,18 +2772,18 @@
namespace js {
template <>
-class RootedBase<JSPropertyDescriptor>
- : public JS::MutablePropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor>>
+class RootedBase<JS::PropertyDescriptor>
+ : public JS::MutablePropertyDescriptorOperations<JS::Rooted<JS::PropertyDescriptor>>
{};
template <>
-class HandleBase<JSPropertyDescriptor>
- : public JS::PropertyDescriptorOperations<JS::Handle<JSPropertyDescriptor>>
+class HandleBase<JS::PropertyDescriptor>
+ : public JS::PropertyDescriptorOperations<JS::Handle<JS::PropertyDescriptor>>
{};
template <>
-class MutableHandleBase<JSPropertyDescriptor>
- : public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JSPropertyDescriptor>>
+class MutableHandleBase<JS::PropertyDescriptor>
+ : public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JS::PropertyDescriptor>>
{};
} /* namespace js */
@@ -2684,7 +2794,17 @@
ObjectToCompletePropertyDescriptor(JSContext* cx,
JS::HandleObject obj,
JS::HandleValue descriptor,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<PropertyDescriptor> desc);
+
+/*
+ * ES6 draft rev 32 (2015 Feb 2) 6.2.4.4 FromPropertyDescriptor(Desc).
+ *
+ * If desc.object() is null, then vp is set to undefined.
+ */
+extern JS_PUBLIC_API(bool)
+FromPropertyDescriptor(JSContext* cx,
+ JS::Handle<JS::PropertyDescriptor> desc,
+ JS::MutableHandleValue vp);
} // namespace JS
@@ -2715,6 +2835,17 @@
JS_GetPrototype(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject result);
/**
+ * If |obj| (underneath any functionally-transparent wrapper proxies) has as
+ * its [[GetPrototypeOf]] trap the ordinary [[GetPrototypeOf]] behavior defined
+ * for ordinary objects, set |*isOrdinary = true| and store |obj|'s prototype
+ * in |result|. Otherwise set |*isOrdinary = false|. In case of error, both
+ * outparams have unspecified value.
+ */
+extern JS_PUBLIC_API(bool)
+JS_GetPrototypeIfOrdinary(JSContext* cx, JS::HandleObject obj, bool* isOrdinary,
+ JS::MutableHandleObject result);
+
+/**
* Change the prototype of obj.
*
* Implements: ES6 [[SetPrototypeOf]] internal method.
@@ -2771,15 +2902,15 @@
*/
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
/**
* Like JS_GetOwnPropertyDescriptorById, but also searches the prototype chain
@@ -2789,11 +2920,11 @@
*/
extern JS_PUBLIC_API(bool)
JS_GetPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
/**
* Define a property on obj.
@@ -2808,7 +2939,7 @@
*/
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::Handle<JSPropertyDescriptor> desc,
+ JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
/**
@@ -2817,7 +2948,7 @@
*/
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::Handle<JSPropertyDescriptor> desc);
+ JS::Handle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
@@ -2869,12 +3000,12 @@
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
- JS::Handle<JSPropertyDescriptor> desc,
+ JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
- JS::Handle<JSPropertyDescriptor> desc);
+ JS::Handle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
@@ -3099,8 +3230,8 @@
* This is the closest thing we currently have to the ES6 [[Enumerate]]
* internal method.
*
- * The JSIdArray returned by JS_Enumerate must be rooted to protect its
- * contents from garbage collection. Use JS::AutoIdArray.
+ * The array of ids returned by JS_Enumerate must be rooted to protect its
+ * contents from garbage collection. Use JS::Rooted<JS::IdVector>.
*/
extern JS_PUBLIC_API(bool)
JS_Enumerate(JSContext* cx, JS::HandleObject obj, JS::MutableHandle<JS::IdVector> props);
@@ -3213,21 +3344,18 @@
*/
extern JS_PUBLIC_API(bool)
Construct(JSContext* cx, JS::HandleValue fun, HandleObject newTarget,
- const JS::HandleValueArray &args, MutableHandleValue rval);
+ const JS::HandleValueArray &args, MutableHandleObject objp);
/**
* Invoke a constructor. This is the C++ equivalent of
* `rval = new fun(...args)`.
*
- * The value left in rval on success is always an object in practice,
- * though at the moment this is not enforced by the C++ type system.
- *
* Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]), when
* newTarget is omitted.
*/
extern JS_PUBLIC_API(bool)
Construct(JSContext* cx, JS::HandleValue fun, const JS::HandleValueArray& args,
- MutableHandleValue rval);
+ MutableHandleObject objp);
} /* namespace JS */
@@ -3304,6 +3432,30 @@
extern JS_PUBLIC_API(bool)
JS_SetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t length);
+namespace JS {
+
+/**
+ * Returns true and sets |*isMap| indicating whether |obj| is an Map object
+ * or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isMap == false| when passed a proxy whose
+ * target is an Map, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+IsMapObject(JSContext* cx, JS::HandleObject obj, bool* isMap);
+
+/**
+ * Returns true and sets |*isSet| indicating whether |obj| is an Set object
+ * or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isSet == false| when passed a proxy whose
+ * target is an Set, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+IsSetObject(JSContext* cx, JS::HandleObject obj, bool* isSet);
+
+} /* namespace JS */
+
/**
* Assign 'undefined' to all of the object's non-reserved slots. Note: this is
* done for all slots, regardless of the associated property descriptor.
@@ -3320,6 +3472,13 @@
JS_NewArrayBufferWithContents(JSContext* cx, size_t nbytes, void* contents);
/**
+ * Create a new array buffer with the given contents. The array buffer does not take ownership of
+ * contents, and JS_DetachArrayBuffer must be called before the contents are disposed of.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_NewArrayBufferWithExternalContents(JSContext* cx, size_t nbytes, void* contents);
+
+/**
* Steal the contents of the given array buffer. The array buffer has its
* length set to 0 and its contents array cleared. The caller takes ownership
* of the return value and must free it or transfer ownership via
@@ -3329,6 +3488,25 @@
JS_StealArrayBufferContents(JSContext* cx, JS::HandleObject obj);
/**
+ * Returns a pointer to the ArrayBuffer |obj|'s data. |obj| and its views will store and expose
+ * the data in the returned pointer: assigning into the returned pointer will affect values exposed
+ * by views of |obj| and vice versa.
+ *
+ * The caller must ultimately deallocate the returned pointer to avoid leaking. The memory is
+ * *not* garbage-collected with |obj|. These steps must be followed to deallocate:
+ *
+ * 1. The ArrayBuffer |obj| must be detached using JS_DetachArrayBuffer.
+ * 2. The returned pointer must be freed using JS_free.
+ *
+ * To perform step 1, callers *must* hold a reference to |obj| until they finish using the returned
+ * pointer. They *must not* attempt to let |obj| be GC'd, then JS_free the pointer.
+ *
+ * If |obj| isn't an ArrayBuffer, this function returns null and reports an error.
+ */
+extern JS_PUBLIC_API(void*)
+JS_ExternalizeArrayBufferContents(JSContext* cx, JS::HandleObject obj);
+
+/**
* Create a new mapped array buffer with the given memory mapped contents. It
* must be legal to free the contents pointer by unmapping it. On success,
* ownership is transferred to the new mapped array buffer.
@@ -3347,7 +3525,7 @@
* Release the allocated resource of mapped array buffer contents before the
* object is created.
* If a new object has been created by JS_NewMappedArrayBufferWithContents()
- * with this content, then JS_NeuterArrayBuffer() should be used instead to
+ * with this content, then JS_DetachArrayBuffer() should be used instead to
* release the resource used by the object.
*/
extern JS_PUBLIC_API(void)
@@ -3357,7 +3535,7 @@
JS_GetReservedSlot(JSObject* obj, uint32_t index);
extern JS_PUBLIC_API(void)
-JS_SetReservedSlot(JSObject* obj, uint32_t index, JS::Value v);
+JS_SetReservedSlot(JSObject* obj, uint32_t index, const JS::Value& v);
/************************************************************************/
@@ -3432,20 +3610,8 @@
extern JS_PUBLIC_API(bool)
JS_IsConstructor(JSFunction* fun);
-/**
- * This enum is used to select if properties with JSPROP_DEFINE_LATE flag
- * should be defined on the object.
- * Normal JSAPI consumers probably always want DefineAllProperties here.
- */
-enum PropertyDefinitionBehavior {
- DefineAllProperties,
- OnlyDefineLateProperties,
- DontDefineLateProperties
-};
-
extern JS_PUBLIC_API(bool)
-JS_DefineFunctions(JSContext* cx, JS::Handle<JSObject*> obj, const JSFunctionSpec* fs,
- PropertyDefinitionBehavior behavior = DefineAllProperties);
+JS_DefineFunctions(JSContext* cx, JS::Handle<JSObject*> obj, const JSFunctionSpec* fs);
extern JS_PUBLIC_API(JSFunction*)
JS_DefineFunction(JSContext* cx, JS::Handle<JSObject*> obj, const char* name, JSNative call,
@@ -3460,6 +3626,12 @@
JS_DefineFunctionById(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSNative call,
unsigned nargs, unsigned attrs);
+extern JS_PUBLIC_API(bool)
+JS_IsFunctionBound(JSFunction* fun);
+
+extern JS_PUBLIC_API(JSObject*)
+JS_GetBoundFunctionTarget(JSFunction* fun);
+
namespace JS {
/**
@@ -3680,7 +3852,6 @@
lineno(1),
column(0),
isRunOnce(false),
- forEval(false),
noScriptRval(false)
{ }
@@ -3704,7 +3875,6 @@
unsigned column;
// isRunOnce only applies to non-function scripts.
bool isRunOnce;
- bool forEval;
bool noScriptRval;
private:
@@ -3726,7 +3896,6 @@
*/
class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
{
- JSRuntime* runtime;
PersistentRootedObject elementRoot;
PersistentRootedString elementAttributeNameRoot;
PersistentRootedScript introductionScriptRoot;
@@ -3778,7 +3947,6 @@
OwningCompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
OwningCompileOptions& setColumn(unsigned c) { column = c; return *this; }
OwningCompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
- OwningCompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
OwningCompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
OwningCompileOptions& setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
OwningCompileOptions& setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
@@ -3808,7 +3976,7 @@
* create an instance of this type, it's up to you to guarantee that
* everything you store in it will outlive it.
*/
-class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOptions
+class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) final : public ReadOnlyCompileOptions
{
RootedObject elementRoot;
RootedString elementAttributeNameRoot;
@@ -3875,7 +4043,6 @@
CompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
CompileOptions& setColumn(unsigned c) { column = c; return *this; }
CompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
- CompileOptions& setForEval(bool eval) { forEval = eval; return *this; }
CompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
CompileOptions& setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
CompileOptions& setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
@@ -3953,10 +4120,11 @@
* After successfully triggering an off thread compile of a script, the
* callback will eventually be invoked with the specified data and a token
* for the compilation. The callback will be invoked while off the main thread,
- * so must ensure that its operations are thread safe. Afterwards,
- * FinishOffThreadScript must be invoked on the main thread to get the result
- * script or nullptr. If maybecx is not specified, the resources will be freed,
- * but no script will be returned.
+ * so must ensure that its operations are thread safe. Afterwards, one of the
+ * following functions must be invoked on the main thread:
+ *
+ * - FinishOffThreadScript, to get the result script (or nullptr on failure).
+ * - CancelOffThreadScript, to free the resources without creating a script.
*
* The characters passed in to CompileOffThread must remain live until the
* callback is invoked, and the resulting script will be rooted until the call
@@ -3969,17 +4137,31 @@
OffThreadCompileCallback callback, void* callbackData);
extern JS_PUBLIC_API(JSScript*)
-FinishOffThreadScript(JSContext* maybecx, JSRuntime* rt, void* token);
+FinishOffThreadScript(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadScript(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(bool)
+CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char16_t* chars, size_t length,
+ OffThreadCompileCallback callback, void* callbackData);
+
+extern JS_PUBLIC_API(JSObject*)
+FinishOffThreadModule(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadModule(JSContext* cx, void* token);
/**
- * Compile a function with scopeChain plus the global as its scope chain.
- * scopeChain must contain objects in the current compartment of cx. The actual
+ * Compile a function with envChain plus the global as its scope chain.
+ * envChain must contain objects in the current compartment of cx. The actual
* scope chain used for the function will consist of With wrappers for those
* objects, followed by the current global of the compartment cx is in. This
* global must not be explicitly included in the scope chain.
*/
extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
const ReadOnlyCompileOptions& options,
const char* name, unsigned nargs, const char* const* argnames,
const char16_t* chars, size_t length, JS::MutableHandleFunction fun);
@@ -3988,7 +4170,7 @@
* Same as above, but taking a SourceBufferHolder for the function body.
*/
extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
const ReadOnlyCompileOptions& options,
const char* name, unsigned nargs, const char* const* argnames,
SourceBufferHolder& srcBuf, JS::MutableHandleFunction fun);
@@ -3997,7 +4179,7 @@
* Same as above, but taking a const char * for the function body.
*/
extern JS_PUBLIC_API(bool)
-CompileFunction(JSContext* cx, AutoObjectVector& scopeChain,
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
const ReadOnlyCompileOptions& options,
const char* name, unsigned nargs, const char* const* argnames,
const char* bytes, size_t length, JS::MutableHandleFunction fun);
@@ -4029,7 +4211,7 @@
* Why a runtime option? The alternative is to add APIs duplicating those
* for the other value of flags, and that doesn't seem worth the code bloat
* cost. Such new entry points would probably have less obvious names, too, so
- * would not tend to be used. The RuntimeOptionsRef adjustment, OTOH, can be
+ * would not tend to be used. The ContextOptionsRef adjustment, OTOH, can be
* more easily hacked into existing code that does not depend on the bug; such
* code can continue to use the familiar JS::Evaluate, etc., entry points.
*/
@@ -4044,16 +4226,16 @@
JS_ExecuteScript(JSContext* cx, JS::HandleScript script);
/**
- * As above, but providing an explicit scope chain. scopeChain must not include
+ * As above, but providing an explicit scope chain. envChain must not include
* the global object on it; that's implicit. It needs to contain the other
* objects that should end up on the script's scope chain.
*/
extern JS_PUBLIC_API(bool)
-JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& scopeChain,
+JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain,
JS::HandleScript script, JS::MutableHandleValue rval);
extern JS_PUBLIC_API(bool)
-JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& scopeChain, JS::HandleScript script);
+JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain, JS::HandleScript script);
namespace JS {
@@ -4062,7 +4244,8 @@
* cross-compartment, it is cloned into the current compartment before executing.
*/
extern JS_PUBLIC_API(bool)
-CloneAndExecuteScript(JSContext* cx, JS::Handle<JSScript*> script);
+CloneAndExecuteScript(JSContext* cx, JS::Handle<JSScript*> script,
+ JS::MutableHandleValue rval);
} /* namespace JS */
@@ -4076,12 +4259,12 @@
SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
/**
- * As above, but providing an explicit scope chain. scopeChain must not include
+ * As above, but providing an explicit scope chain. envChain must not include
* the global object on it; that's implicit. It needs to contain the other
* objects that should end up on the script's scope chain.
*/
extern JS_PUBLIC_API(bool)
-Evaluate(JSContext* cx, AutoObjectVector& scopeChain, const ReadOnlyCompileOptions& options,
+Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
/**
@@ -4092,12 +4275,12 @@
const char16_t* chars, size_t length, JS::MutableHandleValue rval);
/**
- * As above, but providing an explicit scope chain. scopeChain must not include
+ * As above, but providing an explicit scope chain. envChain must not include
* the global object on it; that's implicit. It needs to contain the other
* objects that should end up on the script's scope chain.
*/
extern JS_PUBLIC_API(bool)
-Evaluate(JSContext* cx, AutoObjectVector& scopeChain, const ReadOnlyCompileOptions& options,
+Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
const char16_t* chars, size_t length, JS::MutableHandleValue rval);
/**
@@ -4114,6 +4297,80 @@
Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
const char* filename, JS::MutableHandleValue rval);
+/**
+ * Get the HostResolveImportedModule hook for a global.
+ */
+extern JS_PUBLIC_API(JSFunction*)
+GetModuleResolveHook(JSContext* cx);
+
+/**
+ * Set the HostResolveImportedModule hook for a global to the given function.
+ */
+extern JS_PUBLIC_API(void)
+SetModuleResolveHook(JSContext* cx, JS::HandleFunction func);
+
+/**
+ * Parse the given source buffer as a module in the scope of the current global
+ * of cx and return a source text module record.
+ */
+extern JS_PUBLIC_API(bool)
+CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
+ SourceBufferHolder& srcBuf, JS::MutableHandleObject moduleRecord);
+
+/**
+ * Set the [[HostDefined]] field of a source text module record to the given
+ * value.
+ */
+extern JS_PUBLIC_API(void)
+SetModuleHostDefinedField(JSObject* module, const JS::Value& value);
+
+/**
+ * Get the [[HostDefined]] field of a source text module record.
+ */
+extern JS_PUBLIC_API(JS::Value)
+GetModuleHostDefinedField(JSObject* module);
+
+/*
+ * Perform the ModuleDeclarationInstantiation operation on on the give source
+ * text module record.
+ *
+ * This transitively resolves all module dependencies (calling the
+ * HostResolveImportedModule hook) and initializes the environment record for
+ * the module.
+ */
+extern JS_PUBLIC_API(bool)
+ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Perform the ModuleEvaluation operation on on the give source text module
+ * record.
+ *
+ * This does nothing if this module has already been evaluated. Otherwise, it
+ * transitively evaluates all dependences of this module and then evaluates this
+ * module.
+ *
+ * ModuleDeclarationInstantiation must have completed prior to calling this.
+ */
+extern JS_PUBLIC_API(bool)
+ModuleEvaluation(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Get a list of the module specifiers used by a source text module
+ * record to request importation of modules.
+ *
+ * The result is a JavaScript array of string values. To extract the individual
+ * values use only JS_GetArrayLength and JS_GetElement with indices 0 to
+ * length - 1.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetRequestedModules(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Get the script associated with a module.
+ */
+extern JS_PUBLIC_API(JSScript*)
+GetModuleScript(JSContext* cx, JS::HandleObject moduleRecord);
+
} /* namespace JS */
extern JS_PUBLIC_API(bool)
@@ -4122,7 +4379,7 @@
/*
* These functions allow setting an interrupt callback that will be called
* from the JS thread some time after any thread triggered the callback using
- * JS_RequestInterruptCallback(rt).
+ * JS_RequestInterruptCallback(cx).
*
* To schedule the GC and for other activities the engine internally triggers
* interrupt callbacks. The embedding should thus not rely on callbacks being
@@ -4132,34 +4389,257 @@
* if it re-enters the JS engine. The embedding must ensure that the callback
* is disconnected before attempting such re-entry.
*/
-extern JS_PUBLIC_API(JSInterruptCallback)
-JS_SetInterruptCallback(JSRuntime* rt, JSInterruptCallback callback);
+extern JS_PUBLIC_API(bool)
+JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback);
+
+extern JS_PUBLIC_API(bool)
+JS_DisableInterruptCallback(JSContext* cx);
+
+extern JS_PUBLIC_API(void)
+JS_ResetInterruptCallback(JSContext* cx, bool enable);
+
+extern JS_PUBLIC_API(void)
+JS_RequestInterruptCallback(JSContext* cx);
+
+namespace JS {
+
+/**
+ * Sets the callback that's invoked whenever an incumbent global is required.
+ *
+ * SpiderMonkey doesn't itself have a notion of incumbent globals as defined
+ * by the html spec, so we need the embedding to provide this.
+ * See dom/base/ScriptSettings.h for details.
+ */
+extern JS_PUBLIC_API(void)
+SetGetIncumbentGlobalCallback(JSContext* cx, JSGetIncumbentGlobalCallback callback);
-extern JS_PUBLIC_API(JSInterruptCallback)
-JS_GetInterruptCallback(JSRuntime* rt);
+/**
+ * Sets the callback that's invoked whenever a Promise job should be enqeued.
+ *
+ * SpiderMonkey doesn't schedule Promise resolution jobs itself; instead,
+ * using this function the embedding can provide a callback to do that
+ * scheduling. The provided `callback` is invoked with the promise job,
+ * the corresponding Promise's allocation stack, and the `data` pointer
+ * passed here as arguments.
+ */
+extern JS_PUBLIC_API(void)
+SetEnqueuePromiseJobCallback(JSContext* cx, JSEnqueuePromiseJobCallback callback,
+ void* data = nullptr);
+/**
+ * Sets the callback that's invoked whenever a Promise is rejected without
+ * a rejection handler, and when a Promise that was previously rejected
+ * without a handler gets a handler attached.
+ */
extern JS_PUBLIC_API(void)
-JS_RequestInterruptCallback(JSRuntime* rt);
+SetPromiseRejectionTrackerCallback(JSContext* cx, JSPromiseRejectionTrackerCallback callback,
+ void* data = nullptr);
+/**
+ * Returns a new instance of the Promise builtin class in the current
+ * compartment, with the right slot layout. If a `proto` is passed, that gets
+ * set as the instance's [[Prototype]] instead of the original value of
+ * `Promise.prototype`.
+ */
+extern JS_PUBLIC_API(JSObject*)
+NewPromiseObject(JSContext* cx, JS::HandleObject executor, JS::HandleObject proto = nullptr);
+
+/**
+ * Returns true if the given object is an unwrapped PromiseObject, false
+ * otherwise.
+ */
extern JS_PUBLIC_API(bool)
-JS_IsRunning(JSContext* cx);
+IsPromiseObject(JS::HandleObject obj);
-/*
- * Saving and restoring frame chains.
+/**
+ * Returns the current compartment's original Promise constructor.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseConstructor(JSContext* cx);
+
+/**
+ * Returns the current compartment's original Promise.prototype.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromisePrototype(JSContext* cx);
+
+// Keep this in sync with the PROMISE_STATE defines in SelfHostingDefines.h.
+enum class PromiseState {
+ Pending,
+ Fulfilled,
+ Rejected
+};
+
+/**
+ * Returns the given Promise's state as a JS::PromiseState enum value.
+ *
+ * Returns JS::PromiseState::Pending if the given object is a wrapper that
+ * can't safely be unwrapped.
+ */
+extern JS_PUBLIC_API(PromiseState)
+GetPromiseState(JS::HandleObject promise);
+
+/**
+ * Returns the given Promise's process-unique ID.
+ */
+JS_PUBLIC_API(uint64_t)
+GetPromiseID(JS::HandleObject promise);
+
+/**
+ * Returns the given Promise's result: either the resolution value for
+ * fulfilled promises, or the rejection reason for rejected ones.
+ */
+extern JS_PUBLIC_API(JS::Value)
+GetPromiseResult(JS::HandleObject promise);
+
+/**
+ * Returns a js::SavedFrame linked list of the stack that lead to the given
+ * Promise's allocation.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseAllocationSite(JS::HandleObject promise);
+
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseResolutionSite(JS::HandleObject promise);
+
+#ifdef DEBUG
+extern JS_PUBLIC_API(void)
+DumpPromiseAllocationSite(JSContext* cx, JS::HandleObject promise);
+
+extern JS_PUBLIC_API(void)
+DumpPromiseResolutionSite(JSContext* cx, JS::HandleObject promise);
+#endif
+
+/**
+ * Calls the current compartment's original Promise.resolve on the original
+ * Promise constructor, with `resolutionValue` passed as an argument.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseResolve(JSContext* cx, JS::HandleValue resolutionValue);
+
+/**
+ * Calls the current compartment's original Promise.reject on the original
+ * Promise constructor, with `resolutionValue` passed as an argument.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseReject(JSContext* cx, JS::HandleValue rejectionValue);
+
+/**
+ * Resolves the given Promise with the given `resolutionValue`.
+ *
+ * Calls the `resolve` function that was passed to the executor function when
+ * the Promise was created.
+ */
+extern JS_PUBLIC_API(bool)
+ResolvePromise(JSContext* cx, JS::HandleObject promise, JS::HandleValue resolutionValue);
+
+/**
+ * Rejects the given `promise` with the given `rejectionValue`.
+ *
+ * Calls the `reject` function that was passed to the executor function when
+ * the Promise was created.
+ */
+extern JS_PUBLIC_API(bool)
+RejectPromise(JSContext* cx, JS::HandleObject promise, JS::HandleValue rejectionValue);
+
+/**
+ * Calls the current compartment's original Promise.prototype.then on the
+ * given `promise`, with `onResolve` and `onReject` passed as arguments.
+ *
+ * Asserts if the passed-in `promise` object isn't an unwrapped instance of
+ * `Promise` or a subclass or `onResolve` and `onReject` aren't both either
+ * `nullptr` or callable objects.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseThen(JSContext* cx, JS::HandleObject promise,
+ JS::HandleObject onResolve, JS::HandleObject onReject);
+
+/**
+ * Unforgeable, optimized version of the JS builtin Promise.prototype.then.
*
- * These two functions are used to set aside cx's call stack while that stack
- * is inactive. After a call to JS_SaveFrameChain, it looks as if there is no
- * code running on cx. Before calling JS_RestoreFrameChain, cx's call stack
- * must be balanced and all nested calls to JS_SaveFrameChain must have had
- * matching JS_RestoreFrameChain calls.
+ * Takes a Promise instance and `onResolve`, `onReject` callables to enqueue
+ * as reactions for that promise. In difference to Promise.prototype.then,
+ * this doesn't create and return a new Promise instance.
*
- * JS_SaveFrameChain deals with cx not having any code running on it.
+ * Asserts if the passed-in `promise` object isn't an unwrapped instance of
+ * `Promise` or a subclass or `onResolve` and `onReject` aren't both callable
+ * objects.
*/
extern JS_PUBLIC_API(bool)
-JS_SaveFrameChain(JSContext* cx);
+AddPromiseReactions(JSContext* cx, JS::HandleObject promise,
+ JS::HandleObject onResolve, JS::HandleObject onReject);
+
+/**
+ * Unforgeable version of the JS builtin Promise.all.
+ *
+ * Takes an AutoObjectVector of Promise objects and returns a promise that's
+ * resolved with an array of resolution values when all those promises have
+ * been resolved, or rejected with the rejection value of the first rejected
+ * promise.
+ *
+ * Asserts that all objects in the `promises` vector are, maybe wrapped,
+ * instances of `Promise` or a subclass of `Promise`.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises);
+
+/**
+ * An AsyncTask represents a SpiderMonkey-internal operation that starts on a
+ * JSContext's owner thread, possibly executes on other threads, completes, and
+ * then needs to be scheduled to run again on the JSContext's owner thread. The
+ * embedding provides for this final dispatch back to the JSContext's owner
+ * thread by calling methods on this interface when requested.
+ */
+struct JS_PUBLIC_API(AsyncTask)
+{
+ AsyncTask() : user(nullptr) {}
+ virtual ~AsyncTask() {}
+
+ /**
+ * After the FinishAsyncTaskCallback is called and succeeds, one of these
+ * two functions will be called on the original JSContext's owner thread.
+ */
+ virtual void finish(JSContext* cx) = 0;
+ virtual void cancel(JSContext* cx) = 0;
+
+ /* The embedding may use this field to attach arbitrary data to a task. */
+ void* user;
+};
+
+/**
+ * A new AsyncTask object, created inside SpiderMonkey on the JSContext's owner
+ * thread, will be passed to the StartAsyncTaskCallback before it is dispatched
+ * to another thread. The embedding may use the AsyncTask::user field to attach
+ * additional task state.
+ *
+ * If this function succeeds, SpiderMonkey will call the FinishAsyncTaskCallback
+ * at some point in the future. Otherwise, FinishAsyncTaskCallback will *not*
+ * be called. SpiderMonkey assumes that, if StartAsyncTaskCallback fails, it is
+ * because the JSContext is being shut down.
+ */
+typedef bool
+(*StartAsyncTaskCallback)(JSContext* cx, AsyncTask* task);
+/**
+ * The FinishAsyncTaskCallback may be called from any thread and will only be
+ * passed AsyncTasks that have already been started via StartAsyncTaskCallback.
+ * If the embedding returns 'true', indicating success, the embedding must call
+ * either task->finish() or task->cancel() on the JSContext's owner thread at
+ * some point in the future.
+ */
+typedef bool
+(*FinishAsyncTaskCallback)(AsyncTask* task);
+
+/**
+ * Set the above callbacks for the given context.
+ */
extern JS_PUBLIC_API(void)
-JS_RestoreFrameChain(JSContext* cx);
+SetAsyncTaskCallbacks(JSContext* cx, StartAsyncTaskCallback start, FinishAsyncTaskCallback finish);
+
+} // namespace JS
+
+extern JS_PUBLIC_API(bool)
+JS_IsRunning(JSContext* cx);
namespace JS {
@@ -4184,7 +4664,7 @@
{
JSContext* cx;
RootedObject oldAsyncStack;
- RootedString oldAsyncCause;
+ const char* oldAsyncCause;
bool oldAsyncCallIsExplicit;
public:
@@ -4201,8 +4681,13 @@
// ambiguous whether that would clear any scheduled async stack and make the
// normal stack reappear in the new call, or just keep the async stack
// already scheduled for the new call, if any.
+ //
+ // asyncCause is owned by the caller and its lifetime must outlive the
+ // lifetime of the AutoSetAsyncStackForNewCalls object. It is strongly
+ // encouraged that asyncCause be a string constant or similar statically
+ // allocated string.
AutoSetAsyncStackForNewCalls(JSContext* cx, HandleObject stack,
- HandleString asyncCause,
+ const char* asyncCause,
AsyncCallKind kind = AsyncCallKind::IMPLICIT);
~AutoSetAsyncStackForNewCalls();
};
@@ -4227,9 +4712,21 @@
JS_NewStringCopyZ(JSContext* cx, const char* s);
extern JS_PUBLIC_API(JSString*)
+JS_NewStringCopyUTF8Z(JSContext* cx, const JS::ConstUTF8CharsZ s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars s);
+
+extern JS_PUBLIC_API(JSString*)
JS_AtomizeAndPinJSString(JSContext* cx, JS::HandleString str);
extern JS_PUBLIC_API(JSString*)
+JS_AtomizeStringN(JSContext* cx, const char* s, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeString(JSContext* cx, const char* s);
+
+extern JS_PUBLIC_API(JSString*)
JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length);
extern JS_PUBLIC_API(JSString*)
@@ -4245,6 +4742,12 @@
JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s);
extern JS_PUBLIC_API(JSString*)
+JS_AtomizeUCStringN(JSContext* cx, const char16_t* s, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeUCString(JSContext* cx, const char16_t* s);
+
+extern JS_PUBLIC_API(JSString*)
JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length);
extern JS_PUBLIC_API(JSString*)
@@ -4453,7 +4956,7 @@
}
~JSAutoByteString() {
- js_free(mBytes);
+ JS_free(nullptr, mBytes);
}
/* Take ownership of the given byte array. */
@@ -4498,7 +5001,7 @@
}
private:
- char* mBytes;
+ char* mBytes;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
/* Copy and assignment are not supported. */
@@ -4556,17 +5059,31 @@
GetSymbolDescription(HandleSymbol symbol);
/* Well-known symbols. */
+#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(macro) \
+ macro(isConcatSpreadable) \
+ macro(iterator) \
+ macro(match) \
+ macro(replace) \
+ macro(search) \
+ macro(species) \
+ macro(hasInstance) \
+ macro(split) \
+ macro(toPrimitive) \
+ macro(toStringTag) \
+ macro(unscopables)
+
enum class SymbolCode : uint32_t {
- iterator, // well-known symbols
- match,
- species,
- toPrimitive,
+ // There is one SymbolCode for each well-known symbol.
+#define JS_DEFINE_SYMBOL_ENUM(name) name,
+ JS_FOR_EACH_WELL_KNOWN_SYMBOL(JS_DEFINE_SYMBOL_ENUM) // SymbolCode::iterator, etc.
+#undef JS_DEFINE_SYMBOL_ENUM
+ Limit,
InSymbolRegistry = 0xfffffffe, // created by Symbol.for() or JS::GetSymbolFor()
UniqueSymbol = 0xffffffff // created by Symbol() or JS::NewSymbol()
};
/* For use in loops that iterate over the well-known symbols. */
-const size_t WellKnownSymbolLimit = 4;
+const size_t WellKnownSymbolLimit = size_t(SymbolCode::Limit);
/**
* Return the SymbolCode telling what sort of symbol `symbol` is.
@@ -4625,6 +5142,31 @@
JS_Stringify(JSContext* cx, JS::MutableHandleValue value, JS::HandleObject replacer,
JS::HandleValue space, JSONWriteCallback callback, void* data);
+namespace JS {
+
+/**
+ * An API akin to JS_Stringify but with the goal of not having observable
+ * side-effects when the stringification is performed. This means it does not
+ * allow a replacer or a custom space, and has the following constraints on its
+ * input:
+ *
+ * 1) The input must be a plain object or array, not an abitrary value.
+ * 2) Every value in the graph reached by the algorithm starting with this
+ * object must be one of the following: null, undefined, a string (NOT a
+ * string object!), a boolean, a finite number (i.e. no NaN or Infinity or
+ * -Infinity), a plain object with no accessor properties, or an Array with
+ * no holes.
+ *
+ * The actual behavior differs from JS_Stringify only in asserting the above and
+ * NOT attempting to get the "toJSON" property from things, since that could
+ * clearly have side-effects.
+ */
+JS_PUBLIC_API(bool)
+ToJSONMaybeSafely(JSContext* cx, JS::HandleObject input,
+ JSONWriteCallback callback, void* data);
+
+} /* namespace JS */
+
/**
* JSON.parse as specified by ES5.
*/
@@ -4652,13 +5194,19 @@
* The locale string remains owned by the caller.
*/
extern JS_PUBLIC_API(bool)
-JS_SetDefaultLocale(JSRuntime* rt, const char* locale);
+JS_SetDefaultLocale(JSContext* cx, const char* locale);
+
+/**
+ * Look up the default locale for the ECMAScript Internationalization API.
+ */
+extern JS_PUBLIC_API(JS::UniqueChars)
+JS_GetDefaultLocale(JSContext* cx);
/**
* Reset the default locale to OS defaults.
*/
extern JS_PUBLIC_API(void)
-JS_ResetDefaultLocale(JSRuntime* rt);
+JS_ResetDefaultLocale(JSContext* cx);
/**
* Locale specific string conversion and error message callbacks.
@@ -4672,17 +5220,17 @@
/**
* Establish locale callbacks. The pointer must persist as long as the
- * JSRuntime. Passing nullptr restores the default behaviour.
+ * JSContext. Passing nullptr restores the default behaviour.
*/
extern JS_PUBLIC_API(void)
-JS_SetLocaleCallbacks(JSRuntime* rt, const JSLocaleCallbacks* callbacks);
+JS_SetLocaleCallbacks(JSContext* cx, const JSLocaleCallbacks* callbacks);
/**
* Return the address of the current locale callbacks struct, which may
* be nullptr.
*/
extern JS_PUBLIC_API(const JSLocaleCallbacks*)
-JS_GetLocaleCallbacks(JSRuntime* rt);
+JS_GetLocaleCallbacks(JSContext* cx);
/************************************************************************/
@@ -4696,23 +5244,49 @@
/**
* Report an exception represented by the sprintf-like conversion of format
- * and its arguments. This exception message string is passed to a pre-set
- * JSErrorReporter function (set by JS_SetErrorReporter).
+ * and its arguments.
*/
extern JS_PUBLIC_API(void)
-JS_ReportError(JSContext* cx, const char* format, ...);
+JS_ReportErrorASCII(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorLatin1(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorUTF8(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
/*
* Use an errorNumber to retrieve the format string, args are char*
*/
extern JS_PUBLIC_API(void)
-JS_ReportErrorNumber(JSContext* cx, JSErrorCallback errorCallback,
- void* userRef, const unsigned errorNumber, ...);
+JS_ReportErrorNumberASCII(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberASCIIVA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberLatin1(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
#ifdef va_start
extern JS_PUBLIC_API(void)
-JS_ReportErrorNumberVA(JSContext* cx, JSErrorCallback errorCallback,
- void* userRef, const unsigned errorNumber, va_list ap);
+JS_ReportErrorNumberLatin1VA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
+#endif
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUTF8(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
+
+#ifdef va_start
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUTF8VA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
#endif
/*
@@ -4734,12 +5308,31 @@
* being set, false otherwise.
*/
extern JS_PUBLIC_API(bool)
-JS_ReportWarning(JSContext* cx, const char* format, ...);
+JS_ReportWarningASCII(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportWarningLatin1(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportWarningUTF8(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportErrorFlagsAndNumberASCII(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportErrorFlagsAndNumberLatin1(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
extern JS_PUBLIC_API(bool)
-JS_ReportErrorFlagsAndNumber(JSContext* cx, unsigned flags,
- JSErrorCallback errorCallback, void* userRef,
- const unsigned errorNumber, ...);
+JS_ReportErrorFlagsAndNumberUTF8(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
extern JS_PUBLIC_API(bool)
JS_ReportErrorFlagsAndNumberUC(JSContext* cx, unsigned flags,
@@ -4760,7 +5353,12 @@
class JSErrorReport
{
+ // The (default) error message.
+ // If ownsMessage_ is true, the it is freed in destructor.
+ JS::ConstUTF8CharsZ message_;
+
// Offending source line without final '\n'.
+ // If ownsLinebuf__ is true, the buffer is freed in destructor.
const char16_t* linebuf_;
// Number of chars in linebuf_. Does not include trailing '\0'.
@@ -4772,21 +5370,30 @@
public:
JSErrorReport()
: linebuf_(nullptr), linebufLength_(0), tokenOffset_(0),
- filename(nullptr), lineno(0), column(0), isMuted(false),
- flags(0), errorNumber(0), ucmessage(nullptr),
- messageArgs(nullptr), exnType(0)
+ filename(nullptr), lineno(0), column(0),
+ flags(0), errorNumber(0),
+ exnType(0), isMuted(false),
+ ownsLinebuf_(false), ownsMessage_(false)
{}
+ ~JSErrorReport() {
+ freeLinebuf();
+ freeMessage();
+ }
+
const char* filename; /* source file name, URL, etc., or null */
unsigned lineno; /* source line number */
unsigned column; /* zero-based column index in line */
- bool isMuted; /* See the comment in ReadOnlyCompileOptions. */
unsigned flags; /* error/warning, etc. */
unsigned errorNumber; /* the error number, e.g. see js.msg */
- const char16_t* ucmessage; /* the (default) error message */
- const char16_t** messageArgs; /* arguments for the error message */
int16_t exnType; /* One of the JSExnType constants */
+ bool isMuted : 1; /* See the comment in ReadOnlyCompileOptions. */
+ private:
+ bool ownsLinebuf_ : 1;
+ bool ownsMessage_ : 1;
+
+ public:
const char16_t* linebuf() const {
return linebuf_;
}
@@ -4796,7 +5403,29 @@
size_t tokenOffset() const {
return tokenOffset_;
}
- void initLinebuf(const char16_t* linebuf, size_t linebufLength, size_t tokenOffset);
+ void initOwnedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg) {
+ initBorrowedLinebuf(linebufArg, linebufLengthArg, tokenOffsetArg);
+ ownsLinebuf_ = true;
+ }
+ void initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg);
+ void freeLinebuf();
+
+ const JS::ConstUTF8CharsZ message() const {
+ return message_;
+ }
+
+ void initOwnedMessage(const char* messageArg) {
+ initBorrowedMessage(messageArg);
+ ownsMessage_ = true;
+ }
+ void initBorrowedMessage(const char* messageArg) {
+ MOZ_ASSERT(!message_);
+ message_ = JS::ConstUTF8CharsZ(messageArg, strlen(messageArg));
+ }
+
+ JSString* newMessageString(JSContext* cx);
+
+ void freeMessage();
};
/*
@@ -4807,14 +5436,7 @@
#define JSREPORT_EXCEPTION 0x2 /* exception was thrown */
#define JSREPORT_STRICT 0x4 /* error or warning due to strict option */
-/*
- * This condition is an error in strict mode code, a warning if
- * JS_HAS_STRICT_OPTION(cx), and otherwise should not be reported at
- * all. We check the strictness of the context's top frame's script;
- * where that isn't appropriate, the caller should do the right checks
- * itself instead of using this flag.
- */
-#define JSREPORT_STRICT_MODE_ERROR 0x8
+#define JSREPORT_USER_1 0x8 /* user-defined flag */
/*
* If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
@@ -4826,16 +5448,17 @@
#define JSREPORT_IS_WARNING(flags) (((flags) & JSREPORT_WARNING) != 0)
#define JSREPORT_IS_EXCEPTION(flags) (((flags) & JSREPORT_EXCEPTION) != 0)
#define JSREPORT_IS_STRICT(flags) (((flags) & JSREPORT_STRICT) != 0)
-#define JSREPORT_IS_STRICT_MODE_ERROR(flags) (((flags) & \
- JSREPORT_STRICT_MODE_ERROR) != 0)
-extern JS_PUBLIC_API(JSErrorReporter)
-JS_GetErrorReporter(JSRuntime* rt);
-
-extern JS_PUBLIC_API(JSErrorReporter)
-JS_SetErrorReporter(JSRuntime* rt, JSErrorReporter er);
namespace JS {
+using WarningReporter = void (*)(JSContext* cx, JSErrorReport* report);
+
+extern JS_PUBLIC_API(WarningReporter)
+SetWarningReporter(JSContext* cx, WarningReporter reporter);
+
+extern JS_PUBLIC_API(WarningReporter)
+GetWarningReporter(JSContext* cx);
+
extern JS_PUBLIC_API(bool)
CreateError(JSContext* cx, JSExnType type, HandleObject stack,
HandleString fileName, uint32_t lineNumber, uint32_t columnNumber,
@@ -4959,18 +5582,16 @@
#define JSREG_GLOB 0x02u /* global exec, creates array of matches */
#define JSREG_MULTILINE 0x04u /* treat ^ and $ as begin and end of line */
#define JSREG_STICKY 0x08u /* only match starting at lastIndex */
+#define JSREG_UNICODE 0x10u /* unicode */
extern JS_PUBLIC_API(JSObject*)
-JS_NewRegExpObject(JSContext* cx, JS::HandleObject obj, const char* bytes, size_t length,
- unsigned flags);
+JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags);
extern JS_PUBLIC_API(JSObject*)
-JS_NewUCRegExpObject(JSContext* cx, JS::HandleObject obj, const char16_t* chars, size_t length,
- unsigned flags);
+JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags);
extern JS_PUBLIC_API(bool)
-JS_SetRegExpInput(JSContext* cx, JS::HandleObject obj, JS::HandleString input,
- bool multiline);
+JS_SetRegExpInput(JSContext* cx, JS::HandleObject obj, JS::HandleString input);
extern JS_PUBLIC_API(bool)
JS_ClearRegExpStatics(JSContext* cx, JS::HandleObject obj);
@@ -4982,12 +5603,6 @@
/* RegExp interface for clients without a global object. */
-extern JS_PUBLIC_API(JSObject*)
-JS_NewRegExpObjectNoStatics(JSContext* cx, char* bytes, size_t length, unsigned flags);
-
-extern JS_PUBLIC_API(JSObject*)
-JS_NewUCRegExpObjectNoStatics(JSContext* cx, char16_t* chars, size_t length, unsigned flags);
-
extern JS_PUBLIC_API(bool)
JS_ExecuteRegExpNoStatics(JSContext* cx, JS::HandleObject reobj, char16_t* chars, size_t length,
size_t* indexp, bool test, JS::MutableHandleValue rval);
@@ -5022,9 +5637,6 @@
extern JS_PUBLIC_API(void)
JS_ClearPendingException(JSContext* cx);
-extern JS_PUBLIC_API(bool)
-JS_ReportPendingException(JSContext* cx);
-
namespace JS {
/**
@@ -5102,8 +5714,15 @@
extern JS_PUBLIC_API(JSErrorReport*)
JS_ErrorFromException(JSContext* cx, JS::HandleObject obj);
+/**
+ * If the given object is an exception object (or an unwrappable
+ * cross-compartment wrapper for one), return the stack for that exception, if
+ * any. Will return null if the given object is not an exception object
+ * (including if it's null or a security wrapper that can't be unwrapped) or if
+ * the exception has no stack.
+ */
extern JS_PUBLIC_API(JSObject*)
-ExceptionStackOrNull(JSContext* cx, JS::HandleObject obj);
+ExceptionStackOrNull(JS::HandleObject obj);
/*
* Throws a StopIteration exception on cx.
@@ -5112,23 +5731,20 @@
JS_ThrowStopIteration(JSContext* cx);
extern JS_PUBLIC_API(bool)
-JS_IsStopIteration(JS::Value v);
-
-extern JS_PUBLIC_API(intptr_t)
-JS_GetCurrentThread();
+JS_IsStopIteration(const JS::Value& v);
/**
- * A JS runtime always has an "owner thread". The owner thread is set when the
- * runtime is created (to the current thread) and practically all entry points
- * into the JS engine check that a runtime (or anything contained in the
- * runtime: context, compartment, object, etc) is only touched by its owner
+ * A JS context always has an "owner thread". The owner thread is set when the
+ * context is created (to the current thread) and practically all entry points
+ * into the JS engine check that a context (or anything contained in the
+ * context: runtime, compartment, object, etc) is only touched by its owner
* thread. Embeddings may check this invariant outside the JS engine by calling
* JS_AbortIfWrongThread (which will abort if not on the owner thread, even for
* non-debug builds).
*/
extern JS_PUBLIC_API(void)
-JS_AbortIfWrongThread(JSRuntime* rt);
+JS_AbortIfWrongThread(JSContext* cx);
/************************************************************************/
@@ -5146,7 +5762,7 @@
#define JS_DEFAULT_ZEAL_FREQ 100
extern JS_PUBLIC_API(void)
-JS_GetGCZeal(JSContext* cx, uint8_t* zeal, uint32_t* frequency, uint32_t* nextScheduled);
+JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled);
extern JS_PUBLIC_API(void)
JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency);
@@ -5156,10 +5772,10 @@
#endif
extern JS_PUBLIC_API(void)
-JS_SetParallelParsingEnabled(JSRuntime* rt, bool enabled);
+JS_SetParallelParsingEnabled(JSContext* cx, bool enabled);
extern JS_PUBLIC_API(void)
-JS_SetOffthreadIonCompilationEnabled(JSRuntime* rt, bool enabled);
+JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled);
#define JIT_COMPILER_OPTIONS(Register) \
Register(BASELINE_WARMUP_TRIGGER, "baseline.warmup.trigger") \
@@ -5167,9 +5783,14 @@
Register(ION_GVN_ENABLE, "ion.gvn.enable") \
Register(ION_FORCE_IC, "ion.forceinlineCaches") \
Register(ION_ENABLE, "ion.enable") \
+ Register(ION_INTERRUPT_WITHOUT_SIGNAL, "ion.interrupt-without-signals") \
+ Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis") \
Register(BASELINE_ENABLE, "baseline.enable") \
Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
- Register(SIGNALS_ENABLE, "signals.enable")
+ Register(JUMP_THRESHOLD, "jump-threshold") \
+ Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable") \
+ Register(WASM_TEST_MODE, "wasm.test-mode") \
+ Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets")
typedef enum JSJitCompilerOption {
#define JIT_COMPILER_DECLARE(key, str) \
@@ -5182,9 +5803,9 @@
} JSJitCompilerOption;
extern JS_PUBLIC_API(void)
-JS_SetGlobalJitCompilerOption(JSRuntime* rt, JSJitCompilerOption opt, uint32_t value);
-extern JS_PUBLIC_API(int)
-JS_GetGlobalJitCompilerOption(JSRuntime* rt, JSJitCompilerOption opt);
+JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t value);
+extern JS_PUBLIC_API(bool)
+JS_GetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t* valueOut);
/**
* Convert a uint32_t index into a jsid.
@@ -5214,26 +5835,38 @@
extern JS_PUBLIC_API(bool)
JS_IsIdentifier(const char16_t* chars, size_t length);
+namespace js {
+class ScriptSource;
+} // namespace js
+
namespace JS {
-/**
- * AutoFilename encapsulates a pointer to a C-string and keeps the C-string
- * alive for as long as the associated AutoFilename object is alive.
- */
-class MOZ_STACK_CLASS JS_PUBLIC_API(AutoFilename)
+class MOZ_RAII JS_PUBLIC_API(AutoFilename)
{
- void* scriptSource_;
+ private:
+ js::ScriptSource* ss_;
+ mozilla::Variant<const char*, UniqueChars> filename_;
AutoFilename(const AutoFilename&) = delete;
- void operator=(const AutoFilename&) = delete;
+ AutoFilename& operator=(const AutoFilename&) = delete;
public:
- AutoFilename() : scriptSource_(nullptr) {}
- ~AutoFilename() { reset(nullptr); }
+ AutoFilename()
+ : ss_(nullptr),
+ filename_(mozilla::AsVariant<const char*>(nullptr))
+ {}
- const char* get() const;
+ ~AutoFilename() {
+ reset();
+ }
- void reset(void* newScriptSource);
+ void reset();
+
+ void setOwned(UniqueChars&& filename);
+ void setUnowned(const char* filename);
+ void setScriptSource(js::ScriptSource* ss);
+
+ const char* get() const;
};
/**
@@ -5288,23 +5921,62 @@
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
-} /* namespace JS */
-
/*
* Encode/Decode interpreted scripts and functions to/from memory.
*/
-extern JS_PUBLIC_API(void*)
-JS_EncodeScript(JSContext* cx, JS::HandleScript script, uint32_t* lengthp);
+typedef mozilla::Vector<uint8_t> TranscodeBuffer;
-extern JS_PUBLIC_API(void*)
-JS_EncodeInterpretedFunction(JSContext* cx, JS::HandleObject funobj, uint32_t* lengthp);
+enum TranscodeResult
+{
+ // Successful encoding / decoding.
+ TranscodeResult_Ok = 0,
-extern JS_PUBLIC_API(JSScript*)
-JS_DecodeScript(JSContext* cx, const void* data, uint32_t length);
+ // A warning message, is set to the message out-param.
+ TranscodeResult_Failure = 0x100,
+ TranscodeResult_Failure_BadBuildId = TranscodeResult_Failure | 0x1,
+ TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
+ TranscodeResult_Failure_AsmJSNotSupported = TranscodeResult_Failure | 0x3,
+ TranscodeResult_Failure_UnknownClassKind = TranscodeResult_Failure | 0x4,
-extern JS_PUBLIC_API(JSObject*)
-JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length);
+ // A error, the JSContext has a pending exception.
+ TranscodeResult_Throw = 0x200
+};
+
+extern JS_PUBLIC_API(TranscodeResult)
+EncodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::HandleScript script);
+
+extern JS_PUBLIC_API(TranscodeResult)
+EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::HandleObject funobj);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp,
+ size_t cursorIndex = 0);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleFunction funp,
+ size_t cursorIndex = 0);
+
+} /* namespace JS */
+
+namespace js {
+
+enum class StackFormat { SpiderMonkey, V8, Default };
+
+/*
+ * Sets the format used for stringifying Error stacks.
+ *
+ * The default format is StackFormat::SpiderMonkey. Use StackFormat::V8
+ * in order to emulate V8's stack formatting. StackFormat::Default can't be
+ * used here.
+ */
+extern JS_PUBLIC_API(void)
+SetStackFormat(JSContext* cx, StackFormat format);
+
+extern JS_PUBLIC_API(StackFormat)
+GetStackFormat(JSContext* cx);
+
+}
namespace JS {
@@ -5326,8 +5998,8 @@
/** The list of reasons why an asm.js module may not be stored in the cache. */
enum AsmJSCacheResult
{
- AsmJSCache_MIN,
- AsmJSCache_Success = AsmJSCache_MIN,
+ AsmJSCache_Success,
+ AsmJSCache_MIN = AsmJSCache_Success,
AsmJSCache_ModuleTooSmall,
AsmJSCache_SynchronousScript,
AsmJSCache_QuotaExceeded,
@@ -5336,6 +6008,8 @@
AsmJSCache_Disabled_ShellFlags,
AsmJSCache_Disabled_JitInspector,
AsmJSCache_InternalError,
+ AsmJSCache_Disabled_PrivateBrowsing,
+ AsmJSCache_ESR52,
AsmJSCache_LIMIT
};
@@ -5361,7 +6035,16 @@
typedef void
(* CloseAsmJSCacheEntryForWriteOp)(size_t size, uint8_t* memory, intptr_t handle);
-typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
+struct AsmJSCacheOps
+{
+ OpenAsmJSCacheEntryForReadOp openEntryForRead;
+ CloseAsmJSCacheEntryForReadOp closeEntryForRead;
+ OpenAsmJSCacheEntryForWriteOp openEntryForWrite;
+ CloseAsmJSCacheEntryForWriteOp closeEntryForWrite;
+};
+
+extern JS_PUBLIC_API(void)
+SetAsmJSCacheOps(JSContext* cx, const AsmJSCacheOps* callbacks);
/**
* Return the buildId (represented as a sequence of characters) associated with
@@ -5370,20 +6053,64 @@
* engine, it is critical that the buildId shall change for each new build of
* the JS engine.
*/
+typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
+
typedef bool
(* BuildIdOp)(BuildIdCharVector* buildId);
-struct AsmJSCacheOps
+extern JS_PUBLIC_API(void)
+SetBuildIdOp(JSContext* cx, BuildIdOp buildIdOp);
+
+/**
+ * The WasmModule interface allows the embedding to hold a reference to the
+ * underying C++ implementation of a JS WebAssembly.Module object for purposes
+ * of (de)serialization off the object's JSRuntime's thread.
+ *
+ * - Serialization starts when WebAssembly.Module is passed to the
+ * structured-clone algorithm. JS::GetWasmModule is called on the JSRuntime
+ * thread that initiated the structured clone to get the JS::WasmModule.
+ * This interface is then taken to a background thread where serializedSize()
+ * and serialize() are called to write the object to two files: a bytecode file
+ * that always allows successful deserialization and a compiled-code file keyed
+ * on cpu- and build-id that may become invalid if either of these change between
+ * serialization and deserialization. After serialization, the reference is
+ * dropped from the background thread.
+ *
+ * - Deserialization starts when the structured clone algorithm encounters a
+ * serialized WebAssembly.Module. On a background thread, the compiled-code file
+ * is opened and CompiledWasmModuleAssumptionsMatch is called to see if it is
+ * still valid (as described above). DeserializeWasmModule is then called to
+ * construct a JS::WasmModule (also on the background thread), passing the
+ * bytecode file descriptor and, if valid, the compiled-code file descriptor.
+ * The JS::WasmObject is then transported to the JSRuntime thread (which
+ * originated the request) and the wrapping WebAssembly.Module object is created
+ * by calling createObject().
+ */
+
+struct WasmModule : mozilla::external::AtomicRefCounted<WasmModule>
{
- OpenAsmJSCacheEntryForReadOp openEntryForRead;
- CloseAsmJSCacheEntryForReadOp closeEntryForRead;
- OpenAsmJSCacheEntryForWriteOp openEntryForWrite;
- CloseAsmJSCacheEntryForWriteOp closeEntryForWrite;
- BuildIdOp buildId;
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(WasmModule)
+ virtual ~WasmModule() {}
+
+ virtual void serializedSize(size_t* maybeBytecodeSize, size_t* maybeCompiledSize) const = 0;
+ virtual void serialize(uint8_t* maybeBytecodeBegin, size_t maybeBytecodeSize,
+ uint8_t* maybeCompiledBegin, size_t maybeCompiledSize) const = 0;
+
+ virtual JSObject* createObject(JSContext* cx) = 0;
};
-extern JS_PUBLIC_API(void)
-SetAsmJSCacheOps(JSRuntime* rt, const AsmJSCacheOps* callbacks);
+extern JS_PUBLIC_API(bool)
+IsWasmModuleObject(HandleObject obj);
+
+extern JS_PUBLIC_API(RefPtr<WasmModule>)
+GetWasmModule(HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+CompiledWasmModuleAssumptionsMatch(PRFileDesc* compiled, BuildIdCharVector&& buildId);
+
+extern JS_PUBLIC_API(RefPtr<WasmModule>)
+DeserializeWasmModule(PRFileDesc* bytecode, PRFileDesc* maybeCompiled, BuildIdCharVector&& buildId,
+ JS::UniqueChars filename, unsigned line, unsigned column);
/**
* Convenience class for imitating a JS level for-of loop. Typical usage:
@@ -5475,7 +6202,7 @@
(* LargeAllocationFailureCallback)(void* data);
extern JS_PUBLIC_API(void)
-SetLargeAllocationFailureCallback(JSRuntime* rt, LargeAllocationFailureCallback afc, void* data);
+SetLargeAllocationFailureCallback(JSContext* cx, LargeAllocationFailureCallback afc, void* data);
/**
* Unlike the error reporter, which is only called if the exception for an OOM
@@ -5492,17 +6219,99 @@
(* OutOfMemoryCallback)(JSContext* cx, void* data);
extern JS_PUBLIC_API(void)
-SetOutOfMemoryCallback(JSRuntime* rt, OutOfMemoryCallback cb, void* data);
+SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data);
+
+/**
+ * Capture all frames.
+ */
+struct AllFrames { };
+
+/**
+ * Capture at most this many frames.
+ */
+struct MaxFrames
+{
+ uint32_t maxFrames;
+
+ explicit MaxFrames(uint32_t max)
+ : maxFrames(max)
+ {
+ MOZ_ASSERT(max > 0);
+ }
+};
+
+/**
+ * Capture the first frame with the given principals. By default, do not
+ * consider self-hosted frames with the given principals as satisfying the stack
+ * capture.
+ */
+struct JS_PUBLIC_API(FirstSubsumedFrame)
+{
+ JSContext* cx;
+ JSPrincipals* principals;
+ bool ignoreSelfHosted;
+
+ /**
+ * Use the cx's current compartment's principals.
+ */
+ explicit FirstSubsumedFrame(JSContext* cx, bool ignoreSelfHostedFrames = true);
+ explicit FirstSubsumedFrame(JSContext* ctx, JSPrincipals* p, bool ignoreSelfHostedFrames = true)
+ : cx(ctx)
+ , principals(p)
+ , ignoreSelfHosted(ignoreSelfHostedFrames)
+ {
+ if (principals)
+ JS_HoldPrincipals(principals);
+ }
+
+ // No copying because we want to avoid holding and dropping principals
+ // unnecessarily.
+ FirstSubsumedFrame(const FirstSubsumedFrame&) = delete;
+ FirstSubsumedFrame& operator=(const FirstSubsumedFrame&) = delete;
+
+ FirstSubsumedFrame(FirstSubsumedFrame&& rhs)
+ : principals(rhs.principals)
+ , ignoreSelfHosted(rhs.ignoreSelfHosted)
+ {
+ MOZ_ASSERT(this != &rhs, "self move disallowed");
+ rhs.principals = nullptr;
+ }
+
+ FirstSubsumedFrame& operator=(FirstSubsumedFrame&& rhs) {
+ new (this) FirstSubsumedFrame(mozilla::Move(rhs));
+ return *this;
+ }
+
+ ~FirstSubsumedFrame() {
+ if (principals)
+ JS_DropPrincipals(cx, principals);
+ }
+};
+
+using StackCapture = mozilla::Variant<AllFrames, MaxFrames, FirstSubsumedFrame>;
/**
* Capture the current call stack as a chain of SavedFrame JSObjects, and set
* |stackp| to the SavedFrame for the youngest stack frame, or nullptr if there
- * are no JS frames on the stack. If |maxFrameCount| is non-zero, capture at
- * most the youngest |maxFrameCount| frames.
+ * are no JS frames on the stack.
+ *
+ * The |capture| parameter describes the portion of the JS stack to capture:
+ *
+ * * |JS::AllFrames|: Capture all frames on the stack.
+ *
+ * * |JS::MaxFrames|: Capture no more than |JS::MaxFrames::maxFrames| from the
+ * stack.
+ *
+ * * |JS::FirstSubsumedFrame|: Capture the first frame whose principals are
+ * subsumed by |JS::FirstSubsumedFrame::principals|. By default, do not
+ * consider self-hosted frames; this can be controlled via the
+ * |JS::FirstSubsumedFrame::ignoreSelfHosted| flag. Do not capture any async
+ * stack.
*/
extern JS_PUBLIC_API(bool)
-CaptureCurrentStack(JSContext* cx, MutableHandleObject stackp, unsigned maxFrameCount = 0);
+CaptureCurrentStack(JSContext* cx, MutableHandleObject stackp,
+ StackCapture&& capture = StackCapture(AllFrames()));
/*
* This is a utility function for preparing an async stack to be used
@@ -5632,7 +6441,15 @@
* each line.
*/
extern JS_PUBLIC_API(bool)
-BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp, size_t indent = 0);
+BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp,
+ size_t indent = 0, js::StackFormat stackFormat = js::StackFormat::Default);
+
+/**
+ * Return true iff the given object is either a SavedFrame object or wrapper
+ * around a SavedFrame object, and it is not the SavedFrame.prototype object.
+ */
+extern JS_PUBLIC_API(bool)
+IsSavedFrame(JSObject* obj);
} /* namespace JS */
@@ -5649,7 +6466,7 @@
* provide a concrete implementation of this class, as well as the
* relevant callbacks (see below).
*/
-struct PerformanceGroup {
+struct JS_PUBLIC_API(PerformanceGroup) {
PerformanceGroup();
// The current iteration of the event loop.
@@ -5745,6 +6562,8 @@
uint64_t refCount_;
};
+using PerformanceGroupVector = mozilla::Vector<RefPtr<js::PerformanceGroup>, 0, SystemAllocPolicy>;
+
/**
* Commit any Performance Monitoring data.
*
@@ -5752,19 +6571,19 @@
* to the outside world and can cancelled with a call to `ResetMonitoring`.
*/
extern JS_PUBLIC_API(bool)
-FlushPerformanceMonitoring(JSRuntime*);
+FlushPerformanceMonitoring(JSContext*);
/**
* Cancel any measurement that hasn't been committed.
*/
extern JS_PUBLIC_API(void)
-ResetPerformanceMonitoring(JSRuntime*);
+ResetPerformanceMonitoring(JSContext*);
/**
* Cleanup any memory used by performance monitoring.
*/
extern JS_PUBLIC_API(void)
-DisposePerformanceMonitoring(JSRuntime*);
+DisposePerformanceMonitoring(JSContext*);
/**
* Turn on/off stopwatch-based CPU monitoring.
@@ -5774,20 +6593,17 @@
* happen if we are out of memory.
*/
extern JS_PUBLIC_API(bool)
-SetStopwatchIsMonitoringCPOW(JSRuntime*, bool);
+SetStopwatchIsMonitoringCPOW(JSContext*, bool);
extern JS_PUBLIC_API(bool)
-GetStopwatchIsMonitoringCPOW(JSRuntime*);
+GetStopwatchIsMonitoringCPOW(JSContext*);
extern JS_PUBLIC_API(bool)
-SetStopwatchIsMonitoringJank(JSRuntime*, bool);
-extern JS_PUBLIC_API(bool)
-GetStopwatchIsMonitoringJank(JSRuntime*);
-
+SetStopwatchIsMonitoringJank(JSContext*, bool);
extern JS_PUBLIC_API(bool)
-IsStopwatchActive(JSRuntime*);
+GetStopwatchIsMonitoringJank(JSContext*);
// Extract the CPU rescheduling data.
extern JS_PUBLIC_API(void)
-GetPerfMonitoringTestCpuRescheduling(JSRuntime*, uint64_t* stayed, uint64_t* moved);
+GetPerfMonitoringTestCpuRescheduling(JSContext*, uint64_t* stayed, uint64_t* moved);
/**
@@ -5795,22 +6611,22 @@
* since process start.
*/
extern JS_PUBLIC_API(void)
-AddCPOWPerformanceDelta(JSRuntime*, uint64_t delta);
+AddCPOWPerformanceDelta(JSContext*, uint64_t delta);
typedef bool
(*StopwatchStartCallback)(uint64_t, void*);
extern JS_PUBLIC_API(bool)
-SetStopwatchStartCallback(JSRuntime*, StopwatchStartCallback, void*);
+SetStopwatchStartCallback(JSContext*, StopwatchStartCallback, void*);
typedef bool
-(*StopwatchCommitCallback)(uint64_t, mozilla::Vector<RefPtr<PerformanceGroup>>&, void*);
+(*StopwatchCommitCallback)(uint64_t, PerformanceGroupVector&, void*);
extern JS_PUBLIC_API(bool)
-SetStopwatchCommitCallback(JSRuntime*, StopwatchCommitCallback, void*);
+SetStopwatchCommitCallback(JSContext*, StopwatchCommitCallback, void*);
typedef bool
-(*GetGroupsCallback)(JSContext*, mozilla::Vector<RefPtr<PerformanceGroup>>&, void*);
+(*GetGroupsCallback)(JSContext*, PerformanceGroupVector&, void*);
extern JS_PUBLIC_API(bool)
-SetGetPerformanceGroupsCallback(JSRuntime*, GetGroupsCallback, void*);
+SetGetPerformanceGroupsCallback(JSContext*, GetGroupsCallback, void*);
} /* namespace js */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jscpucfg.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jscpucfg.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jscpucfg.h
@@ -7,119 +7,7 @@
#ifndef jscpucfg_h
#define jscpucfg_h
-#define JS_HAVE_LONG_LONG
-
-#if defined(_WIN64)
-
-# if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# else /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
-# error "CPU type is unknown"
-# endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
-
-#elif defined(_WIN32)
-
-# ifdef __WATCOMC__
-# define HAVE_VA_LIST_AS_ARRAY 1
-# endif
-
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-
-#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
-
-#elif defined(JS_HAVE_ENDIAN_H)
-# include <endian.h>
-
-/*
- * Historically, OSes providing <endian.h> only defined
- * __BYTE_ORDER to either __LITTLE_ENDIAN or __BIG_ENDIAN.
- * The Austin group decided to standardise <endian.h> in
- * POSIX around 2011, expecting it to provide a BYTE_ORDER
- * #define set to either LITTLE_ENDIAN or BIG_ENDIAN. We
- * should try to cope with both possibilities here.
- */
-
-# if defined(__BYTE_ORDER) || defined(BYTE_ORDER)
-# if defined(__BYTE_ORDER)
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# elif __BYTE_ORDER == __BIG_ENDIAN
-# undef IS_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 1
-# endif
-# endif
-# if defined(BYTE_ORDER)
-# if BYTE_ORDER == LITTLE_ENDIAN
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# elif BYTE_ORDER == BIG_ENDIAN
-# undef IS_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 1
-# endif
-# endif
-# else /* !defined(__BYTE_ORDER) */
-# error "endian.h does not define __BYTE_ORDER nor BYTE_ORDER. Cannot determine endianness."
-# endif
-
-/* BSDs */
-#elif defined(JS_HAVE_MACHINE_ENDIAN_H)
-# include <sys/types.h>
-# include <machine/endian.h>
-
-# if defined(_BYTE_ORDER)
-# if _BYTE_ORDER == _LITTLE_ENDIAN
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# elif _BYTE_ORDER == _BIG_ENDIAN
-# undef IS_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 1
-# endif
-# else /* !defined(_BYTE_ORDER) */
-# error "machine/endian.h does not define _BYTE_ORDER. Cannot determine endianness."
-# endif
-
-#elif defined(JS_HAVE_SYS_ISA_DEFS_H)
-# include <sys/isa_defs.h>
-
-# if defined(_BIG_ENDIAN)
-# undef IS_LITTLE_ENDIAN
-# define IS_BIG_ENDIAN 1
-# elif defined(_LITTLE_ENDIAN)
-# define IS_LITTLE_ENDIAN 1
-# undef IS_BIG_ENDIAN
-# else /* !defined(_LITTLE_ENDIAN) */
-# error "sys/isa_defs.h does not define _BIG_ENDIAN or _LITTLE_ENDIAN. Cannot determine endianness."
-# endif
-# if !defined(JS_STACK_GROWTH_DIRECTION)
-# 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(__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__) && ... */
-# error "Cannot determine endianness of your platform. Please add support to jscpucfg.h."
-#endif
+#include "mozilla/EndianUtils.h"
#ifndef JS_STACK_GROWTH_DIRECTION
# ifdef __hppa
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jsfriendapi.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jsfriendapi.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jsfriendapi.h
@@ -9,6 +9,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/Casting.h"
+#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/UniquePtr.h"
@@ -19,6 +20,7 @@
#include "js/CallArgs.h"
#include "js/CallNonGenericMethod.h"
#include "js/Class.h"
+#include "js/Utility.h"
#if JS_STACK_GROWTH_DIRECTION > 0
# define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) < (limit)))
@@ -43,7 +45,7 @@
} /* namespace js */
extern JS_FRIEND_API(void)
-JS_SetGrayGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data);
+JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
extern JS_FRIEND_API(JSObject*)
JS_FindCompilationScope(JSContext* cx, JS::HandleObject obj);
@@ -72,9 +74,6 @@
extern JS_FRIEND_API(size_t)
JS_SetProtoCalled(JSContext* cx);
-extern JS_FRIEND_API(bool)
-JS_ImmutablePrototypesEnabled();
-
extern JS_FRIEND_API(size_t)
JS_GetCustomIteratorCount(JSContext* cx);
@@ -108,36 +107,46 @@
enum {
JS_TELEMETRY_GC_REASON,
- JS_TELEMETRY_GC_IS_COMPARTMENTAL,
+ JS_TELEMETRY_GC_IS_ZONE_GC,
JS_TELEMETRY_GC_MS,
JS_TELEMETRY_GC_BUDGET_MS,
JS_TELEMETRY_GC_ANIMATION_MS,
JS_TELEMETRY_GC_MAX_PAUSE_MS,
JS_TELEMETRY_GC_MARK_MS,
JS_TELEMETRY_GC_SWEEP_MS,
+ JS_TELEMETRY_GC_COMPACT_MS,
JS_TELEMETRY_GC_MARK_ROOTS_MS,
JS_TELEMETRY_GC_MARK_GRAY_MS,
JS_TELEMETRY_GC_SLICE_MS,
JS_TELEMETRY_GC_SLOW_PHASE,
JS_TELEMETRY_GC_MMU_50,
JS_TELEMETRY_GC_RESET,
+ JS_TELEMETRY_GC_RESET_REASON,
JS_TELEMETRY_GC_INCREMENTAL_DISABLED,
JS_TELEMETRY_GC_NON_INCREMENTAL,
+ JS_TELEMETRY_GC_NON_INCREMENTAL_REASON,
JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS,
JS_TELEMETRY_GC_MINOR_REASON,
JS_TELEMETRY_GC_MINOR_REASON_LONG,
JS_TELEMETRY_GC_MINOR_US,
+ JS_TELEMETRY_GC_NURSERY_BYTES,
+ JS_TELEMETRY_GC_PRETENURE_COUNT,
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT,
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS,
- JS_TELEMETRY_ADDON_EXCEPTIONS
+ JS_TELEMETRY_ADDON_EXCEPTIONS,
+ JS_TELEMETRY_AOT_USAGE,
+ JS_TELEMETRY_END
};
typedef void
(*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample, const char* key);
extern JS_FRIEND_API(void)
-JS_SetAccumulateTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback);
+JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback);
+
+extern JS_FRIEND_API(bool)
+JS_GetIsSecureContext(JSCompartment* compartment);
extern JS_FRIEND_API(JSPrincipals*)
JS_GetCompartmentPrincipals(JSCompartment* compartment);
@@ -178,7 +187,7 @@
namespace js {
JS_FRIEND_API(bool)
-GetBuiltinClass(JSContext* cx, JS::HandleObject obj, ESClassValue* classValue);
+GetBuiltinClass(JSContext* cx, JS::HandleObject obj, ESClass* cls);
JS_FRIEND_API(const char*)
ObjectClassName(JSContext* cx, JS::HandleObject obj);
@@ -198,41 +207,57 @@
#ifdef JS_DEBUG
/*
- * Routines to print out values during debugging. These are FRIEND_API to help
+ * Routines to print out values during debugging. These are FRIEND_API to help
* the debugger find them and to support temporarily hacking js::Dump* calls
- * into other code.
+ * into other code. Note that there are overloads that do not require the FILE*
+ * parameter, which will default to stderr.
*/
extern JS_FRIEND_API(void)
-DumpString(JSString* str);
+DumpString(JSString* str, FILE* fp);
extern JS_FRIEND_API(void)
-DumpAtom(JSAtom* atom);
+DumpAtom(JSAtom* atom, FILE* fp);
extern JS_FRIEND_API(void)
-DumpObject(JSObject* obj);
+DumpObject(JSObject* obj, FILE* fp);
extern JS_FRIEND_API(void)
-DumpChars(const char16_t* s, size_t n);
+DumpChars(const char16_t* s, size_t n, FILE* fp);
extern JS_FRIEND_API(void)
-DumpValue(const JS::Value& val);
+DumpValue(const JS::Value& val, FILE* fp);
extern JS_FRIEND_API(void)
-DumpId(jsid id);
+DumpId(jsid id, FILE* fp);
extern JS_FRIEND_API(void)
-DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start = nullptr);
+DumpInterpreterFrame(JSContext* cx, FILE* fp, InterpreterFrame* start = nullptr);
extern JS_FRIEND_API(bool)
-DumpPC(JSContext* cx);
+DumpPC(JSContext* cx, FILE* fp);
extern JS_FRIEND_API(bool)
-DumpScript(JSContext* cx, JSScript* scriptArg);
+DumpScript(JSContext* cx, JSScript* scriptArg, FILE* fp);
+
+// Versions for use directly in a debugger (default parameters are not handled
+// well in gdb; built-in handles like stderr are not handled well in lldb.)
+extern JS_FRIEND_API(void) DumpString(JSString* str);
+extern JS_FRIEND_API(void) DumpAtom(JSAtom* atom);
+extern JS_FRIEND_API(void) DumpObject(JSObject* obj);
+extern JS_FRIEND_API(void) DumpChars(const char16_t* s, size_t n);
+extern JS_FRIEND_API(void) DumpValue(const JS::Value& val);
+extern JS_FRIEND_API(void) DumpId(jsid id);
+extern JS_FRIEND_API(void) DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start = nullptr);
+extern JS_FRIEND_API(bool) DumpPC(JSContext* cx);
+extern JS_FRIEND_API(bool) DumpScript(JSContext* cx, JSScript* scriptArg);
#endif
extern JS_FRIEND_API(void)
+DumpBacktrace(JSContext* cx, FILE* fp);
+
+extern JS_FRIEND_API(void)
DumpBacktrace(JSContext* cx);
} // namespace js
@@ -243,6 +268,13 @@
extern JS_FRIEND_API(char*)
FormatStackDump(JSContext* cx, char* buf, bool showArgs, bool showLocals, bool showThisProps);
+/**
+ * Set all of the uninitialized lexicals on an object to undefined. Return
+ * true if any lexicals were initialized and false otherwise.
+ * */
+extern JS_FRIEND_API(bool)
+ForceLexicalInitialization(JSContext *cx, HandleObject obj);
+
} // namespace JS
/**
@@ -275,7 +307,7 @@
PropertyCopyBehavior copyBehavior = CopyNonConfigurableAsIs);
extern JS_FRIEND_API(bool)
-JS_WrapPropertyDescriptor(JSContext* cx, JS::MutableHandle<JSPropertyDescriptor> desc);
+JS_WrapPropertyDescriptor(JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);
struct JSFunctionSpecWithHelp {
const char* name;
@@ -300,61 +332,37 @@
namespace js {
+extern JS_FRIEND_DATA(const js::ClassOps) ProxyClassOps;
+extern JS_FRIEND_DATA(const js::ClassExtension) ProxyClassExtension;
+extern JS_FRIEND_DATA(const js::ObjectOps) ProxyObjectOps;
+
/*
* Helper Macros for creating JSClasses that function as proxies.
*
* NB: The macro invocation must be surrounded by braces, so as to
* allow for potential JSClass extensions.
*/
-#define PROXY_MAKE_EXT(isWrappedNative, objectMoved) \
+#define PROXY_MAKE_EXT(objectMoved) \
{ \
- isWrappedNative, \
js::proxy_WeakmapKeyDelegate, \
objectMoved \
}
-#define PROXY_CLASS_WITH_EXT(name, flags, ext) \
+#define PROXY_CLASS_WITH_EXT(name, flags, extPtr) \
{ \
name, \
js::Class::NON_NATIVE | \
JSCLASS_IS_PROXY | \
- JSCLASS_DELAY_METADATA_CALLBACK | \
+ JSCLASS_DELAY_METADATA_BUILDER | \
flags, \
- nullptr, /* addProperty */ \
- nullptr, /* delProperty */ \
- nullptr, /* getProperty */ \
- nullptr, /* setProperty */ \
- nullptr, /* enumerate */ \
- nullptr, /* resolve */ \
- nullptr, /* mayResolve */ \
- js::proxy_Finalize, /* finalize */ \
- nullptr, /* call */ \
- js::proxy_HasInstance, /* hasInstance */ \
- nullptr, /* construct */ \
- js::proxy_Trace, /* trace */ \
+ &js::ProxyClassOps, \
JS_NULL_CLASS_SPEC, \
- ext, \
- { \
- js::proxy_LookupProperty, \
- js::proxy_DefineProperty, \
- js::proxy_HasProperty, \
- js::proxy_GetProperty, \
- js::proxy_SetProperty, \
- js::proxy_GetOwnPropertyDescriptor, \
- js::proxy_DeleteProperty, \
- js::proxy_Watch, js::proxy_Unwatch, \
- js::proxy_GetElements, \
- nullptr, /* enumerate */ \
- js::proxy_FunToString, \
- } \
- }
-
-#define PROXY_CLASS_DEF(name, flags) \
- PROXY_CLASS_WITH_EXT(name, flags, \
- PROXY_MAKE_EXT( \
- false, /* isWrappedNative */ \
- js::proxy_ObjectMoved \
- ))
+ extPtr, \
+ &js::ProxyObjectOps \
+ }
+
+#define PROXY_CLASS_DEF(name, flags) \
+ PROXY_CLASS_WITH_EXT(name, flags, &js::ProxyClassExtension)
/*
* Proxy stubs, similar to JS_*Stub, for embedder proxy class definitions.
@@ -367,7 +375,7 @@
JS::MutableHandle<Shape*> propp);
extern JS_FRIEND_API(bool)
proxy_DefineProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::Handle<JSPropertyDescriptor> desc,
+ JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
extern JS_FRIEND_API(bool)
proxy_HasProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
@@ -379,7 +387,7 @@
JS::HandleValue receiver, JS::ObjectOpResult& result);
extern JS_FRIEND_API(bool)
proxy_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandle<JSPropertyDescriptor> desc);
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_FRIEND_API(bool)
proxy_DeleteProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::ObjectOpResult& result);
@@ -436,17 +444,17 @@
};
/**
- * Have |rt| use |hook| to retrieve lazily-retrieved source code. See the
- * comments for SourceHook. The runtime takes ownership of the hook, and
- * will delete it when the runtime itself is deleted, or when a new hook is
+ * Have |cx| use |hook| to retrieve lazily-retrieved source code. See the
+ * comments for SourceHook. The context takes ownership of the hook, and
+ * will delete it when the context itself is deleted, or when a new hook is
* set.
*/
extern JS_FRIEND_API(void)
-SetSourceHook(JSRuntime* rt, mozilla::UniquePtr<SourceHook> hook);
+SetSourceHook(JSContext* cx, mozilla::UniquePtr<SourceHook> hook);
-/** Remove |rt|'s source hook, and return it. The caller now owns the hook. */
+/** Remove |cx|'s source hook, and return it. The caller now owns the hook. */
extern JS_FRIEND_API(mozilla::UniquePtr<SourceHook>)
-ForgetSourceHook(JSRuntime* rt);
+ForgetSourceHook(JSContext* cx);
extern JS_FRIEND_API(JS::Zone*)
GetCompartmentZone(JSCompartment* comp);
@@ -464,7 +472,7 @@
* fp is the file for the dump output.
*/
extern JS_FRIEND_API(void)
-DumpHeap(JSRuntime* rt, FILE* fp, DumpHeapNurseryBehaviour nurseryBehaviour);
+DumpHeap(JSContext* cx, FILE* fp, DumpHeapNurseryBehaviour nurseryBehaviour);
#ifdef JS_OLD_GETTER_SETTER_METHODS
JS_FRIEND_API(bool) obj_defineGetter(JSContext* cx, unsigned argc, JS::Value* vp);
@@ -485,9 +493,9 @@
struct WeakMapTracer
{
- JSRuntime* runtime;
+ JSContext* context;
- explicit WeakMapTracer(JSRuntime* rt) : runtime(rt) {}
+ explicit WeakMapTracer(JSContext* cx) : context(cx) {}
// Weak map tracer callback, called once for every binding of every
// weak map that was live at the time of the last garbage collection.
@@ -502,7 +510,7 @@
TraceWeakMaps(WeakMapTracer* trc);
extern JS_FRIEND_API(bool)
-AreGCGrayBitsValid(JSRuntime* rt);
+AreGCGrayBitsValid(JSContext* cx);
extern JS_FRIEND_API(bool)
ZoneGlobalsAreAllGray(JS::Zone* zone);
@@ -516,15 +524,19 @@
extern JS_FRIEND_API(JSObject*)
GetWeakmapKeyDelegate(JSObject* key);
-JS_FRIEND_API(JS::TraceKind)
-GCThingTraceKind(void* thing);
-
/**
- * Invoke cellCallback on every gray JS_OBJECT in the given zone.
+ * Invoke cellCallback on every gray JSObject in the given zone.
*/
extern JS_FRIEND_API(void)
IterateGrayObjects(JS::Zone* zone, GCThingCallback cellCallback, void* data);
+/**
+ * Invoke cellCallback on every gray JSObject in the given zone while cycle
+ * collection is in progress.
+ */
+extern JS_FRIEND_API(void)
+IterateGrayObjectsUnderCC(JS::Zone* zone, GCThingCallback cellCallback, void* data);
+
#ifdef JS_HAS_CTYPES
extern JS_FRIEND_API(size_t)
SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj);
@@ -632,17 +644,6 @@
JS_FRIEND_API(const Class*)
ProtoKeyToClass(JSProtoKey key);
-// Returns true if the standard class identified by |key| inherits from
-// another standard class (in addition to Object) along its proto chain.
-//
-// In practice, this only returns true for Error subtypes.
-inline bool
-StandardClassIsDependent(JSProtoKey key)
-{
- const Class* clasp = ProtoKeyToClass(key);
- return clasp && clasp->spec.defined() && clasp->spec.dependent();
-}
-
// Returns the key for the class inherited by a given standard class (that
// is to say, the prototype of this standard class's prototype).
//
@@ -651,15 +652,15 @@
// cached proto key, except in cases where multiple JSProtoKeys share a
// JSClass.
inline JSProtoKey
-ParentKeyForStandardClass(JSProtoKey key)
+InheritanceProtoKeyForStandardClass(JSProtoKey key)
{
// [Object] has nothing to inherit from.
if (key == JSProto_Object)
return JSProto_Null;
- // If we're dependent, return the key of the class we depend on.
- if (StandardClassIsDependent(key))
- return ProtoKeyToClass(key)->spec.parentKey();
+ // If we're ClassSpec defined return the proto key from that
+ if (ProtoKeyToClass(key)->specDefined())
+ return ProtoKeyToClass(key)->specInheritanceProtoKey();
// Otherwise, we inherit [Object].
return JSProto_Object;
@@ -729,6 +730,9 @@
JS_FRIEND_API(bool)
GetObjectProto(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject proto);
+extern JS_FRIEND_API(JSObject*)
+GetStaticPrototype(JSObject* obj);
+
JS_FRIEND_API(bool)
GetOriginalEval(JSContext* cx, JS::HandleObject scope,
JS::MutableHandleObject eval);
@@ -884,28 +888,50 @@
return reinterpret_cast<JSLinearString*>(str);
}
+template<typename CharType>
+MOZ_ALWAYS_INLINE void
+CopyLinearStringChars(CharType* dest, JSLinearString* s, size_t len, size_t start = 0);
+
MOZ_ALWAYS_INLINE void
-CopyLinearStringChars(char16_t* dest, JSLinearString* s, size_t len)
+CopyLinearStringChars(char16_t* dest, JSLinearString* s, size_t len, size_t start = 0)
{
+ MOZ_ASSERT(start + len <= GetLinearStringLength(s));
JS::AutoCheckCannotGC nogc;
if (LinearStringHasLatin1Chars(s)) {
const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
for (size_t i = 0; i < len; i++)
- dest[i] = src[i];
+ dest[i] = src[start + i];
} else {
const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
- mozilla::PodCopy(dest, src, len);
+ mozilla::PodCopy(dest, src + start, len);
+ }
+}
+
+MOZ_ALWAYS_INLINE void
+CopyLinearStringChars(char* dest, JSLinearString* s, size_t len, size_t start = 0)
+{
+ MOZ_ASSERT(start + len <= GetLinearStringLength(s));
+ JS::AutoCheckCannotGC nogc;
+ if (LinearStringHasLatin1Chars(s)) {
+ const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
+ for (size_t i = 0; i < len; i++)
+ dest[i] = char(src[start + i]);
+ } else {
+ const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
+ for (size_t i = 0; i < len; i++)
+ dest[i] = char(src[start + i]);
}
}
+template<typename CharType>
inline bool
-CopyStringChars(JSContext* cx, char16_t* dest, JSString* s, size_t len)
+CopyStringChars(JSContext* cx, CharType* dest, JSString* s, size_t len, size_t start = 0)
{
JSLinearString* linear = StringToLinearString(cx, s);
if (!linear)
return false;
- CopyLinearStringChars(dest, linear, len);
+ CopyLinearStringChars(dest, linear, len, start);
return true;
}
@@ -946,15 +972,12 @@
StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
JS_FRIEND_API(void)
-SetPreserveWrapperCallback(JSRuntime* rt, PreserveWrapperCallback callback);
+SetPreserveWrapperCallback(JSContext* cx, PreserveWrapperCallback callback);
JS_FRIEND_API(bool)
IsObjectInContextCompartment(JSObject* obj, const JSContext* cx);
/*
- * NB: these flag bits are encoded into the bytecode stream in the immediate
- * operand of JSOP_ITER, so don't change them without advancing vm/Xdr.h's
- * XDR_BYTECODE_VERSION.
* NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
* The first three are omitted because they shouldn't be used in new code.
*/
@@ -972,9 +995,7 @@
inline uintptr_t
GetNativeStackLimit(JSContext* cx, StackKind kind, int extraAllowance = 0)
{
- PerThreadDataFriendFields* mainThread =
- PerThreadDataFriendFields::getMainThread(GetRuntime(cx));
- uintptr_t limit = mainThread->nativeStackLimit[kind];
+ uintptr_t limit = ContextFriendFields::get(cx)->nativeStackLimit[kind];
#if JS_STACK_GROWTH_DIRECTION > 0
limit += extraAllowance;
#else
@@ -1080,9 +1101,6 @@
JS_FRIEND_API(char*)
GetCodeCoverageSummary(JSContext* cx, size_t* length);
-JS_FRIEND_API(bool)
-ContextHasOutstandingRequests(const JSContext* cx);
-
typedef void
(* ActivityCallback)(void* arg, bool active);
@@ -1092,7 +1110,7 @@
* idle and a request begins.
*/
JS_FRIEND_API(void)
-SetActivityCallback(JSRuntime* rt, ActivityCallback cb, void* arg);
+SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg);
typedef bool
(* DOMInstanceClassHasProtoAtDepth)(const Class* instanceClass,
@@ -1103,10 +1121,10 @@
typedef struct JSDOMCallbacks DOMCallbacks;
extern JS_FRIEND_API(void)
-SetDOMCallbacks(JSRuntime* rt, const DOMCallbacks* callbacks);
+SetDOMCallbacks(JSContext* cx, const DOMCallbacks* callbacks);
extern JS_FRIEND_API(const DOMCallbacks*)
-GetDOMCallbacks(JSRuntime* rt);
+GetDOMCallbacks(JSContext* cx);
extern JS_FRIEND_API(JSObject*)
GetTestingFunctions(JSContext* cx);
@@ -1129,7 +1147,7 @@
* Returns nullptr for invalid arguments and JSEXN_INTERNALERR
*/
extern JS_FRIEND_API(JSFlatString*)
-GetErrorTypeName(JSRuntime* rt, int16_t exnType);
+GetErrorTypeName(JSContext* cx, int16_t exnType);
#ifdef JS_DEBUG
extern JS_FRIEND_API(unsigned)
@@ -1221,10 +1239,9 @@
generation(0)
{}
- void Unlink()
+ void OwnerUnlinked()
{
++generation;
- expando.setUndefined();
}
static size_t offsetOfExpando()
@@ -1306,29 +1323,35 @@
* JSString methods and often the code can be rewritten so that only indexes
* instead of char pointers are used in parts of the code that can GC.
*/
-class MOZ_STACK_CLASS AutoStableStringChars
+class MOZ_STACK_CLASS JS_FRIEND_API(AutoStableStringChars)
{
+ /*
+ * When copying string char, use this many bytes of inline storage. This is
+ * chosen to allow the inline string types to be copied without allocating.
+ * This is asserted in AutoStableStringChars::allocOwnChars.
+ */
+ static const size_t InlineCapacity = 24;
+
/* Ensure the string is kept alive while we're using its chars. */
JS::RootedString s_;
union {
const char16_t* twoByteChars_;
const JS::Latin1Char* latin1Chars_;
};
+ mozilla::Maybe<Vector<uint8_t, InlineCapacity>> ownChars_;
enum State { Uninitialized, Latin1, TwoByte };
State state_;
- bool ownsChars_;
public:
explicit AutoStableStringChars(JSContext* cx)
- : s_(cx), state_(Uninitialized), ownsChars_(false)
+ : s_(cx), state_(Uninitialized)
{}
- ~AutoStableStringChars();
- MOZ_WARN_UNUSED_RESULT
+ MOZ_MUST_USE
bool init(JSContext* cx, JSString* s);
/* Like init(), but Latin1 chars are inflated to TwoByte. */
- MOZ_WARN_UNUSED_RESULT
+ MOZ_MUST_USE
bool initTwoByte(JSContext* cx, JSString* s);
bool isLatin1() const { return state_ == Latin1; }
@@ -1348,46 +1371,79 @@
mozilla::Range<const char16_t> twoByteRange() const {
MOZ_ASSERT(state_ == TwoByte);
return mozilla::Range<const char16_t>(twoByteChars_,
- GetStringLength(s_));
+ GetStringLength(s_));
}
/* If we own the chars, transfer ownership to the caller. */
bool maybeGiveOwnershipToCaller() {
MOZ_ASSERT(state_ != Uninitialized);
- if (!ownsChars_)
+ if (!ownChars_.isSome() || !ownChars_->extractRawBuffer())
return false;
state_ = Uninitialized;
- ownsChars_ = false;
+ ownChars_.reset();
return true;
}
private:
AutoStableStringChars(const AutoStableStringChars& other) = delete;
void operator=(const AutoStableStringChars& other) = delete;
-};
-/**
- * Creates a string of the form |ErrorType: ErrorMessage| for a JSErrorReport,
- * which generally matches the toString() behavior of an ErrorObject.
- */
-extern JS_FRIEND_API(JSString*)
-ErrorReportToString(JSContext* cx, JSErrorReport* reportp);
+ bool baseIsInline(JS::Handle<JSLinearString*> linearString);
+ template <typename T> T* allocOwnChars(JSContext* cx, size_t count);
+ bool copyLatin1Chars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
+ bool copyTwoByteChars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
+ bool copyAndInflateLatin1Chars(JSContext*, JS::Handle<JSLinearString*> linearString);
+};
struct MOZ_STACK_CLASS JS_FRIEND_API(ErrorReport)
{
explicit ErrorReport(JSContext* cx);
~ErrorReport();
- bool init(JSContext* cx, JS::HandleValue exn);
+ enum SniffingBehavior {
+ WithSideEffects,
+ NoSideEffects
+ };
+
+ /**
+ * Generate a JSErrorReport from the provided thrown value.
+ *
+ * If the value is a (possibly wrapped) Error object, the JSErrorReport will
+ * be exactly initialized from the Error object's information, without
+ * observable side effects. (The Error object's JSErrorReport is reused, if
+ * it has one.)
+ *
+ * Otherwise various attempts are made to derive JSErrorReport information
+ * from |exn| and from the current execution state. This process is
+ * *definitely* inconsistent with any standard, and particulars of the
+ * behavior implemented here generally shouldn't be relied upon.
+ *
+ * If the value of |sniffingBehavior| is |WithSideEffects|, some of these
+ * attempts *may* invoke user-configurable behavior when |exn| is an object:
+ * converting |exn| to a string, detecting and getting properties on |exn|,
+ * accessing |exn|'s prototype chain, and others are possible. Users *must*
+ * tolerate |ErrorReport::init| potentially having arbitrary effects. Any
+ * exceptions thrown by these operations will be caught and silently
+ * ignored, and "default" values will be substituted into the JSErrorReport.
+ *
+ * But if the value of |sniffingBehavior| is |NoSideEffects|, these attempts
+ * *will not* invoke any observable side effects. The JSErrorReport will
+ * simply contain fewer, less precise details.
+ *
+ * Unlike some functions involved in error handling, this function adheres
+ * to the usual JSAPI return value error behavior.
+ */
+ bool init(JSContext* cx, JS::HandleValue exn,
+ SniffingBehavior sniffingBehavior);
JSErrorReport* report()
{
return reportp;
}
- const char* message()
+ const JS::ConstUTF8CharsZ toStringResult()
{
- return message_;
+ return toStringResult_;
}
private:
@@ -1397,8 +1453,8 @@
//
// Returns false if we fail to actually populate the ErrorReport
// for some reason (probably out of memory).
- bool populateUncaughtExceptionReport(JSContext* cx, ...);
- bool populateUncaughtExceptionReportVA(JSContext* cx, va_list ap);
+ bool populateUncaughtExceptionReportUTF8(JSContext* cx, ...);
+ bool populateUncaughtExceptionReportUTF8VA(JSContext* cx, va_list ap);
// Reports exceptions from add-on scopes to telementry.
void ReportAddonExceptionToTelementry(JSContext* cx);
@@ -1406,16 +1462,9 @@
// We may have a provided JSErrorReport, so need a way to represent that.
JSErrorReport* reportp;
- // And we may have a message.
- const char* message_;
-
// Or we may need to synthesize a JSErrorReport one of our own.
JSErrorReport ownedReport;
- // Or a message of our own. If this is non-null, we need to clean up both
- // it and ownedReport.
- char* ownedMessage;
-
// And we have a string to maybe keep alive that has pointers into
// it from ownedReport.
JS::RootedString str;
@@ -1426,14 +1475,14 @@
// And we need to root our exception value.
JS::RootedObject exnObject;
- // And possibly some byte storage for our message_.
- JSAutoByteString bytesStorage;
-
// And for our filename.
JSAutoByteString filename;
- // True if we need to free message_ and the stuff in ownedReport
- bool ownsMessageAndReport;
+ // We may have a result of error.toString().
+ // FIXME: We should not call error.toString(), since it could have side
+ // effect (see bug 633623).
+ JS::ConstUTF8CharsZ toStringResult_;
+ JSAutoByteString toStringResultBytesStorage;
};
/* Implemented in vm/StructuredClone.cpp. */
@@ -1465,11 +1514,14 @@
Uint8Clamped,
/**
- * SIMD types don't have their own TypedArray equivalent, for now.
+ * Types that don't have their own TypedArray equivalent, for now.
*/
MaxTypedArrayViewType,
+ Int64,
Float32x4,
+ Int8x16,
+ Int16x8,
Int32x4
};
@@ -1488,8 +1540,11 @@
case Uint32:
case Float32:
return 4;
+ case Int64:
case Float64:
return 8;
+ case Int8x16:
+ case Int16x8:
case Int32x4:
case Float32x4:
return 16;
@@ -1504,6 +1559,9 @@
case Int8:
case Int16:
case Int32:
+ case Int64:
+ case Int8x16:
+ case Int16x8:
case Int32x4:
return true;
case Uint8:
@@ -1529,9 +1587,12 @@
case Uint16:
case Int32:
case Uint32:
+ case Int64:
case Float32:
case Float64:
return false;
+ case Int8x16:
+ case Int16x8:
case Int32x4:
case Float32x4:
return true;
@@ -1544,6 +1605,10 @@
static inline size_t
scalarByteSize(Type atype) {
switch (atype) {
+ case Int8x16:
+ return 1;
+ case Int16x8:
+ return 2;
case Int32x4:
case Float32x4:
return 4;
@@ -1554,6 +1619,7 @@
case Uint16:
case Int32:
case Uint32:
+ case Int64:
case Float32:
case Float64:
case MaxTypedArrayViewType:
@@ -1653,7 +1719,10 @@
uint32_t byteOffset, int32_t length);
/**
- * Create a new SharedArrayBuffer with the given byte length.
+ * Create a new SharedArrayBuffer with the given byte length. This
+ * may only be called if
+ * JS::CompartmentCreationOptionsRef(cx).getSharedMemoryAndAtomicsEnabled() is
+ * true.
*/
extern JS_FRIEND_API(JSObject*)
JS_NewSharedArrayBuffer(JSContext* cx, uint32_t nbytes);
@@ -1889,7 +1958,7 @@
/**
* Return true if the arrayBuffer contains any data. This will return false for
- * ArrayBuffer.prototype and neutered ArrayBuffers.
+ * ArrayBuffer.prototype and detached ArrayBuffers.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
@@ -2010,39 +2079,29 @@
JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
/**
- * Return the ArrayBuffer or SharedArrayBuffer underlying an
- * ArrayBufferView. If the buffer has been neutered, this will still
- * return the neutered buffer. |obj| must be an object that would
+ * Return the ArrayBuffer or SharedArrayBuffer underlying an ArrayBufferView.
+ * This may return a detached buffer. |obj| must be an object that would
* return true for JS_IsArrayBufferViewObject().
*/
extern JS_FRIEND_API(JSObject*)
JS_GetArrayBufferViewBuffer(JSContext* cx, JS::HandleObject obj, bool* isSharedMemory);
-typedef enum {
- ChangeData,
- KeepData
-} NeuterDataDisposition;
-
/**
- * Set an ArrayBuffer's length to 0 and neuter all of its views.
+ * Detach an ArrayBuffer, causing all associated views to no longer refer to
+ * the ArrayBuffer's original attached memory.
*
- * The |changeData| argument is a hint to inform internal behavior with respect
- * to the internal pointer to the ArrayBuffer's data after being neutered.
- * There is no guarantee it will be respected. But if it is respected, the
- * ArrayBuffer's internal data pointer will, or will not, have changed
- * accordingly.
+ * The |changeData| argument is obsolete and ignored.
*/
extern JS_FRIEND_API(bool)
-JS_NeuterArrayBuffer(JSContext* cx, JS::HandleObject obj,
- NeuterDataDisposition changeData);
+JS_DetachArrayBuffer(JSContext* cx, JS::HandleObject obj);
/**
- * Check whether the obj is ArrayBufferObject and neutered. Note that this
- * may return false if a security wrapper is encountered that denies the
+ * Check whether the obj is a detached ArrayBufferObject. Note that this may
+ * return false if a security wrapper is encountered that denies the
* unwrapping.
*/
extern JS_FRIEND_API(bool)
-JS_IsNeuteredArrayBufferObject(JSObject* obj);
+JS_IsDetachedArrayBufferObject(JSObject* obj);
/**
* Check whether obj supports JS_GetDataView* APIs.
@@ -2336,7 +2395,12 @@
js::jit::InlinableNative inlinableNative;
};
- uint16_t depth;
+ union {
+ uint16_t depth;
+
+ // Additional opcode for some InlinableNative functions.
+ uint16_t nativeOp;
+ };
// These fields are carefully packed to take up 4 bytes. If you need more
// bits for whatever reason, please see if you can steal bits from existing
@@ -2602,22 +2666,7 @@
ScriptEnvironmentPreparer::Closure& closure);
JS_FRIEND_API(void)
-SetScriptEnvironmentPreparer(JSRuntime* rt, ScriptEnvironmentPreparer*
-preparer);
-
-/**
- * To help embedders enforce their invariants, we allow them to specify in
- * advance which JSContext should be passed to JSAPI calls. If this is set
- * to a non-null value, the assertSameCompartment machinery does double-
- * duty (in debug builds) to verify that it matches the cx being used.
- */
-#ifdef DEBUG
-JS_FRIEND_API(void)
-Debug_SetActiveJSContext(JSRuntime* rt, JSContext* cx);
-#else
-inline void
-Debug_SetActiveJSContext(JSRuntime* rt, JSContext* cx) {}
-#endif
+SetScriptEnvironmentPreparer(JSContext* cx, ScriptEnvironmentPreparer* preparer);
enum CTypesActivityType {
CTYPES_CALL_BEGIN,
@@ -2634,7 +2683,7 @@
* calling into C.
*/
JS_FRIEND_API(void)
-SetCTypesActivityCallback(JSRuntime* rt, CTypesActivityCallback cb);
+SetCTypesActivityCallback(JSContext* cx, CTypesActivityCallback cb);
class MOZ_RAII JS_FRIEND_API(AutoCTypesActivityCallback) {
private:
@@ -2658,8 +2707,23 @@
}
};
-typedef JSObject*
-(* ObjectMetadataCallback)(JSContext* cx, JSObject* obj);
+// Abstract base class for objects that build allocation metadata for JavaScript
+// values.
+struct AllocationMetadataBuilder {
+ AllocationMetadataBuilder() { }
+
+ // Return a metadata object for the newly constructed object |obj|, or
+ // nullptr if there's no metadata to attach.
+ //
+ // Implementations should treat all errors as fatal; there is no way to
+ // report errors from this callback. In particular, the caller provides an
+ // oomUnsafe for overriding implementations to use.
+ virtual JSObject* build(JSContext* cx, JS::HandleObject obj,
+ AutoEnterOOMUnsafeRegion& oomUnsafe) const
+ {
+ return nullptr;
+ }
+};
/**
* Specify a callback to invoke when creating each JS object in the current
@@ -2667,11 +2731,11 @@
* object.
*/
JS_FRIEND_API(void)
-SetObjectMetadataCallback(JSContext* cx, ObjectMetadataCallback callback);
+SetAllocationMetadataBuilder(JSContext* cx, const AllocationMetadataBuilder *callback);
/** Get the metadata associated with an object. */
JS_FRIEND_API(JSObject*)
-GetObjectMetadata(JSObject* obj);
+GetAllocationMetadata(JSObject* obj);
JS_FRIEND_API(bool)
GetElementsWithAdder(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver,
@@ -2703,11 +2767,11 @@
JS_FRIEND_API(bool)
SetPropertyIgnoringNamedGetter(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::HandleValue v, JS::HandleValue receiver,
- JS::Handle<JSPropertyDescriptor> ownDesc,
+ JS::Handle<JS::PropertyDescriptor> ownDesc,
JS::ObjectOpResult& result);
JS_FRIEND_API(void)
-ReportErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
+ReportASCIIErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
// This function is for one specific use case, please don't use this for anything else!
extern JS_FRIEND_API(bool)
@@ -2745,12 +2809,12 @@
#endif
/**
- * Get the nearest enclosing with scope object for a given function. If the
- * function is not scripted or is not enclosed by a with scope, returns the
- * global.
+ * Get the nearest enclosing with environment object for a given function. If
+ * the function is not scripted or is not enclosed by a with scope, returns
+ * the global.
*/
extern JS_FRIEND_API(JSObject*)
-GetNearestEnclosingWithScopeObjectForFunction(JSFunction* fun);
+GetNearestEnclosingWithEnvironmentObjectForFunction(JSFunction* fun);
/**
* Get the first SavedFrame object in this SavedFrame stack whose principals are
@@ -2776,7 +2840,7 @@
* invariant that actual Window objects (the global objects of web pages) are
* never directly exposed to script. Instead we often substitute a WindowProxy.
*
- * The scope chain, on the other hand, contains the Window and never its
+ * The environment chain, on the other hand, contains the Window and never its
* WindowProxy.
*
* As a result, we have calls to these "substitute-this-object-for-that-object"
@@ -2790,7 +2854,7 @@
* functions below.
*/
extern JS_FRIEND_API(void)
-SetWindowProxyClass(JSRuntime* rt, const Class* clasp);
+SetWindowProxyClass(JSContext* cx, const Class* clasp);
/**
* Associates a WindowProxy with a Window (global object). `windowProxy` must
@@ -2842,26 +2906,6 @@
} /* namespace js */
-extern JS_FRIEND_API(void)
-JS_StoreObjectPostBarrierCallback(JSContext* cx,
- void (*callback)(JSTracer* trc, JSObject* key, void* data),
- JSObject* key, void* data);
-
-extern JS_FRIEND_API(void)
-JS_StoreStringPostBarrierCallback(JSContext* cx,
- void (*callback)(JSTracer* trc, JSString* key, void* data),
- JSString* key, void* data);
-
-/**
- * Forcibly clear postbarrier callbacks queued by the previous two methods.
- * This should be used when the object owning the postbarriered pointers is
- * being destroyed outside of a garbage collection.
- *
- * This currently works by performing a minor GC.
- */
-extern JS_FRIEND_API(void)
-JS_ClearAllPostBarrierCallbacks(JSRuntime *rt);
-
class NativeProfiler
{
public:
@@ -2888,7 +2932,7 @@
class MemProfiler
{
static mozilla::Atomic<uint32_t, mozilla::Relaxed> sActiveProfilerCount;
- static NativeProfiler* sNativeProfiler;
+ static JS_FRIEND_DATA(NativeProfiler*) sNativeProfiler;
static GCHeapProfiler* GetGCHeapProfiler(void* addr);
static GCHeapProfiler* GetGCHeapProfiler(JSRuntime* runtime);
@@ -2903,8 +2947,8 @@
public:
explicit MemProfiler(JSRuntime* aRuntime) : mGCHeapProfiler(nullptr), mRuntime(aRuntime) {}
- void start(GCHeapProfiler* aGCHeapProfiler);
- void stop();
+ JS_FRIEND_API(void) start(GCHeapProfiler* aGCHeapProfiler);
+ JS_FRIEND_API(void) stop();
GCHeapProfiler* getGCHeapProfiler() const {
return mGCHeapProfiler;
@@ -2914,7 +2958,7 @@
return sActiveProfilerCount > 0;
}
- static MemProfiler* GetMemProfiler(JSRuntime* runtime);
+ static JS_FRIEND_API(MemProfiler*) GetMemProfiler(JSContext* context);
static void SetNativeProfiler(NativeProfiler* aProfiler) {
sNativeProfiler = aProfiler;
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jsperf.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jsperf.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jsperf.h
@@ -126,7 +126,7 @@
* Value is not an instance of the wrapper.
*/
extern JS_FRIEND_API(PerfMeasurement*)
- ExtractPerfMeasurement(Value wrapper);
+ ExtractPerfMeasurement(const Value& wrapper);
} // namespace JS
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jsprf.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jsprf.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jsprf.h
@@ -14,34 +14,33 @@
** %x - unsigned hex
** %X - unsigned uppercase hex
** %o - unsigned octal
-** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
-** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
-** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
-** %s - ascii string
-** %hs - ucs2 string
+** %hd, %hu, %hx, %hX, %ho - "short" versions of above
+** %ld, %lu, %lx, %lX, %lo - "long" versions of above
+** %lld, %llu, %llx, %llX, %llo - "long long" versions of above
+** %zd, %zo, %zu, %zx, %zX - size_t versions of above
+** %Id, %Io, %Iu, %Ix, %IX - size_t versions of above (for Windows compat)
+** You should use PRI*SIZE macros instead
+** %s - string
** %c - character
** %p - pointer (deals with machine dependent pointer size)
** %f - float
** %g - float
*/
+#include "mozilla/IntegerPrintfMacros.h"
+#include "mozilla/SizePrintfMacros.h"
+
#include <stdarg.h>
#include "jstypes.h"
/*
-** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
-** of the buffer. Returns the length of the written output, NOT including
-** the NUL, or (uint32_t)-1 if an error occurs.
-*/
-extern JS_PUBLIC_API(uint32_t) JS_snprintf(char* out, uint32_t outlen, const char* fmt, ...);
-
-/*
** sprintf into a malloc'd buffer. Return a pointer to the malloc'd
** buffer on success, nullptr on failure. Call "JS_smprintf_free" to release
** the memory returned.
*/
-extern JS_PUBLIC_API(char*) JS_smprintf(const char* fmt, ...);
+extern JS_PUBLIC_API(char*) JS_smprintf(const char* fmt, ...)
+ MOZ_FORMAT_PRINTF(1, 2);
/*
** Free the memory allocated, for the caller, by JS_smprintf
@@ -55,12 +54,12 @@
** will allocate the initial string. The return value is the new value of
** last for subsequent calls, or nullptr if there is a malloc failure.
*/
-extern JS_PUBLIC_API(char*) JS_sprintf_append(char* last, const char* fmt, ...);
+extern JS_PUBLIC_API(char*) JS_sprintf_append(char* last, const char* fmt, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
/*
** va_list forms of the above.
*/
-extern JS_PUBLIC_API(uint32_t) JS_vsnprintf(char* out, uint32_t outlen, const char* fmt, va_list ap);
extern JS_PUBLIC_API(char*) JS_vsmprintf(const char* fmt, va_list ap);
extern JS_PUBLIC_API(char*) JS_vsprintf_append(char* last, const char* fmt, va_list ap);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jsprototypes.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jsprototypes.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jsprototypes.h
@@ -49,12 +49,24 @@
#define IF_BDATA(real,imaginary) imaginary
#endif
+#ifdef ENABLE_SIMD
+# define IF_SIMD(real,imaginary) real
+#else
+# define IF_SIMD(real,imaginary) imaginary
+#endif
+
#ifdef ENABLE_SHARED_ARRAY_BUFFER
#define IF_SAB(real,imaginary) real
#else
#define IF_SAB(real,imaginary) imaginary
#endif
+#ifdef SPIDERMONKEY_PROMISE
+#define IF_PROMISE(real,imaginary) real
+#else
+#define IF_PROMISE(real,imaginary) imaginary
+#endif
+
#define JS_FOR_PROTOTYPES(real,imaginary) \
imaginary(Null, 0, InitNullClass, dummy) \
real(Object, 1, InitViaClassSpec, OCLASP(Plain)) \
@@ -75,33 +87,42 @@
real(SyntaxError, 16, InitViaClassSpec, ERROR_CLASP(JSEXN_SYNTAXERR)) \
real(TypeError, 17, InitViaClassSpec, ERROR_CLASP(JSEXN_TYPEERR)) \
real(URIError, 18, InitViaClassSpec, ERROR_CLASP(JSEXN_URIERR)) \
- real(Iterator, 19, InitLegacyIteratorClass,OCLASP(PropertyIterator)) \
- real(StopIteration, 20, InitStopIterationClass, OCLASP(StopIteration)) \
- real(ArrayBuffer, 21, InitArrayBufferClass, &js::ArrayBufferObject::protoClass) \
- real(Int8Array, 22, InitViaClassSpec, TYPED_ARRAY_CLASP(Int8)) \
- real(Uint8Array, 23, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8)) \
- real(Int16Array, 24, InitViaClassSpec, TYPED_ARRAY_CLASP(Int16)) \
- real(Uint16Array, 25, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint16)) \
- real(Int32Array, 26, InitViaClassSpec, TYPED_ARRAY_CLASP(Int32)) \
- real(Uint32Array, 27, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint32)) \
- real(Float32Array, 28, InitViaClassSpec, TYPED_ARRAY_CLASP(Float32)) \
- real(Float64Array, 29, InitViaClassSpec, TYPED_ARRAY_CLASP(Float64)) \
- real(Uint8ClampedArray, 30, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8Clamped)) \
- real(Proxy, 31, InitProxyClass, js::ProxyClassPtr) \
- real(WeakMap, 32, InitWeakMapClass, OCLASP(WeakMap)) \
- real(Map, 33, InitMapClass, OCLASP(Map)) \
- real(Set, 34, InitSetClass, OCLASP(Set)) \
- real(DataView, 35, InitDataViewClass, OCLASP(DataView)) \
- real(Symbol, 36, InitSymbolClass, OCLASP(Symbol)) \
-IF_SAB(real,imaginary)(SharedArrayBuffer, 37, InitSharedArrayBufferClass, &js::SharedArrayBufferObject::protoClass) \
-IF_INTL(real,imaginary) (Intl, 38, InitIntlClass, CLASP(Intl)) \
-IF_BDATA(real,imaginary)(TypedObject, 39, InitTypedObjectModuleObject, OCLASP(TypedObjectModule)) \
- real(Reflect, 40, InitReflect, nullptr) \
-IF_BDATA(real,imaginary)(SIMD, 41, InitSIMDClass, OCLASP(SIMD)) \
- real(WeakSet, 42, InitWeakSetClass, OCLASP(WeakSet)) \
- real(TypedArray, 43, InitViaClassSpec, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
-IF_SAB(real,imaginary)(Atomics, 44, InitAtomicsClass, OCLASP(Atomics)) \
- real(SavedFrame, 45, InitViaClassSpec, &js::SavedFrame::class_) \
+ real(DebuggeeWouldRun, 19, InitViaClassSpec, ERROR_CLASP(JSEXN_DEBUGGEEWOULDRUN)) \
+ real(CompileError, 20, InitViaClassSpec, ERROR_CLASP(JSEXN_WASMCOMPILEERROR)) \
+ real(RuntimeError, 21, InitViaClassSpec, ERROR_CLASP(JSEXN_WASMRUNTIMEERROR)) \
+ real(Iterator, 22, InitLegacyIteratorClass,OCLASP(PropertyIterator)) \
+ real(StopIteration, 23, InitStopIterationClass, OCLASP(StopIteration)) \
+ real(ArrayBuffer, 24, InitViaClassSpec, OCLASP(ArrayBuffer)) \
+ real(Int8Array, 25, InitViaClassSpec, TYPED_ARRAY_CLASP(Int8)) \
+ real(Uint8Array, 26, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8)) \
+ real(Int16Array, 27, InitViaClassSpec, TYPED_ARRAY_CLASP(Int16)) \
+ real(Uint16Array, 28, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint16)) \
+ real(Int32Array, 29, InitViaClassSpec, TYPED_ARRAY_CLASP(Int32)) \
+ real(Uint32Array, 30, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint32)) \
+ real(Float32Array, 31, InitViaClassSpec, TYPED_ARRAY_CLASP(Float32)) \
+ real(Float64Array, 32, InitViaClassSpec, TYPED_ARRAY_CLASP(Float64)) \
+ real(Uint8ClampedArray, 33, InitViaClassSpec, TYPED_ARRAY_CLASP(Uint8Clamped)) \
+ real(Proxy, 34, InitProxyClass, js::ProxyClassPtr) \
+ real(WeakMap, 35, InitWeakMapClass, OCLASP(WeakMap)) \
+ real(Map, 36, InitMapClass, OCLASP(Map)) \
+ real(Set, 37, InitSetClass, OCLASP(Set)) \
+ real(DataView, 38, InitDataViewClass, OCLASP(DataView)) \
+ real(Symbol, 39, InitSymbolClass, OCLASP(Symbol)) \
+IF_SAB(real,imaginary)(SharedArrayBuffer, 40, InitViaClassSpec, OCLASP(SharedArrayBuffer)) \
+IF_INTL(real,imaginary) (Intl, 41, InitIntlClass, CLASP(Intl)) \
+IF_BDATA(real,imaginary)(TypedObject, 42, InitTypedObjectModuleObject, OCLASP(TypedObjectModule)) \
+ real(Reflect, 43, InitReflect, nullptr) \
+IF_SIMD(real,imaginary)(SIMD, 44, InitSimdClass, OCLASP(Simd)) \
+ real(WeakSet, 45, InitWeakSetClass, OCLASP(WeakSet)) \
+ real(TypedArray, 46, InitViaClassSpec, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
+IF_SAB(real,imaginary)(Atomics, 47, InitAtomicsClass, OCLASP(Atomics)) \
+ real(SavedFrame, 48, InitViaClassSpec, &js::SavedFrame::class_) \
+ real(WebAssembly, 49, InitWebAssemblyClass, CLASP(WebAssembly)) \
+ imaginary(WasmModule, 50, dummy, dummy) \
+ imaginary(WasmInstance, 51, dummy, dummy) \
+ imaginary(WasmMemory, 52, dummy, dummy) \
+ imaginary(WasmTable, 53, dummy, dummy) \
+IF_PROMISE(real,imaginary)(Promise, 54, InitViaClassSpec, OCLASP(Promise)) \
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jspubtd.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jspubtd.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jspubtd.h
@@ -12,12 +12,14 @@
*/
#include "mozilla/Assertions.h"
+#include "mozilla/EnumeratedArray.h"
#include "mozilla/LinkedList.h"
#include "mozilla/PodOperations.h"
#include "jsprototypes.h"
#include "jstypes.h"
+#include "js/TraceKind.h"
#include "js/TypeDecls.h"
#if defined(JS_GC_ZEAL) || defined(DEBUG)
@@ -26,9 +28,7 @@
namespace JS {
-template <typename T>
-class AutoVectorRooter;
-typedef AutoVectorRooter<jsid> AutoIdVector;
+class AutoIdVector;
class CallArgs;
template <typename T>
@@ -40,13 +40,17 @@
class JS_FRIEND_API(TransitiveCompileOptions);
class JS_PUBLIC_API(CompartmentOptions);
+struct RootingContext;
class Value;
struct Zone;
-} /* namespace JS */
+namespace shadow {
+struct Runtime;
+} // namespace shadow
+
+} // namespace JS
namespace js {
-struct ContextFriendFields;
class RootLists;
} // namespace js
@@ -97,7 +101,6 @@
struct JSLocaleCallbacks;
struct JSObjectMap;
struct JSPrincipals;
-struct JSPropertyDescriptor;
struct JSPropertyName;
struct JSPropertySpec;
struct JSRuntime;
@@ -109,7 +112,6 @@
class JSFlatString;
-typedef struct PRCallOnceType JSCallOnceType;
typedef bool (*JSInitCallback)(void);
template<typename T> struct JSConstScalarSpec;
@@ -117,60 +119,105 @@
typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
/*
- * Generic trace operation that calls JS_CallTracer on each traceable thing
- * stored in data.
+ * Generic trace operation that calls JS::TraceEdge on each traceable thing's
+ * location reachable from data.
*/
typedef void
(* JSTraceDataOp)(JSTracer* trc, void* data);
namespace js {
-
-void FinishGC(JSRuntime* rt);
-
namespace gc {
class AutoTraceSession;
class StoreBuffer;
-void MarkPersistentRootedChains(JSTracer*);
-void MarkPersistentRootedChainsInLists(js::RootLists&, JSTracer*);
-void FinishPersistentRootedChains(js::RootLists&);
} // namespace gc
+
+// Whether the current thread is permitted access to any part of the specified
+// runtime or zone.
+JS_FRIEND_API(bool)
+CurrentThreadCanAccessRuntime(const JSRuntime* rt);
+
+#ifdef DEBUG
+JS_FRIEND_API(bool)
+CurrentThreadIsPerformingGC();
+#endif
+
} // namespace js
namespace JS {
+class JS_PUBLIC_API(AutoEnterCycleCollection);
+class JS_PUBLIC_API(AutoAssertOnBarrier);
+struct JS_PUBLIC_API(PropertyDescriptor);
+
typedef void (*OffThreadCompileCallback)(void* token, void* callbackData);
enum class HeapState {
Idle, // doing nothing with the GC heap
Tracing, // tracing the GC heap without collecting, e.g. IterateCompartments()
MajorCollecting, // doing a GC of the major heap
- MinorCollecting // doing a GC of the minor heap (nursery)
+ MinorCollecting, // doing a GC of the minor heap (nursery)
+ CycleCollecting // in the "Unlink" phase of cycle collection
};
namespace shadow {
struct Runtime
{
- protected:
- // Allow inlining of heapState checks.
- friend class js::gc::AutoTraceSession;
+ private:
JS::HeapState heapState_;
+ protected:
+ void setHeapState(JS::HeapState newState) {
+ MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(asRuntime()));
+ MOZ_ASSERT(heapState_ != newState);
+ heapState_ = newState;
+ }
+
+ JS::HeapState heapState() const {
+ MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(asRuntime()) ||
+ js::CurrentThreadIsPerformingGC());
+ return heapState_;
+ }
+
+ // In some cases, invoking GC barriers (incremental or otherwise) will break
+ // things. These barriers assert if this flag is set.
+ bool allowGCBarriers_;
+ friend class JS::AutoAssertOnBarrier;
+
js::gc::StoreBuffer* gcStoreBufferPtr_;
+ // The gray bits can become invalid if UnmarkGray overflows the stack. A
+ // full GC will reset this bit, since it fills in all the gray bits.
+ bool gcGrayBitsValid_;
+
public:
Runtime()
: heapState_(JS::HeapState::Idle)
+ , allowGCBarriers_(true)
, gcStoreBufferPtr_(nullptr)
+ , gcGrayBitsValid_(false)
{}
- bool isHeapBusy() const { return heapState_ != JS::HeapState::Idle; }
- bool isHeapMajorCollecting() const { return heapState_ == JS::HeapState::MajorCollecting; }
- bool isHeapMinorCollecting() const { return heapState_ == JS::HeapState::MinorCollecting; }
+ bool isHeapBusy() const { return heapState() != JS::HeapState::Idle; }
+ bool isHeapTracing() const { return heapState() == JS::HeapState::Tracing; }
+ bool isHeapMajorCollecting() const { return heapState() == JS::HeapState::MajorCollecting; }
+ bool isHeapMinorCollecting() const { return heapState() == JS::HeapState::MinorCollecting; }
bool isHeapCollecting() const { return isHeapMinorCollecting() || isHeapMajorCollecting(); }
+ bool isCycleCollecting() const {
+ return heapState() == JS::HeapState::CycleCollecting;
+ }
+
+ bool allowGCBarriers() const { return allowGCBarriers_; }
js::gc::StoreBuffer* gcStoreBufferPtr() { return gcStoreBufferPtr_; }
+ bool areGCGrayBitsValid() const { return gcGrayBitsValid_; }
+ void setGCGrayBitsValid(bool valid) { gcGrayBitsValid_ = valid; }
+
+ const JSRuntime* asRuntime() const {
+ return reinterpret_cast<const JSRuntime*>(this);
+ }
+
static JS::shadow::Runtime* asShadowRuntime(JSRuntime* rt) {
return reinterpret_cast<JS::shadow::Runtime*>(rt);
}
@@ -183,11 +230,28 @@
} /* namespace shadow */
+// Decorates the Unlinking phase of CycleCollection so that accidental use
+// of barriered accessors results in assertions instead of leaks.
+class MOZ_STACK_CLASS JS_PUBLIC_API(AutoEnterCycleCollection)
+{
+#ifdef DEBUG
+ JSRuntime* runtime;
+
+ public:
+ explicit AutoEnterCycleCollection(JSContext* cx);
+ ~AutoEnterCycleCollection();
+#else
+ public:
+ explicit AutoEnterCycleCollection(JSContext* cx) {}
+ ~AutoEnterCycleCollection() {}
+#endif
+};
+
class JS_PUBLIC_API(AutoGCRooter)
{
public:
AutoGCRooter(JSContext* cx, ptrdiff_t tag);
- AutoGCRooter(js::ContextFriendFields* cx, ptrdiff_t tag);
+ AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag);
~AutoGCRooter() {
MOZ_ASSERT(this == *stackTop);
@@ -199,13 +263,6 @@
static void traceAll(JSTracer* trc);
static void traceAllWrappers(JSTracer* trc);
- /* T must be a context type */
- template<typename T>
- static void traceAllInContext(T* cx, JSTracer* trc) {
- for (AutoGCRooter* gcr = cx->roots.autoGCRooters_; gcr; gcr = gcr->down)
- gcr->trace(trc);
- }
-
protected:
AutoGCRooter * const down;
@@ -242,6 +299,13 @@
void operator=(AutoGCRooter& ida) = delete;
};
+// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
+// instantiation of MapTypeToRootKind.
+template <>
+struct MapTypeToRootKind<void*> {
+ static const RootKind kind = RootKind::Traceable;
+};
+
} /* namespace JS */
namespace js {
@@ -261,132 +325,98 @@
StackKindCount
};
-enum ThingRootKind
-{
- THING_ROOT_OBJECT,
- THING_ROOT_SHAPE,
- THING_ROOT_BASE_SHAPE,
- THING_ROOT_OBJECT_GROUP,
- THING_ROOT_STRING,
- THING_ROOT_SYMBOL,
- THING_ROOT_JIT_CODE,
- THING_ROOT_SCRIPT,
- THING_ROOT_LAZY_SCRIPT,
- THING_ROOT_ID,
- THING_ROOT_VALUE,
- THING_ROOT_TRACEABLE,
- THING_ROOT_LIMIT
-};
-
-template <typename T>
-struct RootKind;
-
-/*
- * Specifically mark the ThingRootKind of externally visible types, so that
- * JSAPI users may use JSRooted... types without having the class definition
- * available.
- */
-template<typename T, ThingRootKind Kind>
-struct SpecificRootKind
-{
- static ThingRootKind rootKind() { return Kind; }
-};
-
-template <> struct RootKind<JSObject*> : SpecificRootKind<JSObject*, THING_ROOT_OBJECT> {};
-template <> struct RootKind<JSFlatString*> : SpecificRootKind<JSFlatString*, THING_ROOT_STRING> {};
-template <> struct RootKind<JSFunction*> : SpecificRootKind<JSFunction*, THING_ROOT_OBJECT> {};
-template <> struct RootKind<JSString*> : SpecificRootKind<JSString*, THING_ROOT_STRING> {};
-template <> struct RootKind<JS::Symbol*> : SpecificRootKind<JS::Symbol*, THING_ROOT_SYMBOL> {};
-template <> struct RootKind<JSScript*> : SpecificRootKind<JSScript*, THING_ROOT_SCRIPT> {};
-template <> struct RootKind<jsid> : SpecificRootKind<jsid, THING_ROOT_ID> {};
-template <> struct RootKind<JS::Value> : SpecificRootKind<JS::Value, THING_ROOT_VALUE> {};
+using RootedListHeads = mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
+ JS::Rooted<void*>*>;
// Abstracts JS rooting mechanisms so they can be shared between the JSContext
// and JSRuntime.
class RootLists
{
- // Stack GC roots for stack-allocated GC heap pointers.
- JS::Rooted<void*>* stackRoots_[THING_ROOT_LIMIT];
+ // Stack GC roots for Rooted GC heap pointers.
+ RootedListHeads stackRoots_;
template <typename T> friend class JS::Rooted;
- // Stack GC roots for stack-allocated AutoFooRooter classes.
+ // Stack GC roots for AutoFooRooter classes.
JS::AutoGCRooter* autoGCRooters_;
friend class JS::AutoGCRooter;
+ // Heap GC roots for PersistentRooted pointers.
+ mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
+ mozilla::LinkedList<JS::PersistentRooted<void*>>> heapRoots_;
+ template <typename T> friend class JS::PersistentRooted;
+
public:
RootLists() : autoGCRooters_(nullptr) {
- mozilla::PodArrayZero(stackRoots_);
+ for (auto& stackRootPtr : stackRoots_)
+ stackRootPtr = nullptr;
}
- template <class T>
- inline JS::Rooted<T>* gcRooters() {
- js::ThingRootKind kind = RootKind<T>::rootKind();
- return reinterpret_cast<JS::Rooted<T>*>(stackRoots_[kind]);
+ ~RootLists() {
+ // The semantics of PersistentRooted containing pointers and tagged
+ // pointers are somewhat different from those of PersistentRooted
+ // containing a structure with a trace method. PersistentRooted
+ // containing pointers are allowed to outlive the owning RootLists,
+ // whereas those containing a traceable structure are not.
+ //
+ // The purpose of this feature is to support lazy initialization of
+ // global references for the several places in Gecko that do not have
+ // access to a tighter context, but that still need to refer to GC
+ // pointers. For such pointers, FinishPersistentRootedChains ensures
+ // that the contained references are nulled out when the owning
+ // RootLists dies to prevent UAF errors.
+ //
+ // However, for RootKind::Traceable, we do not know the concrete type
+ // of the held thing, so we simply cannot do this without accruing
+ // extra overhead and complexity for all users for a case that is
+ // unlikely to ever be used in practice. For this reason, the following
+ // assertion disallows usage of PersistentRooted<Traceable> that
+ // outlives the RootLists.
+ MOZ_ASSERT(heapRoots_[JS::RootKind::Traceable].isEmpty());
}
+ void traceStackRoots(JSTracer* trc);
void checkNoGCRooters();
- /* Allow inlining of PersistentRooted constructors and destructors. */
- private:
- template <typename Referent> friend class JS::PersistentRooted;
- friend void js::gc::MarkPersistentRootedChains(JSTracer*);
- friend void js::gc::MarkPersistentRootedChainsInLists(RootLists&, JSTracer*);
- friend void js::gc::FinishPersistentRootedChains(RootLists&);
-
- mozilla::LinkedList<JS::PersistentRooted<void*>> heapRoots_[THING_ROOT_LIMIT];
-
- /* Specializations of this return references to the appropriate list. */
- template<typename Referent>
- inline mozilla::LinkedList<JS::PersistentRooted<Referent>>& getPersistentRootedList();
-};
-
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedFunction>&
-RootLists::getPersistentRootedList<JSFunction*>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSFunction*>>&>(
- heapRoots_[THING_ROOT_OBJECT]);
-}
+ void tracePersistentRoots(JSTracer* trc);
+ void finishPersistentRoots();
+};
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedObject>&
-RootLists::getPersistentRootedList<JSObject*>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSObject*>>&>(
- heapRoots_[THING_ROOT_OBJECT]);
-}
+} // namespace js
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedId>&
-RootLists::getPersistentRootedList<jsid>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<jsid>>&>(
- heapRoots_[THING_ROOT_ID]);
-}
+namespace JS {
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedScript>&
-RootLists::getPersistentRootedList<JSScript*>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSScript*>>&>(
- heapRoots_[THING_ROOT_SCRIPT]);
-}
+/*
+ * JS::RootingContext is a base class of ContextFriendFields and JSContext.
+ * This class can be used to let code construct a Rooted<> or PersistentRooted<>
+ * instance, without giving it full access to the JSContext.
+ */
+struct RootingContext
+{
+ js::RootLists roots;
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedString>&
-RootLists::getPersistentRootedList<JSString*>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSString*>>&>(
- heapRoots_[THING_ROOT_STRING]);
-}
+#ifdef DEBUG
+ // Whether the derived class is a JSContext or an ExclusiveContext.
+ bool isJSContext;
+#endif
-template<>
-inline mozilla::LinkedList<JS::PersistentRootedValue>&
-RootLists::getPersistentRootedList<JS::Value>() {
- return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JS::Value>>&>(
- heapRoots_[THING_ROOT_VALUE]);
-}
+ explicit RootingContext(bool isJSContextArg)
+#ifdef DEBUG
+ : isJSContext(isJSContextArg)
+#endif
+ {}
-struct ContextFriendFields
+ static RootingContext* get(JSContext* cx) {
+ return reinterpret_cast<RootingContext*>(cx);
+ }
+};
+
+} // namespace JS
+
+namespace js {
+
+struct ContextFriendFields : public JS::RootingContext
{
protected:
- JSRuntime* const runtime_;
-
/* The current compartment. */
JSCompartment* compartment_;
@@ -394,12 +424,10 @@
JS::Zone* zone_;
public:
- /* Rooting structures. */
- RootLists roots;
+ /* Limit pointer for checking native stack consumption. */
+ uintptr_t nativeStackLimit[js::StackKindCount];
- explicit ContextFriendFields(JSRuntime* rt)
- : runtime_(rt), compartment_(nullptr), zone_(nullptr)
- {}
+ explicit ContextFriendFields(bool isJSContext);
static const ContextFriendFields* get(const JSContext* cx) {
return reinterpret_cast<const ContextFriendFields*>(cx);
@@ -409,7 +437,6 @@
return reinterpret_cast<ContextFriendFields*>(cx);
}
- friend JSRuntime* GetRuntime(const JSContext* cx);
friend JSCompartment* GetContextCompartment(const JSContext* cx);
friend JS::Zone* GetContextZone(const JSContext* cx);
template <typename T> friend class JS::Rooted;
@@ -425,12 +452,6 @@
* usable without resorting to jsfriendapi.h, and when JSContext is an
* incomplete type.
*/
-inline JSRuntime*
-GetRuntime(const JSContext* cx)
-{
- return ContextFriendFields::get(cx)->runtime_;
-}
-
inline JSCompartment*
GetContextCompartment(const JSContext* cx)
{
@@ -443,57 +464,13 @@
return ContextFriendFields::get(cx)->zone_;
}
-class PerThreadData;
-
-struct PerThreadDataFriendFields
-{
- private:
- // Note: this type only exists to permit us to derive the offset of
- // the perThread data within the real JSRuntime* type in a portable
- // way.
- struct RuntimeDummy : JS::shadow::Runtime
- {
- struct PerThreadDummy {
- void* field1;
- uintptr_t field2;
-#ifdef JS_DEBUG
- uint64_t field3;
-#endif
- } mainThread;
- };
-
- public:
- /* Rooting structures. */
- RootLists roots;
-
- PerThreadDataFriendFields();
-
- /* Limit pointer for checking native stack consumption. */
- uintptr_t nativeStackLimit[js::StackKindCount];
-
- static const size_t RuntimeMainThreadOffset = offsetof(RuntimeDummy, mainThread);
-
- static inline PerThreadDataFriendFields* get(js::PerThreadData* pt) {
- return reinterpret_cast<PerThreadDataFriendFields*>(pt);
- }
-
- static inline PerThreadDataFriendFields* getMainThread(JSRuntime* rt) {
- // mainThread must always appear directly after |JS::shadow::Runtime|.
- // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
- return reinterpret_cast<PerThreadDataFriendFields*>(
- reinterpret_cast<char*>(rt) + RuntimeMainThreadOffset);
- }
+} /* namespace js */
- static inline const PerThreadDataFriendFields* getMainThread(const JSRuntime* rt) {
- // mainThread must always appear directly after |JS::shadow::Runtime|.
- // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
- return reinterpret_cast<const PerThreadDataFriendFields*>(
- reinterpret_cast<const char*>(rt) + RuntimeMainThreadOffset);
- }
+MOZ_BEGIN_EXTERN_C
- template <typename T> friend class JS::Rooted;
-};
+// Defined in NSPR prio.h.
+typedef struct PRFileDesc PRFileDesc;
-} /* namespace js */
+MOZ_END_EXTERN_C
#endif /* jspubtd_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jstypes.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jstypes.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jstypes.h
@@ -70,18 +70,16 @@
#if defined(STATIC_JS_API)
# define JS_PUBLIC_API(t) t
# define JS_PUBLIC_DATA(t) t
+# define JS_FRIEND_API(t) t
+# define JS_FRIEND_DATA(t) t
#elif defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
# define JS_PUBLIC_API(t) MOZ_EXPORT t
# define JS_PUBLIC_DATA(t) MOZ_EXPORT t
-#else
-# define JS_PUBLIC_API(t) MOZ_IMPORT_API t
-# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA t
-#endif
-
-#if defined(STATIC_JS_API) || defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
# define JS_FRIEND_API(t) MOZ_EXPORT t
# define JS_FRIEND_DATA(t) MOZ_EXPORT t
#else
+# define JS_PUBLIC_API(t) MOZ_IMPORT_API t
+# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA t
# define JS_FRIEND_API(t) MOZ_IMPORT_API t
# define JS_FRIEND_DATA(t) MOZ_IMPORT_DATA t
#endif
@@ -95,6 +93,14 @@
#define JS_NO_FASTCALL
#endif
+// gcc is buggy and warns on our attempts to JS_PUBLIC_API our
+// forward-declarations or explicit template instantiations. See
+// <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50044>. Add a way to detect
+// that so we can locally disable that warning.
+#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ < 6 || (__GNUC__ == 6 && __GNUC_MINOR__ <= 4))
+#define JS_BROKEN_GCC_ATTRIBUTE_WARNING
+#endif
+
/***********************************************************************
** MACROS: JS_BEGIN_MACRO
** JS_END_MACRO
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jsversion.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jsversion.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jsversion.h
@@ -22,7 +22,7 @@
#define JS_HAS_GENERATORS 1 /* (no longer used) */
#define JS_HAS_BLOCK_SCOPE 1 /* (no longer used) */
#define JS_HAS_DESTRUCTURING 2 /* (no longer used) */
-#define JS_HAS_GENERATOR_EXPRS 1 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_GENERATOR_EXPRS 1 /* (no longer used) */
#define JS_HAS_EXPR_CLOSURES 1 /* has function (formals) listexpr */
/* (no longer used) */
@@ -37,11 +37,4 @@
*/
#define JS_OLD_GETTER_SETTER_METHODS 1
-#ifdef NIGHTLY_BUILD
-
-/* Support for ES7 Exponentiation proposal. */
-#define JS_HAS_EXPONENTIATION 1
-
-#endif // NIGHTLY_BUILD
-
#endif /* jsversion_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/jswrapper.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/jswrapper.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/jswrapper.h
@@ -44,19 +44,88 @@
/*
* A wrapper is a proxy with a target object to which it generally forwards
- * operations, but may restrict access to certain operations or instrument the
- * methods in various ways. A wrapper is distinct from a Direct Proxy Handler
- * in the sense that it can be "unwrapped" in C++, exposing the underlying
- * object (Direct Proxy Handlers have an underlying target object, but don't
- * expect to expose this object via any kind of unwrapping operation). Callers
- * should be careful to avoid unwrapping security wrappers in the wrong
+ * operations, but may restrict access to certain operations or augment those
+ * operations in various ways.
+ *
+ * A wrapper can be "unwrapped" in C++, exposing the underlying object.
+ * Callers should be careful to avoid unwrapping security wrappers in the wrong
* context.
+ *
+ * Important: If you add a method implementation here, you probably also need
+ * to add an override in CrossCompartmentWrapper. If you don't, you risk
+ * compartment mismatches. See bug 945826 comment 0.
*/
-class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
+class JS_FRIEND_API(Wrapper) : public BaseProxyHandler
{
unsigned mFlags;
public:
+ explicit constexpr Wrapper(unsigned aFlags, bool aHasPrototype = false,
+ bool aHasSecurityPolicy = false)
+ : BaseProxyHandler(&family, aHasPrototype, aHasSecurityPolicy),
+ mFlags(aFlags)
+ { }
+
+ virtual bool finalizeInBackground(const Value& priv) const override;
+
+ /* Standard internal methods. */
+ virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
+ MutableHandle<PropertyDescriptor> desc) const override;
+ virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
+ Handle<PropertyDescriptor> desc,
+ ObjectOpResult& result) const override;
+ virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
+ AutoIdVector& props) const override;
+ virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
+ ObjectOpResult& result) const override;
+ virtual bool enumerate(JSContext* cx, HandleObject proxy,
+ MutableHandleObject objp) const override;
+ virtual bool getPrototype(JSContext* cx, HandleObject proxy,
+ MutableHandleObject protop) const override;
+ virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
+ ObjectOpResult& result) const override;
+ virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
+ MutableHandleObject protop) const override;
+ virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
+ bool* succeeded) const override;
+ virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
+ ObjectOpResult& result) const override;
+ virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
+ virtual bool has(JSContext* cx, HandleObject proxy, HandleId id,
+ bool* bp) const override;
+ virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
+ HandleId id, MutableHandleValue vp) const override;
+ virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
+ HandleValue receiver, ObjectOpResult& result) const override;
+ virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
+ virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
+
+ /* SpiderMonkey extensions. */
+ virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
+ MutableHandle<PropertyDescriptor> desc) const override;
+ virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id,
+ bool* bp) const override;
+ virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
+ AutoIdVector& props) const override;
+ virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
+ const CallArgs& args) const override;
+ virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
+ bool* bp) const override;
+ virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls) const override;
+ virtual bool isArray(JSContext* cx, HandleObject proxy,
+ JS::IsArrayAnswer* answer) const override;
+ virtual const char* className(JSContext* cx, HandleObject proxy) const override;
+ virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
+ unsigned indent) const override;
+ virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
+ RegExpGuard* g) const override;
+ virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy,
+ MutableHandleValue vp) const override;
+ virtual bool isCallable(JSObject* obj) const override;
+ virtual bool isConstructor(JSObject* obj) const override;
+ virtual JSObject* weakmapKeyDelegate(JSObject* proxy) const override;
+
+ public:
using BaseProxyHandler::Action;
enum Flags {
@@ -77,15 +146,6 @@
return mFlags;
}
- explicit MOZ_CONSTEXPR Wrapper(unsigned aFlags, bool aHasPrototype = false,
- bool aHasSecurityPolicy = false)
- : DirectProxyHandler(&family, aHasPrototype, aHasSecurityPolicy),
- mFlags(aFlags)
- { }
-
- virtual bool finalizeInBackground(Value priv) const override;
- virtual bool isConstructor(JSObject* obj) const override;
-
static const char family;
static const Wrapper singleton;
static const Wrapper singletonWithPrototype;
@@ -103,16 +163,16 @@
class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
{
public:
- explicit MOZ_CONSTEXPR CrossCompartmentWrapper(unsigned aFlags, bool aHasPrototype = false,
+ explicit constexpr CrossCompartmentWrapper(unsigned aFlags, bool aHasPrototype = false,
bool aHasSecurityPolicy = false)
: Wrapper(CROSS_COMPARTMENT | aFlags, aHasPrototype, aHasSecurityPolicy)
{ }
/* Standard internal methods. */
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
+ MutableHandle<PropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<JSPropertyDescriptor> desc,
+ Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const override;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
@@ -124,6 +184,8 @@
virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
ObjectOpResult& result) const override;
+ virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
+ MutableHandleObject protop) const override;
virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
bool* succeeded) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
@@ -139,7 +201,7 @@
/* SpiderMonkey extensions. */
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
+ MutableHandle<PropertyDescriptor> desc) const override;
virtual bool hasOwn(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
@@ -153,6 +215,9 @@
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
+ // Allocate CrossCompartmentWrappers in the nursery.
+ virtual bool canNurseryAllocate() const override { return true; }
+
static const CrossCompartmentWrapper singleton;
static const CrossCompartmentWrapper singletonWithPrototype;
};
@@ -160,14 +225,14 @@
class JS_FRIEND_API(OpaqueCrossCompartmentWrapper) : public CrossCompartmentWrapper
{
public:
- explicit MOZ_CONSTEXPR OpaqueCrossCompartmentWrapper() : CrossCompartmentWrapper(0)
+ explicit constexpr OpaqueCrossCompartmentWrapper() : CrossCompartmentWrapper(0)
{ }
/* Standard internal methods. */
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
+ MutableHandle<PropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<JSPropertyDescriptor> desc,
+ Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const override;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
@@ -179,6 +244,8 @@
MutableHandleObject protop) const override;
virtual bool setPrototype(JSContext* cx, HandleObject wrapper, HandleObject proto,
ObjectOpResult& result) const override;
+ virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject wrapper, bool* isOrdinary,
+ MutableHandleObject protop) const override;
virtual bool setImmutablePrototype(JSContext* cx, HandleObject wrapper,
bool* succeeded) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
@@ -195,13 +262,12 @@
/* SpiderMonkey extensions. */
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
- MutableHandle<JSPropertyDescriptor> desc) const override;
+ MutableHandle<PropertyDescriptor> desc) const override;
virtual bool hasOwn(JSContext* cx, HandleObject wrapper, HandleId id,
bool* bp) const override;
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper,
- ESClassValue* classValue) const override;
+ virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper, ESClass* cls) const override;
virtual bool isArray(JSContext* cx, HandleObject obj,
JS::IsArrayAnswer* answer) const override;
virtual const char* className(JSContext* cx, HandleObject wrapper) const override;
@@ -223,7 +289,7 @@
class JS_FRIEND_API(SecurityWrapper) : public Base
{
public:
- explicit MOZ_CONSTEXPR SecurityWrapper(unsigned flags, bool hasPrototype = false)
+ explicit constexpr SecurityWrapper(unsigned flags, bool hasPrototype = false)
: Base(flags, hasPrototype, /* hasSecurityPolicy = */ true)
{ }
@@ -231,7 +297,7 @@
bool* bp) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
- Handle<JSPropertyDescriptor> desc,
+ Handle<PropertyDescriptor> desc,
ObjectOpResult& result) const override;
virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper,
@@ -242,8 +308,7 @@
virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
const CallArgs& args) const override;
- virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper,
- ESClassValue* classValue) const override;
+ virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper, ESClass* cls) const override;
virtual bool isArray(JSContext* cx, HandleObject wrapper, JS::IsArrayAnswer* answer) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
@@ -263,7 +328,6 @@
typedef SecurityWrapper<Base> Restrictive;
};
-typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
extern JSObject*
@@ -297,10 +361,10 @@
JS_FRIEND_API(bool)
IsCrossCompartmentWrapper(JSObject* obj);
-void
+JS_FRIEND_API(void)
NukeCrossCompartmentWrapper(JSContext* cx, JSObject* wrapper);
-bool
+void
RemapWrapper(JSContext* cx, JSObject* wobj, JSObject* newTarget);
JS_FRIEND_API(bool)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Alignment.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Alignment.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Alignment.h
@@ -120,6 +120,13 @@
const void* addr() const { return u.mBytes; }
void* addr() { return u.mBytes; }
+
+ AlignedStorage() = default;
+
+ // AlignedStorage is non-copyable: the default copy constructor violates
+ // strict aliasing rules, per bug 1269319.
+ AlignedStorage(const AlignedStorage&) = delete;
+ void operator=(const AlignedStorage&) = delete;
};
template<typename T>
@@ -133,6 +140,13 @@
const T* addr() const { return reinterpret_cast<const T*>(u.mBytes); }
T* addr() { return static_cast<T*>(static_cast<void*>(u.mBytes)); }
+
+ AlignedStorage2() = default;
+
+ // AlignedStorage2 is non-copyable: the default copy constructor violates
+ // strict aliasing rules, per bug 1269319.
+ AlignedStorage2(const AlignedStorage2&) = delete;
+ void operator=(const AlignedStorage2&) = delete;
};
} /* namespace mozilla */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/AllocPolicy.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/AllocPolicy.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/AllocPolicy.h
@@ -12,6 +12,7 @@
#ifndef mozilla_AllocPolicy_h
#define mozilla_AllocPolicy_h
+#include "mozilla/Attributes.h"
#include "mozilla/TemplateLib.h"
#include <stddef.h>
@@ -121,7 +122,7 @@
{
}
- bool checkSimulatedOOM() const
+ MOZ_MUST_USE bool checkSimulatedOOM() const
{
return true;
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/AlreadyAddRefed.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/AlreadyAddRefed.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/AlreadyAddRefed.h
@@ -29,7 +29,7 @@
* because of the sheer number of usages of already_AddRefed.
*/
template<class T>
-struct MOZ_MUST_USE MOZ_NON_AUTOABLE already_AddRefed
+struct MOZ_MUST_USE_TYPE MOZ_NON_AUTOABLE already_AddRefed
{
/*
* We want to allow returning nullptr from functions returning
@@ -111,7 +111,7 @@
aUnused << mutableAlreadyAddRefed->take();
}
- MOZ_WARN_UNUSED_RESULT T* take()
+ MOZ_MUST_USE T* take()
{
T* rawPtr = mRawPtr;
mRawPtr = nullptr;
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Array.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Array.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Array.h
@@ -11,6 +11,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
+#include "mozilla/Move.h"
#include "mozilla/ReverseIterator.h"
#include <stddef.h>
@@ -23,6 +24,16 @@
T mArr[Length];
public:
+ Array() {}
+
+ template <typename... Args>
+ MOZ_IMPLICIT Array(Args&&... aArgs)
+ : mArr{mozilla::Forward<Args>(aArgs)...}
+ {
+ static_assert(sizeof...(aArgs) == Length,
+ "The number of arguments should be equal to the template parameter Length");
+ }
+
T& operator[](size_t aIndex)
{
MOZ_ASSERT(aIndex < Length);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ArrayUtils.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ArrayUtils.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ArrayUtils.h
@@ -52,21 +52,21 @@
* Beware of the implicit trailing '\0' when using this with string constants.
*/
template<typename T, size_t N>
-MOZ_CONSTEXPR size_t
+constexpr size_t
ArrayLength(T (&aArr)[N])
{
return N;
}
template<typename T, size_t N>
-MOZ_CONSTEXPR size_t
+constexpr size_t
ArrayLength(const Array<T, N>& aArr)
{
return N;
}
template<typename E, E N, typename T>
-MOZ_CONSTEXPR size_t
+constexpr size_t
ArrayLength(const EnumeratedArray<E, N, T>& aArr)
{
return size_t(N);
@@ -78,21 +78,21 @@
* Beware of the implicit trailing '\0' when using this with string constants.
*/
template<typename T, size_t N>
-MOZ_CONSTEXPR T*
+constexpr T*
ArrayEnd(T (&aArr)[N])
{
return aArr + ArrayLength(aArr);
}
template<typename T, size_t N>
-MOZ_CONSTEXPR T*
+constexpr T*
ArrayEnd(Array<T, N>& aArr)
{
return &aArr[0] + ArrayLength(aArr);
}
template<typename T, size_t N>
-MOZ_CONSTEXPR const T*
+constexpr const T*
ArrayEnd(const Array<T, N>& aArr)
{
return &aArr[0] + ArrayLength(aArr);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Assertions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Assertions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Assertions.h
@@ -17,23 +17,29 @@
#include "mozilla/Compiler.h"
#include "mozilla/Likely.h"
#include "mozilla/MacroArgs.h"
+#include "mozilla/StaticAnalysisFunctions.h"
+#include "mozilla/Types.h"
#ifdef MOZ_DUMP_ASSERTION_STACK
#include "nsTraceRefcnt.h"
#endif
-#if defined(MOZ_CRASHREPORTER) && defined(MOZILLA_INTERNAL_API) && \
- !defined(MOZILLA_EXTERNAL_LINKAGE) && defined(__cplusplus)
-namespace CrashReporter {
-// This declaration is present here as well as in nsExceptionHandler.h
-// nsExceptionHandler.h is not directly included in this file as it includes
-// windows.h, which can cause problems when it is imported into some files due
-// to the number of macros defined.
-// XXX If you change this definition - also change the definition in
-// nsExceptionHandler.h
-void AnnotateMozCrashReason(const char* aReason);
-} // namespace CrashReporter
+#if defined(MOZ_HAS_MOZGLUE) || defined(MOZILLA_INTERNAL_API)
+/*
+ * The crash reason set by MOZ_CRASH_ANNOTATE is consumed by the crash reporter
+ * if present. It is declared here (and defined in Assertions.cpp) to make it
+ * available to all code, even libraries that don't link with the crash reporter
+ * directly.
+ */
+MOZ_BEGIN_EXTERN_C
+extern MFBT_DATA const char* gMozCrashReason;
+MOZ_END_EXTERN_C
-# define MOZ_CRASH_ANNOTATE(...) CrashReporter::AnnotateMozCrashReason("" __VA_ARGS__)
+static inline void
+AnnotateMozCrashReason(const char* reason)
+{
+ gMozCrashReason = reason;
+}
+# define MOZ_CRASH_ANNOTATE(...) AnnotateMozCrashReason(__VA_ARGS__)
#else
# define MOZ_CRASH_ANNOTATE(...) do { /* nothing */ } while (0)
#endif
@@ -158,7 +164,7 @@
aStr, aFilename, aLine);
#else
fprintf(stderr, "Assertion failure: %s, at %s:%d\n", aStr, aFilename, aLine);
-#if defined (MOZ_DUMP_ASSERTION_STACK) && !defined(MOZILLA_XPCOMRT_API)
+#if defined (MOZ_DUMP_ASSERTION_STACK)
nsTraceRefcnt::WalkTheStack(stderr);
#endif
fflush(stderr);
@@ -174,7 +180,7 @@
"Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
#else
fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
-#if defined(MOZ_DUMP_ASSERTION_STACK) && !defined(MOZILLA_XPCOMRT_API)
+#if defined(MOZ_DUMP_ASSERTION_STACK)
nsTraceRefcnt::WalkTheStack(stderr);
#endif
fflush(stderr);
@@ -212,33 +218,33 @@
__declspec(noreturn) __inline void MOZ_NoReturn() {}
# ifdef __cplusplus
-# define MOZ_REALLY_CRASH() \
+# define MOZ_REALLY_CRASH(line) \
do { \
::__debugbreak(); \
- *((volatile int*) NULL) = __LINE__; \
+ *((volatile int*) NULL) = line; \
::TerminateProcess(::GetCurrentProcess(), 3); \
::MOZ_NoReturn(); \
} while (0)
# else
-# define MOZ_REALLY_CRASH() \
+# define MOZ_REALLY_CRASH(line) \
do { \
__debugbreak(); \
- *((volatile int*) NULL) = __LINE__; \
+ *((volatile int*) NULL) = line; \
TerminateProcess(GetCurrentProcess(), 3); \
MOZ_NoReturn(); \
} while (0)
# endif
#else
# ifdef __cplusplus
-# define MOZ_REALLY_CRASH() \
+# define MOZ_REALLY_CRASH(line) \
do { \
- *((volatile int*) NULL) = __LINE__; \
+ *((volatile int*) NULL) = line; \
::abort(); \
} while (0)
# else
-# define MOZ_REALLY_CRASH() \
+# define MOZ_REALLY_CRASH(line) \
do { \
- *((volatile int*) NULL) = __LINE__; \
+ *((volatile int*) NULL) = line; \
abort(); \
} while (0)
# endif
@@ -269,17 +275,69 @@
# define MOZ_CRASH(...) \
do { \
MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
- MOZ_REALLY_CRASH(); \
+ MOZ_REALLY_CRASH(__LINE__); \
} while (0)
#else
# define MOZ_CRASH(...) \
do { \
MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
- MOZ_REALLY_CRASH(); \
+ MOZ_REALLY_CRASH(__LINE__); \
} while (0)
#endif
+/*
+ * MOZ_CRASH_UNSAFE_OOL(explanation-string) can be used if the explanation
+ * string cannot be a string literal (but no other processing needs to be done
+ * on it). A regular MOZ_CRASH() is preferred wherever possible, as passing
+ * arbitrary strings from a potentially compromised process is not without risk.
+ * If the string being passed is the result of a printf-style function,
+ * consider using MOZ_CRASH_UNSAFE_PRINTF instead.
+ */
+#ifndef DEBUG
+MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
+MOZ_CrashOOL(int aLine, const char* aReason);
+# define MOZ_CRASH_UNSAFE_OOL(reason) MOZ_CrashOOL(__LINE__, reason)
+#else
+MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
+MOZ_CrashOOL(const char* aFilename, int aLine, const char* aReason);
+# define MOZ_CRASH_UNSAFE_OOL(reason) MOZ_CrashOOL(__FILE__, __LINE__, reason)
+#endif
+
+static const size_t sPrintfMaxArgs = 4;
+static const size_t sPrintfCrashReasonSize = 1024;
+
+#ifndef DEBUG
+MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(2, 3) void
+MOZ_CrashPrintf(int aLine, const char* aFormat, ...);
+# define MOZ_CALL_CRASH_PRINTF(format, ...) \
+ MOZ_CrashPrintf(__LINE__, format, __VA_ARGS__)
+#else
+MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(3, 4) void
+MOZ_CrashPrintf(const char* aFilename, int aLine, const char* aFormat, ...);
+# define MOZ_CALL_CRASH_PRINTF(format, ...) \
+ MOZ_CrashPrintf(__FILE__, __LINE__, format, __VA_ARGS__)
+#endif
+
+/*
+ * MOZ_CRASH_UNSAFE_PRINTF(format, arg1 [, args]) can be used when more
+ * information is desired than a string literal can supply. The caller provides
+ * a printf-style format string, which must be a string literal and between
+ * 1 and 4 additional arguments. A regular MOZ_CRASH() is preferred wherever
+ * possible, as passing arbitrary strings to printf from a potentially
+ * compromised process is not without risk.
+ */
+#define MOZ_CRASH_UNSAFE_PRINTF(format, ...) \
+ do { \
+ MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
+ static_assert( \
+ MOZ_PASTE_PREFIX_AND_ARG_COUNT(, __VA_ARGS__) <= sPrintfMaxArgs, \
+ "Only up to 4 additional arguments are allowed!"); \
+ static_assert(sizeof(format) <= sPrintfCrashReasonSize, \
+ "The supplied format string is too long!"); \
+ MOZ_CALL_CRASH_PRINTF("" format, __VA_ARGS__); \
+ } while (0)
+
#ifdef __cplusplus
} /* extern "C" */
#endif
@@ -368,20 +426,20 @@
#define MOZ_ASSERT_HELPER1(expr) \
do { \
MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
- if (MOZ_UNLIKELY(!(expr))) { \
+ if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ")"); \
- MOZ_REALLY_CRASH(); \
+ MOZ_REALLY_CRASH(__LINE__); \
} \
} while (0)
/* Now the two-argument form. */
#define MOZ_ASSERT_HELPER2(expr, explain) \
do { \
MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \
- if (MOZ_UNLIKELY(!(expr))) { \
+ if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ") (" explain ")"); \
- MOZ_REALLY_CRASH(); \
+ MOZ_REALLY_CRASH(__LINE__); \
} \
} while (0)
@@ -397,7 +455,7 @@
# define MOZ_ASSERT(...) do { } while (0)
#endif /* DEBUG */
-#ifdef RELEASE_BUILD
+#ifdef RELEASE_OR_BETA
# define MOZ_DIAGNOSTIC_ASSERT MOZ_ASSERT
#else
# define MOZ_DIAGNOSTIC_ASSERT MOZ_RELEASE_ASSERT
@@ -496,6 +554,45 @@
MOZ_ASSUME_UNREACHABLE_MARKER(); \
} while (0)
+/**
+ * MOZ_FALLTHROUGH_ASSERT is an annotation to suppress compiler warnings about
+ * switch cases that MOZ_ASSERT(false) (or its alias MOZ_ASSERT_UNREACHABLE) in
+ * debug builds, but intentionally fall through in release builds to handle
+ * unexpected values.
+ *
+ * Why do we need MOZ_FALLTHROUGH_ASSERT in addition to MOZ_FALLTHROUGH? In
+ * release builds, the MOZ_ASSERT(false) will expand to `do { } while (0)`,
+ * requiring a MOZ_FALLTHROUGH annotation to suppress a -Wimplicit-fallthrough
+ * warning. In debug builds, the MOZ_ASSERT(false) will expand to something like
+ * `if (true) { MOZ_CRASH(); }` and the MOZ_FALLTHROUGH annotation will cause
+ * a -Wunreachable-code warning. The MOZ_FALLTHROUGH_ASSERT macro breaks this
+ * warning stalemate.
+ *
+ * // Example before MOZ_FALLTHROUGH_ASSERT:
+ * switch (foo) {
+ * default:
+ * // This case wants to assert in debug builds, fall through in release.
+ * MOZ_ASSERT(false); // -Wimplicit-fallthrough warning in release builds!
+ * MOZ_FALLTHROUGH; // but -Wunreachable-code warning in debug builds!
+ * case 5:
+ * return 5;
+ * }
+ *
+ * // Example with MOZ_FALLTHROUGH_ASSERT:
+ * switch (foo) {
+ * default:
+ * // This case asserts in debug builds, falls through in release.
+ * MOZ_FALLTHROUGH_ASSERT("Unexpected foo value?!");
+ * case 5:
+ * return 5;
+ * }
+ */
+#ifdef DEBUG
+# define MOZ_FALLTHROUGH_ASSERT(reason) MOZ_CRASH("MOZ_FALLTHROUGH_ASSERT: " reason)
+#else
+# define MOZ_FALLTHROUGH_ASSERT(...) MOZ_FALLTHROUGH
+#endif
+
/*
* MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
* expression, in debug builds and in release builds both. Then, in debug
@@ -503,21 +600,35 @@
* using MOZ_ASSERT.
*/
#ifdef DEBUG
-# define MOZ_ALWAYS_TRUE(expr) MOZ_ASSERT((expr))
-# define MOZ_ALWAYS_FALSE(expr) MOZ_ASSERT(!(expr))
+# define MOZ_ALWAYS_TRUE(expr) \
+ do { \
+ if ((expr)) { \
+ /* Do nothing. */ \
+ } else { \
+ MOZ_ASSERT(false, #expr); \
+ } \
+ } while (0)
+# define MOZ_ALWAYS_FALSE(expr) \
+ do { \
+ if ((expr)) { \
+ MOZ_ASSERT(false, #expr); \
+ } else { \
+ /* Do nothing. */ \
+ } \
+ } while (0)
#else
# define MOZ_ALWAYS_TRUE(expr) \
- do { \
- if ( ( expr ) ) { \
- /* Silence MOZ_WARN_UNUSED_RESULT. */ \
- } \
- } while (0)
+ do { \
+ if ((expr)) { \
+ /* Silence MOZ_MUST_USE. */ \
+ } \
+ } while (0)
# define MOZ_ALWAYS_FALSE(expr) \
- do { \
- if ( ( expr ) ) { \
- /* Silence MOZ_WARN_UNUSED_RESULT. */ \
- } \
- } while (0)
+ do { \
+ if ((expr)) { \
+ /* Silence MOZ_MUST_USE. */ \
+ } \
+ } while (0)
#endif
#undef MOZ_DUMP_ASSERTION_STACK
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Atomics.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Atomics.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Atomics.h
@@ -323,7 +323,7 @@
template<typename T>
struct ToStorageTypeArgument
{
- static T convert (T aT) { return aT; }
+ static constexpr T convert (T aT) { return aT; }
};
} // namespace detail
@@ -514,13 +514,13 @@
{
typedef typename AtomicStorageType<T>::Type ResultType;
- static ResultType convert (T aT) { return ResultType(aT); }
+ static constexpr ResultType convert (T aT) { return ResultType(aT); }
};
template<typename T>
struct ToStorageTypeArgument<T, false>
{
- static T convert (T aT) { return aT; }
+ static constexpr T convert (T aT) { return aT; }
};
} // namespace detail
@@ -546,8 +546,8 @@
ValueType mValue;
public:
- MOZ_CONSTEXPR AtomicBase() : mValue() {}
- explicit MOZ_CONSTEXPR AtomicBase(T aInit)
+ constexpr AtomicBase() : mValue() {}
+ explicit constexpr AtomicBase(T aInit)
: mValue(ToStorageTypeArgument<T>::convert(aInit))
{}
@@ -598,8 +598,8 @@
typedef typename detail::AtomicBase<T, Order> Base;
public:
- MOZ_CONSTEXPR AtomicBaseIncDec() : Base() {}
- explicit MOZ_CONSTEXPR AtomicBaseIncDec(T aInit) : Base(aInit) {}
+ constexpr AtomicBaseIncDec() : Base() {}
+ explicit constexpr AtomicBaseIncDec(T aInit) : Base(aInit) {}
using Base::operator=;
@@ -654,8 +654,8 @@
typedef typename detail::AtomicBaseIncDec<T, Order> Base;
public:
- MOZ_CONSTEXPR Atomic() : Base() {}
- explicit MOZ_CONSTEXPR Atomic(T aInit) : Base(aInit) {}
+ constexpr Atomic() : Base() {}
+ explicit constexpr Atomic(T aInit) : Base(aInit) {}
using Base::operator=;
@@ -702,8 +702,8 @@
typedef typename detail::AtomicBaseIncDec<T*, Order> Base;
public:
- MOZ_CONSTEXPR Atomic() : Base() {}
- explicit MOZ_CONSTEXPR Atomic(T* aInit) : Base(aInit) {}
+ constexpr Atomic() : Base() {}
+ explicit constexpr Atomic(T* aInit) : Base(aInit) {}
using Base::operator=;
@@ -733,8 +733,8 @@
typedef typename detail::AtomicBase<T, Order> Base;
public:
- MOZ_CONSTEXPR Atomic() : Base() {}
- explicit MOZ_CONSTEXPR Atomic(T aInit) : Base(aInit) {}
+ constexpr Atomic() : Base() {}
+ explicit constexpr Atomic(T aInit) : Base(aInit) {}
operator T() const { return T(Base::Intrinsics::load(Base::mValue)); }
@@ -767,8 +767,8 @@
typedef typename detail::AtomicBase<uint32_t, Order> Base;
public:
- MOZ_CONSTEXPR Atomic() : Base() {}
- explicit MOZ_CONSTEXPR Atomic(bool aInit) : Base(aInit) {}
+ constexpr Atomic() : Base() {}
+ explicit constexpr Atomic(bool aInit) : Base(aInit) {}
// We provide boolean wrappers for the underlying AtomicBase methods.
MOZ_IMPLICIT operator bool() const
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Attributes.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Attributes.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Attributes.h
@@ -45,27 +45,9 @@
* standardly, by checking whether __cplusplus has a C++11 or greater value.
* Current versions of g++ do not correctly set __cplusplus, so we check both
* for forward compatibility.
- *
- * Even though some versions of MSVC support explicit conversion operators, we
- * don't indicate support for them here, due to
- * http://stackoverflow.com/questions/20498142/visual-studio-2013-explicit-keyword-bug
*/
# define MOZ_HAVE_NEVER_INLINE __declspec(noinline)
# define MOZ_HAVE_NORETURN __declspec(noreturn)
-# if _MSC_VER >= 1900
-# define MOZ_HAVE_CXX11_CONSTEXPR
-# define MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
-# define MOZ_HAVE_EXPLICIT_CONVERSION
-# endif
-# ifdef __clang__
- /* clang-cl probably supports constexpr and explicit conversions. */
-# if __has_extension(cxx_constexpr)
-# define MOZ_HAVE_CXX11_CONSTEXPR
-# endif
-# if __has_extension(cxx_explicit_conversions)
-# define MOZ_HAVE_EXPLICIT_CONVERSION
-# endif
-# endif
#elif defined(__clang__)
/*
* Per Clang documentation, "Note that marketing version numbers should not
@@ -75,12 +57,6 @@
# ifndef __has_extension
# define __has_extension __has_feature /* compatibility, for older versions of clang */
# endif
-# if __has_extension(cxx_constexpr)
-# define MOZ_HAVE_CXX11_CONSTEXPR
-# endif
-# if __has_extension(cxx_explicit_conversions)
-# define MOZ_HAVE_EXPLICIT_CONVERSION
-# endif
# if __has_attribute(noinline)
# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
# endif
@@ -88,13 +64,6 @@
# define MOZ_HAVE_NORETURN __attribute__((noreturn))
# endif
#elif defined(__GNUC__)
-# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
-# define MOZ_HAVE_CXX11_CONSTEXPR
-# if MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
-# define MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
-# endif
-# define MOZ_HAVE_EXPLICIT_CONVERSION
-# endif
# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
# define MOZ_HAVE_NORETURN __attribute__((noreturn))
#endif
@@ -110,55 +79,6 @@
#endif
/*
- * The MOZ_CONSTEXPR specifier declares that a C++11 compiler can evaluate a
- * function at compile time. A constexpr function cannot examine any values
- * except its arguments and can have no side effects except its return value.
- * The MOZ_CONSTEXPR_VAR specifier tells a C++11 compiler that a variable's
- * value may be computed at compile time. It should be prefered to just
- * marking variables as MOZ_CONSTEXPR because if the compiler does not support
- * constexpr it will fall back to making the variable const, and some compilers
- * do not accept variables being marked both const and constexpr.
- */
-#ifdef MOZ_HAVE_CXX11_CONSTEXPR
-# define MOZ_CONSTEXPR constexpr
-# define MOZ_CONSTEXPR_VAR constexpr
-# ifdef MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
-# define MOZ_CONSTEXPR_TMPL constexpr
-# else
-# define MOZ_CONSTEXPR_TMPL
-# endif
-#else
-# define MOZ_CONSTEXPR /* no support */
-# define MOZ_CONSTEXPR_VAR const
-# define MOZ_CONSTEXPR_TMPL
-#endif
-
-/*
- * MOZ_EXPLICIT_CONVERSION is a specifier on a type conversion
- * overloaded operator that declares that a C++11 compiler should restrict
- * this operator to allow only explicit type conversions, disallowing
- * implicit conversions.
- *
- * Example:
- *
- * template<typename T>
- * class Ptr
- * {
- * T* mPtr;
- * MOZ_EXPLICIT_CONVERSION operator bool() const
- * {
- * return mPtr != nullptr;
- * }
- * };
- *
- */
-#ifdef MOZ_HAVE_EXPLICIT_CONVERSION
-# define MOZ_EXPLICIT_CONVERSION explicit
-#else
-# define MOZ_EXPLICIT_CONVERSION /* no support */
-#endif
-
-/*
* MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
* method decorated with it must never be inlined, even if the compiler would
* otherwise choose to inline the method. Compilers aren't absolutely
@@ -318,37 +238,48 @@
#endif
/**
- * MOZ_WARN_UNUSED_RESULT tells the compiler to emit a warning if a function's
+ * MOZ_MUST_USE tells the compiler to emit a warning if a function's
* return value is not used by the caller.
*
- * Place this attribute at the very beginning of a function definition. For
+ * Place this attribute at the very beginning of a function declaration. For
* example, write
*
- * MOZ_WARN_UNUSED_RESULT int foo();
+ * MOZ_MUST_USE int foo();
*
* or
*
- * MOZ_WARN_UNUSED_RESULT int foo() { return 42; }
+ * MOZ_MUST_USE int foo() { return 42; }
*/
#if defined(__GNUC__) || defined(__clang__)
-# define MOZ_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+# define MOZ_MUST_USE __attribute__ ((warn_unused_result))
#else
-# define MOZ_WARN_UNUSED_RESULT
+# define MOZ_MUST_USE
#endif
/**
* MOZ_FALLTHROUGH is an annotation to suppress compiler warnings about switch
* cases that fall through without a break or return statement. MOZ_FALLTHROUGH
- * is only needed on cases that have code:
+ * is only needed on cases that have code.
+ *
+ * MOZ_FALLTHROUGH_ASSERT is an annotation to suppress compiler warnings about
+ * switch cases that MOZ_ASSERT(false) (or its alias MOZ_ASSERT_UNREACHABLE) in
+ * debug builds, but intentionally fall through in release builds. See comment
+ * in Assertions.h for more details.
*
* switch (foo) {
* case 1: // These cases have no code. No fallthrough annotations are needed.
* case 2:
- * case 3:
- * foo = 4; // This case has code, so a fallthrough annotation is needed:
+ * case 3: // This case has code, so a fallthrough annotation is needed!
+ * foo++;
* MOZ_FALLTHROUGH;
- * default:
+ * case 4:
* return foo;
+ *
+ * default:
+ * // This case asserts in debug builds, falls through in release.
+ * MOZ_FALLTHROUGH_ASSERT("Unexpected foo value?!");
+ * case 5:
+ * return 5;
* }
*/
#if defined(__clang__) && __cplusplus >= 201103L
@@ -451,10 +382,12 @@
* intended to prevent introducing static initializers. This attribute
* currently makes it a compile-time error to instantiate these classes
* anywhere other than at the global scope, or as a static member of a class.
+ * In non-debug mode, it also prohibits non-trivial constructors and
+ * destructors.
* MOZ_TRIVIAL_CTOR_DTOR: Applies to all classes that must have both a trivial
- * constructor and a trivial destructor. Setting this attribute on a class
- * makes it a compile-time error for that class to get a non-trivial
- * constructor or destructor for any reason.
+ * or constexpr constructor and a trivial destructor. Setting this attribute
+ * on a class makes it a compile-time error for that class to get a
+ * non-trivial constructor or destructor for any reason.
* MOZ_HEAP_ALLOCATOR: Applies to any function. This indicates that the return
* value is allocated on the heap, and will as a result check such allocations
* during MOZ_STACK_CLASS and MOZ_NONHEAP_CLASS annotation checking.
@@ -500,9 +433,9 @@
* function. This is intended to be used with operator->() of our smart
* pointer classes to ensure that the refcount of an object wrapped in a
* smart pointer is not manipulated directly.
- * MOZ_MUST_USE: Applies to type declarations. Makes it a compile time error to not
- * use the return value of a function which has this type. This is intended to be
- * used with types which it is an error to not use.
+ * MOZ_MUST_USE_TYPE: Applies to type declarations. Makes it a compile time
+ * error to not use the return value of a function which has this type. This
+ * is intended to be used with types which it is an error to not use.
* MOZ_NEEDS_NO_VTABLE_TYPE: Applies to template class declarations. Makes it
* a compile time error to instantiate this template with a type parameter which
* has a VTable.
@@ -512,14 +445,35 @@
* template arguments are required to be safe to move in memory using
* memmove(). Passing MOZ_NON_MEMMOVABLE types to these templates is a
* compile time error.
+ * MOZ_NEEDS_MEMMOVABLE_MEMBERS: Applies to class declarations where each member
+ * must be safe to move in memory using memmove(). MOZ_NON_MEMMOVABLE types
+ * used in members of these classes are compile time errors.
* MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS: Applies to template class
* declarations where an instance of the template should be considered, for
* static analysis purposes, to inherit any type annotations (such as
- * MOZ_MUST_USE and MOZ_STACK_CLASS) from its template arguments.
+ * MOZ_MUST_USE_TYPE and MOZ_STACK_CLASS) from its template arguments.
+ * MOZ_INIT_OUTSIDE_CTOR: Applies to class member declarations. Occasionally
+ * there are class members that are not initialized in the constructor,
+ * but logic elsewhere in the class ensures they are initialized prior to use.
+ * Using this attribute on a member disables the check that this member must be
+ * initialized in constructors via list-initialization, in the constructor body,
+ * or via functions called from the constructor body.
+ * MOZ_IS_CLASS_INIT: Applies to class method declarations. Occasionally the
+ * constructor doesn't initialize all of the member variables and another function
+ * is used to initialize the rest. This marker is used to make the static analysis
+ * tool aware that the marked function is part of the initialization process
+ * and to include the marked function in the scan mechanism that determines witch
+ * member variables still remain uninitialized.
+ * MOZ_NON_PARAM: Applies to types. Makes it compile time error to use the type
+ * in parameter without pointer or reference.
* MOZ_NON_AUTOABLE: Applies to class declarations. Makes it a compile time error to
* use `auto` in place of this type in variable declarations. This is intended to
* be used with types which are intended to be implicitly constructed into other
* other types before being assigned to variables.
+ * MOZ_REQUIRED_BASE_METHOD: Applies to virtual class method declarations.
+ * Sometimes derived classes override methods that need to be called by their
+ * overridden counterparts. This marker indicates that the marked method must
+ * be called by the method that it overrides.
*/
#ifdef MOZ_CLANG_PLUGIN
# define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
@@ -541,13 +495,22 @@
# define MOZ_NON_OWNING_REF __attribute__((annotate("moz_weak_ref")))
# define MOZ_UNSAFE_REF(reason) __attribute__((annotate("moz_weak_ref")))
# define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return")))
-# define MOZ_MUST_USE __attribute__((annotate("moz_must_use")))
+# define MOZ_MUST_USE_TYPE __attribute__((annotate("moz_must_use_type")))
# define MOZ_NEEDS_NO_VTABLE_TYPE __attribute__((annotate("moz_needs_no_vtable_type")))
# define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
# define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
+# define MOZ_NEEDS_MEMMOVABLE_MEMBERS __attribute__((annotate("moz_needs_memmovable_members")))
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS \
__attribute__((annotate("moz_inherit_type_annotations_from_template_args")))
# define MOZ_NON_AUTOABLE __attribute__((annotate("moz_non_autoable")))
+# define MOZ_INIT_OUTSIDE_CTOR \
+ __attribute__((annotate("moz_ignore_ctor_initialization")))
+# define MOZ_IS_CLASS_INIT \
+ __attribute__((annotate("moz_is_class_init")))
+# define MOZ_NON_PARAM \
+ __attribute__((annotate("moz_non_param")))
+# define MOZ_REQUIRED_BASE_METHOD \
+ __attribute__((annotate("moz_required_base_method")))
/*
* It turns out that clang doesn't like void func() __attribute__ {} without a
* warning, so use pragmas to disable the warning. This code won't work on GCC
@@ -573,12 +536,17 @@
# define MOZ_NON_OWNING_REF /* nothing */
# define MOZ_UNSAFE_REF(reason) /* nothing */
# define MOZ_NO_ADDREF_RELEASE_ON_RETURN /* nothing */
-# define MOZ_MUST_USE /* nothing */
+# define MOZ_MUST_USE_TYPE /* nothing */
# define MOZ_NEEDS_NO_VTABLE_TYPE /* nothing */
# define MOZ_NON_MEMMOVABLE /* nothing */
# define MOZ_NEEDS_MEMMOVABLE_TYPE /* nothing */
+# define MOZ_NEEDS_MEMMOVABLE_MEMBERS /* nothing */
# define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS /* nothing */
+# define MOZ_INIT_OUTSIDE_CTOR /* nothing */
+# define MOZ_IS_CLASS_INIT /* nothing */
+# define MOZ_NON_PARAM /* nothing */
# define MOZ_NON_AUTOABLE /* nothing */
+# define MOZ_REQUIRED_BASE_METHOD /* nothing */
#endif /* MOZ_CLANG_PLUGIN */
#define MOZ_RAII MOZ_NON_TEMPORARY_CLASS MOZ_STACK_CLASS
@@ -601,4 +569,36 @@
#endif /* __cplusplus */
+/**
+ * Printf style formats. MOZ_FORMAT_PRINTF can be used to annotate a
+ * function or method that is "printf-like"; this will let (some)
+ * compilers check that the arguments match the template string.
+ *
+ * This macro takes two arguments. The first argument is the argument
+ * number of the template string. The second argument is the argument
+ * number of the '...' argument holding the arguments.
+ *
+ * Argument numbers start at 1. Note that the implicit "this"
+ * argument of a non-static member function counts as an argument.
+ *
+ * So, for a simple case like:
+ * void print_something (int whatever, const char *fmt, ...);
+ * The corresponding annotation would be
+ * MOZ_FORMAT_PRINTF(2, 3)
+ * However, if "print_something" were a non-static member function,
+ * then the annotation would be:
+ * MOZ_FORMAT_PRINTF(3, 4)
+ *
+ * Note that the checking is limited to standards-conforming
+ * printf-likes, and in particular this should not be used for
+ * PR_snprintf and friends, which are "printf-like" but which assign
+ * different meanings to the various formats.
+ */
+#ifdef __GNUC__
+#define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck) \
+ __attribute__ ((format (printf, stringIndex, firstToCheck)))
+#else
+#define MOZ_FORMAT_PRINTF(stringIndex, firstToCheck)
+#endif
+
#endif /* mozilla_Attributes_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/BinarySearch.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/BinarySearch.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/BinarySearch.h
@@ -31,7 +31,7 @@
* printf("found 13 at %lu\n", match);
* }
*
- * The BinarySearchIf() version behaves similar, but takes |aComparator|, a
+ * The BinarySearchIf() version behaves similarly, but takes |aComparator|, a
* functor to compare the values with, instead of a value to find.
* That functor should take one argument - the value to compare - and return an
* |int| with the comparison result:
@@ -45,13 +45,13 @@
* Example:
*
* struct Comparator {
- * int operator()(int val) const {
- * if (mTarget < val) return -1;
- * if (mValue > val) return 1;
+ * int operator()(int aVal) const {
+ * if (mTarget < aVal) { return -1; }
+ * if (mTarget > aVal) { return 1; }
* return 0;
* }
- * Comparator(int target) : mTarget(target) {}
- const int mTarget;
+ * explicit Comparator(int aTarget) : mTarget(aTarget) {}
+ * const int mTarget;
* };
*
* Vector<int> sortedInts = ...
@@ -106,12 +106,12 @@
{}
template <class U>
- int operator()(const U& val) const {
- if (mTarget == val) {
+ int operator()(const U& aVal) const {
+ if (mTarget == aVal) {
return 0;
}
- if (mTarget < val) {
+ if (mTarget < aVal) {
return -1;
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/BufferList.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/BufferList.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/BufferList.h
@@ -0,0 +1,568 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_BufferList_h
+#define mozilla_BufferList_h
+
+#include <algorithm>
+#include "mozilla/AllocPolicy.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Move.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/Types.h"
+#include "mozilla/TypeTraits.h"
+#include "mozilla/Vector.h"
+#include <string.h>
+
+// Undo potential #include <windows.h> damage to be able to use std::min.
+#undef min
+
+// BufferList represents a sequence of buffers of data. A BufferList can choose
+// to own its buffers or not. The class handles writing to the buffers,
+// iterating over them, and reading data out. Unlike SegmentedVector, the
+// buffers may be of unequal size. Like SegmentedVector, BufferList is a nice
+// way to avoid large contiguous allocations (which can trigger OOMs).
+
+namespace mozilla {
+
+template<typename AllocPolicy>
+class BufferList : private AllocPolicy
+{
+ // Each buffer in a BufferList has a size and a capacity. The first mSize
+ // bytes are initialized and the remaining |mCapacity - mSize| bytes are free.
+ struct Segment
+ {
+ char* mData;
+ size_t mSize;
+ size_t mCapacity;
+
+ Segment(char* aData, size_t aSize, size_t aCapacity)
+ : mData(aData),
+ mSize(aSize),
+ mCapacity(aCapacity)
+ {
+ }
+
+ Segment(const Segment&) = delete;
+ Segment& operator=(const Segment&) = delete;
+
+ Segment(Segment&&) = default;
+ Segment& operator=(Segment&&) = default;
+
+ char* Start() const { return mData; }
+ char* End() const { return mData + mSize; }
+ };
+
+ template<typename OtherAllocPolicy>
+ friend class BufferList;
+
+ public:
+ // For the convenience of callers, all segments are required to be a multiple
+ // of 8 bytes in capacity. Also, every buffer except the last one is required
+ // to be full (i.e., size == capacity). Therefore, a byte at offset N within
+ // the BufferList and stored in memory at an address A will satisfy
+ // (N % Align == A % Align) if Align == 2, 4, or 8.
+ static const size_t kSegmentAlignment = 8;
+
+ // Allocate a BufferList. The BufferList will free all its buffers when it is
+ // destroyed. An initial buffer of size aInitialSize and capacity
+ // aInitialCapacity is allocated automatically. This data will be contiguous
+ // an can be accessed via |Start()|. Subsequent buffers will be allocated with
+ // capacity aStandardCapacity.
+ BufferList(size_t aInitialSize,
+ size_t aInitialCapacity,
+ size_t aStandardCapacity,
+ AllocPolicy aAP = AllocPolicy())
+ : AllocPolicy(aAP),
+ mOwning(true),
+ mSegments(aAP),
+ mSize(0),
+ mStandardCapacity(aStandardCapacity)
+ {
+ MOZ_ASSERT(aInitialCapacity % kSegmentAlignment == 0);
+ MOZ_ASSERT(aStandardCapacity % kSegmentAlignment == 0);
+
+ if (aInitialCapacity) {
+ AllocateSegment(aInitialSize, aInitialCapacity);
+ }
+ }
+
+ BufferList(const BufferList& aOther) = delete;
+
+ BufferList(BufferList&& aOther)
+ : mOwning(aOther.mOwning),
+ mSegments(Move(aOther.mSegments)),
+ mSize(aOther.mSize),
+ mStandardCapacity(aOther.mStandardCapacity)
+ {
+ aOther.mSegments.clear();
+ aOther.mSize = 0;
+ }
+
+ BufferList& operator=(const BufferList& aOther) = delete;
+
+ BufferList& operator=(BufferList&& aOther)
+ {
+ Clear();
+
+ mOwning = aOther.mOwning;
+ mSegments = Move(aOther.mSegments);
+ mSize = aOther.mSize;
+ aOther.mSegments.clear();
+ aOther.mSize = 0;
+ return *this;
+ }
+
+ ~BufferList() { Clear(); }
+
+ // Returns the sum of the sizes of all the buffers.
+ size_t Size() const { return mSize; }
+
+ void Clear()
+ {
+ if (mOwning) {
+ for (Segment& segment : mSegments) {
+ this->free_(segment.mData);
+ }
+ }
+ mSegments.clear();
+
+ mSize = 0;
+ }
+
+ // Iterates over bytes in the segments. You can advance it by as many bytes as
+ // you choose.
+ class IterImpl
+ {
+ // Invariants:
+ // (0) mSegment <= bufferList.mSegments.size()
+ // (1) mData <= mDataEnd
+ // (2) If mSegment is not the last segment, mData < mDataEnd
+ uintptr_t mSegment;
+ char* mData;
+ char* mDataEnd;
+
+ friend class BufferList;
+
+ public:
+ explicit IterImpl(const BufferList& aBuffers)
+ : mSegment(0),
+ mData(nullptr),
+ mDataEnd(nullptr)
+ {
+ if (!aBuffers.mSegments.empty()) {
+ mData = aBuffers.mSegments[0].Start();
+ mDataEnd = aBuffers.mSegments[0].End();
+ }
+ }
+
+ // Returns a pointer to the raw data. It is valid to access up to
+ // RemainingInSegment bytes of this buffer.
+ char* Data() const
+ {
+ MOZ_RELEASE_ASSERT(!Done());
+ return mData;
+ }
+
+ // Returns true if the memory in the range [Data(), Data() + aBytes) is all
+ // part of one contiguous buffer.
+ bool HasRoomFor(size_t aBytes) const
+ {
+ MOZ_RELEASE_ASSERT(mData <= mDataEnd);
+ return size_t(mDataEnd - mData) >= aBytes;
+ }
+
+ // Returns the maximum value aBytes for which HasRoomFor(aBytes) will be
+ // true.
+ size_t RemainingInSegment() const
+ {
+ MOZ_RELEASE_ASSERT(mData <= mDataEnd);
+ return mDataEnd - mData;
+ }
+
+ // Advances the iterator by aBytes bytes. aBytes must be less than
+ // RemainingInSegment(). If advancing by aBytes takes the iterator to the
+ // end of a buffer, it will be moved to the beginning of the next buffer
+ // unless it is the last buffer.
+ void Advance(const BufferList& aBuffers, size_t aBytes)
+ {
+ const Segment& segment = aBuffers.mSegments[mSegment];
+ MOZ_RELEASE_ASSERT(segment.Start() <= mData);
+ MOZ_RELEASE_ASSERT(mData <= mDataEnd);
+ MOZ_RELEASE_ASSERT(mDataEnd == segment.End());
+
+ MOZ_RELEASE_ASSERT(HasRoomFor(aBytes));
+ mData += aBytes;
+
+ if (mData == mDataEnd && mSegment + 1 < aBuffers.mSegments.length()) {
+ mSegment++;
+ const Segment& nextSegment = aBuffers.mSegments[mSegment];
+ mData = nextSegment.Start();
+ mDataEnd = nextSegment.End();
+ MOZ_RELEASE_ASSERT(mData < mDataEnd);
+ }
+ }
+
+ // Advance the iterator by aBytes, possibly crossing segments. This function
+ // returns false if it runs out of buffers to advance through. Otherwise it
+ // returns true.
+ bool AdvanceAcrossSegments(const BufferList& aBuffers, size_t aBytes)
+ {
+ size_t bytes = aBytes;
+ while (bytes) {
+ size_t toAdvance = std::min(bytes, RemainingInSegment());
+ if (!toAdvance) {
+ return false;
+ }
+ Advance(aBuffers, toAdvance);
+ bytes -= toAdvance;
+ }
+ return true;
+ }
+
+ // Returns true when the iterator reaches the end of the BufferList.
+ bool Done() const
+ {
+ return mData == mDataEnd;
+ }
+
+ private:
+
+ // Count the bytes we would need to advance in order to reach aTarget.
+ size_t BytesUntil(const BufferList& aBuffers, const IterImpl& aTarget) const {
+ size_t offset = 0;
+
+ MOZ_ASSERT(aTarget.IsIn(aBuffers));
+
+ char* data = mData;
+ for (uintptr_t segment = mSegment; segment < aTarget.mSegment; segment++) {
+ offset += aBuffers.mSegments[segment].End() - data;
+ data = aBuffers.mSegments[segment].mData;
+ }
+
+ MOZ_RELEASE_ASSERT(IsIn(aBuffers));
+ MOZ_RELEASE_ASSERT(aTarget.mData >= data);
+
+ offset += aTarget.mData - data;
+ return offset;
+ }
+
+ bool IsIn(const BufferList& aBuffers) const {
+ return mSegment < aBuffers.mSegments.length() &&
+ mData >= aBuffers.mSegments[mSegment].mData &&
+ mData < aBuffers.mSegments[mSegment].End();
+ }
+ };
+
+ // Special convenience method that returns Iter().Data().
+ char* Start() { return mSegments[0].mData; }
+ const char* Start() const { return mSegments[0].mData; }
+
+ IterImpl Iter() const { return IterImpl(*this); }
+
+ // Copies aSize bytes from aData into the BufferList. The storage for these
+ // bytes may be split across multiple buffers. Size() is increased by aSize.
+ inline bool WriteBytes(const char* aData, size_t aSize);
+
+ // Copies possibly non-contiguous byte range starting at aIter into
+ // aData. aIter is advanced by aSize bytes. Returns false if it runs out of
+ // data before aSize.
+ inline bool ReadBytes(IterImpl& aIter, char* aData, size_t aSize) const;
+
+ // Return a new BufferList that shares storage with this BufferList. The new
+ // BufferList is read-only. It allows iteration over aSize bytes starting at
+ // aIter. Borrow can fail, in which case *aSuccess will be false upon
+ // return. The borrowed BufferList can use a different AllocPolicy than the
+ // original one. However, it is not responsible for freeing buffers, so the
+ // AllocPolicy is only used for the buffer vector.
+ template<typename BorrowingAllocPolicy>
+ BufferList<BorrowingAllocPolicy> Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
+ BorrowingAllocPolicy aAP = BorrowingAllocPolicy()) const;
+
+ // Return a new BufferList and move storage from this BufferList to it. The
+ // new BufferList owns the buffers. Move can fail, in which case *aSuccess
+ // will be false upon return. The new BufferList can use a different
+ // AllocPolicy than the original one. The new OtherAllocPolicy is responsible
+ // for freeing buffers, so the OtherAllocPolicy must use freeing method
+ // compatible to the original one.
+ template<typename OtherAllocPolicy>
+ BufferList<OtherAllocPolicy> MoveFallible(bool* aSuccess, OtherAllocPolicy aAP = OtherAllocPolicy());
+
+ // Return a new BufferList that adopts the byte range starting at Iter so that
+ // range [aIter, aIter + aSize) is transplanted to the returned BufferList.
+ // Contents of the buffer before aIter + aSize is left undefined.
+ // Extract can fail, in which case *aSuccess will be false upon return. The
+ // moved buffers are erased from the original BufferList. In case of extract
+ // fails, the original BufferList is intact. All other iterators except aIter
+ // are invalidated.
+ // This method requires aIter and aSize to be 8-byte aligned.
+ BufferList Extract(IterImpl& aIter, size_t aSize, bool* aSuccess);
+
+ // Return the number of bytes from 'start' to 'end', two iterators within
+ // this BufferList.
+ size_t RangeLength(const IterImpl& start, const IterImpl& end) const {
+ MOZ_ASSERT(start.IsIn(*this) && end.IsIn(*this));
+ return start.BytesUntil(*this, end);
+ }
+
+private:
+ explicit BufferList(AllocPolicy aAP)
+ : AllocPolicy(aAP),
+ mOwning(false),
+ mSize(0),
+ mStandardCapacity(0)
+ {
+ }
+
+ void* AllocateSegment(size_t aSize, size_t aCapacity)
+ {
+ MOZ_RELEASE_ASSERT(mOwning);
+
+ char* data = this->template pod_malloc<char>(aCapacity);
+ if (!data) {
+ return nullptr;
+ }
+ if (!mSegments.append(Segment(data, aSize, aCapacity))) {
+ this->free_(data);
+ return nullptr;
+ }
+ mSize += aSize;
+ return data;
+ }
+
+ bool mOwning;
+ Vector<Segment, 1, AllocPolicy> mSegments;
+ size_t mSize;
+ size_t mStandardCapacity;
+};
+
+template<typename AllocPolicy>
+bool
+BufferList<AllocPolicy>::WriteBytes(const char* aData, size_t aSize)
+{
+ MOZ_RELEASE_ASSERT(mOwning);
+ MOZ_RELEASE_ASSERT(mStandardCapacity);
+
+ size_t copied = 0;
+ size_t remaining = aSize;
+
+ if (!mSegments.empty()) {
+ Segment& lastSegment = mSegments.back();
+
+ size_t toCopy = std::min(aSize, lastSegment.mCapacity - lastSegment.mSize);
+ memcpy(lastSegment.mData + lastSegment.mSize, aData, toCopy);
+ lastSegment.mSize += toCopy;
+ mSize += toCopy;
+
+ copied += toCopy;
+ remaining -= toCopy;
+ }
+
+ while (remaining) {
+ size_t toCopy = std::min(remaining, mStandardCapacity);
+
+ void* data = AllocateSegment(toCopy, mStandardCapacity);
+ if (!data) {
+ return false;
+ }
+ memcpy(data, aData + copied, toCopy);
+
+ copied += toCopy;
+ remaining -= toCopy;
+ }
+
+ return true;
+}
+
+template<typename AllocPolicy>
+bool
+BufferList<AllocPolicy>::ReadBytes(IterImpl& aIter, char* aData, size_t aSize) const
+{
+ size_t copied = 0;
+ size_t remaining = aSize;
+ while (remaining) {
+ size_t toCopy = std::min(aIter.RemainingInSegment(), remaining);
+ if (!toCopy) {
+ // We've run out of data in the last segment.
+ return false;
+ }
+ memcpy(aData + copied, aIter.Data(), toCopy);
+ copied += toCopy;
+ remaining -= toCopy;
+
+ aIter.Advance(*this, toCopy);
+ }
+
+ return true;
+}
+
+template<typename AllocPolicy> template<typename BorrowingAllocPolicy>
+BufferList<BorrowingAllocPolicy>
+BufferList<AllocPolicy>::Borrow(IterImpl& aIter, size_t aSize, bool* aSuccess,
+ BorrowingAllocPolicy aAP) const
+{
+ BufferList<BorrowingAllocPolicy> result(aAP);
+
+ size_t size = aSize;
+ while (size) {
+ size_t toAdvance = std::min(size, aIter.RemainingInSegment());
+
+ if (!toAdvance || !result.mSegments.append(typename BufferList<BorrowingAllocPolicy>::Segment(aIter.mData, toAdvance, toAdvance))) {
+ *aSuccess = false;
+ return result;
+ }
+ aIter.Advance(*this, toAdvance);
+ size -= toAdvance;
+ }
+
+ result.mSize = aSize;
+ *aSuccess = true;
+ return result;
+}
+
+template<typename AllocPolicy> template<typename OtherAllocPolicy>
+BufferList<OtherAllocPolicy>
+BufferList<AllocPolicy>::MoveFallible(bool* aSuccess, OtherAllocPolicy aAP)
+{
+ BufferList<OtherAllocPolicy> result(0, 0, mStandardCapacity, aAP);
+
+ IterImpl iter = Iter();
+ while (!iter.Done()) {
+ size_t toAdvance = iter.RemainingInSegment();
+
+ if (!toAdvance || !result.mSegments.append(typename BufferList<OtherAllocPolicy>::Segment(iter.mData, toAdvance, toAdvance))) {
+ *aSuccess = false;
+ result.mSegments.clear();
+ return result;
+ }
+ iter.Advance(*this, toAdvance);
+ }
+
+ result.mSize = mSize;
+ mSegments.clear();
+ mSize = 0;
+ *aSuccess = true;
+ return result;
+}
+
+template<typename AllocPolicy>
+BufferList<AllocPolicy>
+BufferList<AllocPolicy>::Extract(IterImpl& aIter, size_t aSize, bool* aSuccess)
+{
+ MOZ_RELEASE_ASSERT(aSize);
+ MOZ_RELEASE_ASSERT(mOwning);
+ MOZ_ASSERT(aSize % kSegmentAlignment == 0);
+ MOZ_ASSERT(intptr_t(aIter.mData) % kSegmentAlignment == 0);
+
+ auto failure = [this, aSuccess]() {
+ *aSuccess = false;
+ return BufferList(0, 0, mStandardCapacity);
+ };
+
+ // Number of segments we'll need to copy data from to satisfy the request.
+ size_t segmentsNeeded = 0;
+ // If this is None then the last segment is a full segment, otherwise we need
+ // to copy this many bytes.
+ Maybe<size_t> lastSegmentSize;
+ {
+ // Copy of the iterator to walk the BufferList and see how many segments we
+ // need to copy.
+ IterImpl iter = aIter;
+ size_t remaining = aSize;
+ while (!iter.Done() && remaining &&
+ remaining >= iter.RemainingInSegment()) {
+ remaining -= iter.RemainingInSegment();
+ iter.Advance(*this, iter.RemainingInSegment());
+ segmentsNeeded++;
+ }
+
+ if (remaining) {
+ if (iter.Done()) {
+ // We reached the end of the BufferList and there wasn't enough data to
+ // satisfy the request.
+ return failure();
+ }
+ lastSegmentSize.emplace(remaining);
+ // The last block also counts as a segment. This makes the conditionals
+ // on segmentsNeeded work in the rest of the function.
+ segmentsNeeded++;
+ }
+ }
+
+ BufferList result(0, 0, mStandardCapacity);
+ if (!result.mSegments.reserve(segmentsNeeded + lastSegmentSize.isSome())) {
+ return failure();
+ }
+
+ // Copy the first segment, it's special because we can't just steal the
+ // entire Segment struct from this->mSegments.
+ size_t firstSegmentSize = std::min(aSize, aIter.RemainingInSegment());
+ if (!result.WriteBytes(aIter.Data(), firstSegmentSize)) {
+ return failure();
+ }
+ aIter.Advance(*this, firstSegmentSize);
+ segmentsNeeded--;
+
+ // The entirety of the request wasn't in the first segment, now copy the
+ // rest.
+ if (segmentsNeeded) {
+ char* finalSegment = nullptr;
+ // Pre-allocate the final segment so that if this fails, we return before
+ // we delete the elements from |this->mSegments|.
+ if (lastSegmentSize.isSome()) {
+ MOZ_RELEASE_ASSERT(mStandardCapacity >= *lastSegmentSize);
+ finalSegment = this->template pod_malloc<char>(mStandardCapacity);
+ if (!finalSegment) {
+ return failure();
+ }
+ }
+
+ size_t copyStart = aIter.mSegment;
+ // Copy segments from this over to the result and remove them from our
+ // storage. Not needed if the only segment we need to copy is the last
+ // partial one.
+ size_t segmentsToCopy = segmentsNeeded - lastSegmentSize.isSome();
+ for (size_t i = 0; i < segmentsToCopy; ++i) {
+ result.mSegments.infallibleAppend(
+ Segment(mSegments[aIter.mSegment].mData,
+ mSegments[aIter.mSegment].mSize,
+ mSegments[aIter.mSegment].mCapacity));
+ aIter.Advance(*this, aIter.RemainingInSegment());
+ }
+ // Due to the way IterImpl works, there are two cases here: (1) if we've
+ // consumed the entirety of the BufferList, then the iterator is pointed at
+ // the end of the final segment, (2) otherwise it is pointed at the start
+ // of the next segment. We want to verify that we really consumed all
+ // |segmentsToCopy| segments.
+ MOZ_RELEASE_ASSERT(
+ (aIter.mSegment == copyStart + segmentsToCopy) ||
+ (aIter.Done() && aIter.mSegment == copyStart + segmentsToCopy - 1));
+ mSegments.erase(mSegments.begin() + copyStart,
+ mSegments.begin() + copyStart + segmentsToCopy);
+
+ // Reset the iter's position for what we just deleted.
+ aIter.mSegment -= segmentsToCopy;
+
+ if (lastSegmentSize.isSome()) {
+ // We called reserve() on result.mSegments so infallibleAppend is safe.
+ result.mSegments.infallibleAppend(
+ Segment(finalSegment, 0, mStandardCapacity));
+ bool r = result.WriteBytes(aIter.Data(), *lastSegmentSize);
+ MOZ_RELEASE_ASSERT(r);
+ aIter.Advance(*this, *lastSegmentSize);
+ }
+ }
+
+ mSize -= aSize;
+ result.mSize = aSize;
+
+ *aSuccess = true;
+ return result;
+}
+
+} // namespace mozilla
+
+#endif /* mozilla_BufferList_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Casting.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Casting.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Casting.h
@@ -17,16 +17,29 @@
namespace mozilla {
/**
- * Return a value of type |To|, containing the underlying bit pattern of
+ * Sets the outparam value of type |To| with the same underlying bit pattern of
* |aFrom|.
*
* |To| and |From| must be types of the same size; be careful of cross-platform
* size differences, or this might fail to compile on some but not all
* platforms.
+ *
+ * There is also a variant that returns the value directly. In most cases, the
+ * two variants should be identical. However, in the specific case of x86
+ * chips, the behavior differs: returning floating-point values directly is done
+ * through the x87 stack, and x87 loads and stores turn signaling NaNs into
+ * quiet NaNs... silently. Returning floating-point values via outparam,
+ * however, is done entirely within the SSE registers when SSE2 floating-point
+ * is enabled in the compiler, which has semantics-preserving behavior you would
+ * expect.
+ *
+ * If preserving the distinction between signaling NaNs and quiet NaNs is
+ * important to you, you should use the outparam version. In all other cases,
+ * you should use the direct return version.
*/
template<typename To, typename From>
-inline To
-BitwiseCast(const From aFrom)
+inline void
+BitwiseCast(const From aFrom, To* aResult)
{
static_assert(sizeof(From) == sizeof(To),
"To and From must have the same size");
@@ -36,7 +49,16 @@
To mTo;
} u;
u.mFrom = aFrom;
- return u.mTo;
+ *aResult = u.mTo;
+}
+
+template<typename To, typename From>
+inline To
+BitwiseCast(const From aFrom)
+{
+ To temp;
+ BitwiseCast<To, From>(aFrom, &temp);
+ return temp;
}
namespace detail {
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ChaosMode.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ChaosMode.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ChaosMode.h
@@ -27,6 +27,8 @@
IOAmounts = 0x8,
// Iterate over hash tables in random order.
HashTableIteration = 0x10,
+ // Randomly refuse to use cached version of image (when allowed by spec).
+ ImageCache = 0x20,
Any = 0xffffffff,
};
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Char16.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Char16.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Char16.h
@@ -17,38 +17,8 @@
* is a 16-bit code unit of a Unicode code point, not a "character".
*/
-#if defined(_MSC_VER) && _MSC_VER < 1900
- /*
- * C++11 says char16_t is a distinct builtin type, but Windows's yvals.h
- * typedefs char16_t as an unsigned short prior to MSVC 2015, which
- * implemented C++11's distinct char16_t type. We would like to alias
- * char16_t to Windows's 16-bit wchar_t so we can declare UTF-16 literals as
- * constant expressions (and pass char16_t pointers to Windows APIs). We
- * #define _CHAR16T here in order to prevent yvals.h from overriding our
- * char16_t typedefs, which we set to wchar_t for C++ code.
- *
- * In addition, #defining _CHAR16T will prevent yvals.h from defining a
- * char32_t type, so we have to undo that damage here and provide our own,
- * which is identical to the yvals.h type.
- */
-# define MOZ_UTF16_HELPER(s) L##s
-# define _CHAR16T
-typedef wchar_t char16_t;
-typedef unsigned int char32_t;
-#else
- /* C++11 has a builtin char16_t type. */
-# define MOZ_UTF16_HELPER(s) u##s
- /**
- * This macro is used to distinguish when char16_t would be a distinct
- * typedef from wchar_t.
- */
-# define MOZ_CHAR16_IS_NOT_WCHAR
-# ifdef WIN32
-# define MOZ_USE_CHAR16_WRAPPER
-# endif
-#endif
-
-#ifdef MOZ_USE_CHAR16_WRAPPER
+#ifdef WIN32
+# define MOZ_USE_CHAR16_WRAPPER
# include <cstdint>
/**
* Win32 API extensively uses wchar_t, which is represented by a separated
@@ -214,20 +184,10 @@
#endif
-/*
- * Macro arguments used in concatenation or stringification won't be expanded.
- * Therefore, in order for |MOZ_UTF16(FOO)| to work as expected (which is to
- * expand |FOO| before doing whatever |MOZ_UTF16| needs to do to it) a helper
- * macro, |MOZ_UTF16_HELPER| needs to be inserted in between to allow the macro
- * argument to expand. See "3.10.6 Separate Expansion of Macro Arguments" of the
- * CPP manual for a more accurate and precise explanation.
- */
-#define MOZ_UTF16(s) MOZ_UTF16_HELPER(s)
-
static_assert(sizeof(char16_t) == 2, "Is char16_t type 16 bits?");
static_assert(char16_t(-1) > char16_t(0), "Is char16_t type unsigned?");
-static_assert(sizeof(MOZ_UTF16('A')) == 2, "Is char literal 16 bits?");
-static_assert(sizeof(MOZ_UTF16("")[0]) == 2, "Is string char 16 bits?");
+static_assert(sizeof(u'A') == 2, "Is unicode char literal 16 bits?");
+static_assert(sizeof(u""[0]) == 2, "Is unicode string char 16 bits?");
#endif
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Compiler.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Compiler.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Compiler.h
@@ -10,21 +10,24 @@
#define mozilla_Compiler_h
#define MOZ_IS_GCC 0
-#define MOS_IS_MSVC 0
+#define MOZ_IS_MSVC 0
#if !defined(__clang__) && defined(__GNUC__)
# undef MOZ_IS_GCC
# define MOZ_IS_GCC 1
/*
- * This macro should simplify gcc version checking. For example, to check
+ * These macros should simplify gcc version checking. For example, to check
* for gcc 4.7.1 or later, check `#if MOZ_GCC_VERSION_AT_LEAST(4, 7, 1)`.
*/
# define MOZ_GCC_VERSION_AT_LEAST(major, minor, patchlevel) \
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
>= ((major) * 10000 + (minor) * 100 + (patchlevel)))
-# if !MOZ_GCC_VERSION_AT_LEAST(4, 7, 0)
-# error "mfbt (and Gecko) require at least gcc 4.7 to build."
+# define MOZ_GCC_VERSION_AT_MOST(major, minor, patchlevel) \
+ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
+ <= ((major) * 10000 + (minor) * 100 + (patchlevel)))
+# if !MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
+# error "mfbt (and Gecko) require at least gcc 4.8 to build."
# endif
#elif defined(_MSC_VER)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Compression.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Compression.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Compression.h
@@ -61,8 +61,7 @@
/**
* If the source stream is malformed, the function will stop decoding
- * and return a negative result, indicating the byte position of the
- * faulty instruction
+ * and return false.
*
* This function never writes outside of provided buffers, and never
* modifies input buffer.
@@ -71,9 +70,9 @@
* minimum of |aOutputSize| bytes.
*
* @param aOutputSize is the output size, therefore the original size
- * @return the number of bytes read in the source buffer
+ * @return true on success, false on failure
*/
- static MFBT_API bool
+ static MFBT_API MOZ_MUST_USE bool
decompress(const char* aSource, char* aDest, size_t aOutputSize);
/**
@@ -91,8 +90,9 @@
* already allocated)
* @param aOutputSize the actual number of bytes decoded in the destination
* buffer (necessarily <= aMaxOutputSize)
+ * @return true on success, false on failure
*/
- static MFBT_API bool
+ static MFBT_API MOZ_MUST_USE bool
decompress(const char* aSource, size_t aInputSize, char* aDest,
size_t aMaxOutputSize, size_t* aOutputSize);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/DebugOnly.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/DebugOnly.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/DebugOnly.h
@@ -24,17 +24,19 @@
* DebugOnly<bool> check = func();
* MOZ_ASSERT(check);
*
- * more concisely than declaring |check| conditional on #ifdef DEBUG, but also
- * without allocating storage space for |check| in release builds.
+ * more concisely than declaring |check| conditional on #ifdef DEBUG.
*
* DebugOnly instances can only be coerced to T in debug builds. In release
* builds they don't have a value, so type coercion is not well defined.
*
- * Note that DebugOnly instances still take up one byte of space, plus padding,
- * when used as members of structs.
+ * NOTE: DebugOnly instances still take up one byte of space, plus padding, even
+ * in optimized, non-DEBUG builds (see bug 1253094 comment 37 for more info).
+ * For this reason the class is MOZ_STACK_CLASS to prevent consumers using
+ * DebugOnly for struct/class members and unwittingly inflating the size of
+ * their objects in release builds.
*/
template<typename T>
-class DebugOnly
+class MOZ_STACK_CLASS DebugOnly
{
public:
#ifdef DEBUG
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Decimal.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Decimal.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Decimal.h
@@ -30,8 +30,8 @@
/**
* Imported from:
- * http://src.chromium.org/viewvc/blink/trunk/Source/core/platform/Decimal.h
- * Check hg log for the svn rev of the last update from Blink core.
+ * https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/platform/Decimal.h
+ * Check UPSTREAM-GIT-SHA for the commit ID of the last update from Blink core.
*/
#ifndef Decimal_h
@@ -48,25 +48,33 @@
#define ASSERT MOZ_ASSERT
#endif
-// To use WTF_MAKE_FAST_ALLOCATED we'd need:
-// http://src.chromium.org/viewvc/blink/trunk/Source/wtf/FastMalloc.h
+#define PLATFORM_EXPORT
+
+// To use USING_FAST_MALLOC we'd need:
+// https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/wtf/Allocator.h
// Since we don't allocate Decimal objects, no need.
-#define WTF_MAKE_FAST_ALLOCATED \
+#define USING_FAST_MALLOC(type) \
void ignore_this_dummy_method() = delete
-namespace WebCore {
+#define DISALLOW_NEW() \
+ private: \
+ void* operator new(size_t) = delete; \
+ void* operator new(size_t, void*) = delete; \
+ public:
+
+namespace blink {
namespace DecimalPrivate {
class SpecialValueHandler;
-} // namespace DecimalPrivate
+}
// This class represents decimal base floating point number.
//
// FIXME: Once all C++ compiler support decimal type, we should replace this
// class to compiler supported one. See below URI for current status of decimal
// type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
-class Decimal {
- WTF_MAKE_FAST_ALLOCATED;
+class PLATFORM_EXPORT Decimal {
+ USING_FAST_MALLOC(Decimal);
public:
enum Sign {
Positive,
@@ -75,6 +83,7 @@
// You should not use EncodedData other than unit testing.
class EncodedData {
+ DISALLOW_NEW();
// For accessing FormatClass.
friend class Decimal;
friend class DecimalPrivate::SpecialValueHandler;
@@ -93,7 +102,7 @@
bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; }
bool isZero() const { return m_formatClass == ClassZero; }
Sign sign() const { return m_sign; }
- void setSign(Sign aSign) { m_sign = aSign; }
+ void setSign(Sign sign) { m_sign = sign; }
private:
enum FormatClass {
@@ -151,7 +160,7 @@
bool isZero() const { return m_data.isZero(); }
MFBT_API Decimal abs() const;
- MFBT_API Decimal ceiling() const;
+ MFBT_API Decimal ceil() const;
MFBT_API Decimal floor() const;
MFBT_API Decimal remainder(const Decimal&) const;
MFBT_API Decimal round() const;
@@ -196,13 +205,13 @@
EncodedData m_data;
};
-} // namespace WebCore
+} // namespace blink
namespace mozilla {
- typedef WebCore::Decimal Decimal;
+typedef blink::Decimal Decimal;
} // namespace mozilla
-#undef WTF_MAKE_FAST_ALLOCATED
+#undef USING_FAST_MALLOC
#ifdef DEFINED_ASSERT_FOR_DECIMAL_H
#undef DEFINED_ASSERT_FOR_DECIMAL_H
@@ -210,4 +219,3 @@
#endif
#endif // Decimal_h
-
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Endian.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Endian.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Endian.h
@@ -1,697 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/* Functions for reading and writing integers in various endiannesses. */
-
-/*
- * The classes LittleEndian and BigEndian expose static methods for
- * reading and writing 16-, 32-, and 64-bit signed and unsigned integers
- * in their respective endianness. The naming scheme is:
- *
- * {Little,Big}Endian::{read,write}{Uint,Int}<bitsize>
- *
- * For instance, LittleEndian::readInt32 will read a 32-bit signed
- * integer from memory in little endian format. Similarly,
- * BigEndian::writeUint16 will write a 16-bit unsigned integer to memory
- * in big-endian format.
- *
- * The class NativeEndian exposes methods for conversion of existing
- * data to and from the native endianness. These methods are intended
- * for cases where data needs to be transferred, serialized, etc.
- * swap{To,From}{Little,Big}Endian byteswap a single value if necessary.
- * Bulk conversion functions are also provided which optimize the
- * no-conversion-needed case:
- *
- * - copyAndSwap{To,From}{Little,Big}Endian;
- * - swap{To,From}{Little,Big}EndianInPlace.
- *
- * The *From* variants are intended to be used for reading data and the
- * *To* variants for writing data.
- *
- * Methods on NativeEndian work with integer data of any type.
- * Floating-point data is not supported.
- *
- * For clarity in networking code, "Network" may be used as a synonym
- * for "Big" in any of the above methods or class names.
- *
- * As an example, reading a file format header whose fields are stored
- * in big-endian format might look like:
- *
- * class ExampleHeader
- * {
- * private:
- * uint32_t mMagic;
- * uint32_t mLength;
- * uint32_t mTotalRecords;
- * uint64_t mChecksum;
- *
- * public:
- * ExampleHeader(const void* data)
- * {
- * const uint8_t* ptr = static_cast<const uint8_t*>(data);
- * mMagic = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
- * mLength = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
- * mTotalRecords = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
- * mChecksum = BigEndian::readUint64(ptr);
- * }
- * ...
- * };
- */
-
-#ifndef mozilla_Endian_h
-#define mozilla_Endian_h
-
-#include "mozilla/Assertions.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/Compiler.h"
-#include "mozilla/DebugOnly.h"
-#include "mozilla/TypeTraits.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#if defined(_MSC_VER)
-# include <stdlib.h>
-# pragma intrinsic(_byteswap_ushort)
-# pragma intrinsic(_byteswap_ulong)
-# pragma intrinsic(_byteswap_uint64)
-#endif
-
-#if defined(_WIN64)
-# if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
-# define MOZ_LITTLE_ENDIAN 1
-# else
-# error "CPU type is unknown"
-# endif
-#elif defined(_WIN32)
-# if defined(_M_IX86)
-# define MOZ_LITTLE_ENDIAN 1
-# elif defined(_M_ARM)
-# define MOZ_LITTLE_ENDIAN 1
-# else
-# error "CPU type is unknown"
-# endif
-#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__) && \
- defined(__ORDER_BIG_ENDIAN__)
- /*
- * Some versions of GCC provide architecture-independent macros for
- * this. Yes, there are more than two values for __BYTE_ORDER__.
- */
-# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-# define MOZ_LITTLE_ENDIAN 1
-# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-# define MOZ_BIG_ENDIAN 1
-# else
-# error "Can't handle mixed-endian architectures"
-# 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(__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__) || \
- defined(__alpha__) || defined(__AARCH64EL__) || \
- (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
- (defined(__ia64) && !defined(__BIG_ENDIAN__))
-# define MOZ_LITTLE_ENDIAN 1
-#endif
-
-#if MOZ_BIG_ENDIAN
-# define MOZ_LITTLE_ENDIAN 0
-#elif MOZ_LITTLE_ENDIAN
-# define MOZ_BIG_ENDIAN 0
-#else
-# error "Cannot determine endianness"
-#endif
-
-#if defined(__clang__)
-# if __has_builtin(__builtin_bswap16)
-# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
-# endif
-#elif defined(__GNUC__)
-# if MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
-# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
-# endif
-#elif defined(_MSC_VER)
-# define MOZ_HAVE_BUILTIN_BYTESWAP16 _byteswap_ushort
-#endif
-
-namespace mozilla {
-
-namespace detail {
-
-/*
- * We need wrappers here because free functions with default template
- * arguments and/or partial specialization of function templates are not
- * supported by all the compilers we use.
- */
-template<typename T, size_t Size = sizeof(T)>
-struct Swapper;
-
-template<typename T>
-struct Swapper<T, 2>
-{
- static T swap(T aValue)
- {
-#if defined(MOZ_HAVE_BUILTIN_BYTESWAP16)
- return MOZ_HAVE_BUILTIN_BYTESWAP16(aValue);
-#else
- return T(((aValue & 0x00ff) << 8) | ((aValue & 0xff00) >> 8));
-#endif
- }
-};
-
-template<typename T>
-struct Swapper<T, 4>
-{
- static T swap(T aValue)
- {
-#if defined(__clang__) || defined(__GNUC__)
- return T(__builtin_bswap32(aValue));
-#elif defined(_MSC_VER)
- return T(_byteswap_ulong(aValue));
-#else
- return T(((aValue & 0x000000ffU) << 24) |
- ((aValue & 0x0000ff00U) << 8) |
- ((aValue & 0x00ff0000U) >> 8) |
- ((aValue & 0xff000000U) >> 24));
-#endif
- }
-};
-
-template<typename T>
-struct Swapper<T, 8>
-{
- static inline T swap(T aValue)
- {
-#if defined(__clang__) || defined(__GNUC__)
- return T(__builtin_bswap64(aValue));
-#elif defined(_MSC_VER)
- return T(_byteswap_uint64(aValue));
-#else
- return T(((aValue & 0x00000000000000ffULL) << 56) |
- ((aValue & 0x000000000000ff00ULL) << 40) |
- ((aValue & 0x0000000000ff0000ULL) << 24) |
- ((aValue & 0x00000000ff000000ULL) << 8) |
- ((aValue & 0x000000ff00000000ULL) >> 8) |
- ((aValue & 0x0000ff0000000000ULL) >> 24) |
- ((aValue & 0x00ff000000000000ULL) >> 40) |
- ((aValue & 0xff00000000000000ULL) >> 56));
-#endif
- }
-};
-
-enum Endianness { Little, Big };
-
-#if MOZ_BIG_ENDIAN
-# define MOZ_NATIVE_ENDIANNESS detail::Big
-#else
-# define MOZ_NATIVE_ENDIANNESS detail::Little
-#endif
-
-class EndianUtils
-{
- /**
- * Assert that the memory regions [aDest, aDest+aCount) and
- * [aSrc, aSrc+aCount] do not overlap. aCount is given in bytes.
- */
- static void assertNoOverlap(const void* aDest, const void* aSrc,
- size_t aCount)
- {
- DebugOnly<const uint8_t*> byteDestPtr = static_cast<const uint8_t*>(aDest);
- DebugOnly<const uint8_t*> byteSrcPtr = static_cast<const uint8_t*>(aSrc);
- MOZ_ASSERT((byteDestPtr <= byteSrcPtr &&
- byteDestPtr + aCount <= byteSrcPtr) ||
- (byteSrcPtr <= byteDestPtr &&
- byteSrcPtr + aCount <= byteDestPtr));
- }
-
- template<typename T>
- static void assertAligned(T* aPtr)
- {
- MOZ_ASSERT((uintptr_t(aPtr) % sizeof(T)) == 0, "Unaligned pointer!");
- }
-
-protected:
- /**
- * Return |aValue| converted from SourceEndian encoding to DestEndian
- * encoding.
- */
- template<Endianness SourceEndian, Endianness DestEndian, typename T>
- static inline T maybeSwap(T aValue)
- {
- if (SourceEndian == DestEndian) {
- return aValue;
- }
- return Swapper<T>::swap(aValue);
- }
-
- /**
- * Convert |aCount| elements at |aPtr| from SourceEndian encoding to
- * DestEndian encoding.
- */
- template<Endianness SourceEndian, Endianness DestEndian, typename T>
- static inline void maybeSwapInPlace(T* aPtr, size_t aCount)
- {
- assertAligned(aPtr);
-
- if (SourceEndian == DestEndian) {
- return;
- }
- for (size_t i = 0; i < aCount; i++) {
- aPtr[i] = Swapper<T>::swap(aPtr[i]);
- }
- }
-
- /**
- * Write |aCount| elements to the unaligned address |aDest| in DestEndian
- * format, using elements found at |aSrc| in SourceEndian format.
- */
- template<Endianness SourceEndian, Endianness DestEndian, typename T>
- static void copyAndSwapTo(void* aDest, const T* aSrc, size_t aCount)
- {
- assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
- assertAligned(aSrc);
-
- if (SourceEndian == DestEndian) {
- memcpy(aDest, aSrc, aCount * sizeof(T));
- return;
- }
-
- uint8_t* byteDestPtr = static_cast<uint8_t*>(aDest);
- for (size_t i = 0; i < aCount; ++i) {
- union
- {
- T mVal;
- uint8_t mBuffer[sizeof(T)];
- } u;
- u.mVal = maybeSwap<SourceEndian, DestEndian>(aSrc[i]);
- memcpy(byteDestPtr, u.mBuffer, sizeof(T));
- byteDestPtr += sizeof(T);
- }
- }
-
- /**
- * Write |aCount| elements to |aDest| in DestEndian format, using elements
- * found at the unaligned address |aSrc| in SourceEndian format.
- */
- template<Endianness SourceEndian, Endianness DestEndian, typename T>
- static void copyAndSwapFrom(T* aDest, const void* aSrc, size_t aCount)
- {
- assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
- assertAligned(aDest);
-
- if (SourceEndian == DestEndian) {
- memcpy(aDest, aSrc, aCount * sizeof(T));
- return;
- }
-
- const uint8_t* byteSrcPtr = static_cast<const uint8_t*>(aSrc);
- for (size_t i = 0; i < aCount; ++i) {
- union
- {
- T mVal;
- uint8_t mBuffer[sizeof(T)];
- } u;
- memcpy(u.mBuffer, byteSrcPtr, sizeof(T));
- aDest[i] = maybeSwap<SourceEndian, DestEndian>(u.mVal);
- byteSrcPtr += sizeof(T);
- }
- }
-};
-
-template<Endianness ThisEndian>
-class Endian : private EndianUtils
-{
-protected:
- /** Read a uint16_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT uint16_t readUint16(const void* aPtr)
- {
- return read<uint16_t>(aPtr);
- }
-
- /** Read a uint32_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT uint32_t readUint32(const void* aPtr)
- {
- return read<uint32_t>(aPtr);
- }
-
- /** Read a uint64_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT uint64_t readUint64(const void* aPtr)
- {
- return read<uint64_t>(aPtr);
- }
-
- /** Read an int16_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT int16_t readInt16(const void* aPtr)
- {
- return read<int16_t>(aPtr);
- }
-
- /** Read an int32_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT int32_t readInt32(const void* aPtr)
- {
- return read<uint32_t>(aPtr);
- }
-
- /** Read an int64_t in ThisEndian endianness from |aPtr| and return it. */
- static MOZ_WARN_UNUSED_RESULT int64_t readInt64(const void* aPtr)
- {
- return read<int64_t>(aPtr);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeUint16(void* aPtr, uint16_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeUint32(void* aPtr, uint32_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeUint64(void* aPtr, uint64_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeInt16(void* aPtr, int16_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeInt32(void* aPtr, int32_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /** Write |aValue| to |aPtr| using ThisEndian endianness. */
- static void writeInt64(void* aPtr, int64_t aValue)
- {
- write(aPtr, aValue);
- }
-
- /*
- * Converts a value of type T to little-endian format.
- *
- * This function is intended for cases where you have data in your
- * native-endian format and you need it to appear in little-endian
- * format for transmission.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapToLittleEndian(T aValue)
- {
- return maybeSwap<ThisEndian, Little>(aValue);
- }
-
- /*
- * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
- * them to little-endian format if ThisEndian is Big.
- * As with memcpy, |aDest| and |aSrc| must not overlap.
- */
- template<typename T>
- static void copyAndSwapToLittleEndian(void* aDest, const T* aSrc,
- size_t aCount)
- {
- copyAndSwapTo<ThisEndian, Little>(aDest, aSrc, aCount);
- }
-
- /*
- * Likewise, but converts values in place.
- */
- template<typename T>
- static void swapToLittleEndianInPlace(T* aPtr, size_t aCount)
- {
- maybeSwapInPlace<ThisEndian, Little>(aPtr, aCount);
- }
-
- /*
- * Converts a value of type T to big-endian format.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapToBigEndian(T aValue)
- {
- return maybeSwap<ThisEndian, Big>(aValue);
- }
-
- /*
- * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
- * them to big-endian format if ThisEndian is Little.
- * As with memcpy, |aDest| and |aSrc| must not overlap.
- */
- template<typename T>
- static void copyAndSwapToBigEndian(void* aDest, const T* aSrc,
- size_t aCount)
- {
- copyAndSwapTo<ThisEndian, Big>(aDest, aSrc, aCount);
- }
-
- /*
- * Likewise, but converts values in place.
- */
- template<typename T>
- static void swapToBigEndianInPlace(T* aPtr, size_t aCount)
- {
- maybeSwapInPlace<ThisEndian, Big>(aPtr, aCount);
- }
-
- /*
- * Synonyms for the big-endian functions, for better readability
- * in network code.
- */
-
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapToNetworkOrder(T aValue)
- {
- return swapToBigEndian(aValue);
- }
-
- template<typename T>
- static void
- copyAndSwapToNetworkOrder(void* aDest, const T* aSrc, size_t aCount)
- {
- copyAndSwapToBigEndian(aDest, aSrc, aCount);
- }
-
- template<typename T>
- static void
- swapToNetworkOrderInPlace(T* aPtr, size_t aCount)
- {
- swapToBigEndianInPlace(aPtr, aCount);
- }
-
- /*
- * Converts a value of type T from little-endian format.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapFromLittleEndian(T aValue)
- {
- return maybeSwap<Little, ThisEndian>(aValue);
- }
-
- /*
- * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
- * them to little-endian format if ThisEndian is Big.
- * As with memcpy, |aDest| and |aSrc| must not overlap.
- */
- template<typename T>
- static void copyAndSwapFromLittleEndian(T* aDest, const void* aSrc,
- size_t aCount)
- {
- copyAndSwapFrom<Little, ThisEndian>(aDest, aSrc, aCount);
- }
-
- /*
- * Likewise, but converts values in place.
- */
- template<typename T>
- static void swapFromLittleEndianInPlace(T* aPtr, size_t aCount)
- {
- maybeSwapInPlace<Little, ThisEndian>(aPtr, aCount);
- }
-
- /*
- * Converts a value of type T from big-endian format.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapFromBigEndian(T aValue)
- {
- return maybeSwap<Big, ThisEndian>(aValue);
- }
-
- /*
- * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
- * them to big-endian format if ThisEndian is Little.
- * As with memcpy, |aDest| and |aSrc| must not overlap.
- */
- template<typename T>
- static void copyAndSwapFromBigEndian(T* aDest, const void* aSrc,
- size_t aCount)
- {
- copyAndSwapFrom<Big, ThisEndian>(aDest, aSrc, aCount);
- }
-
- /*
- * Likewise, but converts values in place.
- */
- template<typename T>
- static void swapFromBigEndianInPlace(T* aPtr, size_t aCount)
- {
- maybeSwapInPlace<Big, ThisEndian>(aPtr, aCount);
- }
-
- /*
- * Synonyms for the big-endian functions, for better readability
- * in network code.
- */
- template<typename T>
- MOZ_WARN_UNUSED_RESULT static T swapFromNetworkOrder(T aValue)
- {
- return swapFromBigEndian(aValue);
- }
-
- template<typename T>
- static void copyAndSwapFromNetworkOrder(T* aDest, const void* aSrc,
- size_t aCount)
- {
- copyAndSwapFromBigEndian(aDest, aSrc, aCount);
- }
-
- template<typename T>
- static void swapFromNetworkOrderInPlace(T* aPtr, size_t aCount)
- {
- swapFromBigEndianInPlace(aPtr, aCount);
- }
-
-private:
- /**
- * Read a value of type T, encoded in endianness ThisEndian from |aPtr|.
- * Return that value encoded in native endianness.
- */
- template<typename T>
- static T read(const void* aPtr)
- {
- union
- {
- T mVal;
- uint8_t mBuffer[sizeof(T)];
- } u;
- memcpy(u.mBuffer, aPtr, sizeof(T));
- return maybeSwap<ThisEndian, MOZ_NATIVE_ENDIANNESS>(u.mVal);
- }
-
- /**
- * Write a value of type T, in native endianness, to |aPtr|, in ThisEndian
- * endianness.
- */
- template<typename T>
- static void write(void* aPtr, T aValue)
- {
- T tmp = maybeSwap<MOZ_NATIVE_ENDIANNESS, ThisEndian>(aValue);
- memcpy(aPtr, &tmp, sizeof(T));
- }
-
- Endian() = delete;
- Endian(const Endian& aTther) = delete;
- void operator=(const Endian& aOther) = delete;
-};
-
-template<Endianness ThisEndian>
-class EndianReadWrite : public Endian<ThisEndian>
-{
-private:
- typedef Endian<ThisEndian> super;
-
-public:
- using super::readUint16;
- using super::readUint32;
- using super::readUint64;
- using super::readInt16;
- using super::readInt32;
- using super::readInt64;
- using super::writeUint16;
- using super::writeUint32;
- using super::writeUint64;
- using super::writeInt16;
- using super::writeInt32;
- using super::writeInt64;
-};
-
-} /* namespace detail */
-
-class LittleEndian final : public detail::EndianReadWrite<detail::Little>
-{};
-
-class BigEndian final : public detail::EndianReadWrite<detail::Big>
-{};
-
-typedef BigEndian NetworkEndian;
-
-class NativeEndian final : public detail::Endian<MOZ_NATIVE_ENDIANNESS>
-{
-private:
- typedef detail::Endian<MOZ_NATIVE_ENDIANNESS> super;
-
-public:
- /*
- * These functions are intended for cases where you have data in your
- * native-endian format and you need the data to appear in the appropriate
- * endianness for transmission, serialization, etc.
- */
- using super::swapToLittleEndian;
- using super::copyAndSwapToLittleEndian;
- using super::swapToLittleEndianInPlace;
- using super::swapToBigEndian;
- using super::copyAndSwapToBigEndian;
- using super::swapToBigEndianInPlace;
- using super::swapToNetworkOrder;
- using super::copyAndSwapToNetworkOrder;
- using super::swapToNetworkOrderInPlace;
-
- /*
- * These functions are intended for cases where you have data in the
- * given endianness (e.g. reading from disk or a file-format) and you
- * need the data to appear in native-endian format for processing.
- */
- using super::swapFromLittleEndian;
- using super::copyAndSwapFromLittleEndian;
- using super::swapFromLittleEndianInPlace;
- using super::swapFromBigEndian;
- using super::copyAndSwapFromBigEndian;
- using super::swapFromBigEndianInPlace;
- using super::swapFromNetworkOrder;
- using super::copyAndSwapFromNetworkOrder;
- using super::swapFromNetworkOrderInPlace;
-};
-
-#undef MOZ_NATIVE_ENDIANNESS
-
-} /* namespace mozilla */
-
-#endif /* mozilla_Endian_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EndianUtils.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EndianUtils.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EndianUtils.h
@@ -0,0 +1,695 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Functions for reading and writing integers in various endiannesses. */
+
+/*
+ * The classes LittleEndian and BigEndian expose static methods for
+ * reading and writing 16-, 32-, and 64-bit signed and unsigned integers
+ * in their respective endianness. The naming scheme is:
+ *
+ * {Little,Big}Endian::{read,write}{Uint,Int}<bitsize>
+ *
+ * For instance, LittleEndian::readInt32 will read a 32-bit signed
+ * integer from memory in little endian format. Similarly,
+ * BigEndian::writeUint16 will write a 16-bit unsigned integer to memory
+ * in big-endian format.
+ *
+ * The class NativeEndian exposes methods for conversion of existing
+ * data to and from the native endianness. These methods are intended
+ * for cases where data needs to be transferred, serialized, etc.
+ * swap{To,From}{Little,Big}Endian byteswap a single value if necessary.
+ * Bulk conversion functions are also provided which optimize the
+ * no-conversion-needed case:
+ *
+ * - copyAndSwap{To,From}{Little,Big}Endian;
+ * - swap{To,From}{Little,Big}EndianInPlace.
+ *
+ * The *From* variants are intended to be used for reading data and the
+ * *To* variants for writing data.
+ *
+ * Methods on NativeEndian work with integer data of any type.
+ * Floating-point data is not supported.
+ *
+ * For clarity in networking code, "Network" may be used as a synonym
+ * for "Big" in any of the above methods or class names.
+ *
+ * As an example, reading a file format header whose fields are stored
+ * in big-endian format might look like:
+ *
+ * class ExampleHeader
+ * {
+ * private:
+ * uint32_t mMagic;
+ * uint32_t mLength;
+ * uint32_t mTotalRecords;
+ * uint64_t mChecksum;
+ *
+ * public:
+ * ExampleHeader(const void* data)
+ * {
+ * const uint8_t* ptr = static_cast<const uint8_t*>(data);
+ * mMagic = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
+ * mLength = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
+ * mTotalRecords = BigEndian::readUint32(ptr); ptr += sizeof(uint32_t);
+ * mChecksum = BigEndian::readUint64(ptr);
+ * }
+ * ...
+ * };
+ */
+
+#ifndef mozilla_EndianUtils_h
+#define mozilla_EndianUtils_h
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Compiler.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/TypeTraits.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+# include <stdlib.h>
+# pragma intrinsic(_byteswap_ushort)
+# pragma intrinsic(_byteswap_ulong)
+# pragma intrinsic(_byteswap_uint64)
+#endif
+
+#if defined(_WIN64)
+# if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
+# define MOZ_LITTLE_ENDIAN 1
+# else
+# error "CPU type is unknown"
+# endif
+#elif defined(_WIN32)
+# if defined(_M_IX86)
+# define MOZ_LITTLE_ENDIAN 1
+# elif defined(_M_ARM)
+# define MOZ_LITTLE_ENDIAN 1
+# else
+# error "CPU type is unknown"
+# endif
+#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__) && \
+ defined(__ORDER_BIG_ENDIAN__)
+ /*
+ * Some versions of GCC provide architecture-independent macros for
+ * this. Yes, there are more than two values for __BYTE_ORDER__.
+ */
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define MOZ_LITTLE_ENDIAN 1
+# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define MOZ_BIG_ENDIAN 1
+# else
+# error "Can't handle mixed-endian architectures"
+# 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(__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__) || \
+ defined(__alpha__) || defined(__AARCH64EL__) || \
+ (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
+ (defined(__ia64) && !defined(__BIG_ENDIAN__))
+# define MOZ_LITTLE_ENDIAN 1
+#endif
+
+#if MOZ_BIG_ENDIAN
+# define MOZ_LITTLE_ENDIAN 0
+#elif MOZ_LITTLE_ENDIAN
+# define MOZ_BIG_ENDIAN 0
+#else
+# error "Cannot determine endianness"
+#endif
+
+#if defined(__clang__)
+# if __has_builtin(__builtin_bswap16)
+# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
+# endif
+#elif defined(__GNUC__)
+# define MOZ_HAVE_BUILTIN_BYTESWAP16 __builtin_bswap16
+#elif defined(_MSC_VER)
+# define MOZ_HAVE_BUILTIN_BYTESWAP16 _byteswap_ushort
+#endif
+
+namespace mozilla {
+
+namespace detail {
+
+/*
+ * We need wrappers here because free functions with default template
+ * arguments and/or partial specialization of function templates are not
+ * supported by all the compilers we use.
+ */
+template<typename T, size_t Size = sizeof(T)>
+struct Swapper;
+
+template<typename T>
+struct Swapper<T, 2>
+{
+ static T swap(T aValue)
+ {
+#if defined(MOZ_HAVE_BUILTIN_BYTESWAP16)
+ return MOZ_HAVE_BUILTIN_BYTESWAP16(aValue);
+#else
+ return T(((aValue & 0x00ff) << 8) | ((aValue & 0xff00) >> 8));
+#endif
+ }
+};
+
+template<typename T>
+struct Swapper<T, 4>
+{
+ static T swap(T aValue)
+ {
+#if defined(__clang__) || defined(__GNUC__)
+ return T(__builtin_bswap32(aValue));
+#elif defined(_MSC_VER)
+ return T(_byteswap_ulong(aValue));
+#else
+ return T(((aValue & 0x000000ffU) << 24) |
+ ((aValue & 0x0000ff00U) << 8) |
+ ((aValue & 0x00ff0000U) >> 8) |
+ ((aValue & 0xff000000U) >> 24));
+#endif
+ }
+};
+
+template<typename T>
+struct Swapper<T, 8>
+{
+ static inline T swap(T aValue)
+ {
+#if defined(__clang__) || defined(__GNUC__)
+ return T(__builtin_bswap64(aValue));
+#elif defined(_MSC_VER)
+ return T(_byteswap_uint64(aValue));
+#else
+ return T(((aValue & 0x00000000000000ffULL) << 56) |
+ ((aValue & 0x000000000000ff00ULL) << 40) |
+ ((aValue & 0x0000000000ff0000ULL) << 24) |
+ ((aValue & 0x00000000ff000000ULL) << 8) |
+ ((aValue & 0x000000ff00000000ULL) >> 8) |
+ ((aValue & 0x0000ff0000000000ULL) >> 24) |
+ ((aValue & 0x00ff000000000000ULL) >> 40) |
+ ((aValue & 0xff00000000000000ULL) >> 56));
+#endif
+ }
+};
+
+enum Endianness { Little, Big };
+
+#if MOZ_BIG_ENDIAN
+# define MOZ_NATIVE_ENDIANNESS detail::Big
+#else
+# define MOZ_NATIVE_ENDIANNESS detail::Little
+#endif
+
+class EndianUtils
+{
+ /**
+ * Assert that the memory regions [aDest, aDest+aCount) and
+ * [aSrc, aSrc+aCount] do not overlap. aCount is given in bytes.
+ */
+ static void assertNoOverlap(const void* aDest, const void* aSrc,
+ size_t aCount)
+ {
+ DebugOnly<const uint8_t*> byteDestPtr = static_cast<const uint8_t*>(aDest);
+ DebugOnly<const uint8_t*> byteSrcPtr = static_cast<const uint8_t*>(aSrc);
+ MOZ_ASSERT((byteDestPtr <= byteSrcPtr &&
+ byteDestPtr + aCount <= byteSrcPtr) ||
+ (byteSrcPtr <= byteDestPtr &&
+ byteSrcPtr + aCount <= byteDestPtr));
+ }
+
+ template<typename T>
+ static void assertAligned(T* aPtr)
+ {
+ MOZ_ASSERT((uintptr_t(aPtr) % sizeof(T)) == 0, "Unaligned pointer!");
+ }
+
+protected:
+ /**
+ * Return |aValue| converted from SourceEndian encoding to DestEndian
+ * encoding.
+ */
+ template<Endianness SourceEndian, Endianness DestEndian, typename T>
+ static inline T maybeSwap(T aValue)
+ {
+ if (SourceEndian == DestEndian) {
+ return aValue;
+ }
+ return Swapper<T>::swap(aValue);
+ }
+
+ /**
+ * Convert |aCount| elements at |aPtr| from SourceEndian encoding to
+ * DestEndian encoding.
+ */
+ template<Endianness SourceEndian, Endianness DestEndian, typename T>
+ static inline void maybeSwapInPlace(T* aPtr, size_t aCount)
+ {
+ assertAligned(aPtr);
+
+ if (SourceEndian == DestEndian) {
+ return;
+ }
+ for (size_t i = 0; i < aCount; i++) {
+ aPtr[i] = Swapper<T>::swap(aPtr[i]);
+ }
+ }
+
+ /**
+ * Write |aCount| elements to the unaligned address |aDest| in DestEndian
+ * format, using elements found at |aSrc| in SourceEndian format.
+ */
+ template<Endianness SourceEndian, Endianness DestEndian, typename T>
+ static void copyAndSwapTo(void* aDest, const T* aSrc, size_t aCount)
+ {
+ assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
+ assertAligned(aSrc);
+
+ if (SourceEndian == DestEndian) {
+ memcpy(aDest, aSrc, aCount * sizeof(T));
+ return;
+ }
+
+ uint8_t* byteDestPtr = static_cast<uint8_t*>(aDest);
+ for (size_t i = 0; i < aCount; ++i) {
+ union
+ {
+ T mVal;
+ uint8_t mBuffer[sizeof(T)];
+ } u;
+ u.mVal = maybeSwap<SourceEndian, DestEndian>(aSrc[i]);
+ memcpy(byteDestPtr, u.mBuffer, sizeof(T));
+ byteDestPtr += sizeof(T);
+ }
+ }
+
+ /**
+ * Write |aCount| elements to |aDest| in DestEndian format, using elements
+ * found at the unaligned address |aSrc| in SourceEndian format.
+ */
+ template<Endianness SourceEndian, Endianness DestEndian, typename T>
+ static void copyAndSwapFrom(T* aDest, const void* aSrc, size_t aCount)
+ {
+ assertNoOverlap(aDest, aSrc, aCount * sizeof(T));
+ assertAligned(aDest);
+
+ if (SourceEndian == DestEndian) {
+ memcpy(aDest, aSrc, aCount * sizeof(T));
+ return;
+ }
+
+ const uint8_t* byteSrcPtr = static_cast<const uint8_t*>(aSrc);
+ for (size_t i = 0; i < aCount; ++i) {
+ union
+ {
+ T mVal;
+ uint8_t mBuffer[sizeof(T)];
+ } u;
+ memcpy(u.mBuffer, byteSrcPtr, sizeof(T));
+ aDest[i] = maybeSwap<SourceEndian, DestEndian>(u.mVal);
+ byteSrcPtr += sizeof(T);
+ }
+ }
+};
+
+template<Endianness ThisEndian>
+class Endian : private EndianUtils
+{
+protected:
+ /** Read a uint16_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE uint16_t readUint16(const void* aPtr)
+ {
+ return read<uint16_t>(aPtr);
+ }
+
+ /** Read a uint32_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE uint32_t readUint32(const void* aPtr)
+ {
+ return read<uint32_t>(aPtr);
+ }
+
+ /** Read a uint64_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE uint64_t readUint64(const void* aPtr)
+ {
+ return read<uint64_t>(aPtr);
+ }
+
+ /** Read an int16_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE int16_t readInt16(const void* aPtr)
+ {
+ return read<int16_t>(aPtr);
+ }
+
+ /** Read an int32_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE int32_t readInt32(const void* aPtr)
+ {
+ return read<uint32_t>(aPtr);
+ }
+
+ /** Read an int64_t in ThisEndian endianness from |aPtr| and return it. */
+ static MOZ_MUST_USE int64_t readInt64(const void* aPtr)
+ {
+ return read<int64_t>(aPtr);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeUint16(void* aPtr, uint16_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeUint32(void* aPtr, uint32_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeUint64(void* aPtr, uint64_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeInt16(void* aPtr, int16_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeInt32(void* aPtr, int32_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /** Write |aValue| to |aPtr| using ThisEndian endianness. */
+ static void writeInt64(void* aPtr, int64_t aValue)
+ {
+ write(aPtr, aValue);
+ }
+
+ /*
+ * Converts a value of type T to little-endian format.
+ *
+ * This function is intended for cases where you have data in your
+ * native-endian format and you need it to appear in little-endian
+ * format for transmission.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapToLittleEndian(T aValue)
+ {
+ return maybeSwap<ThisEndian, Little>(aValue);
+ }
+
+ /*
+ * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
+ * them to little-endian format if ThisEndian is Big.
+ * As with memcpy, |aDest| and |aSrc| must not overlap.
+ */
+ template<typename T>
+ static void copyAndSwapToLittleEndian(void* aDest, const T* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapTo<ThisEndian, Little>(aDest, aSrc, aCount);
+ }
+
+ /*
+ * Likewise, but converts values in place.
+ */
+ template<typename T>
+ static void swapToLittleEndianInPlace(T* aPtr, size_t aCount)
+ {
+ maybeSwapInPlace<ThisEndian, Little>(aPtr, aCount);
+ }
+
+ /*
+ * Converts a value of type T to big-endian format.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapToBigEndian(T aValue)
+ {
+ return maybeSwap<ThisEndian, Big>(aValue);
+ }
+
+ /*
+ * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
+ * them to big-endian format if ThisEndian is Little.
+ * As with memcpy, |aDest| and |aSrc| must not overlap.
+ */
+ template<typename T>
+ static void copyAndSwapToBigEndian(void* aDest, const T* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapTo<ThisEndian, Big>(aDest, aSrc, aCount);
+ }
+
+ /*
+ * Likewise, but converts values in place.
+ */
+ template<typename T>
+ static void swapToBigEndianInPlace(T* aPtr, size_t aCount)
+ {
+ maybeSwapInPlace<ThisEndian, Big>(aPtr, aCount);
+ }
+
+ /*
+ * Synonyms for the big-endian functions, for better readability
+ * in network code.
+ */
+
+ template<typename T>
+ MOZ_MUST_USE static T swapToNetworkOrder(T aValue)
+ {
+ return swapToBigEndian(aValue);
+ }
+
+ template<typename T>
+ static void
+ copyAndSwapToNetworkOrder(void* aDest, const T* aSrc, size_t aCount)
+ {
+ copyAndSwapToBigEndian(aDest, aSrc, aCount);
+ }
+
+ template<typename T>
+ static void
+ swapToNetworkOrderInPlace(T* aPtr, size_t aCount)
+ {
+ swapToBigEndianInPlace(aPtr, aCount);
+ }
+
+ /*
+ * Converts a value of type T from little-endian format.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapFromLittleEndian(T aValue)
+ {
+ return maybeSwap<Little, ThisEndian>(aValue);
+ }
+
+ /*
+ * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
+ * them to little-endian format if ThisEndian is Big.
+ * As with memcpy, |aDest| and |aSrc| must not overlap.
+ */
+ template<typename T>
+ static void copyAndSwapFromLittleEndian(T* aDest, const void* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapFrom<Little, ThisEndian>(aDest, aSrc, aCount);
+ }
+
+ /*
+ * Likewise, but converts values in place.
+ */
+ template<typename T>
+ static void swapFromLittleEndianInPlace(T* aPtr, size_t aCount)
+ {
+ maybeSwapInPlace<Little, ThisEndian>(aPtr, aCount);
+ }
+
+ /*
+ * Converts a value of type T from big-endian format.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapFromBigEndian(T aValue)
+ {
+ return maybeSwap<Big, ThisEndian>(aValue);
+ }
+
+ /*
+ * Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
+ * them to big-endian format if ThisEndian is Little.
+ * As with memcpy, |aDest| and |aSrc| must not overlap.
+ */
+ template<typename T>
+ static void copyAndSwapFromBigEndian(T* aDest, const void* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapFrom<Big, ThisEndian>(aDest, aSrc, aCount);
+ }
+
+ /*
+ * Likewise, but converts values in place.
+ */
+ template<typename T>
+ static void swapFromBigEndianInPlace(T* aPtr, size_t aCount)
+ {
+ maybeSwapInPlace<Big, ThisEndian>(aPtr, aCount);
+ }
+
+ /*
+ * Synonyms for the big-endian functions, for better readability
+ * in network code.
+ */
+ template<typename T>
+ MOZ_MUST_USE static T swapFromNetworkOrder(T aValue)
+ {
+ return swapFromBigEndian(aValue);
+ }
+
+ template<typename T>
+ static void copyAndSwapFromNetworkOrder(T* aDest, const void* aSrc,
+ size_t aCount)
+ {
+ copyAndSwapFromBigEndian(aDest, aSrc, aCount);
+ }
+
+ template<typename T>
+ static void swapFromNetworkOrderInPlace(T* aPtr, size_t aCount)
+ {
+ swapFromBigEndianInPlace(aPtr, aCount);
+ }
+
+private:
+ /**
+ * Read a value of type T, encoded in endianness ThisEndian from |aPtr|.
+ * Return that value encoded in native endianness.
+ */
+ template<typename T>
+ static T read(const void* aPtr)
+ {
+ union
+ {
+ T mVal;
+ uint8_t mBuffer[sizeof(T)];
+ } u;
+ memcpy(u.mBuffer, aPtr, sizeof(T));
+ return maybeSwap<ThisEndian, MOZ_NATIVE_ENDIANNESS>(u.mVal);
+ }
+
+ /**
+ * Write a value of type T, in native endianness, to |aPtr|, in ThisEndian
+ * endianness.
+ */
+ template<typename T>
+ static void write(void* aPtr, T aValue)
+ {
+ T tmp = maybeSwap<MOZ_NATIVE_ENDIANNESS, ThisEndian>(aValue);
+ memcpy(aPtr, &tmp, sizeof(T));
+ }
+
+ Endian() = delete;
+ Endian(const Endian& aTther) = delete;
+ void operator=(const Endian& aOther) = delete;
+};
+
+template<Endianness ThisEndian>
+class EndianReadWrite : public Endian<ThisEndian>
+{
+private:
+ typedef Endian<ThisEndian> super;
+
+public:
+ using super::readUint16;
+ using super::readUint32;
+ using super::readUint64;
+ using super::readInt16;
+ using super::readInt32;
+ using super::readInt64;
+ using super::writeUint16;
+ using super::writeUint32;
+ using super::writeUint64;
+ using super::writeInt16;
+ using super::writeInt32;
+ using super::writeInt64;
+};
+
+} /* namespace detail */
+
+class LittleEndian final : public detail::EndianReadWrite<detail::Little>
+{};
+
+class BigEndian final : public detail::EndianReadWrite<detail::Big>
+{};
+
+typedef BigEndian NetworkEndian;
+
+class NativeEndian final : public detail::Endian<MOZ_NATIVE_ENDIANNESS>
+{
+private:
+ typedef detail::Endian<MOZ_NATIVE_ENDIANNESS> super;
+
+public:
+ /*
+ * These functions are intended for cases where you have data in your
+ * native-endian format and you need the data to appear in the appropriate
+ * endianness for transmission, serialization, etc.
+ */
+ using super::swapToLittleEndian;
+ using super::copyAndSwapToLittleEndian;
+ using super::swapToLittleEndianInPlace;
+ using super::swapToBigEndian;
+ using super::copyAndSwapToBigEndian;
+ using super::swapToBigEndianInPlace;
+ using super::swapToNetworkOrder;
+ using super::copyAndSwapToNetworkOrder;
+ using super::swapToNetworkOrderInPlace;
+
+ /*
+ * These functions are intended for cases where you have data in the
+ * given endianness (e.g. reading from disk or a file-format) and you
+ * need the data to appear in native-endian format for processing.
+ */
+ using super::swapFromLittleEndian;
+ using super::copyAndSwapFromLittleEndian;
+ using super::swapFromLittleEndianInPlace;
+ using super::swapFromBigEndian;
+ using super::copyAndSwapFromBigEndian;
+ using super::swapFromBigEndianInPlace;
+ using super::swapFromNetworkOrder;
+ using super::copyAndSwapFromNetworkOrder;
+ using super::swapFromNetworkOrderInPlace;
+};
+
+#undef MOZ_NATIVE_ENDIANNESS
+
+} /* namespace mozilla */
+
+#endif /* mozilla_EndianUtils_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumSet.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumSet.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumSet.h
@@ -12,6 +12,8 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
+#include <initializer_list>
+
#include <stdint.h>
namespace mozilla {
@@ -27,7 +29,9 @@
public:
EnumSet()
: mBitField(0)
- { }
+ {
+ initVersion();
+ }
MOZ_IMPLICIT EnumSet(T aEnum)
: mBitField(bitFor(aEnum))
@@ -36,30 +40,48 @@
EnumSet(T aEnum1, T aEnum2)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2))
- { }
+ {
+ initVersion();
+ }
EnumSet(T aEnum1, T aEnum2, T aEnum3)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2) |
bitFor(aEnum3))
- { }
+ {
+ initVersion();
+ }
EnumSet(T aEnum1, T aEnum2, T aEnum3, T aEnum4)
- : mBitField(bitFor(aEnum1) |
- bitFor(aEnum2) |
- bitFor(aEnum3) |
- bitFor(aEnum4))
- { }
+ : mBitField(bitFor(aEnum1) |
+ bitFor(aEnum2) |
+ bitFor(aEnum3) |
+ bitFor(aEnum4))
+ {
+ initVersion();
+ }
+
+ MOZ_IMPLICIT EnumSet(std::initializer_list<T> list)
+ : mBitField(0)
+ {
+ for (auto value : list) {
+ (*this) += value;
+ }
+ initVersion();
+ }
EnumSet(const EnumSet& aEnumSet)
- : mBitField(aEnumSet.mBitField)
- { }
+ : mBitField(aEnumSet.mBitField)
+ {
+ initVersion();
+ }
/**
* Add an element
*/
void operator+=(T aEnum)
{
+ incVersion();
mBitField |= bitFor(aEnum);
}
@@ -78,6 +100,7 @@
*/
void operator+=(const EnumSet<T> aEnumSet)
{
+ incVersion();
mBitField |= aEnumSet.mBitField;
}
@@ -96,6 +119,7 @@
*/
void operator-=(T aEnum)
{
+ incVersion();
mBitField &= ~(bitFor(aEnum));
}
@@ -114,6 +138,7 @@
*/
void operator-=(const EnumSet<T> aEnumSet)
{
+ incVersion();
mBitField &= ~(aEnumSet.mBitField);
}
@@ -132,6 +157,7 @@
*/
void clear()
{
+ incVersion();
mBitField = 0;
}
@@ -140,6 +166,7 @@
*/
void operator&=(const EnumSet<T> aEnumSet)
{
+ incVersion();
mBitField &= aEnumSet.mBitField;
}
@@ -172,7 +199,7 @@
/**
* Return the number of elements in the set.
*/
- uint8_t size()
+ uint8_t size() const
{
uint8_t count = 0;
for (uint32_t bitField = mBitField; bitField; bitField >>= 1) {
@@ -195,18 +222,121 @@
void deserialize(uint32_t aValue)
{
+ incVersion();
mBitField = aValue;
}
+ class ConstIterator
+ {
+ const EnumSet<T>* mSet;
+ uint32_t mPos;
+#ifdef DEBUG
+ uint64_t mVersion;
+#endif
+
+ void checkVersion() {
+ // Check that the set has not been modified while being iterated.
+ MOZ_ASSERT_IF(mSet, mSet->mVersion == mVersion);
+ }
+
+ public:
+ ConstIterator(const EnumSet<T>& aSet, uint32_t aPos)
+ : mSet(&aSet), mPos(aPos)
+ {
+#ifdef DEBUG
+ mVersion = mSet->mVersion;
+#endif
+ MOZ_ASSERT(aPos <= kMaxBits);
+ if (aPos != kMaxBits && !mSet->contains(T(mPos)))
+ ++*this;
+ }
+
+ ConstIterator(const ConstIterator& aOther)
+ : mSet(aOther.mSet), mPos(aOther.mPos)
+ {
+#ifdef DEBUG
+ mVersion = aOther.mVersion;
+ checkVersion();
+#endif
+ }
+
+ ConstIterator(ConstIterator&& aOther)
+ : mSet(aOther.mSet), mPos(aOther.mPos)
+ {
+#ifdef DEBUG
+ mVersion = aOther.mVersion;
+ checkVersion();
+#endif
+ aOther.mSet = nullptr;
+ }
+
+ ~ConstIterator() {
+ checkVersion();
+ }
+
+ bool operator==(const ConstIterator& other) {
+ MOZ_ASSERT(mSet == other.mSet);
+ checkVersion();
+ return mPos == other.mPos;
+ }
+
+ bool operator!=(const ConstIterator& other) {
+ return !(*this == other);
+ }
+
+ T operator*() {
+ MOZ_ASSERT(mSet);
+ MOZ_ASSERT(mPos < kMaxBits);
+ MOZ_ASSERT(mSet->contains(T(mPos)));
+ checkVersion();
+ return T(mPos);
+ }
+
+ ConstIterator& operator++() {
+ MOZ_ASSERT(mSet);
+ MOZ_ASSERT(mPos < kMaxBits);
+ checkVersion();
+ do {
+ mPos++;
+ } while (mPos < kMaxBits && !mSet->contains(T(mPos)));
+ return *this;
+ }
+ };
+
+ ConstIterator begin() const {
+ return ConstIterator(*this, 0);
+ }
+
+ ConstIterator end() const {
+ return ConstIterator(*this, kMaxBits);
+ }
+
private:
static uint32_t bitFor(T aEnum)
{
uint32_t bitNumber = (uint32_t)aEnum;
- MOZ_ASSERT(bitNumber < 32);
+ MOZ_ASSERT(bitNumber < kMaxBits);
return 1U << bitNumber;
}
+ void initVersion() {
+#ifdef DEBUG
+ mVersion = 0;
+#endif
+ }
+
+ void incVersion() {
+#ifdef DEBUG
+ mVersion++;
+#endif
+ }
+
+ static const size_t kMaxBits = 32;
uint32_t mBitField;
+
+#ifdef DEBUG
+ uint64_t mVersion;
+#endif
};
} // namespace mozilla
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumTypeTraits.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumTypeTraits.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumTypeTraits.h
@@ -0,0 +1,70 @@
+/* -*- 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/. */
+
+/* Type traits for enums. */
+
+#ifndef mozilla_EnumTypeTraits_h
+#define mozilla_EnumTypeTraits_h
+
+#include <type_traits>
+
+namespace mozilla {
+
+namespace detail {
+
+template<size_t EnumSize, bool EnumSigned, size_t StorageSize, bool StorageSigned>
+struct EnumFitsWithinHelper;
+
+// Signed enum, signed storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, true, StorageSize, true>
+ : public std::integral_constant<bool, (EnumSize <= StorageSize)>
+{};
+
+// Signed enum, unsigned storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, true, StorageSize, false>
+ : public std::integral_constant<bool, false>
+{};
+
+// Unsigned enum, signed storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, false, StorageSize, true>
+ : public std::integral_constant<bool, (EnumSize * 2 <= StorageSize)>
+{};
+
+// Unsigned enum, unsigned storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, false, StorageSize, false>
+ : public std::integral_constant<bool, (EnumSize <= StorageSize)>
+{};
+
+} // namespace detail
+
+/*
+ * Type trait that determines whether the enum type T can fit within the
+ * integral type Storage without data loss. This trait should be used with
+ * caution with an enum type whose underlying type has not been explicitly
+ * specified: for such enums, the C++ implementation is free to choose a type
+ * no smaller than int whose range encompasses all possible values of the enum.
+ * So for an enum with only small non-negative values, the underlying type may
+ * be either int or unsigned int, depending on the whims of the implementation.
+ */
+template<typename T, typename Storage>
+struct EnumTypeFitsWithin
+ : public detail::EnumFitsWithinHelper<
+ sizeof(T),
+ std::is_signed<typename std::underlying_type<T>::type>::value,
+ sizeof(Storage),
+ std::is_signed<Storage>::value
+ >
+{
+ static_assert(std::is_enum<T>::value, "must provide an enum type");
+ static_assert(std::is_integral<Storage>::value, "must provide an integral type");
+};
+
+} // namespace mozilla
+
+#endif /* mozilla_EnumTypeTraits_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumeratedArray.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumeratedArray.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumeratedArray.h
@@ -10,6 +10,7 @@
#define mozilla_EnumeratedArray_h
#include "mozilla/Array.h"
+#include "mozilla/Move.h"
namespace mozilla {
@@ -53,6 +54,11 @@
public:
EnumeratedArray() {}
+ template <typename... Args>
+ MOZ_IMPLICIT EnumeratedArray(Args&&... aArgs)
+ : mArray{mozilla::Forward<Args>(aArgs)...}
+ {}
+
explicit EnumeratedArray(const EnumeratedArray& aOther)
{
for (size_t i = 0; i < kSize; i++) {
@@ -60,6 +66,13 @@
}
}
+ EnumeratedArray(EnumeratedArray&& aOther)
+ {
+ for (size_t i = 0; i < kSize; i++) {
+ mArray[i] = Move(aOther.mArray[i]);
+ }
+ }
+
ValueType& operator[](IndexType aIndex)
{
return mArray[size_t(aIndex)];
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumeratedRange.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumeratedRange.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/EnumeratedRange.h
@@ -20,23 +20,26 @@
#ifndef mozilla_EnumeratedRange_h
#define mozilla_EnumeratedRange_h
-#include "mozilla/IntegerTypeTraits.h"
+#include <type_traits>
+
#include "mozilla/ReverseIterator.h"
namespace mozilla {
namespace detail {
-template<typename IntTypeT, typename EnumTypeT>
+template<typename EnumTypeT>
class EnumeratedIterator
{
public:
+ typedef typename std::underlying_type<EnumTypeT>::type IntTypeT;
+
template<typename EnumType>
explicit EnumeratedIterator(EnumType aCurrent)
: mCurrent(aCurrent) { }
- template<typename IntType, typename EnumType>
- explicit EnumeratedIterator(const EnumeratedIterator<IntType, EnumType>& aOther)
+ template<typename EnumType>
+ explicit EnumeratedIterator(const EnumeratedIterator<EnumType>& aOther)
: mCurrent(aOther.mCurrent) { }
EnumTypeT operator*() const { return mCurrent; }
@@ -68,77 +71,77 @@
/* Comparison operators */
- template<typename IntType, typename EnumType>
- friend bool operator==(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator!=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator<(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator<=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator>(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
- template<typename IntType, typename EnumType>
- friend bool operator>=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator==(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator<(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator>(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
+ template<typename EnumType>
+ friend bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2);
private:
EnumTypeT mCurrent;
};
-template<typename IntType, typename EnumType>
-bool operator==(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator==(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent == aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator!=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent != aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator<(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator<(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent < aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator<=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent <= aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator>(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator>(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent > aIter2.mCurrent;
}
-template<typename IntType, typename EnumType>
-bool operator>=(const EnumeratedIterator<IntType, EnumType>& aIter1,
- const EnumeratedIterator<IntType, EnumType>& aIter2)
+template<typename EnumType>
+bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
+ const EnumeratedIterator<EnumType>& aIter2)
{
return aIter1.mCurrent >= aIter2.mCurrent;
}
-template<typename IntTypeT, typename EnumTypeT>
+template<typename EnumTypeT>
class EnumeratedRange
{
public:
- typedef EnumeratedIterator<IntTypeT, EnumTypeT> iterator;
- typedef EnumeratedIterator<IntTypeT, EnumTypeT> const_iterator;
+ typedef EnumeratedIterator<EnumTypeT> iterator;
+ typedef EnumeratedIterator<EnumTypeT> const_iterator;
typedef ReverseIterator<iterator> reverse_iterator;
typedef ReverseIterator<const_iterator> const_reverse_iterator;
@@ -171,38 +174,21 @@
#endif
// Create a range to iterate from aBegin to aEnd, exclusive.
-//
-// (Once we can rely on std::underlying_type, we can remove the IntType
-// template parameter.)
-template<typename IntType, typename EnumType>
-inline detail::EnumeratedRange<IntType, EnumType>
+template<typename EnumType>
+inline detail::EnumeratedRange<EnumType>
MakeEnumeratedRange(EnumType aBegin, EnumType aEnd)
{
-#ifdef DEBUG
- typedef typename MakeUnsigned<IntType>::Type UnsignedType;
-#endif
- static_assert(sizeof(IntType) >= sizeof(EnumType),
- "IntType should be at least as big as EnumType!");
MOZ_ASSERT(aBegin <= aEnd, "Cannot generate invalid, unbounded range!");
- MOZ_ASSERT_IF(aBegin < EnumType(0), IsSigned<IntType>::value);
- MOZ_ASSERT_IF(aBegin >= EnumType(0) && IsSigned<IntType>::value,
- UnsignedType(aEnd) <= UnsignedType(MaxValue<IntType>::value));
- return detail::EnumeratedRange<IntType, EnumType>(aBegin, aEnd);
+ return detail::EnumeratedRange<EnumType>(aBegin, aEnd);
}
// Create a range to iterate from EnumType(0) to aEnd, exclusive. EnumType(0)
// should exist, but note that there is no way for us to ensure that it does!
-// Since the enumeration starts at EnumType(0), we know for sure that the values
-// will be in range of our deduced IntType.
template<typename EnumType>
-inline detail::EnumeratedRange<
- typename UnsignedStdintTypeForSize<sizeof(EnumType)>::Type,
- EnumType>
+inline detail::EnumeratedRange<EnumType>
MakeEnumeratedRange(EnumType aEnd)
{
- return MakeEnumeratedRange<
- typename UnsignedStdintTypeForSize<sizeof(EnumType)>::Type>(EnumType(0),
- aEnd);
+ return MakeEnumeratedRange(EnumType(0), aEnd);
}
#ifdef __GNUC__
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/FastBernoulliTrial.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/FastBernoulliTrial.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/FastBernoulliTrial.h
@@ -177,7 +177,10 @@
* random number generator; both may not be zero.
*/
FastBernoulliTrial(double aProbability, uint64_t aState0, uint64_t aState1)
- : mGenerator(aState0, aState1)
+ : mProbability(0)
+ , mInvLogNotProbability(0)
+ , mGenerator(aState0, aState1)
+ , mSkipCount(0)
{
setProbability(aProbability);
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/FloatingPoint.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/FloatingPoint.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/FloatingPoint.h
@@ -117,7 +117,7 @@
/** Determines whether a float/double is NaN. */
template<typename T>
-static MOZ_ALWAYS_INLINE MOZ_CONSTEXPR bool
+static MOZ_ALWAYS_INLINE bool
IsNaN(T aValue)
{
/*
@@ -186,6 +186,18 @@
return bits == Traits::kSignBit;
}
+/** Determines wether a float/double represents +0. */
+template<typename T>
+static MOZ_ALWAYS_INLINE bool
+IsPositiveZero(T aValue)
+{
+ /* All bits are zero if the value is +0. */
+ typedef FloatingPoint<T> Traits;
+ typedef typename Traits::Bits Bits;
+ Bits bits = BitwiseCast<Bits>(aValue);
+ return bits == 0;
+}
+
/**
* Returns 0 if a float/double is NaN or infinite;
* otherwise, the float/double is returned.
@@ -244,21 +256,65 @@
return BitwiseCast<T>(Traits::kSignBit | Traits::kExponentBits);
}
+/**
+ * Computes the bit pattern for a NaN with the specified sign bit and
+ * significand bits.
+ */
+template<typename T,
+ int SignBit,
+ typename FloatingPoint<T>::Bits Significand>
+struct SpecificNaNBits
+{
+ using Traits = FloatingPoint<T>;
+
+ static_assert(SignBit == 0 || SignBit == 1, "bad sign bit");
+ static_assert((Significand & ~Traits::kSignificandBits) == 0,
+ "significand must only have significand bits set");
+ static_assert(Significand & Traits::kSignificandBits,
+ "significand must be nonzero");
-/** Constructs a NaN value with the specified sign bit and significand bits. */
+ static constexpr typename Traits::Bits value =
+ (SignBit * Traits::kSignBit) | Traits::kExponentBits | Significand;
+};
+
+/**
+ * Constructs a NaN value with the specified sign bit and significand bits.
+ *
+ * There is also a variant that returns the value directly. In most cases, the
+ * two variants should be identical. However, in the specific case of x86
+ * chips, the behavior differs: returning floating-point values directly is done
+ * through the x87 stack, and x87 loads and stores turn signaling NaNs into
+ * quiet NaNs... silently. Returning floating-point values via outparam,
+ * however, is done entirely within the SSE registers when SSE2 floating-point
+ * is enabled in the compiler, which has semantics-preserving behavior you would
+ * expect.
+ *
+ * If preserving the distinction between signaling NaNs and quiet NaNs is
+ * important to you, you should use the outparam version. In all other cases,
+ * you should use the direct return version.
+ */
template<typename T>
-static MOZ_ALWAYS_INLINE T
-SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand)
+static MOZ_ALWAYS_INLINE void
+SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand, T* result)
{
typedef FloatingPoint<T> Traits;
MOZ_ASSERT(signbit == 0 || signbit == 1);
MOZ_ASSERT((significand & ~Traits::kSignificandBits) == 0);
MOZ_ASSERT(significand & Traits::kSignificandBits);
- T t = BitwiseCast<T>((signbit ? Traits::kSignBit : 0) |
- Traits::kExponentBits |
- significand);
- MOZ_ASSERT(IsNaN(t));
+ BitwiseCast<T>((signbit ? Traits::kSignBit : 0) |
+ Traits::kExponentBits |
+ significand,
+ result);
+ MOZ_ASSERT(IsNaN(*result));
+}
+
+template<typename T>
+static MOZ_ALWAYS_INLINE T
+SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand)
+{
+ T t;
+ SpecificNaN(signbit, significand, &t);
return t;
}
@@ -401,13 +457,6 @@
T aEpsilon = detail::FuzzyEqualsEpsilon<T>::value())
{
static_assert(IsFloatingPoint<T>::value, "floating point type required");
-
- // Short-circuit the common case in order to avoid the expensive operations
- // below.
- if (aValue1 == aValue2) {
- return true;
- }
-
// can't use std::min because of bug 965340
T smaller = Abs(aValue1) < Abs(aValue2) ? Abs(aValue1) : Abs(aValue2);
return Abs(aValue1 - aValue2) <= aEpsilon * smaller;
@@ -421,7 +470,7 @@
*
* This function isn't inlined to avoid buggy optimizations by MSVC.
*/
-MOZ_WARN_UNUSED_RESULT
+MOZ_MUST_USE
extern MFBT_API bool
IsFloat32Representable(double aFloat32);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Function.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Function.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Function.h
@@ -11,9 +11,10 @@
#include "mozilla/Attributes.h" // for MOZ_IMPLICIT
#include "mozilla/Move.h"
-#include "mozilla/UniquePtr.h"
+#include "mozilla/RefCounted.h"
+#include "mozilla/RefPtr.h"
-// |Function<Signature>| is a wrapper that can hold any type of callable
+// |function<Signature>| is a wrapper that can hold any type of callable
// object that can be invoked in a way that's compatible with |Signature|.
// The standard "type erasure" technique is used to avoid the type of the
// wrapper depending on the concrete type of the wrapped callable.
@@ -28,7 +29,7 @@
// this is a function type; it's not used in any way other than serving as a
// vehicle to encode the return and argument types into a single type.
//
-// |Function| is default-constructible. A default-constructed instance is
+// |function| is default-constructible. A default-constructed instance is
// considered "empty". Invoking an empty instance is undefined behaviour.
// An empty instance can be populated with a callable by assigning to it.
//
@@ -40,9 +41,11 @@
namespace detail {
template<typename ReturnType, typename... Arguments>
-class FunctionImplBase
+class FunctionImplBase : public mozilla::RefCounted<FunctionImplBase<ReturnType, Arguments...>>
{
public:
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(FunctionImplBase)
+
virtual ~FunctionImplBase() {}
virtual ReturnType call(Arguments... aArguments) = 0;
};
@@ -126,32 +129,47 @@
// and |Arguments| in the definition of the specialization without having to
// introspect |Signature|.
template<typename Signature>
-class Function;
+class function;
template<typename ReturnType, typename... Arguments>
-class Function<ReturnType(Arguments...)>
+class function<ReturnType(Arguments...)>
{
public:
- Function() {}
+ function() {}
// This constructor is implicit to match the interface of |std::function|.
template <typename Callable>
- MOZ_IMPLICIT Function(const Callable& aCallable)
- : mImpl(MakeUnique<detail::FunctionImpl<Callable, ReturnType, Arguments...>>(aCallable))
+ MOZ_IMPLICIT function(const Callable& aCallable)
+ : mImpl(new detail::FunctionImpl<Callable, ReturnType, Arguments...>(aCallable))
+ {}
+ MOZ_IMPLICIT function(const function& aFunction)
+ : mImpl(aFunction.mImpl)
+ {}
+ MOZ_IMPLICIT function(decltype(nullptr))
{}
// Move constructor and move assingment operator.
// These should be generated automatically, but MSVC doesn't do that yet.
- Function(Function&& aOther) : mImpl(Move(aOther.mImpl)) {}
- Function& operator=(Function&& aOther) {
+ function(function&& aOther) : mImpl(Move(aOther.mImpl)) {}
+ function& operator=(function&& aOther) {
mImpl = Move(aOther.mImpl);
return *this;
}
template <typename Callable>
- Function& operator=(const Callable& aCallable)
+ function& operator=(const Callable& aCallable)
{
- mImpl = MakeUnique<detail::FunctionImpl<Callable, ReturnType, Arguments...>>(aCallable);
+ mImpl = new detail::FunctionImpl<Callable, ReturnType, Arguments...>(aCallable);
+ return *this;
+ }
+ function& operator=(const function& aFunction)
+ {
+ mImpl = aFunction.mImpl;
+ return *this;
+ }
+ function& operator=(decltype(nullptr))
+ {
+ mImpl = nullptr;
return *this;
}
@@ -161,11 +179,45 @@
MOZ_ASSERT(mImpl);
return mImpl->call(Forward<Args>(aArguments)...);
}
+
+ explicit operator bool() const
+ {
+ return bool(mImpl);
+ }
+
private:
// TODO: Consider implementing a small object optimization.
- UniquePtr<detail::FunctionImplBase<ReturnType, Arguments...>> mImpl;
+ RefPtr<detail::FunctionImplBase<ReturnType, Arguments...>> mImpl;
};
+template<typename Signature>
+bool
+operator==(const function<Signature>& aX, decltype(nullptr))
+{
+ return !aX;
+}
+
+template<typename Signature>
+bool
+operator==(decltype(nullptr), const function<Signature>& aX)
+{
+ return !aX;
+}
+
+template<typename Signature>
+bool
+operator!=(const function<Signature>& aX, decltype(nullptr))
+{
+ return bool(aX);
+}
+
+template<typename Signature>
+bool
+operator!=(decltype(nullptr), const function<Signature>& aX)
+{
+ return bool(aX);
+}
+
} // namespace mozilla
#endif /* mozilla_Function_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/HashFunctions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/HashFunctions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/HashFunctions.h
@@ -10,7 +10,7 @@
* This file exports functions for hashing data down to a 32-bit value,
* including:
*
- * - HashString Hash a char* or uint16_t/wchar_t* of known or unknown
+ * - HashString Hash a char* or char16_t/wchar_t* of known or unknown
* length.
*
* - HashBytes Hash a byte array of known length.
@@ -50,6 +50,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Char16.h"
+#include "mozilla/MathAlgorithms.h"
#include "mozilla/Types.h"
#include <stdint.h>
@@ -156,7 +157,7 @@
* convert to uint32_t, data pointers, and function pointers.
*/
template<typename A>
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
AddToHash(uint32_t aHash, A aA)
{
/*
@@ -167,7 +168,7 @@
}
template<typename A>
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
AddToHash(uint32_t aHash, A* aA)
{
/*
@@ -181,14 +182,14 @@
}
template<>
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
AddToHash(uint32_t aHash, uintptr_t aA)
{
return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, aA);
}
template<typename A, typename... Args>
-MOZ_WARN_UNUSED_RESULT uint32_t
+MOZ_MUST_USE uint32_t
AddToHash(uint32_t aHash, A aArg, Args... aArgs)
{
return AddToHash(AddToHash(aHash, aArg), aArgs...);
@@ -202,7 +203,7 @@
* that x has already been hashed.
*/
template<typename... Args>
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashGeneric(Args... aArgs)
{
return AddToHash(0, aArgs...);
@@ -240,63 +241,49 @@
* If you have the string's length, you might as well call the overload which
* includes the length. It may be marginally faster.
*/
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const char* aStr)
{
return detail::HashUntilZero(reinterpret_cast<const unsigned char*>(aStr));
}
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const char* aStr, size_t aLength)
{
return detail::HashKnownLength(reinterpret_cast<const unsigned char*>(aStr), aLength);
}
-MOZ_WARN_UNUSED_RESULT
+MOZ_MUST_USE
inline uint32_t
HashString(const unsigned char* aStr, size_t aLength)
{
return detail::HashKnownLength(aStr, aLength);
}
-MOZ_WARN_UNUSED_RESULT inline uint32_t
-HashString(const uint16_t* aStr)
-{
- return detail::HashUntilZero(aStr);
-}
-
-MOZ_WARN_UNUSED_RESULT inline uint32_t
-HashString(const uint16_t* aStr, size_t aLength)
-{
- return detail::HashKnownLength(aStr, aLength);
-}
-
-#ifdef MOZ_CHAR16_IS_NOT_WCHAR
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const char16_t* aStr)
{
return detail::HashUntilZero(aStr);
}
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const char16_t* aStr, size_t aLength)
{
return detail::HashKnownLength(aStr, aLength);
}
-#endif
/*
- * On Windows, wchar_t (char16_t) is not the same as uint16_t, even though it's
+ * On Windows, wchar_t is not the same as char16_t, even though it's
* the same width!
*/
#ifdef WIN32
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const wchar_t* aStr)
{
return detail::HashUntilZero(aStr);
}
-MOZ_WARN_UNUSED_RESULT inline uint32_t
+MOZ_MUST_USE inline uint32_t
HashString(const wchar_t* aStr, size_t aLength)
{
return detail::HashKnownLength(aStr, aLength);
@@ -309,9 +296,93 @@
* This hash walks word-by-word, rather than byte-by-byte, so you won't get the
* same result out of HashBytes as you would out of HashString.
*/
-MOZ_WARN_UNUSED_RESULT extern MFBT_API uint32_t
+MOZ_MUST_USE extern MFBT_API uint32_t
HashBytes(const void* bytes, size_t aLength);
+/**
+ * A pseudorandom function mapping 32-bit integers to 32-bit integers.
+ *
+ * This is for when you're feeding private data (like pointer values or credit
+ * card numbers) to a non-crypto hash function (like HashBytes) and then using
+ * the hash code for something that untrusted parties could observe (like a JS
+ * Map). Plug in a HashCodeScrambler before that last step to avoid leaking the
+ * private data.
+ *
+ * By itself, this does not prevent hash-flooding DoS attacks, because an
+ * attacker can still generate many values with exactly equal hash codes by
+ * attacking the non-crypto hash function alone. Equal hash codes will, of
+ * course, still be equal however much you scramble them.
+ *
+ * The algorithm is SipHash-1-3. See <https://131002.net/siphash/>.
+ */
+class HashCodeScrambler
+{
+ struct SipHasher;
+
+ uint64_t mK0, mK1;
+
+public:
+ /** Creates a new scrambler with the given 128-bit key. */
+ constexpr HashCodeScrambler(uint64_t aK0, uint64_t aK1) : mK0(aK0), mK1(aK1) {}
+
+ /**
+ * Scramble a hash code. Always produces the same result for the same
+ * combination of key and hash code.
+ */
+ uint32_t scramble(uint32_t aHashCode) const
+ {
+ SipHasher hasher(mK0, mK1);
+ return uint32_t(hasher.sipHash(aHashCode));
+ }
+
+private:
+ struct SipHasher
+ {
+ SipHasher(uint64_t aK0, uint64_t aK1)
+ {
+ // 1. Initialization.
+ mV0 = aK0 ^ UINT64_C(0x736f6d6570736575);
+ mV1 = aK1 ^ UINT64_C(0x646f72616e646f6d);
+ mV2 = aK0 ^ UINT64_C(0x6c7967656e657261);
+ mV3 = aK1 ^ UINT64_C(0x7465646279746573);
+ }
+
+ uint64_t sipHash(uint64_t aM)
+ {
+ // 2. Compression.
+ mV3 ^= aM;
+ sipRound();
+ mV0 ^= aM;
+
+ // 3. Finalization.
+ mV2 ^= 0xff;
+ for (int i = 0; i < 3; i++)
+ sipRound();
+ return mV0 ^ mV1 ^ mV2 ^ mV3;
+ }
+
+ void sipRound()
+ {
+ mV0 += mV1;
+ mV1 = RotateLeft(mV1, 13);
+ mV1 ^= mV0;
+ mV0 = RotateLeft(mV0, 32);
+ mV2 += mV3;
+ mV3 = RotateLeft(mV3, 16);
+ mV3 ^= mV2;
+ mV0 += mV3;
+ mV3 = RotateLeft(mV3, 21);
+ mV3 ^= mV0;
+ mV2 += mV1;
+ mV1 = RotateLeft(mV1, 17);
+ mV1 ^= mV2;
+ mV2 = RotateLeft(mV2, 32);
+ }
+
+ uint64_t mV0, mV1, mV2, mV3;
+ };
+};
+
} /* namespace mozilla */
#endif /* __cplusplus */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/IndexSequence.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/IndexSequence.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/IndexSequence.h
@@ -74,7 +74,7 @@
template<size_t... Indices>
struct IndexSequence
{
- static MOZ_CONSTEXPR size_t Size() { return sizeof...(Indices); }
+ static constexpr size_t Size() { return sizeof...(Indices); }
};
namespace detail {
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/JSONWriter.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/JSONWriter.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/JSONWriter.h
@@ -95,7 +95,7 @@
#include "mozilla/double-conversion.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/PodOperations.h"
-#include "mozilla/Snprintf.h"
+#include "mozilla/Sprintf.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Vector.h"
@@ -389,7 +389,7 @@
void IntProperty(const char* aName, int64_t aInt)
{
char buf[64];
- snprintf_literal(buf, "%" PRId64, aInt);
+ SprintfLiteral(buf, "%" PRId64, aInt);
Scalar(aName, buf);
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/LinkedList.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/LinkedList.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/LinkedList.h
@@ -68,17 +68,65 @@
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
+#include "mozilla/RefPtr.h"
#ifdef __cplusplus
namespace mozilla {
template<typename T>
+class LinkedListElement;
+
+namespace detail {
+
+/**
+ * LinkedList supports refcounted elements using this adapter class. Clients
+ * using LinkedList<RefPtr<T>> will get a data structure that holds a strong
+ * reference to T as long as T is in the list.
+ */
+template<typename T>
+struct LinkedListElementTraits
+{
+ typedef T* RawType;
+ typedef const T* ConstRawType;
+ typedef T* ClientType;
+ typedef const T* ConstClientType;
+
+ // These static methods are called when an element is added to or removed from
+ // a linked list. It can be used to keep track ownership in lists that are
+ // supposed to own their elements. If elements are transferred from one list
+ // to another, no enter or exit calls happen since the elements still belong
+ // to a list.
+ static void enterList(LinkedListElement<T>* elt) {}
+ static void exitList(LinkedListElement<T>* elt) {}
+};
+
+template<typename T>
+struct LinkedListElementTraits<RefPtr<T>>
+{
+ typedef T* RawType;
+ typedef const T* ConstRawType;
+ typedef RefPtr<T> ClientType;
+ typedef RefPtr<const T> ConstClientType;
+
+ static void enterList(LinkedListElement<RefPtr<T>>* elt) { elt->asT()->AddRef(); }
+ static void exitList(LinkedListElement<RefPtr<T>>* elt) { elt->asT()->Release(); }
+};
+
+} /* namespace detail */
+
+template<typename T>
class LinkedList;
template<typename T>
class LinkedListElement
{
+ typedef typename detail::LinkedListElementTraits<T> Traits;
+ typedef typename Traits::RawType RawType;
+ typedef typename Traits::ConstRawType ConstRawType;
+ typedef typename Traits::ClientType ClientType;
+ typedef typename Traits::ConstClientType ConstClientType;
+
/*
* It's convenient that we return nullptr when getNext() or getPrevious()
* hits the end of the list, but doing so costs an extra word of storage in
@@ -125,34 +173,23 @@
mIsSentinel(false)
{ }
- LinkedListElement(LinkedListElement<T>&& other)
- : mIsSentinel(other.mIsSentinel)
+ /*
+ * Moves |aOther| into |*this|. If |aOther| is already in a list, then
+ * |aOther| is removed from the list and replaced by |*this|.
+ */
+ LinkedListElement(LinkedListElement<T>&& aOther)
+ : mIsSentinel(aOther.mIsSentinel)
{
- if (!other.isInList()) {
- mNext = this;
- mPrev = this;
- return;
- }
-
- MOZ_ASSERT(other.mNext->mPrev == &other);
- MOZ_ASSERT(other.mPrev->mNext == &other);
-
- /*
- * Initialize |this| with |other|'s mPrev/mNext pointers, and adjust those
- * element to point to this one.
- */
- mNext = other.mNext;
- mPrev = other.mPrev;
-
- mNext->mPrev = this;
- mPrev->mNext = this;
+ adjustLinkForMove(Move(aOther));
+ }
- /*
- * Adjust |other| so it doesn't think it's in a list. This makes it
- * safely destructable.
- */
- other.mNext = &other;
- other.mPrev = &other;
+ LinkedListElement& operator=(LinkedListElement<T>&& aOther)
+ {
+ MOZ_ASSERT(mIsSentinel == aOther.mIsSentinel, "Mismatch NodeKind!");
+ MOZ_ASSERT(!isInList(),
+ "Assigning to an element in a list messes up that list!");
+ adjustLinkForMove(Move(aOther));
+ return *this;
}
~LinkedListElement()
@@ -166,21 +203,21 @@
* Get the next element in the list, or nullptr if this is the last element
* in the list.
*/
- T* getNext() { return mNext->asT(); }
- const T* getNext() const { return mNext->asT(); }
+ RawType getNext() { return mNext->asT(); }
+ ConstRawType getNext() const { return mNext->asT(); }
/*
* Get the previous element in the list, or nullptr if this is the first
* element in the list.
*/
- T* getPrevious() { return mPrev->asT(); }
- const T* getPrevious() const { return mPrev->asT(); }
+ RawType getPrevious() { return mPrev->asT(); }
+ ConstRawType getPrevious() const { return mPrev->asT(); }
/*
* Insert aElem after this element in the list. |this| must be part of a
* linked list when you call setNext(); otherwise, this method will assert.
*/
- void setNext(T* aElem)
+ void setNext(RawType aElem)
{
MOZ_ASSERT(isInList());
setNextUnsafe(aElem);
@@ -191,7 +228,7 @@
* linked list when you call setPrevious(); otherwise, this method will
* assert.
*/
- void setPrevious(T* aElem)
+ void setPrevious(RawType aElem)
{
MOZ_ASSERT(isInList());
setPreviousUnsafe(aElem);
@@ -209,6 +246,32 @@
mNext->mPrev = mPrev;
mNext = this;
mPrev = this;
+
+ Traits::exitList(this);
+ }
+
+ /*
+ * Remove this element from the list containing it. Returns a pointer to the
+ * element that follows this element (before it was removed). This method
+ * asserts if the element does not belong to a list.
+ */
+ ClientType removeAndGetNext()
+ {
+ ClientType r = getNext();
+ remove();
+ return r;
+ }
+
+ /*
+ * Remove this element from the list containing it. Returns a pointer to the
+ * previous element in the containing list (before the removal). This method
+ * asserts if the element does not belong to a list.
+ */
+ ClientType removeAndGetPrevious()
+ {
+ ClientType r = getPrevious();
+ remove();
+ return r;
}
/*
@@ -232,36 +295,37 @@
private:
friend class LinkedList<T>;
+ friend struct detail::LinkedListElementTraits<T>;
- enum NodeKind {
- NODE_KIND_NORMAL,
- NODE_KIND_SENTINEL
+ enum class NodeKind {
+ Normal,
+ Sentinel
};
explicit LinkedListElement(NodeKind nodeKind)
: mNext(this),
mPrev(this),
- mIsSentinel(nodeKind == NODE_KIND_SENTINEL)
+ mIsSentinel(nodeKind == NodeKind::Sentinel)
{ }
/*
* Return |this| cast to T* if we're a normal node, or return nullptr if
* we're a sentinel node.
*/
- T* asT()
+ RawType asT()
{
- return mIsSentinel ? nullptr : static_cast<T*>(this);
+ return mIsSentinel ? nullptr : static_cast<RawType>(this);
}
- const T* asT() const
+ ConstRawType asT() const
{
- return mIsSentinel ? nullptr : static_cast<const T*>(this);
+ return mIsSentinel ? nullptr : static_cast<ConstRawType>(this);
}
/*
* Insert aElem after this element, but don't check that this element is in
* the list. This is called by LinkedList::insertFront().
*/
- void setNextUnsafe(T* aElem)
+ void setNextUnsafe(RawType aElem)
{
LinkedListElement *listElem = static_cast<LinkedListElement*>(aElem);
MOZ_ASSERT(!listElem->isInList());
@@ -270,13 +334,15 @@
listElem->mPrev = this;
this->mNext->mPrev = listElem;
this->mNext = listElem;
+
+ Traits::enterList(aElem);
}
/*
* Insert aElem before this element, but don't check that this element is in
* the list. This is called by LinkedList::insertBack().
*/
- void setPreviousUnsafe(T* aElem)
+ void setPreviousUnsafe(RawType aElem)
{
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(aElem);
MOZ_ASSERT(!listElem->isInList());
@@ -285,9 +351,51 @@
listElem->mPrev = this->mPrev;
this->mPrev->mNext = listElem;
this->mPrev = listElem;
+
+ Traits::enterList(aElem);
+ }
+
+ /*
+ * Adjust mNext and mPrev for implementing move constructor and move
+ * assignment.
+ */
+ void adjustLinkForMove(LinkedListElement<T>&& aOther)
+ {
+ if (!aOther.isInList()) {
+ mNext = this;
+ mPrev = this;
+ return;
+ }
+
+ if (!mIsSentinel) {
+ Traits::enterList(this);
+ }
+
+ MOZ_ASSERT(aOther.mNext->mPrev == &aOther);
+ MOZ_ASSERT(aOther.mPrev->mNext == &aOther);
+
+ /*
+ * Initialize |this| with |aOther|'s mPrev/mNext pointers, and adjust those
+ * element to point to this one.
+ */
+ mNext = aOther.mNext;
+ mPrev = aOther.mPrev;
+
+ mNext->mPrev = this;
+ mPrev->mNext = this;
+
+ /*
+ * Adjust |aOther| so it doesn't think it's in a list. This makes it
+ * safely destructable.
+ */
+ aOther.mNext = &aOther;
+ aOther.mPrev = &aOther;
+
+ if (!mIsSentinel) {
+ Traits::exitList(&aOther);
+ }
}
-private:
LinkedListElement& operator=(const LinkedListElement<T>& aOther) = delete;
LinkedListElement(const LinkedListElement<T>& aOther) = delete;
};
@@ -296,16 +404,22 @@
class LinkedList
{
private:
+ typedef typename detail::LinkedListElementTraits<T> Traits;
+ typedef typename Traits::RawType RawType;
+ typedef typename Traits::ConstRawType ConstRawType;
+ typedef typename Traits::ClientType ClientType;
+ typedef typename Traits::ConstClientType ConstClientType;
+
LinkedListElement<T> sentinel;
public:
class Iterator {
- T* mCurrent;
+ RawType mCurrent;
public:
- explicit Iterator(T* aCurrent) : mCurrent(aCurrent) {}
+ explicit Iterator(RawType aCurrent) : mCurrent(aCurrent) {}
- T* operator *() const {
+ RawType operator *() const {
return mCurrent;
}
@@ -319,18 +433,30 @@
}
};
- LinkedList() : sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL) { }
+ LinkedList() : sentinel(LinkedListElement<T>::NodeKind::Sentinel) { }
LinkedList(LinkedList<T>&& aOther)
: sentinel(mozilla::Move(aOther.sentinel))
{ }
- ~LinkedList() { MOZ_ASSERT(isEmpty()); }
+ LinkedList& operator=(LinkedList<T>&& aOther)
+ {
+ MOZ_ASSERT(isEmpty(), "Assigning to a non-empty list leaks elements in that list!");
+ sentinel = mozilla::Move(aOther.sentinel);
+ return *this;
+ }
+
+ ~LinkedList() {
+ MOZ_ASSERT(isEmpty(),
+ "failing this assertion means this LinkedList's creator is "
+ "buggy: it should have removed all this list's elements before "
+ "the list's destruction");
+ }
/*
* Add aElem to the front of the list.
*/
- void insertFront(T* aElem)
+ void insertFront(RawType aElem)
{
/* Bypass setNext()'s this->isInList() assertion. */
sentinel.setNextUnsafe(aElem);
@@ -339,7 +465,7 @@
/*
* Add aElem to the back of the list.
*/
- void insertBack(T* aElem)
+ void insertBack(RawType aElem)
{
sentinel.setPreviousUnsafe(aElem);
}
@@ -347,24 +473,24 @@
/*
* Get the first element of the list, or nullptr if the list is empty.
*/
- T* getFirst() { return sentinel.getNext(); }
- const T* getFirst() const { return sentinel.getNext(); }
+ RawType getFirst() { return sentinel.getNext(); }
+ ConstRawType getFirst() const { return sentinel.getNext(); }
/*
* Get the last element of the list, or nullptr if the list is empty.
*/
- T* getLast() { return sentinel.getPrevious(); }
- const T* getLast() const { return sentinel.getPrevious(); }
+ RawType getLast() { return sentinel.getPrevious(); }
+ ConstRawType getLast() const { return sentinel.getPrevious(); }
/*
* Get and remove the first element of the list. If the list is empty,
* return nullptr.
*/
- T* popFirst()
+ ClientType popFirst()
{
- T* ret = sentinel.getNext();
+ ClientType ret = sentinel.getNext();
if (ret) {
- static_cast<LinkedListElement<T>*>(ret)->remove();
+ static_cast<LinkedListElement<T>*>(RawType(ret))->remove();
}
return ret;
}
@@ -373,11 +499,11 @@
* Get and remove the last element of the list. If the list is empty,
* return nullptr.
*/
- T* popLast()
+ ClientType popLast()
{
- T* ret = sentinel.getPrevious();
+ ClientType ret = sentinel.getPrevious();
if (ret) {
- static_cast<LinkedListElement<T>*>(ret)->remove();
+ static_cast<LinkedListElement<T>*>(RawType(ret))->remove();
}
return ret;
}
@@ -498,10 +624,10 @@
private:
friend class LinkedListElement<T>;
- void assertContains(const T* aValue) const
+ void assertContains(const RawType aValue) const
{
#ifdef DEBUG
- for (const T* elem = getFirst(); elem; elem = elem->getNext()) {
+ for (ConstRawType elem = getFirst(); elem; elem = elem->getNext()) {
if (elem == aValue) {
return;
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/MacroArgs.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/MacroArgs.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/MacroArgs.h
@@ -11,6 +11,10 @@
#ifndef mozilla_MacroArgs_h
#define mozilla_MacroArgs_h
+// Concatenates pre-processor tokens in a way that can be used with __LINE__.
+#define MOZ_CONCAT2(x, y) x ## y
+#define MOZ_CONCAT(x, y) MOZ_CONCAT2(x, y)
+
/*
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) counts the number of variadic
* arguments and prefixes it with |aPrefix|. For example:
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/MathAlgorithms.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/MathAlgorithms.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/MathAlgorithms.h
@@ -340,7 +340,7 @@
return detail::CountPopulation32(aValue);
}
-/** Analogous to CoutPopulation32, but for 64-bit numbers */
+/** Analogous to CountPopulation32, but for 64-bit numbers */
inline uint_fast8_t
CountPopulation64(uint64_t aValue)
{
@@ -515,7 +515,7 @@
* Zero is not an integer power of two. (-Inf is not an integer)
*/
template<typename T>
-inline bool
+constexpr bool
IsPowerOfTwo(T x)
{
static_assert(IsUnsigned<T>::value,
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Maybe.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Maybe.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Maybe.h
@@ -16,6 +16,7 @@
#include "mozilla/TypeTraits.h"
#include <new> // for placement new
+#include <type_traits>
namespace mozilla {
@@ -101,6 +102,26 @@
}
}
+ /**
+ * Maybe<T*> can be copy-constructed from a Maybe<U*> if U* and T* are
+ * compatible, or from Maybe<decltype(nullptr)>.
+ */
+ template<typename U,
+ typename =
+ typename std::enable_if<std::is_pointer<T>::value &&
+ (std::is_same<U, decltype(nullptr)>::value ||
+ (std::is_pointer<U>::value &&
+ std::is_base_of<typename std::remove_pointer<T>::type,
+ typename std::remove_pointer<U>::type>::value))>::type>
+ MOZ_IMPLICIT
+ Maybe(const Maybe<U>& aOther)
+ : mIsSome(false)
+ {
+ if (aOther.isSome()) {
+ emplace(*aOther);
+ }
+ }
+
Maybe(Maybe&& aOther)
: mIsSome(false)
{
@@ -110,6 +131,27 @@
}
}
+ /**
+ * Maybe<T*> can be move-constructed from a Maybe<U*> if U* and T* are
+ * compatible, or from Maybe<decltype(nullptr)>.
+ */
+ template<typename U,
+ typename =
+ typename std::enable_if<std::is_pointer<T>::value &&
+ (std::is_same<U, decltype(nullptr)>::value ||
+ (std::is_pointer<U>::value &&
+ std::is_base_of<typename std::remove_pointer<T>::type,
+ typename std::remove_pointer<U>::type>::value))>::type>
+ MOZ_IMPLICIT
+ Maybe(Maybe<U>&& aOther)
+ : mIsSome(false)
+ {
+ if (aOther.isSome()) {
+ emplace(Move(*aOther));
+ aOther.reset();
+ }
+ }
+
Maybe& operator=(const Maybe& aOther)
{
if (&aOther != this) {
@@ -324,53 +366,57 @@
/* If |isSome()|, runs the provided function or functor on the contents of
* this Maybe. */
- template<typename F, typename... Args>
- void apply(F&& aFunc, Args&&... aArgs)
+ template<typename Func>
+ Maybe& apply(Func aFunc)
{
if (isSome()) {
- aFunc(ref(), Forward<Args>(aArgs)...);
+ aFunc(ref());
}
+ return *this;
}
- template<typename F, typename... Args>
- void apply(F&& aFunc, Args&&... aArgs) const
+ template<typename Func>
+ const Maybe& apply(Func aFunc) const
{
if (isSome()) {
- aFunc(ref(), Forward<Args>(aArgs)...);
+ aFunc(ref());
}
+ return *this;
}
/*
* If |isSome()|, runs the provided function and returns the result wrapped
* in a Maybe. If |isNothing()|, returns an empty Maybe value.
*/
- template<typename R, typename... FArgs, typename... Args>
- Maybe<R> map(R (*aFunc)(T&, FArgs...), Args&&... aArgs)
+ template<typename Func>
+ auto map(Func aFunc) -> Maybe<decltype(aFunc(DeclVal<Maybe<T>>().ref()))>
{
+ using ReturnType = decltype(aFunc(ref()));
if (isSome()) {
- Maybe<R> val;
- val.emplace(aFunc(ref(), Forward<Args>(aArgs)...));
+ Maybe<ReturnType> val;
+ val.emplace(aFunc(ref()));
return val;
}
- return Maybe<R>();
+ return Maybe<ReturnType>();
}
- template<typename R, typename... FArgs, typename... Args>
- Maybe<R> map(R (*aFunc)(const T&, FArgs...), Args&&... aArgs) const
+ template<typename Func>
+ auto map(Func aFunc) const -> Maybe<decltype(aFunc(DeclVal<Maybe<T>>().ref()))>
{
+ using ReturnType = decltype(aFunc(ref()));
if (isSome()) {
- Maybe<R> val;
- val.emplace(aFunc(ref(), Forward<Args>(aArgs)...));
+ Maybe<ReturnType> val;
+ val.emplace(aFunc(ref()));
return val;
}
- return Maybe<R>();
+ return Maybe<ReturnType>();
}
/* If |isSome()|, empties this Maybe and destroys its contents. */
void reset()
{
if (isSome()) {
- ref().~T();
+ ref().T::~T();
mIsSome = false;
}
}
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/NotNull.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/NotNull.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/NotNull.h
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_NotNull_h
+#define mozilla_NotNull_h
+
+// It's often unclear if a particular pointer, be it raw (T*) or smart
+// (RefPtr<T>, nsCOMPtr<T>, etc.) can be null. This leads to missing null
+// checks (which can cause crashes) and unnecessary null checks (which clutter
+// the code).
+//
+// C++ has a built-in alternative that avoids these problems: references. This
+// module defines another alternative, NotNull, which can be used in cases
+// where references are not suitable.
+//
+// In the comments below we use the word "handle" to cover all varieties of
+// pointers and references.
+//
+// References
+// ----------
+// References are always non-null. (You can do |T& r = *p;| where |p| is null,
+// but that's undefined behaviour. C++ doesn't provide any built-in, ironclad
+// guarantee of non-nullness.)
+//
+// A reference works well when you need a temporary handle to an existing
+// single object, e.g. for passing a handle to a function, or as a local handle
+// within another object. (In Rust parlance, this is a "borrow".)
+//
+// A reference is less appropriate in the following cases.
+//
+// - As a primary handle to an object. E.g. code such as this is possible but
+// strange: |T& t = *new T(); ...; delete &t;|
+//
+// - As a handle to an array. It's common for |T*| to refer to either a single
+// |T| or an array of |T|, but |T&| cannot refer to an array of |T| because
+// you can't index off a reference (at least, not without first converting it
+// to a pointer).
+//
+// - When the handle identity is meaningful, e.g. if you have a hashtable of
+// handles, because you have to use |&| on the reference to convert it to a
+// pointer.
+//
+// - Some people don't like using non-const references as function parameters,
+// because it is not clear at the call site that the argument might be
+// modified.
+//
+// - When you need "smart" behaviour. E.g. we lack reference equivalents to
+// RefPtr and nsCOMPtr.
+//
+// - When interfacing with code that uses pointers a lot, sometimes using a
+// reference just feels like an odd fit.
+//
+// Furthermore, a reference is impossible in the following cases.
+//
+// - When the handle is rebound to another object. References don't allow this.
+//
+// - When the handle has type |void|. |void&| is not allowed.
+//
+// NotNull is an alternative that can be used in any of the above cases except
+// for the last one, where the handle type is |void|. See below.
+
+#include "mozilla/Assertions.h"
+
+namespace mozilla {
+
+// NotNull can be used to wrap a "base" pointer (raw or smart) to indicate it
+// is not null. Some examples:
+//
+// - NotNull<char*>
+// - NotNull<RefPtr<Event>>
+// - NotNull<nsCOMPtr<Event>>
+//
+// NotNull has the following notable properties.
+//
+// - It has zero space overhead.
+//
+// - It must be initialized explicitly. There is no default initialization.
+//
+// - It auto-converts to the base pointer type.
+//
+// - It does not auto-convert from a base pointer. Implicit conversion from a
+// less-constrained type (e.g. T*) to a more-constrained type (e.g.
+// NotNull<T*>) is dangerous. Creation and assignment from a base pointer can
+// only be done with WrapNotNull(), which makes them impossible to overlook,
+// both when writing and reading code.
+//
+// - When initialized (or assigned) it is checked, and if it is null we abort.
+// This guarantees that it cannot be null.
+//
+// - |operator bool()| is deleted. This means you cannot check a NotNull in a
+// boolean context, which eliminates the possibility of unnecessary null
+// checks.
+//
+// NotNull currently doesn't work with UniquePtr. See
+// https://github.com/Microsoft/GSL/issues/89 for some discussion.
+//
+template <typename T>
+class NotNull
+{
+ template <typename U> friend NotNull<U> WrapNotNull(U aBasePtr);
+
+ T mBasePtr;
+
+ // This constructor is only used by WrapNotNull().
+ template <typename U>
+ explicit NotNull(U aBasePtr) : mBasePtr(aBasePtr) {}
+
+public:
+ // Disallow default construction.
+ NotNull() = delete;
+
+ // Construct/assign from another NotNull with a compatible base pointer type.
+ template <typename U>
+ MOZ_IMPLICIT NotNull(const NotNull<U>& aOther) : mBasePtr(aOther.get()) {}
+
+ // Default copy/move construction and assignment.
+ NotNull(const NotNull<T>&) = default;
+ NotNull<T>& operator=(const NotNull<T>&) = default;
+ NotNull(NotNull<T>&&) = default;
+ NotNull<T>& operator=(NotNull<T>&&) = default;
+
+ // Disallow null checks, which are unnecessary for this type.
+ explicit operator bool() const = delete;
+
+ // Explicit conversion to a base pointer. Use only to resolve ambiguity or to
+ // get a castable pointer.
+ const T& get() const { return mBasePtr; }
+
+ // Implicit conversion to a base pointer. Preferable to get().
+ operator const T&() const { return get(); }
+
+ // Dereference operators.
+ const T& operator->() const { return get(); }
+ decltype(*mBasePtr) operator*() const { return *mBasePtr; }
+};
+
+template <typename T>
+NotNull<T>
+WrapNotNull(const T aBasePtr)
+{
+ NotNull<T> notNull(aBasePtr);
+ MOZ_RELEASE_ASSERT(aBasePtr);
+ return notNull;
+}
+
+// Compare two NotNulls.
+template <typename T, typename U>
+inline bool
+operator==(const NotNull<T>& aLhs, const NotNull<U>& aRhs)
+{
+ return aLhs.get() == aRhs.get();
+}
+template <typename T, typename U>
+inline bool
+operator!=(const NotNull<T>& aLhs, const NotNull<U>& aRhs)
+{
+ return aLhs.get() != aRhs.get();
+}
+
+// Compare a NotNull to a base pointer.
+template <typename T, typename U>
+inline bool
+operator==(const NotNull<T>& aLhs, const U& aRhs)
+{
+ return aLhs.get() == aRhs;
+}
+template <typename T, typename U>
+inline bool
+operator!=(const NotNull<T>& aLhs, const U& aRhs)
+{
+ return aLhs.get() != aRhs;
+}
+
+// Compare a base pointer to a NotNull.
+template <typename T, typename U>
+inline bool
+operator==(const T& aLhs, const NotNull<U>& aRhs)
+{
+ return aLhs == aRhs.get();
+}
+template <typename T, typename U>
+inline bool
+operator!=(const T& aLhs, const NotNull<U>& aRhs)
+{
+ return aLhs != aRhs.get();
+}
+
+// Disallow comparing a NotNull to a nullptr.
+template <typename T>
+bool
+operator==(const NotNull<T>&, decltype(nullptr)) = delete;
+template <typename T>
+bool
+operator!=(const NotNull<T>&, decltype(nullptr)) = delete;
+
+// Disallow comparing a nullptr to a NotNull.
+template <typename T>
+bool
+operator==(decltype(nullptr), const NotNull<T>&) = delete;
+template <typename T>
+bool
+operator!=(decltype(nullptr), const NotNull<T>&) = delete;
+
+} // namespace mozilla
+
+#endif /* mozilla_NotNull_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/NumericLimits.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/NumericLimits.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/NumericLimits.h
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/* Compatibility with std::numeric_limits<char16_t>. */
-
-#ifndef mozilla_NumericLimits_h
-#define mozilla_NumericLimits_h
-
-#include "mozilla/Char16.h"
-
-#include <limits>
-#include <stdint.h>
-
-namespace mozilla {
-
-/**
- * The NumericLimits class provides a compatibility layer with
- * std::numeric_limits for char16_t, otherwise it is exactly the same as
- * std::numeric_limits. Code which does not need std::numeric_limits<char16_t>
- * should avoid using NumericLimits.
- */
-template<typename T>
-class NumericLimits : public std::numeric_limits<T>
-{
-};
-
-#ifdef MOZ_CHAR16_IS_NOT_WCHAR
-template<>
-class NumericLimits<char16_t> : public std::numeric_limits<uint16_t>
-{
- // char16_t and uint16_t numeric limits should be exactly the same.
-};
-#endif
-
-} // namespace mozilla
-
-#endif /* mozilla_NumericLimits_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/OperatorNewExtensions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/OperatorNewExtensions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/OperatorNewExtensions.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* A version of |operator new| that eschews mandatory null-checks. */
+
+#ifndef mozilla_OperatorNewExtensions_h
+#define mozilla_OperatorNewExtensions_h
+
+#include "mozilla/Assertions.h"
+
+// Credit goes to WebKit for this implementation, cf.
+// https://bugs.webkit.org/show_bug.cgi?id=74676
+namespace mozilla {
+enum NotNullTag {
+ KnownNotNull,
+};
+} // namespace mozilla
+
+/*
+ * The logic here is a little subtle. [expr.new] states that if the allocation
+ * function being called returns null, then object initialization must not be
+ * done, and the entirety of the new expression must return null. Non-throwing
+ * (noexcept) functions are defined to return null to indicate failure. The
+ * standard placement operator new is defined in such a way, and so it requires
+ * a null check, even when that null check would be extraneous. Functions
+ * declared without such a specification are defined to throw std::bad_alloc if
+ * they fail, and return a non-null pointer otherwise. We compile without
+ * exceptions, so any placement new overload we define that doesn't declare
+ * itself as noexcept must therefore avoid generating a null check. Below is
+ * just such an overload.
+ *
+ * You might think that MOZ_NONNULL might perform the same function, but
+ * MOZ_NONNULL isn't supported on all of our compilers, and even when it is
+ * supported, doesn't work on all the versions we support. And even keeping
+ * those limitations in mind, we can't put MOZ_NONNULL on the global,
+ * standardized placement new function in any event.
+ *
+ * We deliberately don't add MOZ_NONNULL(3) to tag |p| as non-null, to benefit
+ * hypothetical static analyzers. Doing so makes |MOZ_ASSERT(p)|'s internal
+ * test vacuous, and some compilers warn about such vacuous tests.
+ */
+inline void*
+operator new(size_t, mozilla::NotNullTag, void* p)
+{
+ MOZ_ASSERT(p);
+ return p;
+}
+
+#endif // mozilla_OperatorNewExtensions_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Poison.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Poison.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Poison.h
@@ -59,4 +59,50 @@
MOZ_END_EXTERN_C
+#if defined(__cplusplus)
+
+namespace mozilla {
+
+/**
+ * This class is designed to cause crashes when various kinds of memory
+ * corruption are observed. For instance, let's say we have a class C where we
+ * suspect out-of-bounds writes to some members. We can insert a member of type
+ * Poison near the members we suspect are being corrupted by out-of-bounds
+ * writes. Or perhaps we have a class K we suspect is subject to use-after-free
+ * violations, in which case it doesn't particularly matter where in the class
+ * we add the member of type Poison.
+ *
+ * In either case, we then insert calls to Check() throughout the code. Doing
+ * so enables us to narrow down the location where the corruption is occurring.
+ * A pleasant side-effect of these additional Check() calls is that crash
+ * signatures may become more regular, as crashes will ideally occur
+ * consolidated at the point of a Check(), rather than scattered about at
+ * various uses of the corrupted memory.
+ */
+class CorruptionCanary {
+public:
+ CorruptionCanary() {
+ mValue = kCanarySet;
+ }
+
+ ~CorruptionCanary() {
+ Check();
+ mValue = mozPoisonValue();
+ }
+
+ void Check() const {
+ if (mValue != kCanarySet) {
+ MOZ_CRASH("Canary check failed, check lifetime");
+ }
+ }
+
+private:
+ static const uintptr_t kCanarySet = 0x0f0b0f0b;
+ uintptr_t mValue;
+};
+
+} // mozilla
+
+#endif
+
#endif /* mozilla_Poison_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Range.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Range.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Range.h
@@ -8,6 +8,7 @@
#define mozilla_Range_h
#include "mozilla/RangedPtr.h"
+#include "mozilla/TypeTraits.h"
#include <stddef.h>
@@ -26,8 +27,24 @@
: mStart(aPtr, aPtr, aPtr + aLength),
mEnd(aPtr + aLength, aPtr, aPtr + aLength)
{}
+ Range(const RangedPtr<T>& aStart, const RangedPtr<T>& aEnd)
+ : mStart(aStart.get(), aStart.get(), aEnd.get()),
+ mEnd(aEnd.get(), aStart.get(), aEnd.get())
+ {
+ // Only accept two RangedPtrs within the same range.
+ aStart.checkIdenticalRange(aEnd);
+ MOZ_ASSERT(aStart <= aEnd);
+ }
+
+ template<typename U,
+ class = typename EnableIf<IsConvertible<U (*)[], T (*)[]>::value,
+ int>::Type>
+ MOZ_IMPLICIT Range(const Range<U>& aOther)
+ : mStart(aOther.mStart),
+ mEnd(aOther.mEnd)
+ {}
- RangedPtr<T> start() const { return mStart; }
+ RangedPtr<T> begin() const { return mStart; }
RangedPtr<T> end() const { return mEnd; }
size_t length() const { return mEnd - mStart; }
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RangedPtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RangedPtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RangedPtr.h
@@ -117,6 +117,12 @@
explicit operator bool() const { return mPtr != nullptr; }
+ void checkIdenticalRange(const RangedPtr<T>& aOther) const
+ {
+ MOZ_ASSERT(mRangeStart == aOther.mRangeStart);
+ MOZ_ASSERT(mRangeEnd == aOther.mRangeEnd);
+ }
+
/*
* You can only assign one RangedPtr into another if the two pointers have
* the same valid range:
@@ -129,21 +135,20 @@
*/
RangedPtr<T>& operator=(const RangedPtr<T>& aOther)
{
- MOZ_ASSERT(mRangeStart == aOther.mRangeStart);
- MOZ_ASSERT(mRangeEnd == aOther.mRangeEnd);
+ checkIdenticalRange(aOther);
mPtr = aOther.mPtr;
checkSanity();
return *this;
}
- RangedPtr<T> operator+(size_t aInc)
+ RangedPtr<T> operator+(size_t aInc) const
{
MOZ_ASSERT(aInc <= size_t(-1) / sizeof(T));
MOZ_ASSERT(asUintptr() + aInc * sizeof(T) >= asUintptr());
return create(mPtr + aInc);
}
- RangedPtr<T> operator-(size_t aDec)
+ RangedPtr<T> operator-(size_t aDec) const
{
MOZ_ASSERT(aDec <= size_t(-1) / sizeof(T));
MOZ_ASSERT(asUintptr() - aDec * sizeof(T) <= asUintptr());
@@ -220,6 +225,13 @@
return *mPtr;
}
+ T* operator->() const
+ {
+ MOZ_ASSERT(mPtr >= mRangeStart);
+ MOZ_ASSERT(mPtr < mRangeEnd);
+ return mPtr;
+ }
+
template <typename U>
bool operator==(const RangedPtr<U>& aOther) const
{
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RefCounted.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RefCounted.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RefCounted.h
@@ -22,7 +22,6 @@
#endif
#if defined(MOZILLA_INTERNAL_API) && \
- !defined(MOZILLA_XPCOMRT_API) && \
(defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
#define MOZ_REFCOUNTED_LEAK_CHECKING
#endif
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RefPtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RefPtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/RefPtr.h
@@ -19,6 +19,28 @@
namespace mozilla {
template<class T> class OwningNonNull;
+template<class T> class StaticRefPtr;
+
+// Traditionally, RefPtr supports automatic refcounting of any pointer type
+// with AddRef() and Release() methods that follow the traditional semantics.
+//
+// This traits class can be specialized to operate on other pointer types. For
+// example, we specialize this trait for opaque FFI types that represent
+// refcounted objects in Rust.
+//
+// Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
+// qualified type.
+template<class U>
+struct RefPtrTraits
+{
+ static void AddRef(U* aPtr) {
+ aPtr->AddRef();
+ }
+ static void Release(U* aPtr) {
+ aPtr->Release();
+ }
+};
+
} // namespace mozilla
template <class T>
@@ -29,7 +51,7 @@
assign_with_AddRef(T* aRawPtr)
{
if (aRawPtr) {
- AddRefTraits<T>::AddRef(aRawPtr);
+ ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
}
assign_assuming_AddRef(aRawPtr);
}
@@ -40,7 +62,7 @@
T* oldPtr = mRawPtr;
mRawPtr = aNewPtr;
if (oldPtr) {
- AddRefTraits<T>::Release(oldPtr);
+ ConstRemovingRefPtrTraits<T>::Release(oldPtr);
}
}
@@ -53,14 +75,14 @@
~RefPtr()
{
if (mRawPtr) {
- AddRefTraits<T>::Release(mRawPtr);
+ ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
}
}
// Constructors
RefPtr()
- : mRawPtr(0)
+ : mRawPtr(nullptr)
// default constructor
{
}
@@ -70,7 +92,7 @@
// copy-constructor
{
if (mRawPtr) {
- AddRefTraits<T>::AddRef(mRawPtr);
+ ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
}
}
@@ -86,10 +108,15 @@
: mRawPtr(aRawPtr)
{
if (mRawPtr) {
- AddRefTraits<T>::AddRef(mRawPtr);
+ ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
}
}
+ MOZ_IMPLICIT RefPtr(decltype(nullptr))
+ : mRawPtr(nullptr)
+ {
+ }
+
template <typename I>
MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
: mRawPtr(aSmartPtr.take())
@@ -110,7 +137,7 @@
// copy-construct from a smart pointer with a related pointer type
{
if (mRawPtr) {
- AddRefTraits<T>::AddRef(mRawPtr);
+ ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
}
}
@@ -127,9 +154,20 @@
template<class U>
MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther);
+ // Defined in StaticPtr.h
+ template<class U>
+ MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
+
// Assignment operators
RefPtr<T>&
+ operator=(decltype(nullptr))
+ {
+ assign_assuming_AddRef(nullptr);
+ return *this;
+ }
+
+ RefPtr<T>&
operator=(const RefPtr<T>& aRhs)
// copy assignment operator
{
@@ -187,6 +225,11 @@
RefPtr<T>&
operator=(const mozilla::OwningNonNull<U>& aOther);
+ // Defined in StaticPtr.h
+ template<class U>
+ RefPtr<T>&
+ operator=(const mozilla::StaticRefPtr<U>& aOther);
+
// Other pointer operators
void
@@ -212,7 +255,7 @@
// return the value of mRawPtr and null out mRawPtr. Useful for
// already_AddRefed return values.
{
- T* temp = 0;
+ T* temp = nullptr;
swap(temp);
return already_AddRefed<T>(temp);
}
@@ -227,7 +270,7 @@
{
MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
*aRhs = mRawPtr;
- mRawPtr = 0;
+ mRawPtr = nullptr;
}
T*
@@ -272,7 +315,7 @@
T*
operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
{
- MOZ_ASSERT(mRawPtr != 0,
+ MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator->().");
return get();
}
@@ -299,7 +342,7 @@
template <typename R, typename... Args>
Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const
{
- MOZ_ASSERT(mRawPtr != 0,
+ MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator->*().");
return Proxy<R, Args...>(get(), aFptr);
}
@@ -324,7 +367,7 @@
T&
operator*() const
{
- MOZ_ASSERT(mRawPtr != 0,
+ MOZ_ASSERT(mRawPtr != nullptr,
"You can't dereference a NULL RefPtr with operator*().");
return *get();
}
@@ -332,7 +375,7 @@
T**
StartAssignment()
{
- assign_assuming_AddRef(0);
+ assign_assuming_AddRef(nullptr);
return reinterpret_cast<T**>(&mRawPtr);
}
private:
@@ -346,40 +389,24 @@
// This should be sound because while |RefPtr<const T>| provides a
// const view of an object, the object itself should not be const (it
// would have to be allocated as |new const T| or similar to be const).
-
- // Because some classes make their AddRef/Release implementations private
- // and then friend RefPtr to make them visible, we redirect AddRefTraits's
- // calls to static helper functions in RefPtr so we don't have to figure
- // out how to make AddRefTraits visible to *those* classes.
- static MOZ_ALWAYS_INLINE void
- AddRefTraitsAddRefHelper(typename mozilla::RemoveConst<T>::Type* aPtr)
- {
- aPtr->AddRef();
- }
- static MOZ_ALWAYS_INLINE void
- AddRefTraitsReleaseHelper(typename mozilla::RemoveConst<T>::Type* aPtr)
- {
- aPtr->Release();
- }
-
template<class U>
- struct AddRefTraits
+ struct ConstRemovingRefPtrTraits
{
static void AddRef(U* aPtr) {
- RefPtr<T>::AddRefTraitsAddRefHelper(aPtr);
+ mozilla::RefPtrTraits<U>::AddRef(aPtr);
}
static void Release(U* aPtr) {
- RefPtr<T>::AddRefTraitsReleaseHelper(aPtr);
+ mozilla::RefPtrTraits<U>::Release(aPtr);
}
};
template<class U>
- struct AddRefTraits<const U>
+ struct ConstRemovingRefPtrTraits<const U>
{
static void AddRef(const U* aPtr) {
- RefPtr<T>::AddRefTraitsAddRefHelper(const_cast<U*>(aPtr));
+ mozilla::RefPtrTraits<U>::AddRef(const_cast<U*>(aPtr));
}
static void Release(const U* aPtr) {
- RefPtr<T>::AddRefTraitsReleaseHelper(const_cast<U*>(aPtr));
+ mozilla::RefPtrTraits<U>::Release(const_cast<U*>(aPtr));
}
};
};
@@ -591,7 +618,15 @@
template <class T>
inline already_AddRefed<T>
-do_AddRef(T*&& aObj)
+do_AddRef(T* aObj)
+{
+ RefPtr<T> ref(aObj);
+ return ref.forget();
+}
+
+template <class T>
+inline already_AddRefed<T>
+do_AddRef(const RefPtr<T>& aObj)
{
RefPtr<T> ref(aObj);
return ref.forget();
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Saturate.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Saturate.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Saturate.h
@@ -0,0 +1,288 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Provides saturation arithmetics for scalar types. */
+
+#ifndef mozilla_Saturate_h
+#define mozilla_Saturate_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Move.h"
+#include "mozilla/TypeTraits.h"
+
+#include <limits>
+
+namespace mozilla {
+namespace detail {
+
+/**
+ * |SaturateOp<T>| wraps scalar values for saturation arithmetics. Usage:
+ *
+ * uint32_t value = 1;
+ *
+ * ++SaturateOp<uint32_t>(value); // value is 2
+ * --SaturateOp<uint32_t>(value); // value is 1
+ * --SaturateOp<uint32_t>(value); // value is 0
+ * --SaturateOp<uint32_t>(value); // value is still 0
+ *
+ * Please add new operators when required.
+ *
+ * |SaturateOp<T>| will saturate at the minimum and maximum values of
+ * type T. If you need other bounds, implement a clamped-type class and
+ * specialize the type traits accordingly.
+ */
+template <typename T>
+class SaturateOp
+{
+public:
+ explicit SaturateOp(T& aValue)
+ : mValue(aValue)
+ {
+ // We should actually check for |std::is_scalar<T>::value| to be
+ // true, but this type trait is not available everywhere. Relax
+ // this assertion if you want to use floating point values as well.
+ static_assert(IsIntegral<T>::value,
+ "Integral type required in instantiation");
+ }
+
+ // Add and subtract operators
+
+ T operator+(const T& aRhs) const
+ {
+ return T(mValue) += aRhs;
+ }
+
+ T operator-(const T& aRhs) const
+ {
+ return T(mValue) -= aRhs;
+ }
+
+ // Compound operators
+
+ const T& operator+=(const T& aRhs) const
+ {
+ const T min = std::numeric_limits<T>::min();
+ const T max = std::numeric_limits<T>::max();
+
+ if (aRhs > static_cast<T>(0)) {
+ mValue = (max - aRhs) < mValue ? max : mValue + aRhs;
+ } else {
+ mValue = (min - aRhs) > mValue ? min : mValue + aRhs;
+ }
+ return mValue;
+ }
+
+ const T& operator-=(const T& aRhs) const
+ {
+ const T min = std::numeric_limits<T>::min();
+ const T max = std::numeric_limits<T>::max();
+
+ if (aRhs > static_cast<T>(0)) {
+ mValue = (min + aRhs) > mValue ? min : mValue - aRhs;
+ } else {
+ mValue = (max + aRhs) < mValue ? max : mValue - aRhs;
+ }
+ return mValue;
+ }
+
+ // Increment and decrement operators
+
+ const T& operator++() const // prefix
+ {
+ return operator+=(static_cast<T>(1));
+ }
+
+ T operator++(int) const // postfix
+ {
+ const T value(mValue);
+ operator++();
+ return value;
+ }
+
+ const T& operator--() const // prefix
+ {
+ return operator-=(static_cast<T>(1));
+ }
+
+ T operator--(int) const // postfix
+ {
+ const T value(mValue);
+ operator--();
+ return value;
+ }
+
+private:
+ SaturateOp(const SaturateOp<T>&) = delete;
+ SaturateOp(SaturateOp<T>&&) = delete;
+ SaturateOp& operator=(const SaturateOp<T>&) = delete;
+ SaturateOp& operator=(SaturateOp<T>&&) = delete;
+
+ T& mValue;
+};
+
+/**
+ * |Saturate<T>| is a value type for saturation arithmetics. It's
+ * build on top of |SaturateOp<T>|.
+ */
+template <typename T>
+class Saturate
+{
+public:
+ Saturate() = default;
+ MOZ_IMPLICIT Saturate(const Saturate<T>&) = default;
+
+ MOZ_IMPLICIT Saturate(Saturate<T>&& aValue)
+ {
+ mValue = Move(aValue.mValue);
+ }
+
+ explicit Saturate(const T& aValue)
+ : mValue(aValue)
+ { }
+
+ const T& value() const
+ {
+ return mValue;
+ }
+
+ // Compare operators
+
+ bool operator==(const Saturate<T>& aRhs) const
+ {
+ return mValue == aRhs.mValue;
+ }
+
+ bool operator!=(const Saturate<T>& aRhs) const
+ {
+ return !operator==(aRhs);
+ }
+
+ bool operator==(const T& aRhs) const
+ {
+ return mValue == aRhs;
+ }
+
+ bool operator!=(const T& aRhs) const
+ {
+ return !operator==(aRhs);
+ }
+
+ // Assignment operators
+
+ Saturate<T>& operator=(const Saturate<T>&) = default;
+
+ Saturate<T>& operator=(Saturate<T>&& aRhs)
+ {
+ mValue = Move(aRhs.mValue);
+ return *this;
+ }
+
+ // Add and subtract operators
+
+ Saturate<T> operator+(const Saturate<T>& aRhs) const
+ {
+ Saturate<T> lhs(mValue);
+ return lhs += aRhs.mValue;
+ }
+
+ Saturate<T> operator+(const T& aRhs) const
+ {
+ Saturate<T> lhs(mValue);
+ return lhs += aRhs;
+ }
+
+ Saturate<T> operator-(const Saturate<T>& aRhs) const
+ {
+ Saturate<T> lhs(mValue);
+ return lhs -= aRhs.mValue;
+ }
+
+ Saturate<T> operator-(const T& aRhs) const
+ {
+ Saturate<T> lhs(mValue);
+ return lhs -= aRhs;
+ }
+
+ // Compound operators
+
+ Saturate<T>& operator+=(const Saturate<T>& aRhs)
+ {
+ SaturateOp<T>(mValue) += aRhs.mValue;
+ return *this;
+ }
+
+ Saturate<T>& operator+=(const T& aRhs)
+ {
+ SaturateOp<T>(mValue) += aRhs;
+ return *this;
+ }
+
+ Saturate<T>& operator-=(const Saturate<T>& aRhs)
+ {
+ SaturateOp<T>(mValue) -= aRhs.mValue;
+ return *this;
+ }
+
+ Saturate<T>& operator-=(const T& aRhs)
+ {
+ SaturateOp<T>(mValue) -= aRhs;
+ return *this;
+ }
+
+ // Increment and decrement operators
+
+ Saturate<T>& operator++() // prefix
+ {
+ ++SaturateOp<T>(mValue);
+ return *this;
+ }
+
+ Saturate<T> operator++(int) // postfix
+ {
+ return Saturate<T>(SaturateOp<T>(mValue)++);
+ }
+
+ Saturate<T>& operator--() // prefix
+ {
+ --SaturateOp<T>(mValue);
+ return *this;
+ }
+
+ Saturate<T> operator--(int) // postfix
+ {
+ return Saturate<T>(SaturateOp<T>(mValue)--);
+ }
+
+private:
+ T mValue;
+};
+
+} // namespace detail
+
+typedef detail::Saturate<int8_t> SaturateInt8;
+typedef detail::Saturate<int16_t> SaturateInt16;
+typedef detail::Saturate<int32_t> SaturateInt32;
+typedef detail::Saturate<uint8_t> SaturateUint8;
+typedef detail::Saturate<uint16_t> SaturateUint16;
+typedef detail::Saturate<uint32_t> SaturateUint32;
+
+} // namespace mozilla
+
+template<typename LhsT, typename RhsT>
+bool
+operator==(LhsT aLhs, const mozilla::detail::Saturate<RhsT>& aRhs)
+{
+ return aRhs.operator==(static_cast<RhsT>(aLhs));
+}
+
+template<typename LhsT, typename RhsT>
+bool
+operator!=(LhsT aLhs, const mozilla::detail::Saturate<RhsT>& aRhs)
+{
+ return !(aLhs == aRhs);
+}
+
+#endif // mozilla_Saturate_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Scoped.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Scoped.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Scoped.h
@@ -15,20 +15,16 @@
* Resource Acquisition Is Initialization is a programming idiom used
* to write robust code that is able to deallocate resources properly,
* even in presence of execution errors or exceptions that need to be
- * propagated. The Scoped* classes defined in this header perform the
+ * propagated. The Scoped* classes defined via the |SCOPED_TEMPLATE|
+ * and |MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLTE| macros perform the
* deallocation of the resource they hold once program execution
* reaches the end of the scope for which they have been defined.
+ * These macros have been used to automatically close file
+ * descriptors/file handles when reaching the end of the scope,
+ * graphics contexts, etc.
*
- * This header provides the following RAII classes:
- *
- * - |ScopedFreePtr| - a container for a pointer, that automatically calls
- * |free()| at the end of the scope;
- * - |ScopedDeletePtr| - a container for a pointer, that automatically calls
- * |delete| at the end of the scope;
- *
- * |ScopedDeleteArray| is removed in favor of |UniquePtr<T[]>|.
- *
- * The general scenario for each of the RAII classes is the following:
+ * The general scenario for RAII classes created by the above macros
+ * is the following:
*
* ScopedClass foo(create_value());
* // ... In this scope, |foo| is defined. Use |foo.get()| or |foo.rwget()|
@@ -44,14 +40,6 @@
* the end of the scope;
* - if |forget()| has been called, any control on the resource is unbound
* and the resource is not deallocated by the class.
- *
- * Extension:
- *
- * In addition, this header provides class |Scoped| and macros |SCOPED_TEMPLATE|
- * and |MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE| to simplify the definition
- * of RAII classes for other scenarios. These macros have been used to
- * automatically close file descriptors/file handles when reaching the end of
- * the scope, graphics contexts, etc.
*/
#include "mozilla/Assertions.h"
@@ -220,35 +208,6 @@
};
/*
- * ScopedFreePtr is a RAII wrapper for pointers that need to be free()d.
- *
- * struct S { ... };
- * ScopedFreePtr<S> foo = malloc(sizeof(S));
- * ScopedFreePtr<char> bar = strdup(str);
- */
-template<typename T>
-struct ScopedFreePtrTraits
-{
- typedef T* type;
- static T* empty() { return nullptr; }
- static void release(T* aPtr) { free(aPtr); }
-};
-SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
-
-/*
- * ScopedDeletePtr is a RAII wrapper for pointers that need to be deleted.
- *
- * struct S { ... };
- * ScopedDeletePtr<S> foo = new S();
- */
-template<typename T>
-struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
-{
- static void release(T* aPtr) { delete aPtr; }
-};
-SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
-
-/*
* MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE makes it easy to create scoped
* pointers for types with custom deleters; just overload
* TypeSpecificDelete(T*) in the same namespace as T to call the deleter for
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/SegmentedVector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/SegmentedVector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/SegmentedVector.h
@@ -159,7 +159,7 @@
// Returns false if the allocation failed. (If you are using an infallible
// allocation policy, use InfallibleAppend() instead.)
template<typename U>
- MOZ_WARN_UNUSED_RESULT bool Append(U&& aU)
+ MOZ_MUST_USE bool Append(U&& aU)
{
Segment* last = mSegments.getLast();
if (!last || last->Length() == kSegmentCapacity) {
@@ -218,6 +218,56 @@
}
}
+ // Equivalent to calling |PopLast| |aNumElements| times, but potentially
+ // more efficient.
+ void PopLastN(uint32_t aNumElements)
+ {
+ MOZ_ASSERT(aNumElements <= Length());
+
+ Segment* last;
+
+ // Pop full segments for as long as we can. Note that this loop
+ // cleanly handles the case when the initial last segment is not
+ // full and we are popping more elements than said segment contains.
+ do {
+ last = mSegments.getLast();
+
+ // The list is empty. We're all done.
+ if (!last) {
+ return;
+ }
+
+ // Check to see if the list contains too many elements. Handle
+ // that in the epilogue.
+ uint32_t segmentLen = last->Length();
+ if (segmentLen > aNumElements) {
+ break;
+ }
+
+ // Destroying the segment destroys all elements contained therein.
+ mSegments.popLast();
+ last->~Segment();
+ this->free_(last);
+
+ MOZ_ASSERT(aNumElements >= segmentLen);
+ aNumElements -= segmentLen;
+ if (aNumElements == 0) {
+ return;
+ }
+ } while (true);
+
+ // Handle the case where the last segment contains more elements
+ // than we want to pop.
+ MOZ_ASSERT(last);
+ MOZ_ASSERT(last == mSegments.getLast());
+ MOZ_ASSERT(aNumElements != 0);
+ MOZ_ASSERT(aNumElements < last->Length());
+ for (uint32_t i = 0; i < aNumElements; ++i) {
+ last->PopLast();
+ }
+ MOZ_ASSERT(last->Length() != 0);
+ }
+
// Use this class to iterate over a SegmentedVector, like so:
//
// for (auto iter = v.Iter(); !iter.Done(); iter.Next()) {
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Snprintf.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Snprintf.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Snprintf.h
@@ -1,50 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/* Polyfills snprintf() on platforms that don't provide it, and provides
- * related utilities. */
-
-#ifndef mozilla_Snprintf_h_
-#define mozilla_Snprintf_h_
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-// Older MSVC versions do not provide snprintf(), but they do provide
-// vsnprintf(), which has the same semantics except that if the number of
-// characters written equals the buffer size, it does not write a null
-// terminator, so we wrap it to do so.
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#include "mozilla/Attributes.h"
-MOZ_ALWAYS_INLINE int snprintf(char* buffer, size_t n, const char* format, ...)
-{
- va_list args;
- va_start(args, format);
- int result = vsnprintf(buffer, n, format, args);
- va_end(args);
- buffer[n - 1] = '\0';
- return result;
-}
-#endif
-
-// In addition, in C++ code, on all platforms, provide an snprintf_literal()
-// function which uses template argument deduction to deduce the size of the
-// buffer, avoiding the need for the user to pass it in explicitly.
-#ifdef __cplusplus
-template <size_t N>
-int snprintf_literal(char (&buffer)[N], const char* format, ...)
-{
- va_list args;
- va_start(args, format);
- int result = vsnprintf(buffer, N, format, args);
- va_end(args);
- buffer[N - 1] = '\0';
- return result;
-}
-#endif
-
-#endif /* mozilla_Snprintf_h_ */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/SplayTree.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/SplayTree.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/SplayTree.h
@@ -56,7 +56,7 @@
T* mRoot;
public:
- MOZ_CONSTEXPR SplayTree()
+ constexpr SplayTree()
: mRoot(nullptr)
{}
@@ -76,19 +76,19 @@
return Comparator::compare(aValue, *last) == 0 ? last : nullptr;
}
- bool insert(T* aValue)
+ void insert(T* aValue)
{
MOZ_ASSERT(!find(*aValue), "Duplicate elements are not allowed.");
if (!mRoot) {
mRoot = aValue;
- return true;
+ return;
}
T* last = lookup(*aValue);
int cmp = Comparator::compare(*aValue, *last);
finishInsertion(last, cmp, aValue);
- return true;
+ return;
}
T* findOrInsert(const T& aValue);
@@ -194,7 +194,7 @@
return parent;
}
- T* finishInsertion(T* aLast, int32_t aCmp, T* aNew)
+ void finishInsertion(T* aLast, int32_t aCmp, T* aNew)
{
MOZ_ASSERT(aCmp, "Nodes shouldn't be equal!");
@@ -204,7 +204,6 @@
aNew->mParent = aLast;
splay(aNew);
- return aNew;
}
/**
@@ -321,7 +320,9 @@
return last;
}
- return finishInsertion(last, cmp, new T(aValue));
+ T* t = new T(aValue);
+ finishInsertion(last, cmp, t);
+ return t;
}
} /* namespace mozilla */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Sprintf.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Sprintf.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Sprintf.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Provides a safer sprintf for printing to fixed-size character arrays. */
+
+#ifndef mozilla_Sprintf_h_
+#define mozilla_Sprintf_h_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+
+#ifdef __cplusplus
+
+template <size_t N>
+int VsprintfLiteral(char (&buffer)[N], const char* format, va_list args)
+{
+ MOZ_ASSERT(format != buffer);
+ int result = vsnprintf(buffer, N, format, args);
+ buffer[N - 1] = '\0';
+ return result;
+}
+
+template <size_t N>
+MOZ_FORMAT_PRINTF(2, 3)
+int SprintfLiteral(char (&buffer)[N], const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ int result = VsprintfLiteral(buffer, format, args);
+ va_end(args);
+ return result;
+}
+
+#endif
+#endif /* mozilla_Sprintf_h_ */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StackWalk.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StackWalk.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StackWalk.h
@@ -52,8 +52,6 @@
* May skip some stack frames due to compiler optimizations or code
* generation.
*
- * Note: this (and other helper methods) will only be available when
- * MOZ_STACKWALKING is defined, so any new consumers must #if based on that.
*/
MFBT_API bool
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StackWalk_windows.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StackWalk_windows.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StackWalk_windows.h
@@ -0,0 +1,21 @@
+#ifndef mozilla_StackWalk_windows_h
+#define mozilla_StackWalk_windows_h
+
+#include "mozilla/Types.h"
+
+/**
+ * Allow stack walkers to work around the egregious win64 dynamic lookup table
+ * list API by locking around SuspendThread to avoid deadlock.
+ *
+ * See comment in StackWalk.cpp
+ */
+MFBT_API void
+AcquireStackWalkWorkaroundLock();
+
+MFBT_API bool
+TryAcquireStackWalkWorkaroundLock();
+
+MFBT_API void
+ReleaseStackWalkWorkaroundLock();
+
+#endif // mozilla_StackWalk_windows_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StaticAnalysisFunctions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StaticAnalysisFunctions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/StaticAnalysisFunctions.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_StaticAnalysisFunctions_h
+#define mozilla_StaticAnalysisFunctions_h
+
+#ifndef __cplusplus
+#ifndef bool
+#include <stdbool.h>
+#endif
+#endif
+/*
+ * Functions that are used as markers in Gecko code for static analysis. Their
+ * purpose is to have different AST nodes generated during compile time and to
+ * match them based on different checkers implemented in build/clang-plugin
+ */
+
+#ifdef MOZ_CLANG_PLUGIN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * MOZ_AssertAssignmentTest - used in MOZ_ASSERT in order to test the possible
+ * presence of assignment instead of logical comparisons.
+ *
+ * Example:
+ * MOZ_ASSERT(retVal = true);
+ */
+static MOZ_ALWAYS_INLINE bool MOZ_AssertAssignmentTest(bool exprResult) {
+ return exprResult;
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#define MOZ_CHECK_ASSERT_ASSIGNMENT(expr) MOZ_AssertAssignmentTest(!!(expr))
+
+#else
+
+#define MOZ_CHECK_ASSERT_ASSIGNMENT(expr) (!!(expr))
+
+#endif /* MOZ_CLANG_PLUGIN */
+#endif /* StaticAnalysisFunctions_h */
\ No newline at end of file
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TextUtils.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TextUtils.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TextUtils.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Character/text operations. */
+
+#ifndef mozilla_TextUtils_h
+#define mozilla_TextUtils_h
+
+#include "mozilla/TypeTraits.h"
+
+namespace mozilla {
+
+namespace detail {
+
+template<typename Char>
+class MakeUnsignedChar
+ : public MakeUnsigned<Char>
+{};
+
+template<>
+class MakeUnsignedChar<char16_t>
+{
+public:
+ using Type = char16_t;
+};
+
+template<>
+class MakeUnsignedChar<char32_t>
+{
+public:
+ using Type = char32_t;
+};
+
+} // namespace detail
+
+/**
+ * Returns true iff |aChar| matches [a-zA-Z].
+ *
+ * This function is basically what you thought isalpha was, except its behavior
+ * doesn't depend on the user's current locale.
+ */
+template<typename Char>
+constexpr bool
+IsAsciiAlpha(Char aChar)
+{
+ using UnsignedChar = typename detail::MakeUnsignedChar<Char>::Type;
+ return ('a' <= static_cast<UnsignedChar>(aChar) &&
+ static_cast<UnsignedChar>(aChar) <= 'z') ||
+ ('A' <= static_cast<UnsignedChar>(aChar) &&
+ static_cast<UnsignedChar>(aChar) <= 'Z');
+}
+
+} // namespace mozilla
+
+#endif /* mozilla_TextUtils_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ThreadLocal.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ThreadLocal.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/ThreadLocal.h
@@ -42,11 +42,28 @@
typedef sig_atomic_t sig_safe_t;
#endif
+namespace detail {
+
+#if defined(HAVE_THREAD_TLS_KEYWORD)
+#define MOZ_HAS_THREAD_LOCAL
+#endif
+
/*
* Thread Local Storage helpers.
*
* Usage:
*
+ * Do not directly instantiate this class. Instead, use the
+ * MOZ_THREAD_LOCAL macro to declare or define instances. The macro
+ * takes a type name as its argument.
+ *
+ * Declare like this:
+ * extern MOZ_THREAD_LOCAL(int) tlsInt;
+ * Define like this:
+ * MOZ_THREAD_LOCAL(int) tlsInt;
+ * or:
+ * static MOZ_THREAD_LOCAL(int) tlsInt;
+ *
* Only static-storage-duration (e.g. global variables, or static class members)
* objects of this class should be instantiated. This class relies on
* zero-initialization, which is implicit for static-storage-duration objects.
@@ -56,9 +73,10 @@
*
* // Create a TLS item.
* //
- * // Note that init() should be invoked exactly once, before any usage of set()
- * // or get().
- * mozilla::ThreadLocal<int> tlsKey;
+ * // Note that init() should be invoked before the first use of set()
+ * // or get(). It is ok to call it multiple times. This must be
+ * // called in a way that avoids possible races with other threads.
+ * MOZ_THREAD_LOCAL(int) tlsKey;
* if (!tlsKey.init()) {
* // deal with the error
* }
@@ -72,6 +90,7 @@
template<typename T>
class ThreadLocal
{
+#ifndef MOZ_HAS_THREAD_LOCAL
#if defined(XP_WIN)
typedef unsigned long key_t;
#else
@@ -93,19 +112,38 @@
{
typedef S *Type;
};
+#endif
+
+ bool initialized() const {
+#ifdef MOZ_HAS_THREAD_LOCAL
+ return true;
+#else
+ return mInited;
+#endif
+ }
public:
- MOZ_WARN_UNUSED_RESULT inline bool init();
+ // __thread does not allow non-trivial constructors, but we can
+ // instead rely on zero-initialization.
+#ifndef MOZ_HAS_THREAD_LOCAL
+ ThreadLocal()
+ : mKey(0), mInited(false)
+ {}
+#endif
+
+ MOZ_MUST_USE inline bool init();
inline T get() const;
inline void set(const T aValue);
- bool initialized() const { return mInited; }
-
private:
+#ifdef MOZ_HAS_THREAD_LOCAL
+ T mValue;
+#else
key_t mKey;
bool mInited;
+#endif
};
template<typename T>
@@ -118,20 +156,29 @@
static_assert(sizeof(T) <= sizeof(void*),
"mozilla::ThreadLocal can't be used for types larger than "
"a pointer");
- MOZ_ASSERT(!initialized());
+
+#ifdef MOZ_HAS_THREAD_LOCAL
+ return true;
+#else
+ if (!initialized()) {
#ifdef XP_WIN
- mKey = TlsAlloc();
- mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
+ mKey = TlsAlloc();
+ mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
#else
- mInited = !pthread_key_create(&mKey, nullptr);
+ mInited = !pthread_key_create(&mKey, nullptr);
#endif
+ }
return mInited;
+#endif
}
template<typename T>
inline T
ThreadLocal<T>::get() const
{
+#ifdef MOZ_HAS_THREAD_LOCAL
+ return mValue;
+#else
MOZ_ASSERT(initialized());
void* h;
#ifdef XP_WIN
@@ -140,12 +187,16 @@
h = pthread_getspecific(mKey);
#endif
return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
+#endif
}
template<typename T>
inline void
ThreadLocal<T>::set(const T aValue)
{
+#ifdef MOZ_HAS_THREAD_LOCAL
+ mValue = aValue;
+#else
MOZ_ASSERT(initialized());
void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
#ifdef XP_WIN
@@ -156,8 +207,16 @@
if (!succeeded) {
MOZ_CRASH();
}
+#endif
}
+#ifdef MOZ_HAS_THREAD_LOCAL
+#define MOZ_THREAD_LOCAL(TYPE) __thread mozilla::detail::ThreadLocal<TYPE>
+#else
+#define MOZ_THREAD_LOCAL(TYPE) mozilla::detail::ThreadLocal<TYPE>
+#endif
+
+} // namespace detail
} // namespace mozilla
#endif /* mozilla_ThreadLocal_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TimeStamp.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TimeStamp.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TimeStamp.h
@@ -62,7 +62,7 @@
{
public:
// The default duration is 0.
- MOZ_CONSTEXPR BaseTimeDuration() : mValue(0) {}
+ constexpr BaseTimeDuration() : mValue(0) {}
// Allow construction using '0' as the initial value, for readability,
// but no other numbers (so we don't have any implicit unit conversions).
struct _SomethingVeryRandomHere;
@@ -395,7 +395,7 @@
/**
* Initialize to the "null" moment
*/
- MOZ_CONSTEXPR TimeStamp() : mValue(0) {}
+ constexpr TimeStamp() : mValue(0) {}
// Default copy-constructor and assignment are OK
/**
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TimeStamp_windows.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TimeStamp_windows.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TimeStamp_windows.h
@@ -30,7 +30,7 @@
MFBT_API uint64_t CheckQPC(const TimeStampValue& aOther) const;
struct _SomethingVeryRandomHere;
- MOZ_CONSTEXPR TimeStampValue(_SomethingVeryRandomHere* aNullValue)
+ constexpr TimeStampValue(_SomethingVeryRandomHere* aNullValue)
: mGTC(0)
, mQPC(0)
, mHasQPC(false)
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Tuple.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Tuple.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Tuple.h
@@ -95,7 +95,12 @@
* of an empty tuple).
*/
template<std::size_t Index>
-struct TupleImpl<Index> {};
+struct TupleImpl<Index> {
+ bool operator==(const TupleImpl<Index>& aOther) const
+ {
+ return true;
+ }
+};
/*
* One node of the recursive inheritance hierarchy. It stores the element at
@@ -182,6 +187,10 @@
Tail(*this) = Move(Tail(aOther));
return *this;
}
+ bool operator==(const TupleImpl& aOther) const
+ {
+ return Head(*this) == Head(aOther) && Tail(*this) == Tail(aOther);
+ }
private:
HeadT mHead; // The element stored at this index in the tuple.
};
@@ -246,6 +255,10 @@
static_cast<Impl&>(*this) = Move(aOther);
return *this;
}
+ bool operator==(const Tuple& aOther) const
+ {
+ return static_cast<const Impl&>(*this) == static_cast<const Impl&>(aOther);
+ }
};
/**
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TypeTraits.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TypeTraits.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TypeTraits.h
@@ -98,9 +98,7 @@
template<> struct IsIntegralHelper<unsigned long long> : TrueType {};
template<> struct IsIntegralHelper<bool> : TrueType {};
template<> struct IsIntegralHelper<wchar_t> : TrueType {};
-#ifdef MOZ_CHAR16_IS_NOT_WCHAR
template<> struct IsIntegralHelper<char16_t> : TrueType {};
-#endif
} /* namespace detail */
@@ -112,9 +110,6 @@
* mozilla::IsIntegral<const long>::value is true;
* mozilla::IsIntegral<int*>::value is false;
* mozilla::IsIntegral<double>::value is false;
- *
- * Note that the behavior of IsIntegral on char16_t and char32_t is
- * unspecified.
*/
template<typename T>
struct IsIntegral : detail::IsIntegralHelper<typename RemoveCV<T>::Type>
@@ -355,6 +350,41 @@
: IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value>
{};
+namespace detail {
+
+template<typename T>
+struct IsMemberPointerHelper : FalseType {};
+
+template<typename T, typename U>
+struct IsMemberPointerHelper<T U::*> : TrueType {};
+
+} // namespace detail
+
+/**
+ * IsMemberPointer determines whether a type is pointer to non-static member
+ * object or a pointer to non-static member function.
+ *
+ * mozilla::IsMemberPointer<int(cls::*)>::value is true
+ * mozilla::IsMemberPointer<int*>::value is false
+ */
+template<typename T>
+struct IsMemberPointer
+ : detail::IsMemberPointerHelper<typename RemoveCV<T>::Type>
+{};
+
+/**
+ * IsScalar determines whether a type is a scalar type.
+ *
+ * mozilla::IsScalar<int>::value is true
+ * mozilla::IsScalar<int*>::value is true
+ * mozilla::IsScalar<cls>::value is false
+ */
+template<typename T>
+struct IsScalar
+ : IntegralConstant<bool, IsArithmetic<T>::value || IsEnum<T>::value ||
+ IsPointer<T>::value || IsMemberPointer<T>::value>
+{};
+
/* 20.9.4.3 Type properties [meta.unary.prop] */
/**
@@ -409,9 +439,7 @@
template<> struct IsPod<float> : TrueType {};
template<> struct IsPod<double> : TrueType {};
template<> struct IsPod<wchar_t> : TrueType {};
-#ifdef MOZ_CHAR16_IS_NOT_WCHAR
template<> struct IsPod<char16_t> : TrueType {};
-#endif
template<typename T> struct IsPod<T*> : TrueType {};
namespace detail {
@@ -544,6 +572,27 @@
template<typename T>
struct IsUnsigned : detail::IsUnsignedHelper<T> {};
+namespace detail {
+
+struct DoIsDestructibleImpl
+{
+ template<typename T, typename = decltype(DeclVal<T&>().~T())>
+ static TrueType test(int);
+ template<typename T>
+ static FalseType test(...);
+};
+
+template<typename T>
+struct IsDestructibleImpl : public DoIsDestructibleImpl
+{
+ typedef decltype(test<T>(0)) Type;
+};
+
+} // namespace detail
+
+template<typename T>
+struct IsDestructible : public detail::IsDestructibleImpl<T>::Type {};
+
/* 20.9.5 Type property queries [meta.unary.prop.query] */
/* 20.9.6 Relationships between types [meta.rel] */
@@ -644,18 +693,15 @@
namespace detail {
-// This belongs inside ConvertibleTester, but it's pulled out to
-// work around a bug in the compiler used for hazard builds.
-template <typename To>
-static void ConvertibleTestHelper(To);
-
template<typename From, typename To>
struct ConvertibleTester
{
private:
- template<typename From1, typename To1,
- typename = decltype(ConvertibleTestHelper<To1>(DeclVal<From>()))>
- static char test(int);
+ template<typename To1>
+ static char test_helper(To1);
+
+ template<typename From1, typename To1>
+ static decltype(test_helper<To1>(DeclVal<From1>())) test(int);
template<typename From1, typename To1>
static int test(...);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TypedEnumBits.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TypedEnumBits.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/TypedEnumBits.h
@@ -47,34 +47,34 @@
const E mValue;
public:
- explicit MOZ_CONSTEXPR CastableTypedEnumResult(E aValue)
+ explicit constexpr CastableTypedEnumResult(E aValue)
: mValue(aValue)
{}
- MOZ_CONSTEXPR operator E() const { return mValue; }
+ constexpr operator E() const { return mValue; }
template<typename DestinationType>
- MOZ_EXPLICIT_CONVERSION MOZ_CONSTEXPR
+ explicit constexpr
operator DestinationType() const { return DestinationType(mValue); }
- MOZ_CONSTEXPR bool operator !() const { return !bool(mValue); }
+ constexpr bool operator !() const { return !bool(mValue); }
};
#define MOZ_CASTABLETYPEDENUMRESULT_BINOP(Op, OtherType, ReturnType) \
template<typename E> \
-MOZ_CONSTEXPR ReturnType \
+constexpr ReturnType \
operator Op(const OtherType& aE, const CastableTypedEnumResult<E>& aR) \
{ \
return ReturnType(aE Op OtherType(aR)); \
} \
template<typename E> \
-MOZ_CONSTEXPR ReturnType \
+constexpr ReturnType \
operator Op(const CastableTypedEnumResult<E>& aR, const OtherType& aE) \
{ \
return ReturnType(OtherType(aR) Op aE); \
} \
template<typename E> \
-MOZ_CONSTEXPR ReturnType \
+constexpr ReturnType \
operator Op(const CastableTypedEnumResult<E>& aR1, \
const CastableTypedEnumResult<E>& aR2) \
{ \
@@ -90,7 +90,7 @@
MOZ_CASTABLETYPEDENUMRESULT_BINOP(&&, bool, bool)
template <typename E>
-MOZ_CONSTEXPR CastableTypedEnumResult<E>
+constexpr CastableTypedEnumResult<E>
operator ~(const CastableTypedEnumResult<E>& aR)
{
return CastableTypedEnumResult<E>(~(E(aR)));
@@ -123,7 +123,7 @@
} // namespace mozilla
#define MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, Op) \
- inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
+ inline constexpr mozilla::CastableTypedEnumResult<Name> \
operator Op(Name a, Name b) \
{ \
typedef mozilla::CastableTypedEnumResult<Name> Result; \
@@ -145,7 +145,7 @@
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, |) \
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, &) \
MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, ^) \
- inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
+ inline constexpr mozilla::CastableTypedEnumResult<Name> \
operator~(Name a) \
{ \
typedef mozilla::CastableTypedEnumResult<Name> Result; \
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Types.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Types.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Types.h
@@ -89,7 +89,7 @@
* symbols. We add the weak attribute to the import version of the MFBT API
* macros to exploit this.
*/
-# if defined(MOZ_GLUE_IN_PROGRAM) && !defined(MOZILLA_XPCOMRT_API)
+# if defined(MOZ_GLUE_IN_PROGRAM)
# define MFBT_API __attribute__((weak)) MOZ_IMPORT_API
# define MFBT_DATA __attribute__((weak)) MOZ_IMPORT_DATA
# else
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/UniquePtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/UniquePtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/UniquePtr.h
@@ -25,6 +25,39 @@
namespace mozilla {
+namespace detail {
+
+struct HasPointerTypeHelper
+{
+ template <class U> static double Test(...);
+ template <class U> static char Test(typename U::pointer* = 0);
+};
+
+template <class T>
+class HasPointerType : public IntegralConstant<bool, sizeof(HasPointerTypeHelper::Test<T>(0)) == 1>
+{
+};
+
+template <class T, class D, bool = HasPointerType<D>::value>
+struct PointerTypeImpl
+{
+ typedef typename D::pointer Type;
+};
+
+template <class T, class D>
+struct PointerTypeImpl<T, D, false>
+{
+ typedef T* Type;
+};
+
+template <class T, class D>
+struct PointerType
+{
+ typedef typename PointerTypeImpl<T, typename RemoveReference<D>::Type>::Type Type;
+};
+
+} // namespace detail
+
/**
* UniquePtr is a smart pointer that wholly owns a resource. Ownership may be
* transferred out of a UniquePtr through explicit action, but otherwise the
@@ -127,10 +160,11 @@
* The constructors and mutating methods only accept array pointers (not T*, U*
* that converts to T*, or UniquePtr<U[]> or UniquePtr<U>) or |nullptr|.
*
- * It's perfectly okay to return a UniquePtr from a method to assure the related
- * resource is properly deleted. You'll need to use |Move()| when returning a
- * local UniquePtr. Otherwise you can return |nullptr|, or you can return
- * |UniquePtr(ptr)|.
+ * It's perfectly okay for a function to return a UniquePtr. This transfers
+ * the UniquePtr's sole ownership of the data, to the fresh UniquePtr created
+ * in the calling function, that will then solely own that data. Such functions
+ * can return a local variable UniquePtr, |nullptr|, |UniquePtr(ptr)| where
+ * |ptr| is a |T*|, or a UniquePtr |Move()|'d from elsewhere.
*
* UniquePtr will commonly be a member of a class, with lifetime equivalent to
* that of that class. If you want to expose the related resource, you could
@@ -154,9 +188,9 @@
class UniquePtr
{
public:
- typedef T* Pointer;
typedef T ElementType;
typedef D DeleterType;
+ typedef typename detail::PointerType<T, DeleterType>::Type Pointer;
private:
Pair<Pointer, DeleterType> mTuple;
@@ -171,7 +205,7 @@
/**
* Construct a UniquePtr containing |nullptr|.
*/
- MOZ_CONSTEXPR UniquePtr()
+ constexpr UniquePtr()
: mTuple(static_cast<Pointer>(nullptr), DeleterType())
{
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
@@ -226,7 +260,7 @@
}
UniquePtr(UniquePtr&& aOther)
- : mTuple(aOther.release(), Forward<DeleterType>(aOther.getDeleter()))
+ : mTuple(aOther.release(), Forward<DeleterType>(aOther.get_deleter()))
{}
MOZ_IMPLICIT
@@ -247,7 +281,7 @@
? IsSame<D, E>::value
: IsConvertible<E, D>::value),
int>::Type aDummy = 0)
- : mTuple(aOther.release(), Forward<E>(aOther.getDeleter()))
+ : mTuple(aOther.release(), Forward<E>(aOther.get_deleter()))
{
}
@@ -256,7 +290,7 @@
UniquePtr& operator=(UniquePtr&& aOther)
{
reset(aOther.release());
- getDeleter() = Forward<DeleterType>(aOther.getDeleter());
+ get_deleter() = Forward<DeleterType>(aOther.get_deleter());
return *this;
}
@@ -270,7 +304,7 @@
"can't assign from UniquePtr holding an array");
reset(aOther.release());
- getDeleter() = Forward<E>(aOther.getDeleter());
+ get_deleter() = Forward<E>(aOther.get_deleter());
return *this;
}
@@ -291,10 +325,10 @@
Pointer get() const { return ptr(); }
- DeleterType& getDeleter() { return del(); }
- const DeleterType& getDeleter() const { return del(); }
+ DeleterType& get_deleter() { return del(); }
+ const DeleterType& get_deleter() const { return del(); }
- Pointer release()
+ MOZ_MUST_USE Pointer release()
{
Pointer p = ptr();
ptr() = nullptr;
@@ -306,7 +340,7 @@
Pointer old = ptr();
ptr() = aPtr;
if (old != nullptr) {
- getDeleter()(old);
+ get_deleter()(old);
}
}
@@ -338,7 +372,7 @@
/**
* Construct a UniquePtr containing nullptr.
*/
- MOZ_CONSTEXPR UniquePtr()
+ constexpr UniquePtr()
: mTuple(static_cast<Pointer>(nullptr), DeleterType())
{
static_assert(!IsPointer<D>::value, "must provide a deleter instance");
@@ -395,7 +429,7 @@
= delete;
UniquePtr(UniquePtr&& aOther)
- : mTuple(aOther.release(), Forward<DeleterType>(aOther.getDeleter()))
+ : mTuple(aOther.release(), Forward<DeleterType>(aOther.get_deleter()))
{}
MOZ_IMPLICIT
@@ -411,7 +445,7 @@
UniquePtr& operator=(UniquePtr&& aOther)
{
reset(aOther.release());
- getDeleter() = Forward<DeleterType>(aOther.getDeleter());
+ get_deleter() = Forward<DeleterType>(aOther.get_deleter());
return *this;
}
@@ -426,10 +460,10 @@
T& operator[](decltype(sizeof(int)) aIndex) const { return get()[aIndex]; }
Pointer get() const { return mTuple.first(); }
- DeleterType& getDeleter() { return mTuple.second(); }
- const DeleterType& getDeleter() const { return mTuple.second(); }
+ DeleterType& get_deleter() { return mTuple.second(); }
+ const DeleterType& get_deleter() const { return mTuple.second(); }
- Pointer release()
+ MOZ_MUST_USE Pointer release()
{
Pointer p = mTuple.first();
mTuple.first() = nullptr;
@@ -463,12 +497,24 @@
void operator=(const UniquePtr& aOther) = delete; // assign using Move()!
};
-/** A default deletion policy using plain old operator delete. */
+/**
+ * A default deletion policy using plain old operator delete.
+ *
+ * Note that this type can be specialized, but authors should beware of the risk
+ * that the specialization may at some point cease to match (either because it
+ * gets moved to a different compilation unit or the signature changes). If the
+ * non-specialized (|delete|-based) version compiles for that type but does the
+ * wrong thing, bad things could happen.
+ *
+ * This is a non-issue for types which are always incomplete (i.e. opaque handle
+ * types), since |delete|-ing such a type will always trigger a compilation
+ * error.
+ */
template<typename T>
class DefaultDelete
{
public:
- MOZ_CONSTEXPR DefaultDelete() {}
+ constexpr DefaultDelete() {}
template<typename U>
MOZ_IMPLICIT DefaultDelete(const DefaultDelete<U>& aOther,
@@ -488,7 +534,7 @@
class DefaultDelete<T[]>
{
public:
- MOZ_CONSTEXPR DefaultDelete() {}
+ constexpr DefaultDelete() {}
void operator()(T* aPtr) const
{
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/UniquePtrExtensions.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/UniquePtrExtensions.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/UniquePtrExtensions.h
@@ -37,6 +37,21 @@
typename detail::UniqueSelector<T>::KnownBound
MakeUniqueFallible(Args&&... aArgs) = delete;
+namespace detail {
+
+template<typename T>
+struct FreePolicy
+{
+ void operator()(const void* ptr) {
+ free(const_cast<void*>(ptr));
+ }
+};
+
+} // namespace detail
+
+template<typename T>
+using UniqueFreePtr = UniquePtr<T, detail::FreePolicy<T>>;
+
} // namespace mozilla
#endif // mozilla_UniquePtrExtensions_h
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Variant.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Variant.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Variant.h
@@ -7,10 +7,12 @@
/* A template class for tagged unions. */
#include <new>
+#include <stdint.h>
#include "mozilla/Alignment.h"
#include "mozilla/Assertions.h"
#include "mozilla/Move.h"
+#include "mozilla/TypeTraits.h"
#ifndef mozilla_Variant_h
#define mozilla_Variant_h
@@ -61,43 +63,112 @@
template<typename Needle, typename T, typename... Haystack>
struct IsVariant<Needle, T, Haystack...> : public IsVariant<Needle, Haystack...> { };
+/// SelectVariantTypeHelper is used in the implementation of SelectVariantType.
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper;
+
+template<typename T>
+struct SelectVariantTypeHelper<T>
+{ };
+
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper<T, T, Variants...>
+{
+ typedef T Type;
+};
+
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper<T, const T, Variants...>
+{
+ typedef const T Type;
+};
+
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper<T, const T&, Variants...>
+{
+ typedef const T& Type;
+};
+
+template<typename T, typename... Variants>
+struct SelectVariantTypeHelper<T, T&&, Variants...>
+{
+ typedef T&& Type;
+};
+
+template<typename T, typename Head, typename... Variants>
+struct SelectVariantTypeHelper<T, Head, Variants...>
+ : public SelectVariantTypeHelper<T, Variants...>
+{ };
+
+/**
+ * SelectVariantType takes a type T and a list of variant types Variants and
+ * yields a type Type, selected from Variants, that can store a value of type T
+ * or a reference to type T. If no such type was found, Type is not defined.
+ */
+template <typename T, typename... Variants>
+struct SelectVariantType
+ : public SelectVariantTypeHelper<typename RemoveConst<typename RemoveReference<T>::Type>::Type,
+ Variants...>
+{ };
+
+// Compute a fast, compact type that can be used to hold integral values that
+// distinctly map to every type in Ts.
+template<typename... Ts>
+struct VariantTag
+{
+private:
+ static const size_t TypeCount = sizeof...(Ts);
+
+public:
+ using Type =
+ typename Conditional<TypeCount < 3,
+ bool,
+ typename Conditional<TypeCount < (1 << 8),
+ uint_fast8_t,
+ size_t // stop caring past a certain point :-)
+ >::Type
+ >::Type;
+};
+
// TagHelper gets the given sentinel tag value for the given type T. This has to
-// be split out from VariantImplementation because you can't nest a partial template
-// specialization within a template class.
+// be split out from VariantImplementation because you can't nest a partial
+// template specialization within a template class.
-template<size_t N, typename T, typename U, typename Next, bool isMatch>
+template<typename Tag, size_t N, typename T, typename U, typename Next, bool isMatch>
struct TagHelper;
// In the case where T != U, we continue recursion.
-template<size_t N, typename T, typename U, typename Next>
-struct TagHelper<N, T, U, Next, false>
+template<typename Tag, size_t N, typename T, typename U, typename Next>
+struct TagHelper<Tag, N, T, U, Next, false>
{
- static size_t tag() { return Next::template tag<U>(); }
+ static Tag tag() { return Next::template tag<U>(); }
};
// In the case where T == U, return the tag number.
-template<size_t N, typename T, typename U, typename Next>
-struct TagHelper<N, T, U, Next, true>
+template<typename Tag, size_t N, typename T, typename U, typename Next>
+struct TagHelper<Tag, N, T, U, Next, true>
{
- static size_t tag() { return N; }
+ static Tag tag() { return Tag(N); }
};
-// The VariantImplementation template provides the guts of mozilla::Variant. We create
-// an VariantImplementation for each T in Ts... which handles construction,
-// destruction, etc for when the Variant's type is T. If the Variant's type is
-// not T, it punts the request on to the next VariantImplementation.
+// The VariantImplementation template provides the guts of mozilla::Variant. We
+// create a VariantImplementation for each T in Ts... which handles
+// construction, destruction, etc for when the Variant's type is T. If the
+// Variant's type isn't T, it punts the request on to the next
+// VariantImplementation.
-template<size_t N, typename... Ts>
+template<typename Tag, size_t N, typename... Ts>
struct VariantImplementation;
// The singly typed Variant / recursion base case.
-template<size_t N, typename T>
-struct VariantImplementation<N, T> {
+template<typename Tag, size_t N, typename T>
+struct VariantImplementation<Tag, N, T>
+{
template<typename U>
- static size_t tag() {
+ static Tag tag() {
static_assert(mozilla::IsSame<T, U>::value,
"mozilla::Variant: tag: bad type!");
- return N;
+ return Tag(N);
}
template<typename Variant>
@@ -122,22 +193,24 @@
}
template<typename Matcher, typename ConcreteVariant>
- static typename Matcher::ReturnType
- match(Matcher& aMatcher, ConcreteVariant& aV) {
+ static auto
+ match(Matcher&& aMatcher, ConcreteVariant& aV)
+ -> decltype(aMatcher.match(aV.template as<T>()))
+ {
return aMatcher.match(aV.template as<T>());
}
};
// VariantImplementation for some variant type T.
-template<size_t N, typename T, typename... Ts>
-struct VariantImplementation<N, T, Ts...>
+template<typename Tag, size_t N, typename T, typename... Ts>
+struct VariantImplementation<Tag, N, T, Ts...>
{
// The next recursive VariantImplementation.
- using Next = VariantImplementation<N + 1, Ts...>;
+ using Next = VariantImplementation<Tag, N + 1, Ts...>;
template<typename U>
- static size_t tag() {
- return TagHelper<N, T, U, Next, IsSame<T, U>::value>::tag();
+ static Tag tag() {
+ return TagHelper<Tag, N, T, U, Next, IsSame<T, U>::value>::tag();
}
template<typename Variant>
@@ -178,8 +251,9 @@
}
template<typename Matcher, typename ConcreteVariant>
- static typename Matcher::ReturnType
- match(Matcher& aMatcher, ConcreteVariant& aV)
+ static auto
+ match(Matcher&& aMatcher, ConcreteVariant& aV)
+ -> decltype(aMatcher.match(aV.template as<T>()))
{
if (aV.template is<T>()) {
return aMatcher.match(aV.template as<T>());
@@ -199,6 +273,39 @@
}
};
+/**
+ * AsVariantTemporary stores a value of type T to allow construction of a
+ * Variant value via type inference. Because T is copied and there's no
+ * guarantee that the copy can be elided, AsVariantTemporary is best used with
+ * primitive or very small types.
+ */
+template <typename T>
+struct AsVariantTemporary
+{
+ explicit AsVariantTemporary(const T& aValue)
+ : mValue(aValue)
+ {}
+
+ template<typename U>
+ explicit AsVariantTemporary(U&& aValue)
+ : mValue(Forward<U>(aValue))
+ {}
+
+ AsVariantTemporary(const AsVariantTemporary& aOther)
+ : mValue(aOther.mValue)
+ {}
+
+ AsVariantTemporary(AsVariantTemporary&& aOther)
+ : mValue(Move(aOther.mValue))
+ {}
+
+ AsVariantTemporary() = delete;
+ void operator=(const AsVariantTemporary&) = delete;
+ void operator=(AsVariantTemporary&&) = delete;
+
+ typename RemoveConst<typename RemoveReference<T>::Type>::Type mValue;
+};
+
} // namespace detail
/**
@@ -222,6 +329,18 @@
* Variant<char, uint32_t> v1('a');
* Variant<UniquePtr<A>, B, C> v2(MakeUnique<A>());
*
+ * Because specifying the full type of a Variant value is often verbose,
+ * AsVariant() can be used to construct a Variant value using type inference in
+ * contexts such as expressions or when returning values from functions. Because
+ * AsVariant() must copy or move the value into a temporary and this cannot
+ * necessarily be elided by the compiler, it's mostly appropriate only for use
+ * with primitive or very small types.
+ *
+ *
+ * Variant<char, uint32_t> Foo() { return AsVariant('x'); }
+ * // ...
+ * Variant<char, uint32_t> v1 = Foo(); // v1 holds char('x').
+ *
* All access to the contained value goes through type-safe accessors.
*
* void
@@ -275,11 +394,11 @@
* // Good!
* struct FooMatcher
* {
- * using ReturnType = char*;
- * ReturnType match(A& a) { ... }
- * ReturnType match(B& b) { ... }
- * ReturnType match(C& c) { ... }
- * ReturnType match(D& d) { ... } // Compile-time error to forget D!
+ * // The return type of all matchers must be identical.
+ * char* match(A& a) { ... }
+ * char* match(B& b) { ... }
+ * char* match(C& c) { ... }
+ * char* match(D& d) { ... } // Compile-time error to forget D!
* }
* char* foo(Variant<A, B, C, D>& v) {
* return v.match(FooMatcher());
@@ -313,18 +432,19 @@
* };
*/
template<typename... Ts>
-class Variant
+class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Variant
{
- using Impl = detail::VariantImplementation<0, Ts...>;
+ using Tag = typename detail::VariantTag<Ts...>::Type;
+ using Impl = detail::VariantImplementation<Tag, 0, Ts...>;
using RawData = AlignedStorage<detail::MaxSizeOf<Ts...>::size>;
- // Each type is given a unique size_t sentinel. This tag lets us keep track of
- // the contained variant value's type.
- size_t tag;
-
// Raw storage for the contained variant value.
RawData raw;
+ // Each type is given a unique tag value that lets us keep track of the
+ // contained variant value's type.
+ Tag tag;
+
void* ptr() {
return reinterpret_cast<void*>(&raw);
}
@@ -336,12 +456,24 @@
// perfect forwarding), so we have to remove those qualifiers here
// when ensuring that T is a variant of this type, and getting T's
// tag, etc.
- typename T = typename RemoveReference<typename RemoveConst<RefT>::Type>::Type,
- typename = typename EnableIf<detail::IsVariant<T, Ts...>::value, void>::Type>
+ typename T = typename detail::SelectVariantType<RefT, Ts...>::Type>
explicit Variant(RefT&& aT)
: tag(Impl::template tag<T>())
{
- new (ptr()) T(Forward<T>(aT));
+ new (ptr()) T(Forward<RefT>(aT));
+ }
+
+ /**
+ * Constructs this Variant from an AsVariantTemporary<T> such that T can be
+ * stored in one of the types allowable in this Variant. This is used in the
+ * implementation of AsVariant().
+ */
+ template<typename RefT,
+ typename T = typename detail::SelectVariantType<RefT, Ts...>::Type>
+ MOZ_IMPLICIT Variant(detail::AsVariantTemporary<RefT>&& aValue)
+ : tag(Impl::template tag<T>())
+ {
+ new (ptr()) T(Move(aValue.mValue));
}
/** Copy construction. */
@@ -374,6 +506,15 @@
return *this;
}
+ /** Move assignment from AsVariant(). */
+ template <typename T>
+ Variant& operator=(detail::AsVariantTemporary<T>&& aValue)
+ {
+ this->~Variant();
+ new (this) Variant(Move(aValue));
+ return *this;
+ }
+
~Variant()
{
Impl::destroy(*this);
@@ -438,23 +579,47 @@
return T(Move(as<T>()));
}
- // Exhaustive matching of all variant types no the contained value.
+ // Exhaustive matching of all variant types on the contained value.
/** Match on an immutable const reference. */
template<typename Matcher>
- typename Matcher::ReturnType
- match(Matcher& aMatcher) const {
+ auto
+ match(Matcher&& aMatcher) const
+ -> decltype(Impl::match(aMatcher, *this))
+ {
return Impl::match(aMatcher, *this);
}
- /** Match on a mutable non-const reference. */
+ /** Match on a mutable non-const reference. */
template<typename Matcher>
- typename Matcher::ReturnType
- match(Matcher& aMatcher) {
+ auto
+ match(Matcher&& aMatcher)
+ -> decltype(Impl::match(aMatcher, *this))
+ {
return Impl::match(aMatcher, *this);
}
};
+/*
+ * AsVariant() is used to construct a Variant<T,...> value containing the
+ * provided T value using type inference. It can be used to construct Variant
+ * values in expressions or return them from functions without specifying the
+ * entire Variant type.
+ *
+ * Because AsVariant() must copy or move the value into a temporary and this
+ * cannot necessarily be elided by the compiler, it's mostly appropriate only
+ * for use with primitive or very small types.
+ *
+ * AsVariant() returns a AsVariantTemporary value which is implicitly
+ * convertible to any Variant that can hold a value of type T.
+ */
+template<typename T>
+detail::AsVariantTemporary<T>
+AsVariant(T&& aValue)
+{
+ return detail::AsVariantTemporary<T>(Forward<T>(aValue));
+}
+
} // namespace mozilla
#endif /* mozilla_Variant_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Vector.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Vector.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/Vector.h
@@ -17,6 +17,7 @@
#include "mozilla/MathAlgorithms.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
+#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/ReentrancyGuard.h"
#include "mozilla/TemplateLib.h"
#include "mozilla/TypeTraits.h"
@@ -56,22 +57,13 @@
struct VectorImpl
{
/*
- * Constructs a default object in the uninitialized memory at *aDst.
+ * Constructs an object in the uninitialized memory at *aDst with aArgs.
*/
+ template<typename... Args>
MOZ_NONNULL(1)
- static inline void new_(T* aDst)
- {
- new(aDst) T();
- }
-
- /*
- * Constructs an object in the uninitialized memory at *aDst from aSrc.
- */
- template<typename U>
- MOZ_NONNULL(1)
- static inline void new_(T* aDst, U&& aU)
+ static inline void new_(T* aDst, Args&&... aArgs)
{
- new(aDst) T(Forward<U>(aU));
+ new(KnownNotNull, aDst) T(Forward<Args>(aArgs)...);
}
/* Destroys constructed objects in the range [aBegin, aEnd). */
@@ -137,7 +129,7 @@
* aNewCap has not overflowed, and (2) multiplying aNewCap by sizeof(T) will
* not overflow.
*/
- static inline bool
+ static inline MOZ_MUST_USE bool
growTo(Vector<T, N, AP>& aV, size_t aNewCap)
{
MOZ_ASSERT(!aV.usingInlineStorage());
@@ -168,15 +160,16 @@
template<typename T, size_t N, class AP>
struct VectorImpl<T, N, AP, true>
{
- static inline void new_(T* aDst)
- {
- *aDst = T();
- }
-
- template<typename U>
- static inline void new_(T* aDst, U&& aU)
+ template<typename... Args>
+ MOZ_NONNULL(1)
+ static inline void new_(T* aDst, Args&&... aArgs)
{
- *aDst = Forward<U>(aU);
+ // Explicitly construct a local object instead of using a temporary since
+ // T(args...) will be treated like a C-style cast in the unary case and
+ // allow unsafe conversions. Both forms should be equivalent to an
+ // optimizing compiler.
+ T temp(Forward<Args>(aArgs)...);
+ *aDst = temp;
}
static inline void destroy(T*, T*) {}
@@ -228,7 +221,7 @@
}
}
- static inline bool
+ static inline MOZ_MUST_USE bool
growTo(Vector<T, N, AP>& aV, size_t aNewCap)
{
MOZ_ASSERT(!aV.usingInlineStorage());
@@ -242,6 +235,20 @@
aV.mCapacity = aNewCap;
return true;
}
+
+ static inline void
+ podResizeToFit(Vector<T, N, AP>& aV)
+ {
+ if (aV.usingInlineStorage() || aV.mLength == aV.mCapacity) {
+ return;
+ }
+ T* newbuf = aV.template pod_realloc<T>(aV.mBegin, aV.mCapacity, aV.mLength);
+ if (MOZ_UNLIKELY(!newbuf)) {
+ return;
+ }
+ aV.mBegin = newbuf;
+ aV.mCapacity = aV.mLength;
+ }
};
// A struct for TestVector.cpp to access private internal fields.
@@ -281,8 +288,9 @@
friend struct detail::VectorTesting;
- bool growStorageBy(size_t aIncr);
- bool convertToHeapStorage(size_t aNewCap);
+ MOZ_MUST_USE bool growStorageBy(size_t aIncr);
+ MOZ_MUST_USE bool convertToHeapStorage(size_t aNewCap);
+ MOZ_MUST_USE bool maybeCheckSimulatedOOM(size_t aRequestedSize);
/* magic constants */
@@ -519,10 +527,24 @@
/* mutators */
/**
- * Given that the vector is empty and has no inline storage, grow to
- * |capacity|.
+ * Reverse the order of the elements in the vector in place.
+ */
+ void reverse();
+
+ /**
+ * Given that the vector is empty, grow the internal capacity to |aRequest|,
+ * keeping the length 0.
+ */
+ MOZ_MUST_USE bool initCapacity(size_t aRequest);
+
+ /**
+ * Given that the vector is empty, grow the internal capacity and length to
+ * |aRequest| leaving the elements' memory completely uninitialized (with all
+ * the associated hazards and caveats). This avoids the usual allocation-size
+ * rounding that happens in resize and overhead of initialization for elements
+ * that are about to be overwritten.
*/
- bool initCapacity(size_t aRequest);
+ MOZ_MUST_USE bool initLengthUninitialized(size_t aRequest);
/**
* If reserve(aRequest) succeeds and |aRequest >= length()|, then appending
@@ -532,7 +554,7 @@
* A request to reserve an amount less than the current length does not affect
* reserved space.
*/
- bool reserve(size_t aRequest);
+ MOZ_MUST_USE bool reserve(size_t aRequest);
/**
* Destroy elements in the range [end() - aIncr, end()). Does not deallocate
@@ -540,19 +562,25 @@
*/
void shrinkBy(size_t aIncr);
+ /**
+ * Destroy elements in the range [aNewLength, end()). Does not deallocate
+ * or unreserve storage for those elements.
+ */
+ void shrinkTo(size_t aNewLength);
+
/** Grow the vector by aIncr elements. */
- bool growBy(size_t aIncr);
+ MOZ_MUST_USE bool growBy(size_t aIncr);
/** Call shrinkBy or growBy based on whether newSize > length(). */
- bool resize(size_t aNewLength);
+ MOZ_MUST_USE bool resize(size_t aNewLength);
/**
* Increase the length of the vector, but don't initialize the new elements
* -- leave them as uninitialized memory.
*/
- bool growByUninitialized(size_t aIncr);
+ MOZ_MUST_USE bool growByUninitialized(size_t aIncr);
void infallibleGrowByUninitialized(size_t aIncr);
- bool resizeUninitialized(size_t aNewLength);
+ MOZ_MUST_USE bool resizeUninitialized(size_t aNewLength);
/** Shorthand for shrinkBy(length()). */
void clear();
@@ -561,6 +589,13 @@
void clearAndFree();
/**
+ * Calls the AllocPolicy's pod_realloc to release excess capacity. Since
+ * realloc is only safe on PODs, this method fails to compile if IsPod<T>
+ * is false.
+ */
+ void podResizeToFit();
+
+ /**
* If true, appending |aNeeded| elements won't reallocate elements storage.
* This *doesn't* mean that infallibleAppend may be used! You still must
* reserve the extra space, even if this method indicates that appends won't
@@ -575,25 +610,25 @@
* vector, instead of copying it. If it fails, |aU| is left unmoved. ("We are
* not amused.")
*/
- template<typename U> bool append(U&& aU);
+ template<typename U> MOZ_MUST_USE bool append(U&& aU);
/**
* Construct a T in-place as a new entry at the end of this vector.
*/
template<typename... Args>
- bool emplaceBack(Args&&... aArgs)
+ MOZ_MUST_USE bool emplaceBack(Args&&... aArgs)
{
if (!growByUninitialized(1))
return false;
- new (&back()) T(Forward<Args>(aArgs)...);
+ Impl::new_(&back(), Forward<Args>(aArgs)...);
return true;
}
template<typename U, size_t O, class BP>
- bool appendAll(const Vector<U, O, BP>& aU);
- bool appendN(const T& aT, size_t aN);
- template<typename U> bool append(const U* aBegin, const U* aEnd);
- template<typename U> bool append(const U* aBegin, size_t aLength);
+ MOZ_MUST_USE bool appendAll(const Vector<U, O, BP>& aU);
+ MOZ_MUST_USE bool appendN(const T& aT, size_t aN);
+ template<typename U> MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd);
+ template<typename U> MOZ_MUST_USE bool append(const U* aBegin, size_t aLength);
/*
* Guaranteed-infallible append operations for use upon vectors whose
@@ -620,7 +655,7 @@
void infallibleEmplaceBack(Args&&... aArgs)
{
infallibleGrowByUninitialized(1);
- new (&back()) T(Forward<Args>(aArgs)...);
+ Impl::new_(&back(), Forward<Args>(aArgs)...);
}
void popBack();
@@ -628,16 +663,34 @@
T popCopy();
/**
- * Transfers ownership of the internal buffer used by this vector to the
- * caller. (It's the caller's responsibility to properly deallocate this
- * buffer, in accordance with this vector's AllocPolicy.) After this call,
- * the vector is empty. Since the returned buffer may need to be allocated
- * (if the elements are currently stored in-place), the call can fail,
- * returning nullptr.
+ * If elements are stored in-place, return nullptr and leave this vector
+ * unmodified.
+ *
+ * Otherwise return this vector's elements buffer, and clear this vector as if
+ * by clearAndFree(). The caller now owns the buffer and is responsible for
+ * deallocating it consistent with this vector's AllocPolicy.
*
* N.B. Although a T*, only the range [0, length()) is constructed.
*/
- T* extractRawBuffer();
+ MOZ_MUST_USE T* extractRawBuffer();
+
+ /**
+ * If elements are stored in-place, allocate a new buffer, move this vector's
+ * elements into it, and return that buffer.
+ *
+ * Otherwise return this vector's elements buffer. The caller now owns the
+ * buffer and is responsible for deallocating it consistent with this vector's
+ * AllocPolicy.
+ *
+ * This vector is cleared, as if by clearAndFree(), when this method
+ * succeeds. This method fails and returns nullptr only if new elements buffer
+ * allocation fails.
+ *
+ * N.B. Only the range [0, length()) of the returned buffer is constructed.
+ * If any of these elements are uninitialized (as growByUninitialized
+ * enables), behavior is undefined.
+ */
+ MOZ_MUST_USE T* extractOrCopyRawBuffer();
/**
* Transfer ownership of an array of objects into the vector. The caller
@@ -665,7 +718,7 @@
* This is inherently a linear-time operation. Be careful!
*/
template<typename U>
- T* insert(T* aP, U&& aVal);
+ MOZ_MUST_USE T* insert(T* aP, U&& aVal);
/**
* Removes the element |aT|, which must fall in the bounds [begin, end),
@@ -767,7 +820,7 @@
{
MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
this->~Vector();
- new(this) Vector(Move(aRhs));
+ new(KnownNotNull, this) Vector(Move(aRhs));
return *this;
}
@@ -782,6 +835,18 @@
}
}
+template<typename T, size_t N, class AP>
+MOZ_ALWAYS_INLINE void
+Vector<T, N, AP>::reverse() {
+ MOZ_REENTRANCY_GUARD_ET_AL;
+ T* elems = mBegin;
+ size_t len = mLength;
+ size_t mid = len / 2;
+ for (size_t i = 0; i < mid; i++) {
+ Swap(elems[i], elems[len - i - 1]);
+ }
+}
+
/*
* This function will create a new heap buffer with capacity aNewCap,
* move all elements in the inline buffer to this new buffer,
@@ -916,6 +981,34 @@
template<typename T, size_t N, class AP>
inline bool
+Vector<T, N, AP>::initLengthUninitialized(size_t aRequest)
+{
+ if (!initCapacity(aRequest)) {
+ return false;
+ }
+ infallibleGrowByUninitialized(aRequest);
+ return true;
+}
+
+template<typename T, size_t N, class AP>
+inline bool
+Vector<T, N, AP>::maybeCheckSimulatedOOM(size_t aRequestedSize)
+{
+ if (aRequestedSize <= N) {
+ return true;
+ }
+
+#ifdef DEBUG
+ if (aRequestedSize <= mReserved) {
+ return true;
+ }
+#endif
+
+ return allocPolicy().checkSimulatedOOM();
+}
+
+template<typename T, size_t N, class AP>
+inline bool
Vector<T, N, AP>::reserve(size_t aRequest)
{
MOZ_REENTRANCY_GUARD_ET_AL;
@@ -923,10 +1016,8 @@
if (MOZ_UNLIKELY(!growStorageBy(aRequest - mLength))) {
return false;
}
- } else if (aRequest > N) {
- if (!allocPolicy().checkSimulatedOOM()) {
- return false;
- }
+ } else if (!maybeCheckSimulatedOOM(aRequest)) {
+ return false;
}
#ifdef DEBUG
if (aRequest > mReserved) {
@@ -949,6 +1040,14 @@
}
template<typename T, size_t N, class AP>
+MOZ_ALWAYS_INLINE void
+Vector<T, N, AP>::shrinkTo(size_t aNewLength)
+{
+ MOZ_ASSERT(aNewLength <= mLength);
+ shrinkBy(mLength - aNewLength);
+}
+
+template<typename T, size_t N, class AP>
MOZ_ALWAYS_INLINE bool
Vector<T, N, AP>::growBy(size_t aIncr)
{
@@ -957,10 +1056,8 @@
if (MOZ_UNLIKELY(!growStorageBy(aIncr))) {
return false;
}
- } else if (aIncr + mLength > N) {
- if (!allocPolicy().checkSimulatedOOM()) {
- return false;
- }
+ } else if (!maybeCheckSimulatedOOM(mLength + aIncr)) {
+ return false;
}
MOZ_ASSERT(mLength + aIncr <= mCapacity);
T* newend = endNoCheck() + aIncr;
@@ -983,11 +1080,14 @@
if (MOZ_UNLIKELY(!growStorageBy(aIncr))) {
return false;
}
- } else if (aIncr + mLength > N) {
- if (!allocPolicy().checkSimulatedOOM()) {
- return false;
- }
+ } else if (!maybeCheckSimulatedOOM(mLength + aIncr)) {
+ return false;
}
+#ifdef DEBUG
+ if (mLength + aIncr > mReserved) {
+ mReserved = mLength + aIncr;
+ }
+#endif
infallibleGrowByUninitialized(aIncr);
return true;
}
@@ -996,13 +1096,8 @@
MOZ_ALWAYS_INLINE void
Vector<T, N, AP>::infallibleGrowByUninitialized(size_t aIncr)
{
- MOZ_ASSERT(mLength + aIncr <= mCapacity);
+ MOZ_ASSERT(mLength + aIncr <= reserved());
mLength += aIncr;
-#ifdef DEBUG
- if (mLength > mReserved) {
- mReserved = mLength;
- }
-#endif
}
template<typename T, size_t N, class AP>
@@ -1056,6 +1151,15 @@
}
template<typename T, size_t N, class AP>
+inline void
+Vector<T, N, AP>::podResizeToFit()
+{
+ // This function is only defined if IsPod is true and will fail to compile
+ // otherwise.
+ Impl::podResizeToFit(*this);
+}
+
+template<typename T, size_t N, class AP>
inline bool
Vector<T, N, AP>::canAppendWithoutRealloc(size_t aNeeded) const
{
@@ -1090,9 +1194,8 @@
if (MOZ_UNLIKELY(!growStorageBy(aNeeded))) {
return false;
}
- } else if (mLength + aNeeded > N) {
- if (!allocPolicy().checkSimulatedOOM())
- return false;
+ } else if (!maybeCheckSimulatedOOM(mLength + aNeeded)) {
+ return false;
}
#ifdef DEBUG
if (mLength + aNeeded > mReserved) {
@@ -1177,8 +1280,7 @@
if (MOZ_UNLIKELY(!growStorageBy(aNeeded))) {
return false;
}
- } else if (mLength + aNeeded > N) {
- if (!allocPolicy().checkSimulatedOOM())
+ } else if (!maybeCheckSimulatedOOM(mLength + aNeeded)) {
return false;
}
#ifdef DEBUG
@@ -1211,8 +1313,7 @@
if (MOZ_UNLIKELY(!growStorageBy(1))) {
return false;
}
- } else if (mLength + 1 > N) {
- if (!allocPolicy().checkSimulatedOOM())
+ } else if (!maybeCheckSimulatedOOM(mLength + 1)) {
return false;
}
#ifdef DEBUG
@@ -1263,29 +1364,49 @@
inline T*
Vector<T, N, AP>::extractRawBuffer()
{
- T* ret;
+ MOZ_REENTRANCY_GUARD_ET_AL;
+
if (usingInlineStorage()) {
- ret = this->template pod_malloc<T>(mLength);
- if (!ret) {
- return nullptr;
- }
- Impl::copyConstruct(ret, beginNoCheck(), endNoCheck());
- Impl::destroy(beginNoCheck(), endNoCheck());
- /* mBegin, mCapacity are unchanged. */
- mLength = 0;
- } else {
- ret = mBegin;
- mBegin = static_cast<T*>(mStorage.addr());
- mLength = 0;
- mCapacity = kInlineCapacity;
+ return nullptr;
+ }
+
+ T* ret = mBegin;
+ mBegin = static_cast<T*>(mStorage.addr());
+ mLength = 0;
+ mCapacity = kInlineCapacity;
#ifdef DEBUG
- mReserved = 0;
+ mReserved = 0;
#endif
- }
return ret;
}
template<typename T, size_t N, class AP>
+inline T*
+Vector<T, N, AP>::extractOrCopyRawBuffer()
+{
+ if (T* ret = extractRawBuffer()) {
+ return ret;
+ }
+
+ MOZ_REENTRANCY_GUARD_ET_AL;
+
+ T* copy = this->template pod_malloc<T>(mLength);
+ if (!copy) {
+ return nullptr;
+ }
+
+ Impl::moveConstruct(copy, beginNoCheck(), endNoCheck());
+ Impl::destroy(beginNoCheck(), endNoCheck());
+ mBegin = static_cast<T*>(mStorage.addr());
+ mLength = 0;
+ mCapacity = kInlineCapacity;
+#ifdef DEBUG
+ mReserved = 0;
+#endif
+ return copy;
+}
+
+template<typename T, size_t N, class AP>
inline void
Vector<T, N, AP>::replaceRawBuffer(T* aP, size_t aLength)
{
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/WeakPtr.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/WeakPtr.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/WeakPtr.h
@@ -76,6 +76,58 @@
#include <string.h>
+// Weak referencing is not implemeted as thread safe. When a WeakPtr
+// is created or dereferenced on thread A but the real object is just
+// being Released() on thread B, there is a possibility of a race
+// when the proxy object (detail::WeakReference) is notified about
+// the real object destruction just between when thread A is storing
+// the object pointer locally and is about to add a reference to it.
+//
+// Hence, a non-null weak proxy object is considered to have a single
+// "owning thread". It means that each query for a weak reference,
+// its dereference, and destruction of the real object must all happen
+// on a single thread. The following macros implement assertions for
+// checking these conditions.
+//
+// We disable this on MinGW. MinGW has two threading models: win32
+// API based, which disables std::thread; and POSIX based which
+// enables it but requires an emulation library (winpthreads).
+// Rather than attempting to switch to pthread emulation at this point,
+// we are disabling the std::thread based assertion checking.
+//
+// In the future, to enable it we could
+// a. have libgcc/stdc++ support win32 threads natively
+// b. switch to POSIX-based threading in MinGW with pthread emulation
+// c. refactor it to not use std::thread
+
+#if !defined(__MINGW32__) && (defined(DEBUG) || (defined(NIGHTLY_BUILD) && !defined(MOZ_PROFILING)))
+
+#include <thread>
+#define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK \
+ std::thread::id _owningThread; \
+ bool _empty; // If it was initialized as a placeholder with mPtr = nullptr.
+#define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() \
+ do { \
+ _owningThread = std::this_thread::get_id(); \
+ _empty = !p; \
+ } while (false)
+#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() \
+ MOZ_DIAGNOSTIC_ASSERT(_empty || _owningThread == std::this_thread::get_id(), \
+ "WeakPtr used on multiple threads")
+#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(that) \
+ (that)->AssertThreadSafety();
+
+#define MOZ_WEAKPTR_THREAD_SAFETY_CHECKING 1
+
+#else
+
+#define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK
+#define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() do { } while (false)
+#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() do { } while (false)
+#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(that) do { } while (false)
+
+#endif
+
namespace mozilla {
template <typename T> class WeakPtr;
@@ -96,9 +148,15 @@
class WeakReference : public ::mozilla::RefCounted<WeakReference<T> >
{
public:
- explicit WeakReference(T* p) : mPtr(p) {}
+ explicit WeakReference(T* p) : mPtr(p)
+ {
+ MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK();
+ }
- T* get() const { return mPtr; }
+ T* get() const {
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY();
+ return mPtr;
+ }
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
const char* typeName() const
@@ -110,12 +168,20 @@
size_t typeSize() const { return sizeof(*this); }
#endif
+#ifdef MOZ_WEAKPTR_THREAD_SAFETY_CHECKING
+ void AssertThreadSafety() { MOZ_WEAKPTR_ASSERT_THREAD_SAFETY(); }
+#endif
+
private:
friend class mozilla::SupportsWeakPtr<T>;
- void detach() { mPtr = nullptr; }
+ void detach() {
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY();
+ mPtr = nullptr;
+ }
T* MOZ_NON_OWNING_REF mPtr;
+ MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK
};
} // namespace detail
@@ -138,6 +204,8 @@
{
if (!mSelfReferencingWeakPtr) {
mSelfReferencingWeakPtr.mRef = new detail::WeakReference<T>(static_cast<T*>(this));
+ } else {
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mSelfReferencingWeakPtr.mRef);
}
return mSelfReferencingWeakPtr;
}
@@ -163,11 +231,13 @@
WeakPtr& operator=(const WeakPtr& aOther)
{
mRef = aOther.mRef;
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mRef);
return *this;
}
WeakPtr(const WeakPtr& aOther)
{
+ // The thread safety check is performed inside of the operator= method.
*this = aOther;
}
@@ -179,12 +249,15 @@
// Ensure that mRef is dereferenceable in the uninitialized state.
mRef = new WeakReference(nullptr);
}
+ // The thread safety check happens inside SelfReferencingWeakPtr
+ // or is initialized in the WeakReference constructor.
return *this;
}
MOZ_IMPLICIT WeakPtr(T* aOther)
{
*this = aOther;
+ MOZ_WEAKPTR_ASSERT_THREAD_SAFETY_DELEGATED(mRef);
}
// Ensure that mRef is dereferenceable in the uninitialized state.
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/WindowsVersion.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/WindowsVersion.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/WindowsVersion.h
@@ -172,6 +172,12 @@
}
MOZ_ALWAYS_INLINE bool
+IsWin8Point1OrLater()
+{
+ return IsWindowsVersionOrLater(0x06030000ul);
+}
+
+MOZ_ALWAYS_INLINE bool
IsWin10OrLater()
{
return IsWindowsVersionOrLater(0x0a000000ul);
@@ -184,6 +190,41 @@
IsWindowsBuildOrLater(7600);
}
+MOZ_ALWAYS_INLINE bool
+IsWin7AndPre2000Compatible() {
+ /*
+ * See Bug 1279171.
+ * We'd like to avoid using WMF on specific OS version when compatibility
+ * mode is in effect. The purpose of this function is to check if FF runs on
+ * Win7 OS with application compatibility mode being set to 95/98/ME.
+ * Those compatibility mode options (95/98/ME) can only display and
+ * be selected for 32-bit application.
+ * If the compatibility mode is in effect, the GetVersionEx function will
+ * report the OS as it identifies itself, which may not be the OS that is
+ * installed.
+ * Note : 1) We only target for Win7 build number greater than 7600.
+ * 2) GetVersionEx may be altered or unavailable for release after
+ * Win8.1. Set pragma to avoid build warning as error.
+ */
+ bool isWin7 = IsNotWin7PreRTM() && !IsWin8OrLater();
+ if (!isWin7) {
+ return false;
+ }
+
+ OSVERSIONINFOEX info;
+ ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
+
+ info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+#pragma warning(push)
+#pragma warning(disable:4996)
+ bool success = GetVersionEx((LPOSVERSIONINFO) &info);
+#pragma warning(pop)
+ if (!success) {
+ return false;
+ }
+ return info.dwMajorVersion < 5;
+}
+
} // namespace mozilla
#endif /* mozilla_WindowsVersion_h */
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/XorShift128PlusRNG.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/XorShift128PlusRNG.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/XorShift128PlusRNG.h
@@ -33,6 +33,11 @@
* Intel(R) Core(TM) i7-4770 CPU @3.40GHz (Haswell). It is the fastest
* generator we are aware of with such empirical statistical properties.
*
+ * The stream of numbers produced by this method repeats every 2**128 - 1 calls
+ * (i.e. never, for all practical purposes). Zero appears 2**64 - 1 times in
+ * this period; all other numbers appear 2**64 times. Additionally, each *bit*
+ * in the produced numbers repeats every 2**128 - 1 calls.
+ *
* This generator is not suitable as a cryptographically secure random number
* generator.
*/
@@ -42,14 +47,20 @@
public:
/*
* Construct a xorshift128+ pseudo-random number stream using |aInitial0| and
- * |aInitial1| as the initial state. These may not both be zero; ideally, they
- * should have an almost even mix of zero and one bits.
+ * |aInitial1| as the initial state. These MUST NOT both be zero.
+ *
+ * If the initial states contain many zeros, for a few iterations you'll see
+ * many zeroes in the generated numbers. It's suggested to seed a SplitMix64
+ * generator <http://xorshift.di.unimi.it/splitmix64.c> and use its first two
+ * outputs to seed xorshift128+.
*/
XorShift128PlusRNG(uint64_t aInitial0, uint64_t aInitial1) {
setState(aInitial0, aInitial1);
}
- /* Return a pseudo-random 64-bit number. */
+ /**
+ * Return a pseudo-random 64-bit number.
+ */
uint64_t next() {
/*
* The offsetOfState*() methods below are provided so that exceedingly-rare
@@ -66,9 +77,10 @@
}
/*
- * Return a pseudo-random floating-point value in the range [0, 1).
- * More precisely, choose an integer in the range [0, 2**53) and
- * divide it by 2**53.
+ * Return a pseudo-random floating-point value in the range [0, 1). More
+ * precisely, choose an integer in the range [0, 2**53) and divide it by
+ * 2**53. Given the 2**128 - 1 period noted above, the produced doubles are
+ * all but uniformly distributed in this range.
*/
double nextDouble() {
/*
@@ -78,7 +90,7 @@
* is the width of the bitfield in the in-memory format, so we must add one
* to get the mantissa's range.
*/
- static MOZ_CONSTEXPR_VAR int kMantissaBits =
+ static constexpr int kMantissaBits =
mozilla::FloatingPoint<double>::kExponentShift + 1;
uint64_t mantissa = next() & ((UINT64_C(1) << kMantissaBits) - 1);
return double(mantissa) / (UINT64_C(1) << kMantissaBits);
Index: ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/mozalloc.h
===================================================================
--- ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/mozalloc.h
+++ ps/trunk/libraries/source/spidermonkey/include-win32-release/mozilla/mozalloc.h
@@ -12,14 +12,22 @@
* https://bugzilla.mozilla.org/show_bug.cgi?id=427099
*/
-#include <stdlib.h>
-#include <string.h>
#if defined(__cplusplus)
# include <new>
+// Since libstdc++ 6, including the C headers (e.g. stdlib.h) instead of the
+// corresponding C++ header (e.g. cstdlib) can cause confusion in C++ code
+// using things defined there. Specifically, with stdlib.h, the use of abs()
+// in gfx/graphite2/src/inc/UtfCodec.h somehow ends up picking the wrong abs()
+# include <cstdlib>
+# include <cstring>
+#else
+# include <stdlib.h>
+# include <string.h>
#endif
#if defined(__cplusplus)
#include "mozilla/fallible.h"
+#include "mozilla/mozalloc_abort.h"
#include "mozilla/TemplateLib.h"
#endif
#include "mozilla/Attributes.h"
@@ -37,8 +45,8 @@
/* Workaround build problem with Sun Studio 12 */
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-# undef MOZ_WARN_UNUSED_RESULT
-# define MOZ_WARN_UNUSED_RESULT
+# undef MOZ_MUST_USE
+# define MOZ_MUST_USE
# undef MOZ_ALLOCATOR
# define MOZ_ALLOCATOR
#endif
@@ -97,10 +105,10 @@
#if defined(HAVE_POSIX_MEMALIGN)
-MFBT_API MOZ_WARN_UNUSED_RESULT
+MFBT_API MOZ_MUST_USE
int moz_xposix_memalign(void **ptr, size_t alignment, size_t size);
-MFBT_API MOZ_WARN_UNUSED_RESULT
+MFBT_API MOZ_MUST_USE
int moz_posix_memalign(void **ptr, size_t alignment, size_t size);
#endif /* if defined(HAVE_POSIX_MEMALIGN) */
@@ -282,10 +290,28 @@
{
public:
template <typename T>
+ T* maybe_pod_malloc(size_t aNumElems)
+ {
+ return pod_malloc<T>(aNumElems);
+ }
+
+ template <typename T>
+ T* maybe_pod_calloc(size_t aNumElems)
+ {
+ return pod_calloc<T>(aNumElems);
+ }
+
+ template <typename T>
+ T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
+ {
+ return pod_realloc<T>(aPtr, aOldSize, aNewSize);
+ }
+
+ template <typename T>
T* pod_malloc(size_t aNumElems)
{
if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
- return nullptr;
+ reportAllocOverflow();
}
return static_cast<T*>(moz_xmalloc(aNumElems * sizeof(T)));
}
@@ -300,7 +326,7 @@
T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
{
if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
- return nullptr;
+ reportAllocOverflow();
}
return static_cast<T*>(moz_xrealloc(aPtr, aNewSize * sizeof(T)));
}
@@ -312,6 +338,12 @@
void reportAllocOverflow() const
{
+ mozalloc_abort("alloc overflow");
+ }
+
+ bool checkSimulatedOOM() const
+ {
+ return true;
}
};
Index: ps/trunk/libraries/source/spidermonkey/patch.sh
===================================================================
--- ps/trunk/libraries/source/spidermonkey/patch.sh
+++ ps/trunk/libraries/source/spidermonkey/patch.sh
@@ -2,59 +2,30 @@
# Apply patches if needed
# This script gets called from build-osx-libs.sh and build.sh.
-# Remove the unnecessary NSPR dependency.
-# Will be included in SM52.
-# https://bugzilla.mozilla.org/show_bug.cgi?id=1379539
-patch -p1 < ../RemoveNSPRDependency.diff
-
-# Fix the path to the moz.build file in the zlib module
-patch -p1 < ../FixZLibMozBuild.diff
-
-# === Fix the SM45 tracelogger ===
-# This patch is a squashed version of several patches that were adapted
-# to fix failing hunks.
-#
-# Applied in the following order, they are:
-# * https://bugzilla.mozilla.org/show_bug.cgi?id=1266649
-# Handle failing to add to pointermap gracefully.
-# * https://bugzilla.mozilla.org/show_bug.cgi?id=1280648
-# Don't cache based on pointers to movable GC things.
-# * https://bugzilla.mozilla.org/show_bug.cgi?id=1255766
-# Also mark resizing of memory.
-# * https://bugzilla.mozilla.org/show_bug.cgi?id=1259403
-# Only increase capacity by multiples of 2.
-# Always make sure there are 3 free slots for events.
-# ===
-patch -p1 < ../FixTracelogger.diff
-
# Patch embedded python psutil to work with FreeBSD 12 after revision 315662
# Based on: https://svnweb.freebsd.org/ports/head/sysutils/py-psutil121/files/patch-_psutil_bsd.c?revision=436575&view=markup
# psutil will be upgraded in SM60: https://bugzilla.mozilla.org/show_bug.cgi?id=1436857
patch -p0 < ../FixpsutilFreeBSD.diff
-# Patch some parts of the code to support extra processor architectures
-# Includes:
-# * https://bugzilla.mozilla.org/show_bug.cgi?id=1143022 (for arm64)
-# * https://bugzilla.mozilla.org/show_bug.cgi?id=1277742 (for aarch64)
-# * https://bugzilla.mozilla.org/show_bug.cgi?id=1266366 (for ppc64)
-patch -p1 < ../FixNonx86.diff
-
-# Always link mozglue into the shared library when building standalone.
-# Will be included in SM60. Custom version of the patch for SM45, which doesn't have the same build system.
-# https://bugzilla.mozilla.org/show_bug.cgi?id=1176787
-patch -p1 < ../FixMozglueStatic.diff
-
-# JSPropertyDescriptor is not public in SM45.
-# Will be fixed in SM52.
-# https://bugzilla.mozilla.org/show_bug.cgi?id=1316079
-patch -p1 < ../ExportJSPropertyDescriptor.diff
-
-# When trying to link pyrogenesis, js::oom::GetThreadType() and js::ReportOutOfMemory()
-# are marked as unresolved symbols.
-# Will be included in SM52.
-# https://bugzilla.mozilla.org/show_bug.cgi?id=1379538
-patch -p1 < ../FixLinking.diff
-
-# Allow the use of JS::PersistentRootedSymbol in debug builds.
-# This check will be removed in SM52.
-patch -p1 < ../FixPersistentRootedSymbol.diff
+# Static builds have a few issues.
+# First, mozglue symbols need to be linked against. This is partly fixed in SM60+, party still there in SM78.
+# (see https://bugzilla.mozilla.org/show_bug.cgi?id=1176787 ).
+# Secondly, the SDK_LIBRARY flag isn't set. This is still an issue in SM78.
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1588340
+patch -p1 < ../FixMozglue.diff
+
+# Update library names to have separate debug/release libraries.
+patch -p1 < ../RenameLibs.diff
+
+# After https://bugzilla.mozilla.org/show_bug.cgi?id=1289934 landed in
+# Firefox 51, MSVC compilation has been broken due to bug
+# https://developercommunity.visualstudio.com/content/problem/25334/error-code-c2971-when-specifying-a-function-as-the.html
+# (resolved in Visual Studio 2017). The following fix was applied
+# to not drop compiler support and will be included in SM 60.
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1300925
+patch -p1 < ../FixMSVCBuild.diff
+
+# GCC 9 and 10 fail to build with -Werror=format, so disable it.
+# https://bugs.gentoo.org/693556
+patch -p1 < ../DisableGCC9WerrorFormat.diff
+
Index: ps/trunk/source/scriptinterface/ScriptTypes.h
===================================================================
--- ps/trunk/source/scriptinterface/ScriptTypes.h
+++ ps/trunk/source/scriptinterface/ScriptTypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2016 Wildfire Games.
+/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -71,7 +71,7 @@
# pragma GCC diagnostic pop
#endif
-#if MOZJS_MAJOR_VERSION != 45
+#if MOZJS_MAJOR_VERSION != 52
#error Your compiler is trying to use an incorrect major version of the \
SpiderMonkey library. The only version that works is the one in the \
libraries/spidermonkey/ directory, and it will not work with a typical \
@@ -79,7 +79,7 @@
include paths.
#endif
-#if MOZJS_MINOR_VERSION != 0
+#if MOZJS_MINOR_VERSION != 9
#error Your compiler is trying to use an untested minor version of the \
SpiderMonkey library. If you are a package maintainer, please make sure \
to check very carefully that this version does not change the behaviour \
Index: ps/trunk/source/tools/tracelogger/tracelogger_options.sh
===================================================================
--- ps/trunk/source/tools/tracelogger/tracelogger_options.sh
+++ ps/trunk/source/tools/tracelogger/tracelogger_options.sh
@@ -9,13 +9,15 @@
# The last tested version of the tool is 1c67e97e794b5039d0cae95f72ea0c76e4aa4696,
# it can be used if more recent versions cause trouble.
+export TLDIR="$(dirname $(realpath $0))"
+
# Use semicolons to separate values on Windows.
# If that produces bogus output, you can try with commas instead.
if [ "${OS}" = "Windows_NT" ]
then
- export TLLOG="Defaults;IonCompiler"
+ export TLLOG="Default;IonCompiler"
export TLOPTIONS="EnableMainThread;EnableOffThread;EnableGraph"
else
- export TLLOG=Defaults,IonCompiler
+ export TLLOG=Default,IonCompiler
export TLOPTIONS=EnableMainThread,EnableOffThread,EnableGraph
fi

File Metadata

Mime Type
text/plain
Expires
Sat, Sep 28, 8:07 AM (13 h, 45 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
20/1d/cbe14700161a9814f459b428a516
Default Alt Text
D3094.diff (1 MB)

Event Timeline