Fix compile errors pt 2 (before the HELL)

This commit is contained in:
wuggy 2026-08-04 22:05:22 -07:00
commit 622cee0b14
12 changed files with 191 additions and 25 deletions

View file

@ -108,6 +108,8 @@ const size_t gStackSize = 8192;
// Maximum amount of time that should elapse between incremental GC slices
#define NS_INTERSLICE_GC_DELAY 100 // ms
#define NS_INTERSLICE_GC_BUDGET 5 // ms
// Maximum amount of time that should elapse between incremental GC slices
#define NS_INTERSLICE_GC_DELAY 100 // ms
@ -189,6 +191,8 @@ static bool sNeedsFullGC = false;
static bool sNeedsGCAfterCC = false;
static bool sIncrementalCC = false;
static int32_t sActiveIntersliceGCBudget = 5; // ms;
static bool sDidPaintAfterPreviousICCSlice = false;
static uint32_t sCCTimerFireCount = 0;
static nsScriptNameSpaceManager *gNameSpaceManager;
static PRTime sFirstCollectionTime;
@ -1531,7 +1535,7 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
//static
void
nsJSContext::RunCycleCollectorSlice()
nsJSContext::RunCycleCollectorSlice(const TimeStamp& aDeadline)
{
if (!NS_IsMainThread()) {
return;
@ -1637,7 +1641,7 @@ ICCTimerFired(nsITimer* aTimer, void* aClosure)
}
}
nsJSContext::RunCycleCollectorSlice();
nsJSContext::RunCycleCollectorSlice(TimeStamp());
}
//static
@ -1816,6 +1820,7 @@ InterSliceGCTimerFired(nsITimer *aTimer, void *aClosure)
// We use longer budgets when the CC has been locked out but the CC has tried
// to run since that means we may have significant amount garbage to collect
// and better to GC in several longer slices than in a very long one.
TimeStamp aDeadline; // no idle deadline available in timer callback
int64_t budget = aDeadline.IsNull() ?
int64_t(sActiveIntersliceGCBudget * 2) :
int64_t((aDeadline - TimeStamp::Now()).ToMilliseconds());
@ -1829,8 +1834,8 @@ InterSliceGCTimerFired(nsITimer *aTimer, void *aClosure)
std::max((double)budget, percentOfLockedTime * maxSliceGCBudget));
}
uintptr_t reason = reinterpret_cast<uintptr_t>(aData);
nsJSContext::GarbageCollectNow(aData ?
uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
nsJSContext::GarbageCollectNow(aClosure ?
static_cast<JS::gcreason::Reason>(reason) :
JS::gcreason::INTER_SLICE_GC,
nsJSContext::IncrementalGC,
@ -1906,9 +1911,10 @@ CCTimerFired(nsITimer *aTimer, void *aClosure)
int32_t numEarlyTimerFires = std::max((int32_t)ccDelay / NS_CC_SKIPPABLE_DELAY - 2, 1);
bool isLateTimerFire = sCCRunnerFireCount > numEarlyTimerFires;
uint32_t suspected = nsCycleCollector_suspectedCount();
TimeStamp deadline; // no idle deadline in timer callback
if (isLateTimerFire && ShouldTriggerCC(suspected)) {
if (sCCRunnerFireCount == numEarlyTimerFires + 1) {
FireForgetSkippable(suspected, true, aDeadline);
FireForgetSkippable(suspected, true, deadline);
didDoWork = true;
if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
// Our efforts to avoid a CC have failed, so we return to let the
@ -1919,14 +1925,14 @@ CCTimerFired(nsITimer *aTimer, void *aClosure)
// We are in the final timer fire and still meet the conditions for
// triggering a CC. Let RunCycleCollectorSlice finish the current IGC, if
// any because that will allow us to include the GC time in the CC pause.
nsJSContext::RunCycleCollectorSlice(aDeadline);
nsJSContext::RunCycleCollectorSlice(deadline);
didDoWork = true;
}
} else if (((sPreviousSuspectedCount + 100) <= suspected) ||
(sCleanupsSinceLastGC < NS_MAJOR_FORGET_SKIPPABLE_CALLS)) {
// Only do a forget skippable if there are more than a few new objects
// or we're doing the initial forget skippables.
FireForgetSkippable(suspected, false, aDeadline);
FireForgetSkippable(suspected, false, deadline);
didDoWork = true;
}
@ -2034,7 +2040,7 @@ nsJSContext::RunNextCollectorTimer()
// static
void
nsJSContext::PokeGC(JS::gcreason::Reason aReason, int aDelay)
nsJSContext::PokeGC(JS::gcreason::Reason aReason, int aDelay, JSObject* aObj)
{
sNeedsFullGC = sNeedsFullGC || aReason != JS::gcreason::CC_WAITING;
@ -2147,6 +2153,16 @@ nsJSContext::KillGCTimer()
}
}
//static
void
nsJSContext::KillCCTimer()
{
if (sCCTimer) {
sCCTimer->Cancel();
NS_RELEASE(sCCTimer);
}
}
void
nsJSContext::KillFullGCTimer()
{

View file

@ -91,7 +91,7 @@ public:
int32_t aExtraForgetSkippableCalls = 0);
// Run a cycle collector slice, using a heuristic to decide how long to run it.
static void RunCycleCollectorSlice();
static void RunCycleCollectorSlice(const mozilla::TimeStamp& aDeadline = mozilla::TimeStamp());
// Run a cycle collector slice, using the given work budget.
static void RunCycleCollectorWorkSlice(int64_t aWorkBudget);
@ -105,9 +105,11 @@ public:
static void RunNextCollectorTimer();
static void PokeGC(JS::gcreason::Reason aReason, int aDelay = 0);
static void PokeGC(JS::gcreason::Reason aReason, int aDelay = 0, JSObject* aObj = nullptr);
static void KillGCTimer();
static void KillCCTimer();
static void PokeShrinkingGC();
static void KillShrinkingGCTimer();
@ -117,6 +119,8 @@ public:
static void KillFullGCTimer();
static void KillInterSliceGCRunner();
static void NotifyDidPaint();
// Calling LikelyShortLivingObjectCreated() makes a GC more likely.
static void LikelyShortLivingObjectCreated();

View file

@ -323,7 +323,7 @@ typedef void
* can be called off the main thread.
*/
struct JSStringFinalizer {
void (*finalize)(const JSStringFinalizer* fin, char16_t* chars);
void (*finalize)(JS::Zone* zone, const JSStringFinalizer* fin, char16_t* chars);
};
@ -346,6 +346,7 @@ struct Zone;
D(OUT_OF_NURSERY) \
D(EVICT_NURSERY) \
D(FULL_STORE_BUFFER) \
D(FULL_SLOT_BUFFER) \
D(SHARED_MEMORY_LIMIT) \
D(UNUSED1) \
D(INCREMENTAL_TOO_SLOW) \
@ -986,6 +987,9 @@ JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp);
extern JS_PUBLIC_API(void)
JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value);
extern JS_PUBLIC_API(void)
JS_SetGGCMode(JSContext* cx, bool enabled);
extern JS_PUBLIC_API(void)
JS_ResetGCParameter(JSContext* cx, JSGCParamKey key);

