icecat: add release icecat-140.9.0-1gnu1 for ecne
This commit is contained in:
parent
8eb1f1732f
commit
a5f93cb214
1197 changed files with 30593 additions and 15344 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
@ -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()) {}
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -1346,7 +1346,6 @@ class MWasmLoadTableElement : public MBinaryInstruction,
|
|||
wasm::RefType refType)
|
||||
: MBinaryInstruction(classOpcode, elements, index) {
|
||||
setResultType(MIRType::WasmAnyRef);
|
||||
setMovable();
|
||||
initWasmRefType(wasm::MaybeRefType(refType));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue