diff --git a/build/autoconf/icu.m4 b/build/autoconf/icu.m4 index d025dcc80a..8b497a0048 100644 --- a/build/autoconf/icu.m4 +++ b/build/autoconf/icu.m4 @@ -95,7 +95,7 @@ if test -n "$USE_ICU"; then MOZ_ICU_DBG_SUFFIX=d fi ;; - Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD|GNU/kFreeBSD) + Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD|GNU/kFreeBSD|SunOS) ICU_LIB_NAMES="icui18n icuuc icudata" ;; *) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 5acc9ed692..1f2be4c66b 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -107,6 +107,10 @@ const size_t gStackSize = 8192; #define NS_FULL_GC_DELAY 60000 // ms +// The amount of time to wait from the user being idle to starting a shrinking +// GC. +#define NS_SHRINKING_GC_DELAY 15000 // ms + // Maximum amount of time that should elapse between incremental GC slices #define NS_INTERSLICE_GC_DELAY 100 // ms @@ -148,6 +152,7 @@ static const uint32_t kMaxICCDuration = 2000; // ms static nsITimer *sGCTimer; static nsITimer *sShrinkGCBuffersTimer; +static nsITimer *sShrinkingGCTimer; static nsITimer *sCCTimer; static nsITimer *sICCTimer; static nsITimer *sFullGCTimer; @@ -212,6 +217,7 @@ static nsIScriptSecurityManager *sSecurityManager; // the appropriate pref is set. static bool sGCOnMemoryPressure; +static bool sCompactOnUserInactive; // In testing, we call RunNextCollectorTimer() to ensure that the collectors are run more // aggressively than they would be in regular browsing. sExpensiveCollectorPokes keeps @@ -234,6 +240,7 @@ static void KillTimers() { nsJSContext::KillGCTimer(); + nsJSContext::KillShrinkingGCTimer(); nsJSContext::KillShrinkGCBuffersTimer(); nsJSContext::KillCCTimer(); nsJSContext::KillICCTimer(); @@ -266,22 +273,30 @@ NS_IMETHODIMP nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { - if (sGCOnMemoryPressure && !nsCRT::strcmp(aTopic, "memory-pressure")) { - if(StringBeginsWith(nsDependentString(aData), - NS_LITERAL_STRING("low-memory-ongoing"))) { - // Don't GC/CC if we are in an ongoing low-memory state since its very - // slow and it likely won't help us anyway. - return NS_OK; - } - nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE, - nsJSContext::NonIncrementalGC, - nsJSContext::ShrinkingGC); - nsJSContext::CycleCollectNow(); - if (NeedsGCAfterCC()) { + if (!nsCRT::strcmp(aTopic, "memory-pressure")) { + if (sGCOnMemoryPressure) { + if(StringBeginsWith(nsDependentString(aData), + NS_LITERAL_STRING("low-memory-ongoing"))) { + // Don't GC/CC if we are in an ongoing low-memory state since its very + // slow and it likely won't help us anyway. + return NS_OK; + } nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE, nsJSContext::NonIncrementalGC, nsJSContext::ShrinkingGC); + nsJSContext::CycleCollectNow(); + if (NeedsGCAfterCC()) { + nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE, + nsJSContext::NonIncrementalGC, + nsJSContext::ShrinkingGC); + } } + } else if (!nsCRT::strcmp(aTopic, "user-interaction-inactive")) { + if (sCompactOnUserInactive) { + nsJSContext::PokeShrinkingGC(); + } + } else if (!nsCRT::strcmp(aTopic, "user-interaction-active")) { + nsJSContext::KillShrinkingGCTimer(); } else if (!nsCRT::strcmp(aTopic, "quit-application") || !nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { sShuttingDown = true; @@ -1284,12 +1299,11 @@ nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason, return; } + JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL; JS::PrepareForFullGC(sRuntime); if (aIncremental == IncrementalGC) { - MOZ_ASSERT(aShrinking == NonShrinkingGC); - JS::StartIncrementalGC(sRuntime, GC_NORMAL, aReason, aSliceMillis); + JS::StartIncrementalGC(sRuntime, gckind, aReason, aSliceMillis); } else { - JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL; JS::GCForReason(sRuntime, gckind, aReason); } } @@ -1798,6 +1812,16 @@ ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure) nsJSContext::ShrinkGCBuffersNow(); } +// static +void +ShrinkingGCTimerFired(nsITimer* aTimer, void* aClosure) +{ + nsJSContext::KillShrinkingGCTimer(); + nsJSContext::GarbageCollectNow(JS::gcreason::USER_INACTIVE, + nsJSContext::IncrementalGC, + nsJSContext::ShrinkingGC); +} + static bool ShouldTriggerCC(uint32_t aSuspected) { @@ -2030,6 +2054,26 @@ nsJSContext::PokeShrinkGCBuffers() nsITimer::TYPE_ONE_SHOT); } +// static +void +nsJSContext::PokeShrinkingGC() +{ + if (sShrinkingGCTimer || sShuttingDown) { + return; + } + + CallCreateInstance("@mozilla.org/timer;1", &sShrinkingGCTimer); + + if (!sShrinkingGCTimer) { + // Failed to create timer (probably because we're in XPCOM shutdown) + return; + } + + sShrinkingGCTimer->InitWithFuncCallback(ShrinkingGCTimerFired, nullptr, + NS_SHRINKING_GC_DELAY, + nsITimer::TYPE_ONE_SHOT); +} + // static void nsJSContext::MaybePokeCC() @@ -2091,6 +2135,16 @@ nsJSContext::KillShrinkGCBuffersTimer() } } +//static +void +nsJSContext::KillShrinkingGCTimer() +{ + if (sShrinkingGCTimer) { + sShrinkingGCTimer->Cancel(); + NS_RELEASE(sShrinkingGCTimer); + } +} + //static void nsJSContext::KillCCTimer() @@ -2282,7 +2336,7 @@ void mozilla::dom::StartupJSEnvironment() { // initialize all our statics, so that we can restart XPCOM - sGCTimer = sFullGCTimer = sCCTimer = sICCTimer = nullptr; + sGCTimer = sShrinkingGCTimer = sFullGCTimer = sCCTimer = sICCTimer = nullptr; sCCLockedOut = false; sCCLockedOutTime = 0; sLastCCEndTime = TimeStamp(); @@ -2692,8 +2746,14 @@ nsJSContext::EnsureStatics() "javascript.options.gc_on_memory_pressure", true); + Preferences::AddBoolVarCache(&sCompactOnUserInactive, + "javascript.options.compact_on_user_inactive", + true); + nsIObserver* observer = new nsJSEnvironmentObserver(); obs->AddObserver(observer, "memory-pressure", false); + obs->AddObserver(observer, "user-interaction-inactive", false); + obs->AddObserver(observer, "user-interaction-active", false); obs->AddObserver(observer, "quit-application", false); obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index 6b9086d095..7447f8dc4f 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -116,6 +116,9 @@ public: static void PokeShrinkGCBuffers(); static void KillShrinkGCBuffersTimer(); + static void PokeShrinkingGC(); + static void KillShrinkingGCTimer(); + static void MaybePokeCC(); static void KillCCTimer(); static void KillICCTimer(); diff --git a/dom/xbl/nsXBLMaybeCompiled.h b/dom/xbl/nsXBLMaybeCompiled.h index b5977c848a..abf6084b37 100644 --- a/dom/xbl/nsXBLMaybeCompiled.h +++ b/dom/xbl/nsXBLMaybeCompiled.h @@ -91,11 +91,6 @@ struct GCMethods > static nsXBLMaybeCompiled initial() { return nsXBLMaybeCompiled(); } - static bool poisoned(nsXBLMaybeCompiled function) - { - return function.IsCompiled() && Base::poisoned(function.GetJSFunction()); - } - static bool needsPostBarrier(nsXBLMaybeCompiled function) { return function.IsCompiled() && Base::needsPostBarrier(function.GetJSFunction()); diff --git a/js/public/GCAPI.h b/js/public/GCAPI.h index 2721d67942..c287748a57 100644 --- a/js/public/GCAPI.h +++ b/js/public/GCAPI.h @@ -99,7 +99,8 @@ namespace JS { D(REFRESH_FRAME) \ D(FULL_GC_TIMER) \ D(SHUTDOWN_CC) \ - D(FINISH_LARGE_EVALUATE) + D(FINISH_LARGE_EVALUATE) \ + D(USER_INACTIVE) namespace gcreason { diff --git a/js/public/HashTable.h b/js/public/HashTable.h index 36f37d6852..00e6655e8e 100644 --- a/js/public/HashTable.h +++ b/js/public/HashTable.h @@ -546,7 +546,6 @@ struct PointerHasher { typedef Key Lookup; static HashNumber hash(const Lookup& l) { - MOZ_ASSERT(!JS::IsPoisonedPtr(l)); size_t word = reinterpret_cast(l) >> zeroBits; static_assert(sizeof(HashNumber) == 4, "subsequent code assumes a four-byte hash"); @@ -560,8 +559,6 @@ struct PointerHasher #endif } static bool match(const Key& k, const Lookup& l) { - MOZ_ASSERT(!JS::IsPoisonedPtr(k)); - MOZ_ASSERT(!JS::IsPoisonedPtr(l)); return k == l; } static void rekey(Key& k, const Key& newKey) { diff --git a/js/public/Id.h b/js/public/Id.h index 92df7396e5..74b5142ef5 100644 --- a/js/public/Id.h +++ b/js/public/Id.h @@ -126,7 +126,6 @@ SYMBOL_TO_JSID(JS::Symbol* sym) MOZ_ASSERT(sym != nullptr); MOZ_ASSERT((size_t(sym) & JSID_TYPE_MASK) == 0); MOZ_ASSERT(!js::gc::IsInsideNursery(reinterpret_cast(sym))); - MOZ_ASSERT(!JS::IsPoisonedPtr(sym)); JSID_BITS(id) = (size_t(sym) | JSID_TYPE_SYMBOL); return id; } @@ -169,20 +168,9 @@ extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE; namespace js { -inline bool -IsPoisonedId(jsid id) -{ - if (JSID_IS_STRING(id)) - return JS::IsPoisonedPtr(JSID_TO_STRING(id)); - if (JSID_IS_SYMBOL(id)) - return JS::IsPoisonedPtr(JSID_TO_SYMBOL(id)); - return false; -} - template <> struct GCMethods { static jsid initial() { return JSID_VOID; } - static bool poisoned(jsid id) { return IsPoisonedId(id); } static bool needsPostBarrier(jsid id) { return false; } static void postBarrier(jsid* idp) {} static void relocate(jsid* idp) {} diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 8465c79653..727ae9659c 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -282,14 +282,12 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase private: void init(T newPtr) { - MOZ_ASSERT(!js::GCMethods::poisoned(newPtr)); ptr = newPtr; if (js::GCMethods::needsPostBarrier(ptr)) post(); } void set(T newPtr) { - MOZ_ASSERT(!js::GCMethods::poisoned(newPtr)); if (js::GCMethods::needsPostBarrier(newPtr)) { ptr = newPtr; post(); @@ -362,7 +360,6 @@ class TenuredHeap : public js::HeapBase void setPtr(T newPtr) { MOZ_ASSERT((reinterpret_cast(newPtr) & flagsMask) == 0); - MOZ_ASSERT(!js::GCMethods::poisoned(newPtr)); if (newPtr) AssertGCThingMustBeTenured(newPtr); bits = (bits & flagsMask) | reinterpret_cast(newPtr); @@ -526,7 +523,6 @@ class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase public: void set(T v) { - MOZ_ASSERT(!js::GCMethods::poisoned(v)); *ptr = v; } @@ -642,7 +638,6 @@ template struct GCMethods { static T* initial() { return nullptr; } - static bool poisoned(T* v) { return JS::IsPoisonedPtr(v); } static bool needsPostBarrier(T* v) { return false; } static void postBarrier(T** vp) {} static void relocate(T** vp) {} @@ -652,7 +647,6 @@ template <> struct GCMethods { static JSObject* initial() { return nullptr; } - static bool poisoned(JSObject* v) { return JS::IsPoisonedPtr(v); } static gc::Cell* asGCThingOrNull(JSObject* v) { if (!v) return nullptr; @@ -674,7 +668,6 @@ template <> struct GCMethods { static JSFunction* initial() { return nullptr; } - static bool poisoned(JSFunction* v) { return JS::IsPoisonedPtr(v); } static bool needsPostBarrier(JSFunction* v) { return v != nullptr && gc::IsInsideNursery(reinterpret_cast(v)); } @@ -708,8 +701,6 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase this->stack = &cx->thingGCRooters[kind]; this->prev = *stack; *stack = reinterpret_cast*>(this); - - MOZ_ASSERT(!js::GCMethods::poisoned(ptr)); } public: @@ -789,7 +780,6 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase * interchangeably with a MutableHandleValue. */ void set(T value) { - MOZ_ASSERT(!js::GCMethods::poisoned(value)); ptr = value; } @@ -889,7 +879,6 @@ class FakeRooted : public RootedBase T ptr; void set(const T& value) { - MOZ_ASSERT(!GCMethods::poisoned(value)); ptr = value; } @@ -912,7 +901,6 @@ class FakeMutableHandle : public js::MutableHandleBase } void set(T v) { - MOZ_ASSERT(!js::GCMethods::poisoned(v)); *ptr = v; } @@ -1169,7 +1157,6 @@ class PersistentRooted : public js::PersistentRootedBase, private: void set(T value) { MOZ_ASSERT(initialized()); - MOZ_ASSERT(!js::GCMethods::poisoned(value)); ptr = value; } diff --git a/js/public/Utility.h b/js/public/Utility.h index b6a9e6b666..1001493d5c 100644 --- a/js/public/Utility.h +++ b/js/public/Utility.h @@ -415,40 +415,6 @@ ScrambleHashCode(HashNumber h) } /* namespace js */ -namespace JS { - -/* - * Methods for poisoning GC heap pointer words and checking for poisoned words. - * These are in this file for use in Value methods and so forth. - * - * If the moving GC hazard analysis is in use and detects a non-rooted stack - * pointer to a GC thing, one byte of that pointer is poisoned to refer to an - * invalid location. For both 32 bit and 64 bit systems, the fourth byte of the - * pointer is overwritten, to reduce the likelihood of accidentally changing - * a live integer value. - */ - -inline void PoisonPtr(void* v) -{ -#if defined(JSGC_ROOT_ANALYSIS) && defined(JS_DEBUG) - uint8_t* ptr = (uint8_t*) v + 3; - *ptr = JS_FREE_PATTERN; -#endif -} - -template -inline bool IsPoisonedPtr(T* v) -{ -#if defined(JSGC_ROOT_ANALYSIS) && defined(JS_DEBUG) - uint32_t mask = uintptr_t(v) & 0xff000000; - return mask == uint32_t(JS_FREE_PATTERN << 24); -#else - return false; -#endif -} - -} - /* sixgill annotation defines */ #ifndef HAVE_STATIC_ANNOTATIONS # define HAVE_STATIC_ANNOTATIONS diff --git a/js/public/Value.h b/js/public/Value.h index 5232d89a5e..1490b7c2eb 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -1043,17 +1043,14 @@ class Value } void setString(JSString* str) { - MOZ_ASSERT(!IsPoisonedPtr(str)); data = STRING_TO_JSVAL_IMPL(str); } void setSymbol(JS::Symbol* sym) { - MOZ_ASSERT(!IsPoisonedPtr(sym)); data = SYMBOL_TO_JSVAL_IMPL(sym); } void setObject(JSObject& obj) { - MOZ_ASSERT(!IsPoisonedPtr(&obj)); data = OBJECT_TO_JSVAL_IMPL(&obj); } @@ -1641,17 +1638,11 @@ namespace js { template <> struct GCMethods { static JS::Value initial() { return JS::UndefinedValue(); } - static bool poisoned(const JS::Value& v) { - return v.isMarkable() && JS::IsPoisonedPtr(v.toGCThing()); - } }; template <> struct GCMethods { static JS::Value initial() { return JS::UndefinedValue(); } - static bool poisoned(const JS::Value& v) { - return v.isMarkable() && JS::IsPoisonedPtr(v.toGCThing()); - } static gc::Cell* asGCThingOrNull(const JS::Value& v) { return v.isMarkable() ? v.toGCThing() : nullptr; } @@ -1890,12 +1881,6 @@ IMPL_TO_JSVAL(jsval_layout l) namespace JS { -inline bool -IsPoisonedValue(const Value& v) -{ - return js::GCMethods::poisoned(v); -} - #ifdef JS_DEBUG namespace detail { diff --git a/js/src/NamespaceImports.h b/js/src/NamespaceImports.h index a78d42d00e..84e0a0e494 100644 --- a/js/src/NamespaceImports.h +++ b/js/src/NamespaceImports.h @@ -56,7 +56,6 @@ using JS::BooleanValue; using JS::DoubleValue; using JS::Float32Value; using JS::Int32Value; -using JS::IsPoisonedValue; using JS::MagicValue; using JS::NullValue; using JS::NumberValue; @@ -67,8 +66,6 @@ using JS::PrivateValue; using JS::StringValue; using JS::UndefinedValue; -using JS::IsPoisonedPtr; - using JS::Latin1Char; using JS::Latin1Chars; using JS::Latin1CharsZ; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 1eff7f396e..22979dff35 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -56,7 +56,6 @@ typedef Handle HandleStaticBlockObject; typedef Rooted RootedNestedScopeObject; typedef Handle HandleNestedScopeObject; - /* Read a token. Report an error and return null() if that token isn't of type tt. */ #define MUST_MATCH_TOKEN(tt, errno) \ JS_BEGIN_MACRO \ @@ -568,7 +567,7 @@ template ObjectBox* Parser::newObjectBox(NativeObject* obj) { - MOZ_ASSERT(obj && !IsPoisonedPtr(obj)); + MOZ_ASSERT(obj); /* * We use JSContext.tempLifoAlloc to allocate parsed objects and place them @@ -646,7 +645,7 @@ FunctionBox* Parser::newFunctionBox(Node fn, JSFunction* fun, ParseContext* outerpc, Directives inheritedDirectives, GeneratorKind generatorKind) { - MOZ_ASSERT(fun && !IsPoisonedPtr(fun)); + MOZ_ASSERT(fun); /* * We use JSContext.tempLifoAlloc to allocate parsed objects and place them @@ -4378,40 +4377,16 @@ Parser::isValidForStatementLHS(ParseNode* pn1, JSVersion versi bool isForDecl, bool isForEach, ParseNodeKind headKind) { - if (isForDecl) { - if (pn1->pn_count > 1) - return false; - if (pn1->isKind(PNK_CONST)) - return false; - - // In JS 1.7 only, for (var [K, V] in EXPR) has a special meaning. - // Hence all other destructuring decls are banned there. - if (version == JSVERSION_1_7 && !isForEach && headKind == PNK_FORIN) { - ParseNode* lhs = pn1->pn_head; - if (lhs->isKind(PNK_ASSIGN)) - lhs = lhs->pn_left; - - if (lhs->isKind(PNK_OBJECT)) - return false; - if (lhs->isKind(PNK_ARRAY) && lhs->pn_count != 2) - return false; - } - return true; - } + if (isForDecl) + return pn1->pn_count < 2 && !pn1->isKind(PNK_CONST); switch (pn1->getKind()) { - case PNK_NAME: - case PNK_DOT: - case PNK_CALL: - case PNK_ELEM: - return true; - case PNK_ARRAY: + case PNK_CALL: + case PNK_DOT: + case PNK_ELEM: + case PNK_NAME: case PNK_OBJECT: - // In JS 1.7 only, for ([K, V] in EXPR) has a special meaning. - // Hence all other destructuring left-hand sides are banned there. - if (version == JSVERSION_1_7 && !isForEach && headKind == PNK_FORIN) - return pn1->isKind(PNK_ARRAY) && pn1->pn_count == 2; return true; default: @@ -4703,29 +4678,12 @@ Parser::forStatement() return null(); } - switch (pn2->getKind()) { - case PNK_NAME: + ParseNodeKind kind2 = pn2->getKind(); + MOZ_ASSERT(kind2 != PNK_ASSIGN, "forStatement TOK_ASSIGN"); + + if (kind2 == PNK_NAME) { /* Beware 'for (arguments in ...)' with or without a 'var'. */ pn2->markAsAssigned(); - break; - - case PNK_ASSIGN: - MOZ_CRASH("forStatement TOK_ASSIGN"); - - case PNK_ARRAY: - case PNK_OBJECT: - if (versionNumber() == JSVERSION_1_7) { - /* - * Destructuring for-in requires [key, value] enumeration - * in JS1.7. - */ - if (!isForEach && headKind == PNK_FORIN) { - iflags |= JSITER_FOREACH | JSITER_KEYVALUE; - } - } - break; - - default:; } } else { if (isForEach) { @@ -5840,7 +5798,6 @@ Parser::statement(bool canHaveDirectives) return null(); return classStatement(); - /* TOK_CATCH and TOK_FINALLY are both handled in the TOK_TRY case */ case TOK_CATCH: report(ParseError, false, null(), JSMSG_CATCH_WITHOUT_TRY); @@ -6877,22 +6834,6 @@ Parser::legacyComprehensionTail(ParseNode* bodyExpr, unsigned case TOK_LC: if (!checkDestructuring(&data, pn3)) return null(); - - if (versionNumber() == JSVERSION_1_7 && - !(pn2->pn_iflags & JSITER_FOREACH) && - !isForOf) - { - /* Destructuring requires [key, value] enumeration in JS1.7. */ - if (!pn3->isKind(PNK_ARRAY) || pn3->pn_count != 2) { - report(ParseError, false, null(), JSMSG_BAD_FOR_LEFTSIDE); - return null(); - } - - MOZ_ASSERT(pn2->isOp(JSOP_ITER)); - MOZ_ASSERT(pn2->pn_iflags & JSITER_ENUMERATE); - MOZ_ASSERT(headKind == PNK_FORIN); - pn2->pn_iflags |= JSITER_FOREACH | JSITER_KEYVALUE; - } break; case TOK_NAME: diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h index fa09c579f5..d2f917d7fb 100644 --- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -115,7 +115,6 @@ struct Token void setName(PropertyName* name) { MOZ_ASSERT(type == TOK_NAME); - MOZ_ASSERT(!IsPoisonedPtr(name)); u.name = name; } @@ -123,7 +122,6 @@ struct Token MOZ_ASSERT(type == TOK_STRING || type == TOK_TEMPLATE_HEAD || type == TOK_NO_SUBS_TEMPLATE); - MOZ_ASSERT(!IsPoisonedPtr(atom)); u.atom = atom; } diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index 56f5c0c610..0e593d32c2 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -443,7 +443,6 @@ class MOZ_NON_MEMMOVABLE BarrieredBase : public BarrieredBaseMixins public: void init(T v) { - MOZ_ASSERT(!GCMethods::poisoned(v)); this->value = v; } @@ -508,7 +507,6 @@ class PreBarriered : public BarrieredBase private: void set(const T& v) { this->pre(); - MOZ_ASSERT(!GCMethods::poisoned(v)); this->value = v; } }; @@ -541,7 +539,6 @@ class HeapPtr : public BarrieredBase #endif void init(T v) { - MOZ_ASSERT(!GCMethods::poisoned(v)); this->value = v; post(); } @@ -554,7 +551,6 @@ class HeapPtr : public BarrieredBase private: void set(const T& v) { this->pre(); - MOZ_ASSERT(!GCMethods::poisoned(v)); this->value = v; post(); } @@ -652,7 +648,6 @@ class RelocatablePtr : public BarrieredBase } void postBarrieredSet(const T& v) { - MOZ_ASSERT(!GCMethods::poisoned(v)); if (GCMethods::needsPostBarrier(v)) { this->value = v; post(); @@ -858,14 +853,12 @@ class HeapSlot : public BarrieredBase explicit HeapSlot(NativeObject* obj, Kind kind, uint32_t slot, const Value& v) : BarrieredBase(v) { - MOZ_ASSERT(!IsPoisonedValue(v)); post(obj, kind, slot, v); } explicit HeapSlot(NativeObject* obj, Kind kind, uint32_t slot, const HeapSlot& s) : BarrieredBase(s.value) { - MOZ_ASSERT(!IsPoisonedValue(s.value)); post(obj, kind, slot, s); } @@ -886,7 +879,6 @@ class HeapSlot : public BarrieredBase void set(NativeObject* owner, Kind kind, uint32_t slot, const Value& v) { MOZ_ASSERT(preconditionForSet(owner, kind, slot)); - MOZ_ASSERT(!IsPoisonedValue(v)); pre(); value = v; post(owner, kind, slot, v); @@ -894,7 +886,6 @@ class HeapSlot : public BarrieredBase void set(Zone* zone, NativeObject* owner, Kind kind, uint32_t slot, const Value& v) { MOZ_ASSERT(preconditionForSet(zone, owner, kind, slot)); - MOZ_ASSERT(!IsPoisonedValue(v)); pre(zone); value = v; post(owner, kind, slot, v); diff --git a/js/src/jit/shared/Assembler-shared.h b/js/src/jit/shared/Assembler-shared.h index bb02473ac2..b39338666b 100644 --- a/js/src/jit/shared/Assembler-shared.h +++ b/js/src/jit/shared/Assembler-shared.h @@ -226,8 +226,6 @@ class ImmMaybeNurseryPtr public: explicit ImmMaybeNurseryPtr(const gc::Cell* ptr) : value(ptr) { - MOZ_ASSERT(!IsPoisonedPtr(ptr)); - // asm.js shouldn't be creating GC things MOZ_ASSERT(!IsCompilingAsmJS()); } @@ -257,7 +255,6 @@ class ImmGCPtr explicit ImmGCPtr(const gc::Cell* ptr) : value(ptr) { - MOZ_ASSERT(!IsPoisonedPtr(ptr)); MOZ_ASSERT_IF(ptr, ptr->isTenured()); // asm.js shouldn't be creating GC things @@ -266,7 +263,6 @@ class ImmGCPtr explicit ImmGCPtr(IonNurseryPtr ptr) : value(ptr.ptr) { - MOZ_ASSERT(!IsPoisonedPtr(value)); MOZ_ASSERT(value); // asm.js shouldn't be creating GC things @@ -279,8 +275,6 @@ class ImmGCPtr friend class AssemblerShared; explicit ImmGCPtr(ImmMaybeNurseryPtr ptr) : value(ptr.value) { - MOZ_ASSERT(!IsPoisonedPtr(ptr.value)); - // asm.js shouldn't be creating GC things MOZ_ASSERT(!IsCompilingAsmJS()); } diff --git a/js/src/js.msg b/js/src/js.msg index 2a8ddd70ae..0fe97f2ded 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -231,6 +231,7 @@ MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 0, JSEXN_SYNTAXERR, "missing } in compoun 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_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") diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 6e2f529ecd..52e97c1378 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2670,12 +2670,6 @@ namespace js { template <> struct GCMethods { static JSPropertyDescriptor initial() { return JSPropertyDescriptor(); } - static bool poisoned(const JSPropertyDescriptor& desc) { - return (desc.obj && JS::IsPoisonedPtr(desc.obj)) || - (desc.attrs & JSPROP_GETTER && desc.getter && JS::IsPoisonedPtr(desc.getter)) || - (desc.attrs & JSPROP_SETTER && desc.setter && JS::IsPoisonedPtr(desc.setter)) || - (desc.value.isGCThing() && JS::IsPoisonedPtr(desc.value.toGCThing())); - } }; template <> diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 9d298a029f..3fb07ea38c 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -383,7 +383,6 @@ ExclusiveContext::typeLifoAlloc() inline void JSContext::setPendingException(js::Value v) { - MOZ_ASSERT(!IsPoisonedValue(v)); // overRecursed_ is set after the fact by ReportOverRecursed. this->overRecursed_ = false; this->throwing = true; diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 5ebe5f76b5..57450d96d2 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -46,6 +46,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options = isSelfHosting(false), marked(true), warnedAboutNoSuchMethod(false), + warnedAboutFlagsArgument(false), addonId(options.addonIdOrNull()), #ifdef DEBUG firedOnNewGlobalObject(false), @@ -241,9 +242,6 @@ bool JSCompartment::putWrapper(JSContext* cx, const CrossCompartmentKey& wrapped, const js::Value& wrapper) { MOZ_ASSERT(wrapped.wrapped); - MOZ_ASSERT(!IsPoisonedPtr(wrapped.wrapped)); - MOZ_ASSERT(!IsPoisonedPtr(wrapped.debugger)); - MOZ_ASSERT(!IsPoisonedPtr(wrapper.toGCThing())); MOZ_ASSERT_IF(wrapped.kind == CrossCompartmentKey::StringWrapper, wrapper.isString()); MOZ_ASSERT_IF(wrapped.kind != CrossCompartmentKey::StringWrapper, wrapper.isObject()); bool success = crossCompartmentWrappers.put(wrapped, ReadBarriered(wrapper)); diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 598c98114e..2915ba1b24 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -110,7 +110,6 @@ struct CrossCompartmentKey struct WrapperHasher : public DefaultHasher { static HashNumber hash(const CrossCompartmentKey& key) { - MOZ_ASSERT(!IsPoisonedPtr(key.wrapped)); static_assert(sizeof(HashNumber) == sizeof(uint32_t), "subsequent code assumes a four-byte hash"); return uint32_t(uintptr_t(key.wrapped)) | uint32_t(key.kind); @@ -150,6 +149,7 @@ struct JSCompartment bool isSelfHosting; bool marked; bool warnedAboutNoSuchMethod; + bool warnedAboutFlagsArgument; // A null add-on ID means that the compartment is not associated with an // add-on. @@ -542,12 +542,13 @@ struct JSCompartment enum DeprecatedLanguageExtension { DeprecatedForEach = 0, // JS 1.6+ - DeprecatedDestructuringForIn = 1, // JS 1.7 only + // NO LONGER USING 1 DeprecatedLegacyGenerator = 2, // JS 1.7+ DeprecatedExpressionClosure = 3, // Added in JS 1.8 DeprecatedLetBlock = 4, // Added in JS 1.7 // No longer using 5 (was: let expressions) DeprecatedNoSuchMethod = 6, // JS 1.7+ + DeprecatedFlagsArgument = 7, // JS 1.3 or older DeprecatedLanguageExtensionCount }; }; diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 96e88a774b..1c97c5072e 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -363,7 +363,9 @@ js::AssertSameCompartment(JSObject* objA, JSObject* objB) JS_FRIEND_API(void) js::NotifyAnimationActivity(JSObject* obj) { - obj->compartment()->lastAnimationTime = PRMJ_Now(); + int64_t timeNow = PRMJ_Now(); + obj->compartment()->lastAnimationTime = timeNow; + obj->runtimeFromMainThread()->lastAnimationTime = timeNow; } JS_FRIEND_API(uint32_t) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index f6076d5463..e2f8f134af 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1893,7 +1893,10 @@ ArenaLists::allocateFromArenaInner(JS::Zone* zone, ArenaHeader* aheader, AllocKi bool GCRuntime::shouldCompact() { - return invocationKind == GC_SHRINK && isCompactingGCEnabled(); + // Compact on shrinking GC if enabled, but skip compacting in incremental + // GCs if we are currently animating. + return invocationKind == GC_SHRINK && isCompactingGCEnabled() && + (!isIncremental || rt->lastAnimationTime + PRMJ_USEC_PER_SEC < PRMJ_Now()); } void diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 2f2ce3677e..630e6b820d 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -323,9 +323,6 @@ class Bindings template <> struct GCMethods { static Bindings initial(); - static bool poisoned(const Bindings& bindings) { - return IsPoisonedPtr(bindings.callObjShape()); - } }; class ScriptCounts diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 11d803458f..cb8c7f8d76 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2139,6 +2139,13 @@ class MOZ_STACK_CLASS StringRegExpGuard /* Build RegExp from pattern string. */ RootedString opt(cx); if (optarg < args.length()) { + if (!cx->compartment()->warnedAboutFlagsArgument) { + if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, GetErrorMessage, nullptr, + JSMSG_DEPRECATED_FLAGS_ARG)) + return false; + cx->compartment()->warnedAboutFlagsArgument = true; + } + opt = ToString(cx, args[optarg]); if (!opt) return false; diff --git a/js/src/tests/js1_5/String/replace-flags.js b/js/src/tests/js1_5/String/replace-flags.js new file mode 100644 index 0000000000..656d4acfa6 --- /dev/null +++ b/js/src/tests/js1_5/String/replace-flags.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!xulRuntime.shell) + +var BUGNUMBER = 1142351; +var summary = 'Add console warnings for non-standard flag argument of String.prototype.{search,match,replace}.'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +options("werror"); +assertEq(evaluate("'aaaA'.match('a', 'i')", {catchTermination: true}), "terminated"); +assertEq(evaluate("'aaaA'.search('a', 'i')", {catchTermination: true}), "terminated"); +assertEq(evaluate("'aaaA'.replace('a', 'b', 'g')", {catchTermination: true}), "terminated"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/js1_7/expressions/destructuring-scope.js b/js/src/tests/js1_7/expressions/destructuring-scope.js index d856e11259..374c1bec98 100644 --- a/js/src/tests/js1_7/expressions/destructuring-scope.js +++ b/js/src/tests/js1_7/expressions/destructuring-scope.js @@ -24,19 +24,23 @@ function f() { } function g() { + // Before JS1.7's destructuring for…in was fixed to match JS1.8's, + // the expected values were a == "x" and b == 7. for (var [a,b] in {x:7}) { - if (a != "x" || b != 7) + if (a !== "x" || typeof b !== "undefined") throw "fail"; } { + // Before JS1.7's destructuring for…in was fixed to match JS1.8's, + // the expected values were a == "y" and b == 8. for (let [a,b] in {y:8}) { - if (a != "y" || b != 8) + if (a !== "y" || typeof b !== "undefined") throw "fail"; } } - if (a != "x" || b != 7) + if (a !== "x" || typeof b !== "undefined") throw "fail"; } @@ -47,17 +51,17 @@ if (typeof a != "undefined" || typeof b != "undefined" || typeof x != "undefined throw "fail"; function h() { + // Before JS1.7's destructuring for…in was fixed to match JS1.8's, + // the expected values were a == "x" and b == 9. for ([a,b] in {z:9}) { - if (a != "z" || b != 9) + if (a !== "z" || typeof b !== "undefined") throw "fail"; } } h(); -if (a != "z" || b != 9) +if (a !== "z" || typeof b !== "undefined") throw "fail"; - reportCompare(expect, actual, summary); - diff --git a/js/src/tests/js1_7/geniter/regress-345736.js b/js/src/tests/js1_7/geniter/regress-345736.js index bb7d3c9496..1748c094c6 100644 --- a/js/src/tests/js1_7/geniter/regress-345736.js +++ b/js/src/tests/js1_7/geniter/regress-345736.js @@ -34,13 +34,19 @@ function test() actual = arr.toString(); reportCompare(expect, actual, summary); + // Before JS1.7's destructuring for…in was fixed to match JS1.8's, + // the expected result was 'aa,bb,cc'. arr=[x+x for ([,x] in ["a","b","c"])]; - expect = 'aa,bb,cc'; + expect = 'NaN,NaN,NaN'; actual = arr.toString(); + reportCompare(expect, actual, summary); + // Before JS1.7's destructuring for…in was fixed to match JS1.8's, + // the expected result was '0a,1b,2c'. arr=[x+y for ([x,y] in ["a","b","c"])]; - expect = '0a,1b,2c'; + expect = '0undefined,1undefined,2undefined'; actual = arr.toString(); + reportCompare(expect, actual, summary); exitFunc ('test'); } diff --git a/js/src/tests/js1_7/geniter/regress-347593.js b/js/src/tests/js1_7/geniter/regress-347593.js index f3117665be..353d9412ca 100644 --- a/js/src/tests/js1_7/geniter/regress-347593.js +++ b/js/src/tests/js1_7/geniter/regress-347593.js @@ -19,15 +19,21 @@ function test() enterFunc ('test'); printBugNumber(BUGNUMBER); printStatus (summary); - - expect = '23'; - actual = ''; - for (let [, { a: b }] in [{ a: 2 }, { a: 3 }]) - { - actual += b; - } - reportCompare(expect, actual, summary); + // Before JS1.7's destructuring for…in was fixed to match JS1.8's, + // the expected result was '23'. + expect = 'TypeError'; + actual = ''; + try { + for (let [, { a: b }] in [{ a: 2 }, { a: 3 }]) { + actual += b; + } + reportCompare(expect, actual, summary); + } catch (ex) { + actual = ex.name; + } + + expect = '23'; actual = ''; for each (let { a: b } in [{ a: 2 }, { a: 3 }]) { diff --git a/js/src/tests/js1_7/geniter/regress-366941.js b/js/src/tests/js1_7/geniter/regress-366941.js index d1d1f0f17b..74ee3a9372 100644 --- a/js/src/tests/js1_7/geniter/regress-366941.js +++ b/js/src/tests/js1_7/geniter/regress-366941.js @@ -60,24 +60,24 @@ function test() reportCompare(expect, actual, summary + ': 3'); - // syntax error in js17 + // Before JS1.7's destructuring for…in was fixed to match JS1.8's, + // the expected result was a SyntaxError about the for…in loop's lhs. var iter2 = gen(list2); - expect = /SyntaxError: (invalid for.in left-hand side|Left hand side of for..in loop must be an array of length 2 to accept key.value pair.)/; + expect = '1,2,3;4,5,6;7,8,9;'; actual = ''; try { eval('for (var [foo, bar, baz] in iter2) {' + - 'actual += foo + "," + bar + "," + baz + ";";' + + 'actual += foo + "," + bar + "," + baz + ";";' + '}'); - actual = 'No Error'; } catch(ex) { actual = ex + ''; } - - reportMatch(expect, actual, summary + ': 4'); + + reportCompare(expect, actual, summary + ': 4'); exitFunc ('test'); } diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 5a8661eed5..4eff3365c6 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -6122,8 +6122,6 @@ EvaluateInEnv(JSContext* cx, Handle env, HandleValue thisv, AbstractFrameP MOZ_ASSERT_IF(frame, thisv.get() == frame.thisValue()); MOZ_ASSERT_IF(frame, pc); - MOZ_ASSERT(!IsPoisonedPtr(chars.start().get())); - /* * NB: This function breaks the assumption that the compiler can see all * calls and properly compute a static level. In practice, any non-zero diff --git a/js/src/vm/ObjectGroup.h b/js/src/vm/ObjectGroup.h index 21fc1ab970..44f32ac77c 100644 --- a/js/src/vm/ObjectGroup.h +++ b/js/src/vm/ObjectGroup.h @@ -71,13 +71,11 @@ struct RootKind template <> struct GCMethods { static TaggedProto initial() { return TaggedProto(); } - static bool poisoned(const TaggedProto& v) { return IsPoisonedPtr(v.raw()); } }; template <> struct GCMethods { static TaggedProto initial() { return TaggedProto(); } - static bool poisoned(const TaggedProto& v) { return IsPoisonedPtr(v.raw()); } }; template diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index ce67d5a469..6046ab2331 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -214,7 +214,8 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime) #endif largeAllocationFailureCallback(nullptr), oomCallback(nullptr), - debuggerMallocSizeOf(ReturnZeroSize) + debuggerMallocSizeOf(ReturnZeroSize), + lastAnimationTime(0) { setGCStoreBufferPtr(&gc.storeBuffer); diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index b88b2b0389..357b813d0f 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1435,6 +1435,9 @@ struct JSRuntime : public JS::shadow::Runtime, * function to assess the size of malloc'd blocks of memory. */ mozilla::MallocSizeOf debuggerMallocSizeOf; + + /* Last time at which an animation was played for this runtime. */ + int64_t lastAnimationTime; }; namespace js { diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index 7092644097..1c550d2d88 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -162,10 +162,7 @@ AutoRooterGetterSetter::Inner::Inner(ExclusiveContext *cx, uint8_t attrs, GetterOp *pgetter_, SetterOp *psetter_) : CustomAutoRooter(cx), attrs(attrs), pgetter(pgetter_), psetter(psetter_) -{ - MOZ_ASSERT_IF(attrs & JSPROP_GETTER, !IsPoisonedPtr(*pgetter)); - MOZ_ASSERT_IF(attrs & JSPROP_SETTER, !IsPoisonedPtr(*psetter)); -} +{} inline AutoRooterGetterSetter::AutoRooterGetterSetter(ExclusiveContext *cx, uint8_t attrs, diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 4b9f03ad91..827f5d8b45 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -1289,9 +1289,6 @@ struct StackShape {} void updateGetterSetter(GetterOp rawGetter, SetterOp rawSetter) { - MOZ_ASSERT_IF((attrs & JSPROP_GETTER) && rawGetter, !IsPoisonedPtr(rawGetter)); - MOZ_ASSERT_IF((attrs & JSPROP_SETTER) && rawSetter, !IsPoisonedPtr(rawSetter)); - if (rawGetter || rawSetter || (attrs & (JSPROP_GETTER|JSPROP_SETTER))) flags |= Shape::ACCESSOR_SHAPE; else diff --git a/js/src/vm/String-inl.h b/js/src/vm/String-inl.h index 132e9bda86..2b10974b32 100644 --- a/js/src/vm/String-inl.h +++ b/js/src/vm/String-inl.h @@ -136,7 +136,6 @@ MOZ_ALWAYS_INLINE void JSDependentString::init(js::ExclusiveContext *cx, JSLinearString *base, size_t start, size_t length) { - MOZ_ASSERT(!js::IsPoisonedPtr(base)); MOZ_ASSERT(start + length <= base->length()); d.u1.length = length; JS::AutoCheckCannotGC nogc; diff --git a/js/src/vm/TypeInference-inl.h b/js/src/vm/TypeInference-inl.h index cf98f1262a..b725d7ea89 100644 --- a/js/src/vm/TypeInference-inl.h +++ b/js/src/vm/TypeInference-inl.h @@ -1098,20 +1098,12 @@ template <> struct GCMethods { static TypeSet::Type initial() { return TypeSet::UnknownType(); } - static bool poisoned(TypeSet::Type v) { - return (v.isGroup() && IsPoisonedPtr(v.group())) - || (v.isSingleton() && IsPoisonedPtr(v.singleton())); - } }; template <> struct GCMethods { static TypeSet::Type initial() { return TypeSet::UnknownType(); } - static bool poisoned(TypeSet::Type v) { - return (v.isGroup() && IsPoisonedPtr(v.group())) - || (v.isSingleton() && IsPoisonedPtr(v.singleton())); - } }; } // namespace js diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index 69268513e0..74d112cdbf 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -29,11 +29,11 @@ namespace js { * * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode */ -static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 255; +static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 256; static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND); -static_assert(JSErr_Limit == 383, +static_assert(JSErr_Limit == 384, "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or " "removed MSG_DEFs from js.msg, you should increment " "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's " diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 6183138031..f6300ff530 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1386,6 +1386,7 @@ pref("javascript.options.mem.gc_compacting", true); pref("javascript.options.mem.log", false); pref("javascript.options.mem.notify", false); pref("javascript.options.gc_on_memory_pressure", true); +pref("javascript.options.compact_on_user_inactive", true); pref("javascript.options.mem.gc_high_frequency_time_limit_ms", 1000); pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 100); diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 10d486a5c0..65e610af81 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -340,7 +340,7 @@ "expires_in_version": "never", "kind": "enumerated", "n_values": 10, - "description": "Use of SpiderMonkey's deprecated language extensions in web content: ForEach=0, DestructuringForIn=1, LegacyGenerator=2, ExpressionClosure=3, LetBlock=4, LetExpression=5, NoSuchMethod=6" + "description": "Use of SpiderMonkey's deprecated language extensions in web content: ForEach=0, DestructuringForIn=1, LegacyGenerator=2, ExpressionClosure=3, LetBlock=4, LetExpression=5, NoSuchMethod=6, FlagsArgument=7" }, "TELEMETRY_PING": { "expires_in_version": "never",