113
js/src/ds/Bitmap.h Normal file
View file

@ -0,0 +1,113 @@
/* -*- 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 ds_Bitmap_h
#define ds_Bitmap_h
#include "mozilla/PodOperations.h"
#include <stdint.h>
#include <string.h>
namespace js {
// DenseBitmap is an simple dynamically-sized bitmap backed by a vector of
// words.
class DenseBitmap
{
using Word = uintptr_t;
Word* data_;
size_t numWords_;
public:
DenseBitmap()
: data_(nullptr), numWords_(0)
{}
~DenseBitmap()
{
js_free(data_);
}
bool ensureSpace(size_t newWords)
{
if (newWords <= numWords_)
return true;
size_t newSize = sizeof(Word) * newWords;
Word* newData = static_cast<Word*>(js_realloc(data_, newSize));
if (!newData)
return false;
mozilla::PodZero(newData + numWords_, newWords - numWords_);
data_ = newData;
numWords_ = newWords;
return true;
}
void copyBitsFrom(size_t dstStart, size_t wordCount, const Word* src)
{
MOZ_ASSERT(dstStart + wordCount <= numWords_);
memcpy(data_ + dstStart, src, sizeof(Word) * wordCount);
}
void bitwiseAndWith(const DenseBitmap& other)
{
MOZ_ASSERT(numWords_ == other.numWords_);
for (size_t i = 0; i < numWords_; i++)
data_[i] &= other.data_[i];
}
void bitwiseOrRangeInto(size_t srcStart, size_t wordCount, Word* dst) const
{
MOZ_ASSERT(srcStart + wordCount <= numWords_);
for (size_t i = 0; i < wordCount; i++)
dst[i] |= data_[srcStart + i];
}
void bitwiseOrInto(DenseBitmap& other) const
{
MOZ_ASSERT(numWords_ == other.numWords_);
for (size_t i = 0; i < numWords_; i++)
other.data_[i] |= data_[i];
}
void bitwiseOrWith(const DenseBitmap& other)
{
MOZ_ASSERT(numWords_ == other.numWords_);
for (size_t i = 0; i < numWords_; i++)
data_[i] |= other.data_[i];
}
bool getBit(size_t bit) const
{
size_t wordIndex = bit / (sizeof(Word) * 8);
size_t bitIndex = bit % (sizeof(Word) * 8);
MOZ_ASSERT(wordIndex < numWords_);
return data_[wordIndex] & (Word(1) << bitIndex);
}
void setBit(size_t bit)
{
size_t wordIndex = bit / (sizeof(Word) * 8);
size_t bitIndex = bit % (sizeof(Word) * 8);
MOZ_ASSERT(wordIndex < numWords_);
data_[wordIndex] |= (Word(1) << bitIndex);
}
MOZ_MUST_USE bool init()
{
return true;
}
Word* data() { return data_; }
size_t numWords() const { return numWords_; }
};
} // namespace js
#endif // ds_Bitmap_h

View file

@ -613,7 +613,7 @@ struct ChunkBitmap
uintptr_t** wordp, uintptr_t* maskp)
{
MOZ_ASSERT(size_t(colorBit) < MarkBitsPerCell);
detail::GetGCThingMarkWordAndMask(uintptr_t(cell), colorBit, wordp, maskp);
detail::GetGCThingMarkWordAndMask(uintptr_t(cell), uint32_t(colorBit), wordp, maskp);
}
MOZ_ALWAYS_INLINE MOZ_TSAN_BLACKLIST bool markBit(const TenuredCell* cell, ColorBit colorBit) {
@ -637,7 +637,7 @@ struct ChunkBitmap
// The return value indicates if the cell went from unmarked to marked.
MOZ_ALWAYS_INLINE bool markIfUnmarked(const TenuredCell* cell, MarkColor color) {
uintptr_t* word, mask;
getMarkWordAndMask(cell, BLACK, &word, &mask);
getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask);
if (*word & mask)
return false;
if (color == MarkColor::Black) {
@ -647,7 +647,7 @@ struct ChunkBitmap
* We use getMarkWordAndMask to recalculate both mask and word as
* doing just mask << color may overflow the mask.
*/
getMarkWordAndMask(cell, color, &word, &mask);
getMarkWordAndMask(cell, ColorBit(uint32_t(color)), &word, &mask);
if (*word & mask)
return false;
*word |= mask;
@ -657,8 +657,8 @@ struct ChunkBitmap
MOZ_ALWAYS_INLINE void markBlack(const TenuredCell* cell) {
uintptr_t* word, mask;
getMarkWordAndMask(cell, color, &word, &mask);
*word &= ~mask;
getMarkWordAndMask(cell, ColorBit::BlackBit, &word, &mask);
*word |= mask;
}
MOZ_ALWAYS_INLINE void copyMarkBit(TenuredCell* dst, const TenuredCell* src,

View file

@ -9,6 +9,7 @@
#define gc_Nursery_h
#include "mozilla/EnumeratedArray.h"
#include "mozilla/TimeStamp.h"
#include "js/Class.h"
#include "js/HeapAPI.h"
@ -381,6 +382,8 @@ class Nursery
*/
unsigned chunkCountLimit_;
mozilla::Atomic<JS::gcreason::Reason, mozilla::Relaxed> minorGCTriggerReason_;
mozilla::TimeDuration timeInChunkAlloc_;
/* Promotion rate for the previous minor collection. */
@ -471,7 +474,7 @@ class Nursery
* sweep. This is because this structure is used to help implement
* stable object hashing and we have to break the cycle somehow.
*/
using CellsWithUniqueIdSet = HashSet<gc::Cell*, PointerHasher<gc::Cell*, 3>, SystemAllocPolicy>;
using CellsWithUniqueIdSet = HashSet<gc::Cell*, PointerHasher<gc::Cell*>, SystemAllocPolicy>;
CellsWithUniqueIdSet cellsWithUid_;
struct SweepAction;
@ -502,7 +505,6 @@ class Nursery
MOZ_ALWAYS_INLINE uintptr_t currentEnd() const;
uintptr_t position() const { return position_; }
void* addressOfPosition() const { return (void*)&position_; }
JSRuntime* runtime() const { return runtime_; }

View file

@ -625,6 +625,13 @@ struct Zone : public JS::shadow::Zone,
js::ZoneGroupData<bool> gcPreserveCode_;
js::ZoneGroupData<bool> keepShapeTables_;
js::ZoneGroupData<js::DenseBitmap> markedAtoms_;
public:
js::DenseBitmap& markedAtoms() { return markedAtoms_.ref(); }
private:
// Allow zones to be linked into a list
friend class js::gc::ZoneList;
static Zone * const NotOnList;

View file

@ -837,10 +837,10 @@ JS_IsBuiltinFunctionConstructor(JSFunction* fun);
* See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
*/
extern JS_PUBLIC_API(JSContext*)
JS_NewContext(uint32_t maxbytes,
uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
JSRuntime* parentRuntime = nullptr);
extern JS_PUBLIC_API(JSContext*)
JS_NewContext(uint32_t maxbytes,
uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
JSContext* parentContext = nullptr);
// The methods below for controlling the active context in a cooperatively
// multithreaded runtime are not threadsafe, and the caller must ensure they

View file

@ -1030,7 +1030,7 @@ class NativeObject : public ShapedObject
for (size_t i = 0; i < count; i++) {
const Value& v = elements_[start + i];
if (v.isObject() && IsInsideNursery(&v.toObject())) {
JS::shadow::Runtime* shadowRuntime = shadowRuntimeFromMainThread();
JS::shadow::Runtime* shadowRuntime = JS::shadow::Runtime::asShadowRuntime(runtimeFromMainThread());
shadowRuntime->gcStoreBufferPtr()->putSlot(this, HeapSlot::Element,
start + i, count - i);
return;

View file

@ -160,7 +160,7 @@ class TraceLoggerThread
private:
typedef HashMap<const void*,
TraceLoggerEventPayload*,
PointerHasher<const void*, 3>,
PointerHasher<const void*>,
SystemAllocPolicy> PointerHashMap;
typedef HashMap<uint32_t,
TraceLoggerEventPayload*,

View file

@ -1492,7 +1492,7 @@ ReloadPrefsCallback(const char* pref, void* data)
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_WARMUP_TRIGGER,
baselineWarmUpThreshold);
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ION_WARMUP_TRIGGER,
useIonEager ? 0 : ionThreshold);
useIonEager ? 0 : ionWarmUpThreshold);
#ifdef DEBUG
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_FULL_DEBUG_CHECKS, fullJitDebugChecks);
#endif

View file

@ -916,6 +916,20 @@ template<typename S>
struct IsParameterStorageClass<StorensRefPtrPassByPtr<S>>
: public mozilla::TrueType {};
template<typename T>
struct StorensAutoPtrPassByRRef
{
typedef nsAutoPtr<T> stored_type;
typedef nsAutoPtr<T> passed_type;
stored_type m;
template <typename A>
MOZ_IMPLICIT StorensAutoPtrPassByRRef(A&& a) : m(mozilla::Forward<A>(a)) {}
passed_type PassAsParameter() { return mozilla::Move(m); }
};
template<typename S>
struct IsParameterStorageClass<StorensAutoPtrPassByRRef<S>>
: public mozilla::TrueType {};
template<typename T>
struct StorePtrPassByPtr
{
@ -1022,6 +1036,12 @@ struct SmartPointerStorageClass
StoreCopyPassByConstLRef<T>>
{};
template<typename T>
struct SmartPointerStorageClass<nsAutoPtr<T>>
{
typedef StorensAutoPtrPassByRRef<T> Type;
};
template<typename T>
struct NonLValueReferenceStorageClass
: mozilla::Conditional<mozilla::IsRvalueReference<T>::value,