Skip to content

Commit

Permalink
Merge mozilla-inbound to mozilla-central a=merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Razvan Maries committed May 21, 2019
2 parents 3a21dca + 0bbd4dc commit 366383f
Show file tree
Hide file tree
Showing 25 changed files with 512 additions and 493 deletions.
10 changes: 10 additions & 0 deletions dom/webidl/MozFrameLoaderOwner.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ dictionary RemotenessOptions {
boolean replaceBrowsingContext = false;
};

/**
* An interface implemented by elements that are 'browsing context containers'
* in HTML5 terms (that is, elements such as iframe that creates a new
* browsing context):
*
* https://html.spec.whatwg.org/#browsing-context-container
*
* Object implementing this interface must implement nsFrameLoaderOwner in
* native C++ code.
*/
[NoInterfaceObject]
interface MozFrameLoaderOwner {
[ChromeOnly]
Expand Down
6 changes: 1 addition & 5 deletions js/src/gc/ArenaList.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class ArenaLists {
ZoneData<Arena*> gcScriptArenasToUpdate;
ZoneData<Arena*> gcObjectGroupArenasToUpdate;

// The list of empty arenas which are collected during sweep phase and
// The list of empty arenas which are collected during the sweep phase and
// released at the end of sweeping every sweep group.
ZoneData<Arena*> savedEmptyArenas;

Expand Down Expand Up @@ -350,10 +350,6 @@ class ArenaLists {

void setParallelAllocEnabled(bool enabled);

// When finalizing arenas, whether to keep empty arenas on the list or
// release them immediately.
enum KeepArenasEnum { RELEASE_ARENAS, KEEP_ARENAS };

private:
inline JSRuntime* runtime();
inline JSRuntime* runtimeFromAnyThread();
Expand Down
65 changes: 29 additions & 36 deletions js/src/gc/GC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,18 +637,13 @@ inline size_t Arena::finalize(FreeOp* fop, AllocKind thingKind,
template <typename T>
static inline bool FinalizeTypedArenas(FreeOp* fop, Arena** src,
SortedArenaList& dest,
AllocKind thingKind, SliceBudget& budget,
ArenaLists::KeepArenasEnum keepArenas) {
AllocKind thingKind, SliceBudget& budget) {
// When operating in the foreground, take the lock at the top.
Maybe<AutoLockGC> maybeLock;
if (fop->onMainThread()) {
maybeLock.emplace(fop->runtime());
}

// During background sweeping free arenas are released later on in
// sweepBackgroundThings().
MOZ_ASSERT_IF(!fop->onMainThread(), keepArenas == ArenaLists::KEEP_ARENAS);

size_t thingSize = Arena::thingSize(thingKind);
size_t thingsPerArena = Arena::thingsPerArena(thingKind);

Expand All @@ -659,10 +654,8 @@ static inline bool FinalizeTypedArenas(FreeOp* fop, Arena** src,

if (nmarked) {
dest.insertAt(arena, nfree);
} else if (keepArenas == ArenaLists::KEEP_ARENAS) {
arena->chunk()->recycleArena(arena, dest, thingsPerArena);
} else {
fop->runtime()->gc.releaseArena(arena, maybeLock.ref());
arena->chunk()->recycleArena(arena, dest, thingsPerArena);
}

budget.step(thingsPerArena);
Expand All @@ -678,14 +671,12 @@ static inline bool FinalizeTypedArenas(FreeOp* fop, Arena** src,
* Finalize the list of areans.
*/
static bool FinalizeArenas(FreeOp* fop, Arena** src, SortedArenaList& dest,
AllocKind thingKind, SliceBudget& budget,
ArenaLists::KeepArenasEnum keepArenas) {
AllocKind thingKind, SliceBudget& budget) {
switch (thingKind) {
#define EXPAND_CASE(allocKind, traceKind, type, sizedType, bgFinal, nursery, \
compact) \
case AllocKind::allocKind: \
return FinalizeTypedArenas<type>(fop, src, dest, thingKind, budget, \
keepArenas);
return FinalizeTypedArenas<type>(fop, src, dest, thingKind, budget);
FOR_EACH_ALLOCKIND(EXPAND_CASE)
#undef EXPAND_CASE

Expand Down Expand Up @@ -3152,8 +3143,7 @@ void ArenaLists::backgroundFinalize(FreeOp* fop, Arena* listHead,
SortedArenaList finalizedSorted(thingsPerArena);

auto unlimited = SliceBudget::unlimited();
FinalizeArenas(fop, &listHead, finalizedSorted, thingKind, unlimited,
KEEP_ARENAS);
FinalizeArenas(fop, &listHead, finalizedSorted, thingKind, unlimited);
MOZ_ASSERT(!listHead);

finalizedSorted.extractEmpty(empty);
Expand Down Expand Up @@ -5466,18 +5456,21 @@ static void SweepCompressionTasks(GCParallelTask* task) {
}
}

static void SweepWeakMaps(GCParallelTask* task) {
void js::gc::SweepLazyScripts(GCParallelTask* task) {
JSRuntime* runtime = task->runtime();
for (SweepGroupZonesIter zone(runtime); !zone.done(); zone.next()) {
/* Clear all weakrefs that point to unmarked things. */
for (auto edge : zone->gcWeakRefs()) {
/* Edges may be present multiple times, so may already be nulled. */
if (*edge && IsAboutToBeFinalizedDuringSweep(**edge)) {
for (auto i = zone->cellIter<LazyScript>(); !i.done(); i.next()) {
WeakHeapPtrScript* edge = &i.unbarrieredGet()->script_;
if (*edge && IsAboutToBeFinalized(edge)) {
*edge = nullptr;
}
}
zone->gcWeakRefs().clear();
}
}

static void SweepWeakMaps(GCParallelTask* task) {
JSRuntime* runtime = task->runtime();
for (SweepGroupZonesIter zone(runtime); !zone.done(); zone.next()) {
/* No need to look up any more weakmap keys from this sweep group. */
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!zone->gcWeakKeys().clear()) {
Expand Down Expand Up @@ -5735,6 +5728,8 @@ IncrementalProgress GCRuntime::beginSweepingSweepGroup(FreeOp* fop,
AutoRunParallelTask sweepMisc(rt, SweepMisc, PhaseKind::SWEEP_MISC, lock);
AutoRunParallelTask sweepCompTasks(rt, SweepCompressionTasks,
PhaseKind::SWEEP_COMPRESSION, lock);
AutoRunParallelTask sweepLazyScripts(rt, SweepLazyScripts,
PhaseKind::SWEEP_LAZYSCRIPTS, lock);
AutoRunParallelTask sweepWeakMaps(rt, SweepWeakMaps,
PhaseKind::SWEEP_WEAKMAPS, lock);
AutoRunParallelTask sweepUniqueIds(rt, SweepUniqueIds,
Expand Down Expand Up @@ -5875,13 +5870,12 @@ bool ArenaLists::foregroundFinalize(FreeOp* fop, AllocKind thingKind,
return true;
}

// Empty object arenas are not released until all foreground GC things have
// been swept.
KeepArenasEnum keepArenas =
IsObjectAllocKind(thingKind) ? KEEP_ARENAS : RELEASE_ARENAS;

// Empty arenas are not released until all foreground finalized GC things in
// the current sweep group have been finalized. This allows finalizers for
// other cells in the same sweep group to call IsAboutToBeFinalized on cells
// in this arena.
if (!FinalizeArenas(fop, &arenaListsToSweep(thingKind), sweepList, thingKind,
sliceBudget, keepArenas)) {
sliceBudget)) {
incrementalSweptArenaKind = thingKind;
incrementalSweptArenas = sweepList.toArenaList();
return false;
Expand All @@ -5890,9 +5884,7 @@ bool ArenaLists::foregroundFinalize(FreeOp* fop, AllocKind thingKind,
// Clear any previous incremental sweep state we may have saved.
incrementalSweptArenas.ref().clear();

if (IsObjectAllocKind(thingKind)) {
sweepList.extractEmpty(&savedEmptyArenas.ref());
}
sweepList.extractEmpty(&savedEmptyArenas.ref());

ArenaList finalized = sweepList.toArenaList();
arenaLists(thingKind) =
Expand Down Expand Up @@ -5984,13 +5976,14 @@ IncrementalProgress GCRuntime::sweepTypeInformation(FreeOp* fop,
}

IncrementalProgress GCRuntime::releaseSweptEmptyArenas(FreeOp* fop,
SliceBudget& budget,
Zone* zone) {
// Foreground finalized objects have already been finalized, and now their
SliceBudget& budget) {
// Foreground finalized GC things have already been finalized, and now their
// arenas can be reclaimed by freeing empty ones and making non-empty ones
// available for allocation.

zone->arenas.releaseForegroundSweptEmptyArenas();
for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next()) {
zone->arenas.releaseForegroundSweptEmptyArenas();
}
return Finished;
}

Expand Down Expand Up @@ -6559,8 +6552,8 @@ bool GCRuntime::initSweepActions() {
ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
Call(&GCRuntime::finalizeAllocKind)),
MaybeYieldInZoneLoop(ZealMode::YieldBeforeSweepingShapeTrees),
Call(&GCRuntime::sweepShapeTree),
Call(&GCRuntime::releaseSweptEmptyArenas))),
Call(&GCRuntime::sweepShapeTree))),
Call(&GCRuntime::releaseSweptEmptyArenas),
Call(&GCRuntime::endSweepingSweepGroup)));

return sweepActions != nullptr;
Expand Down
4 changes: 0 additions & 4 deletions js/src/gc/GCMarker.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,6 @@ class GCMarker : public JSTracer {
traverseEdge(source, target);
}

// Notes a weak graph edge for later sweeping.
template <typename T>
void noteWeakEdge(T* edge);

/*
* Care must be taken changing the mark color from gray to black. The cycle
* collector depends on the invariant that there are no black to gray edges
Expand Down
3 changes: 1 addition & 2 deletions js/src/gc/GCRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -629,8 +629,7 @@ class GCRuntime {
IncrementalProgress performSweepActions(SliceBudget& sliceBudget);
IncrementalProgress sweepTypeInformation(FreeOp* fop, SliceBudget& budget,
Zone* zone);
IncrementalProgress releaseSweptEmptyArenas(FreeOp* fop, SliceBudget& budget,
Zone* zone);
IncrementalProgress releaseSweptEmptyArenas(FreeOp* fop, SliceBudget& budget);
void startSweepingAtomsTable();
IncrementalProgress sweepAtomsTable(FreeOp* fop, SliceBudget& budget);
IncrementalProgress sweepWeakCaches(FreeOp* fop, SliceBudget& budget);
Expand Down
1 change: 1 addition & 0 deletions js/src/gc/GenerateStatsPhases.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def __init__(self, name, descr, bucket, children=[]):
PhaseKind("SWEEP_BREAKPOINT", "Sweep Breakpoints", 27),
PhaseKind("SWEEP_REGEXP", "Sweep Regexps", 28),
PhaseKind("SWEEP_COMPRESSION", "Sweep Compression Tasks", 62),
PhaseKind("SWEEP_LAZYSCRIPTS", "Sweep LazyScripts", 71),
PhaseKind("SWEEP_WEAKMAPS", "Sweep WeakMaps", 63),
PhaseKind("SWEEP_UNIQUEIDS", "Sweep Unique IDs", 64),
PhaseKind("SWEEP_JIT_DATA", "Sweep JIT Data", 65),
Expand Down
2 changes: 1 addition & 1 deletion js/src/gc/Heap-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
inline void js::gc::Arena::init(JS::Zone* zoneArg, AllocKind kind,
const AutoLockGC& lock) {
MOZ_ASSERT(firstFreeSpan.isEmpty());
MOZ_ASSERT(!zone);
MOZ_ASSERT((uintptr_t(zone) & 0xff) == JS_FREED_ARENA_PATTERN);
MOZ_ASSERT(!allocated());
MOZ_ASSERT(!onDelayedMarkingList_);
MOZ_ASSERT(!hasDelayedBlackMarking_);
Expand Down
6 changes: 5 additions & 1 deletion js/src/gc/Heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,11 @@ class Arena {
// previously allocated for some zone, use release() instead.
void setAsNotAllocated() {
firstFreeSpan.initAsEmpty();
zone = nullptr;

// Poison zone pointer to highlight UAF on released arenas in crash data.
AlwaysPoison(&zone, JS_FREED_ARENA_PATTERN, sizeof(zone),
MemCheckKind::MakeUndefined);

allocKind = size_t(AllocKind::LIMIT);
onDelayedMarkingList_ = 0;
hasDelayedBlackMarking_ = 0;
Expand Down
65 changes: 4 additions & 61 deletions js/src/gc/Marking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,6 @@ template <typename T>
void DoMarking(GCMarker* gcmarker, T* thing);
template <typename T>
void DoMarking(GCMarker* gcmarker, const T& thing);
template <typename T>
void NoteWeakEdge(GCMarker* gcmarker, T** thingp);
template <typename T>
void NoteWeakEdge(GCMarker* gcmarker, T* thingp);

template <typename T>
JS_PUBLIC_API void js::gc::TraceExternalEdge(JSTracer* trc, T* thingp,
Expand Down Expand Up @@ -447,7 +443,6 @@ namespace gc {

#define INSTANTIATE_INTERNAL_TRACE_FUNCTIONS(type) \
template void TraceEdgeInternal<type>(JSTracer*, type*, const char*); \
template void TraceWeakEdgeInternal<type>(JSTracer*, type*, const char*); \
template void TraceRangeInternal<type>(JSTracer*, size_t len, type*, \
const char*);

Expand Down Expand Up @@ -568,19 +563,6 @@ void js::gc::TraceEdgeInternal(JSTracer* trc, T* thingp, const char* name) {
DoCallback(trc->asCallbackTracer(), thingp, name);
}

template <typename T>
void js::gc::TraceWeakEdgeInternal(JSTracer* trc, T* thingp, const char* name) {
if (!trc->isMarkingTracer()) {
// Non-marking tracers can select whether or not they see weak edges.
if (trc->traceWeakEdges()) {
TraceEdgeInternal(trc, thingp, name);
}
return;
}

NoteWeakEdge(GCMarker::fromTracer(trc), thingp);
}

template <typename T>
void js::gc::TraceRangeInternal(JSTracer* trc, size_t len, T* vec,
const char* name) {
Expand Down Expand Up @@ -762,44 +744,6 @@ JS_PUBLIC_API void js::gc::PerformIncrementalReadBarrier(JS::GCCellPtr thing) {
});
}

template <typename T>
void NoteWeakEdge(GCMarker* gcmarker, T** thingp) {
// Do per-type marking precondition checks.
if (!ShouldMark(gcmarker, *thingp)) {
return;
}

CheckTracedThing(gcmarker, *thingp);

// If the target is already marked, there's no need to store the edge.
if (IsMarkedUnbarriered(gcmarker->runtime(), thingp)) {
return;
}

gcmarker->noteWeakEdge(thingp);
}

template <typename T>
void NoteWeakEdge(GCMarker* gcmarker, T* thingp) {
MOZ_CRASH("the gc does not support tagged pointers as weak edges");
}

template <typename T>
void js::GCMarker::noteWeakEdge(T* edge) {
static_assert(IsBaseOf<Cell, typename mozilla::RemovePointer<T>::Type>::value,
"edge must point to a GC pointer");
MOZ_ASSERT((*edge)->isTenured());

// Note: we really want the *source* Zone here. The edge may start in a
// non-gc heap location, however, so we use the fact that cross-zone weak
// references are not allowed and use the *target's* zone.
JS::Zone::WeakEdges& weakRefs = (*edge)->asTenured().zone()->gcWeakRefs();
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!weakRefs.append(reinterpret_cast<TenuredCell**>(edge))) {
oomUnsafe.crash("Failed to record a weak edge for sweeping.");
}
}

// The simplest traversal calls out to the fully generic traceChildren function
// to visit the child edges. In the absence of other traversal mechanisms, this
// function will rapidly grow the stack past its bounds and crash the process.
Expand Down Expand Up @@ -991,8 +935,8 @@ bool js::GCMarker::mark(T* thing) {
// traversing equivalent subgraphs.

void LazyScript::traceChildren(JSTracer* trc) {
if (script_) {
TraceWeakEdge(trc, &script_, "script");
if (trc->traceWeakEdges()) {
TraceNullableEdge(trc, &script_, "script");
}

if (function_) {
Expand Down Expand Up @@ -1029,9 +973,7 @@ void LazyScript::traceChildren(JSTracer* trc) {
}
}
inline void js::GCMarker::eagerlyMarkChildren(LazyScript* thing) {
if (thing->script_) {
noteWeakEdge(thing->script_.unsafeUnbarrieredForTracing());
}
// script_ is weak so is not traced here.

if (thing->function_) {
traverseEdge(thing, static_cast<JSObject*>(thing->function_));
Expand Down Expand Up @@ -1548,6 +1490,7 @@ bool GCMarker::markUntilBudgetExhausted(SliceBudget& budget) {
if (hasGrayEntries()) {
AutoSetMarkColor autoSetGray(*this, MarkColor::Gray);
do {
MOZ_ASSERT(!hasBlackEntries());
processMarkStackTop(budget);
if (budget.isOverBudget()) {
return false;
Expand Down

0 comments on commit 366383f

Please sign in to comment.