icecat: add release icecat-140.9.0-1gnu1 for ecne

This commit is contained in:
Ark74 2026-03-28 14:10:24 -06:00
parent 8eb1f1732f
commit a5f93cb214
1197 changed files with 30593 additions and 15344 deletions

View file

@ -426,7 +426,7 @@ constexpr uint64_t CanonicalizedNaNSignificand = 0x8000000000000;
#endif
#if defined(JS_RUNTIME_CANONICAL_NAN)
extern uint64_t CanonicalizedNaNBits;
extern JS_PUBLIC_API uint64_t CanonicalizedNaNBits;
#else
constexpr uint64_t CanonicalizedNaNBits =
mozilla::SpecificNaNBits<double, detail::CanonicalizedNaNSignBit,

View file

@ -99,6 +99,7 @@ void DebugScriptObject::finalize(JS::GCContext* gcx, JSObject* obj) {
/* static */
DebugScript* DebugScript::get(JSScript* script) {
MOZ_ASSERT(!IsAboutToBeFinalizedUnbarriered(script));
MOZ_ASSERT(script->hasDebugScript());
DebugScriptMap* map = script->zone()->debugScriptMap;
MOZ_ASSERT(map);
@ -205,7 +206,12 @@ JSBreakpointSite* DebugScript::getOrCreateBreakpointSite(JSContext* cx,
/* static */
void DebugScript::destroyBreakpointSite(JS::GCContext* gcx, JSScript* script,
jsbytecode* pc) {
if (IsAboutToBeFinalizedUnbarriered(script)) {
return;
}
DebugScript* debug = get(script);
JSBreakpointSite*& site = debug->breakpoints[script->pcToOffset(pc)];
MOZ_ASSERT(site);
MOZ_ASSERT(site->isEmpty());
@ -283,6 +289,10 @@ bool DebugScript::incrementStepperCount(JSContext* cx, HandleScript script) {
/* static */
void DebugScript::decrementStepperCount(JS::GCContext* gcx, JSScript* script) {
if (IsAboutToBeFinalizedUnbarriered(script)) {
return;
}
DebugScript* debug = get(script);
MOZ_ASSERT(debug);
MOZ_ASSERT(debug->stepperCount > 0);
@ -328,6 +338,10 @@ bool DebugScript::incrementGeneratorObserverCount(JSContext* cx,
/* static */
void DebugScript::decrementGeneratorObserverCount(JS::GCContext* gcx,
JSScript* script) {
if (IsAboutToBeFinalizedUnbarriered(script)) {
return;
}
DebugScript* debug = get(script);
MOZ_ASSERT(debug);
MOZ_ASSERT(debug->generatorObserverCount > 0);
@ -393,6 +407,10 @@ void DebugAPI::checkDebugScriptAfterMovingGC(DebugScript* ds) {
/* static */
bool DebugAPI::stepModeEnabledSlow(JSScript* script) {
if (IsAboutToBeFinalizedUnbarriered(script)) {
return false;
}
return DebugScript::get(script)->stepperCount > 0;
}

View file

@ -2025,26 +2025,27 @@ Completion Completion::fromJSFramePop(JSContext* cx, AbstractFramePtr frame,
//
// GetGeneratorObjectForFrame can return nullptr even when a generator
// object does exist, if the frame is paused between the Generator and
// SetAliasedVar opcodes. But by checking the opcode first we eliminate that
// possibility, so it's fine to call genObj->isClosed().
// SetAliasedVar opcodes.
Rooted<AbstractGeneratorObject*> generatorObj(
cx, GetGeneratorObjectForFrame(cx, frame));
switch (JSOp(*pc)) {
case JSOp::InitialYield:
MOZ_ASSERT(!generatorObj->isClosed());
return Completion(InitialYield(generatorObj));
case JSOp::Yield:
MOZ_ASSERT(!generatorObj->isClosed());
return Completion(Yield(generatorObj, frame.returnValue()));
if (generatorObj && !generatorObj->isClosed()) {
switch (JSOp(*pc)) {
case JSOp::InitialYield:
return Completion(InitialYield(generatorObj));
case JSOp::Await:
MOZ_ASSERT(!generatorObj->isClosed());
return Completion(Await(generatorObj, frame.returnValue()));
case JSOp::Yield:
return Completion(Yield(generatorObj, frame.returnValue()));
default:
return Completion(Return(frame.returnValue()));
case JSOp::Await:
return Completion(Await(generatorObj, frame.returnValue()));
default:
break;
}
}
return Completion(Return(frame.returnValue()));
}
void Completion::trace(JSTracer* trc) {

View file

@ -894,7 +894,10 @@ bool MarkPagesUnusedSoft(void* region, size_t length) {
int status;
do {
# if defined(XP_DARWIN)
status = madvise(region, length, MADV_FREE_REUSABLE);
// Note: we use MADV_FREE instead of MADV_FREE_REUSABLE + MADV_FREE_REUSE to
// work around a kernel bug on macOS Tahoe. We should change this back once
// that bug is fixed. See bug 2015359.
status = madvise(region, length, MADV_FREE);
# elif defined(XP_SOLARIS)
status = posix_madvise(region, length, POSIX_MADV_DONTNEED);
# else
@ -925,11 +928,6 @@ void MarkPagesInUseSoft(void* region, size_t length) {
MOZ_ASSERT(DecommitEnabled());
CheckDecommit(region, length);
#if defined(XP_DARWIN)
while (madvise(region, length, MADV_FREE_REUSE) == -1 && errno == EAGAIN) {
}
#endif
MOZ_MAKE_MEM_UNDEFINED(region, length);
}

View file

@ -1215,10 +1215,14 @@ void GCRuntime::checkHeapBeforeMinorGC(AutoHeapSession& session) {
// to tenured strings but contain nursery data.
for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
if (zone->isGCFinished()) {
continue; // Don't access zones that are being swept off thread.
}
for (ArenaIter aiter(zone, gc::AllocKind::STRING); !aiter.done();
aiter.next()) {
for (ArenaCellIterUnderGC cell(aiter.get()); !cell.done(); cell.next()) {
if (cell->is<JSString>() && cell->as<JSString>()->isDependent()) {
if (cell->as<JSString>()->isDependent()) {
JSDependentString* str = &cell->as<JSString>()->asDependent();
if (str->isTenured() && str->base()->isTenured()) {
MOZ_RELEASE_ASSERT(!str->hasCharsInCollectedNurseryRegion());

View file

@ -0,0 +1,17 @@
gczeal(23);
String + "";
var g = newGlobal({ newCompartment: true });
var dbg = Debugger(g);
dbg.onNewScript = function (script) {
script.setBreakpoint(0, () => {});
};
g.eval("");
// Trigger GC, which will mark the eval script about to be finalized,
// and the DebugScriptMap entry will be removed.
Uint8Array;
// This shouldn't try to use the DebugScriptMap entry.
dbg.clearAllBreakpoints();

View file

@ -0,0 +1,31 @@
// Don't crash on {return:} from onStep in a generator at a Yield.
// This test force-returns from each bytecode instruction in a generator.
let g = newGlobal({ newCompartment: true });
g.eval(`
function* gen() {
yield 1;
}
`)
let dbg = new Debugger(g);
let targetSteps = 0;
let found = true;
dbg.onEnterFrame = (frame) => {
let steps = 0;
frame.onStep = () => {
if (steps++ == targetSteps) {
found = true;
return { return: 0xdead };
}
}
}
dbg.uncaughtExceptionHook = () => undefined
while (found) {
found = false;
targetSteps++;
for (var y of g.gen()) {}
}

View file

@ -568,8 +568,9 @@ static bool BlockIsSingleTest(MBasicBlock* phiBlock, MBasicBlock* testBlock,
*ptest = nullptr;
if (phiBlock != testBlock) {
MOZ_ASSERT(phiBlock->numSuccessors() == 1 &&
phiBlock->getSuccessor(0) == testBlock);
MOZ_RELEASE_ASSERT(phiBlock->lastIns()->isGoto());
MOZ_RELEASE_ASSERT(phiBlock->lastIns()->toGoto()->target() == testBlock);
MOZ_RELEASE_ASSERT(testBlock->numPredecessors() == 1);
if (!phiBlock->begin()->isGoto()) {
return false;
}
@ -686,7 +687,7 @@ static bool IsTestInputMaybeToBool(MTest* test, MDefinition* value) {
blockResult->setImplicitlyUsedUnchecked();
MInstruction* ins = block->lastIns();
MOZ_ASSERT(ins->isGoto());
MOZ_RELEASE_ASSERT(ins->isGoto());
ins->toGoto()->target()->removePredecessor(block);
block->discardLastIns();
@ -707,15 +708,14 @@ static bool IsTestInputMaybeToBool(MTest* test, MDefinition* value) {
MInstruction* ins = block->lastIns();
if (ins->isTest()) {
MTest* test = ins->toTest();
MOZ_ASSERT(test->input() == value);
MOZ_RELEASE_ASSERT(test->input() == value);
if (ifTrue != test->ifTrue()) {
test->ifTrue()->removePredecessor(block);
if (!ifTrue->addPredecessorSameInputsAs(block, existingPred)) {
return false;
}
MOZ_ASSERT(test->ifTrue() == test->getSuccessor(0));
test->replaceSuccessor(0, ifTrue);
test->replaceSuccessor(MTest::TrueBranchIndex, ifTrue);
}
if (ifFalse != test->ifFalse()) {
@ -723,14 +723,13 @@ static bool IsTestInputMaybeToBool(MTest* test, MDefinition* value) {
if (!ifFalse->addPredecessorSameInputsAs(block, existingPred)) {
return false;
}
MOZ_ASSERT(test->ifFalse() == test->getSuccessor(1));
test->replaceSuccessor(1, ifFalse);
test->replaceSuccessor(MTest::FalseBranchIndex, ifFalse);
}
return true;
}
MOZ_ASSERT(ins->isGoto());
MOZ_RELEASE_ASSERT(ins->isGoto());
ins->toGoto()->target()->removePredecessor(block);
block->discardLastIns();
@ -775,8 +774,8 @@ static bool IsDiamondPattern(MBasicBlock* initialBlock) {
return false;
}
MBasicBlock* phiBlock = trueBranch->getSuccessor(0);
if (phiBlock != falseBranch->getSuccessor(0)) {
MBasicBlock* phiBlock = trueBranch->lastIns()->toGoto()->target();
if (phiBlock != falseBranch->lastIns()->toGoto()->target()) {
return false;
}
if (phiBlock->numPredecessors() != 2) {
@ -820,13 +819,13 @@ static bool IsDiamondPattern(MBasicBlock* initialBlock) {
return true;
}
MBasicBlock* phiBlock = trueBranch->getSuccessor(0);
MBasicBlock* phiBlock = trueBranch->lastIns()->toGoto()->target();
MBasicBlock* testBlock = phiBlock;
if (testBlock->numSuccessors() == 1) {
if (testBlock->lastIns()->isGoto()) {
if (testBlock->isLoopBackedge()) {
return true;
}
testBlock = testBlock->getSuccessor(0);
testBlock = testBlock->lastIns()->toGoto()->target();
if (testBlock->numPredecessors() != 1) {
return true;
}
@ -838,7 +837,7 @@ static bool IsDiamondPattern(MBasicBlock* initialBlock) {
return true;
}
MOZ_ASSERT(phi->numOperands() == 2);
MOZ_RELEASE_ASSERT(phi->numOperands() == 2);
// Make sure the test block does not have any outgoing loop backedges.
if (!SplitCriticalEdgesForBlock(graph, testBlock)) {
@ -929,8 +928,8 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
MBasicBlock* trueBranch = initialTest->ifTrue();
MBasicBlock* falseBranch = initialTest->ifFalse();
if (trueBranch->numSuccessors() == 1 &&
trueBranch->getSuccessor(0) == falseBranch) {
if (trueBranch->lastIns()->isGoto() &&
trueBranch->lastIns()->toGoto()->target() == falseBranch) {
if (trueBranch->numPredecessors() != 1) {
return false;
}
@ -940,8 +939,8 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
return true;
}
if (falseBranch->numSuccessors() == 1 &&
falseBranch->getSuccessor(0) == trueBranch) {
if (falseBranch->lastIns()->isGoto() &&
falseBranch->lastIns()->toGoto()->target() == trueBranch) {
if (trueBranch->numPredecessors() != 2) {
return false;
}
@ -999,19 +998,19 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
}
MBasicBlock* phiBlock;
if (trueBranch->numSuccessors() == 1 &&
trueBranch->getSuccessor(0) == falseBranch) {
if (trueBranch->lastIns()->isGoto() &&
trueBranch->lastIns()->toGoto()->target() == falseBranch) {
phiBlock = falseBranch;
} else {
MOZ_ASSERT(falseBranch->getSuccessor(0) == trueBranch);
MOZ_ASSERT(falseBranch->lastIns()->toGoto()->target() == trueBranch);
phiBlock = trueBranch;
}
MBasicBlock* testBlock = phiBlock;
if (testBlock->numSuccessors() == 1) {
MOZ_ASSERT(!testBlock->isLoopBackedge());
if (testBlock->lastIns()->isGoto()) {
MOZ_RELEASE_ASSERT(!testBlock->isLoopBackedge());
testBlock = testBlock->getSuccessor(0);
testBlock = testBlock->lastIns()->toGoto()->target();
if (testBlock->numPredecessors() != 1) {
return true;
}
@ -1023,7 +1022,7 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
return true;
}
MOZ_ASSERT(phi->numOperands() == 2);
MOZ_RELEASE_ASSERT(phi->numOperands() == 2);
// If the phi-operand doesn't match the initial input, we can't fold the test.
auto* phiInputForInitialBlock =
@ -1194,17 +1193,17 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
}
MBasicBlock* testBlock = phiBlock;
if (testBlock->numSuccessors() == 1) {
if (testBlock->lastIns()->isGoto()) {
if (testBlock->isLoopBackedge()) {
return true;
}
testBlock = testBlock->getSuccessor(0);
testBlock = testBlock->lastIns()->toGoto()->target();
if (testBlock->numPredecessors() != 1) {
return true;
}
}
MOZ_ASSERT(!phiBlock->isLoopBackedge());
MOZ_RELEASE_ASSERT(!phiBlock->isLoopBackedge());
MPhi* phi = nullptr;
MTest* finalTest = nullptr;
@ -1212,7 +1211,7 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
return true;
}
MOZ_ASSERT(phiBlock->numPredecessors() == phi->numOperands());
MOZ_RELEASE_ASSERT(phiBlock->numPredecessors() == phi->numOperands());
// If the phi-operand doesn't match the initial input, we can't fold the test.
auto* phiInputForInitialBlock =
@ -1243,7 +1242,7 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
return true;
}
MOZ_ASSERT(!pred->isLoopBackedge());
MOZ_RELEASE_ASSERT(!pred->isLoopBackedge());
}
// Ensure we found the single goto block.
@ -1270,7 +1269,7 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
// Update all test instructions to point to the final target.
while (phiBlock->numPredecessors()) {
mozilla::DebugOnly<size_t> oldNumPred = phiBlock->numPredecessors();
size_t oldNumPred = phiBlock->numPredecessors();
auto* pred = phiBlock->getPredecessor(0);
auto* test = pred->lastIns()->toTest();
@ -1281,7 +1280,7 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
return false;
}
} else {
MOZ_ASSERT(test->ifFalse() == phiBlock);
MOZ_RELEASE_ASSERT(test->ifFalse() == phiBlock);
if (!UpdateTestSuccessors(graph.alloc(), pred, test->input(),
test->ifTrue(), finalTest->ifFalse(),
testBlock)) {
@ -1290,7 +1289,7 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
}
// Ensure we've made progress.
MOZ_ASSERT(phiBlock->numPredecessors() + 1 == oldNumPred);
MOZ_RELEASE_ASSERT(phiBlock->numPredecessors() + 1 == oldNumPred);
}
// Remove phiBlock, if different from testBlock.

View file

@ -1346,7 +1346,6 @@ class MWasmLoadTableElement : public MBinaryInstruction,
wasm::RefType refType)
: MBinaryInstruction(classOpcode, elements, index) {
setResultType(MIRType::WasmAnyRef);
setMovable();
initWasmRefType(wasm::MaybeRefType(refType));
}

View file

@ -2266,36 +2266,15 @@ ResizableArrayBufferObject::createBufferAndData(
size_t sourceByteLength = source->byteLength();
size_t newMaxByteLength = source->maxByteLength();
if (newByteLength > sourceByteLength) {
// Copy into a larger buffer.
AutoSetNewObjectMetadata metadata(cx);
auto [buffer, toFill] = createBufferAndData<FillContents::Zero>(
cx, newByteLength, newMaxByteLength, metadata, nullptr);
if (!buffer) {
return nullptr;
}
// The `createBufferAndData()` call first zero-initializes the complete
// buffer and then we copy over |sourceByteLength| bytes from |source|. It
// seems prudent to only zero-initialize the trailing bytes of |toFill|
// to avoid writing twice to `toFill[0..newByteLength]`. We don't yet
// implement this optimization, because this method is only called for
// small, inline buffers, so any write optimizations probably won't make
// much of a difference.
std::copy_n(source->dataPointer(), sourceByteLength, toFill);
return buffer;
}
// Copy into a smaller or same size buffer.
AutoSetNewObjectMetadata metadata(cx);
auto [buffer, toFill] = createBufferAndData<FillContents::Uninitialized>(
auto [buffer, toFill] = createBufferAndData<FillContents::Zero>(
cx, newByteLength, newMaxByteLength, metadata, nullptr);
if (!buffer) {
return nullptr;
}
std::uninitialized_copy_n(source->dataPointer(), newByteLength, toFill);
size_t nbytes = std::min(newByteLength, sourceByteLength);
std::copy_n(source->dataPointer(), nbytes, toFill);
return buffer;
}