mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Backed out 7 changesets (bug 1084651) for ASAN Bustage on a CLOSED TREE
Backed out changeset dd2b3e78b425 (bug 1084651) Backed out changeset 2711fbd91819 (bug 1084651) Backed out changeset 59a163addd79 (bug 1084651) Backed out changeset d36f6dbbf925 (bug 1084651) Backed out changeset 78102b62a4a0 (bug 1084651) Backed out changeset 06387a2343a0 (bug 1084651) Backed out changeset 2f8e7c39573e (bug 1084651)
This commit is contained in:
parent
5fcc967a48
commit
13de0f42c9
@ -45,7 +45,6 @@
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jswrapper.h"
|
||||
#include "js/SliceBudget.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
@ -1693,24 +1692,24 @@ nsJSContext::RunCycleCollectorSlice()
|
||||
|
||||
// Decide how long we want to budget for this slice. By default,
|
||||
// use an unlimited budget.
|
||||
js::SliceBudget budget;
|
||||
int64_t sliceBudget = -1;
|
||||
|
||||
if (sIncrementalCC) {
|
||||
if (gCCStats.mBeginTime.IsNull()) {
|
||||
// If no CC is in progress, use the standard slice time.
|
||||
budget = js::SliceBudget(js::TimeBudget(kICCSliceBudget));
|
||||
sliceBudget = kICCSliceBudget;
|
||||
} else {
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
// Only run a limited slice if we're within the max running time.
|
||||
if (TimeBetween(gCCStats.mBeginTime, now) < kMaxICCDuration) {
|
||||
float sliceMultiplier = std::max(TimeBetween(gCCStats.mEndSliceTime, now) / (float)kICCIntersliceDelay, 1.0f);
|
||||
budget = js::SliceBudget(js::TimeBudget(kICCSliceBudget * sliceMultiplier));
|
||||
sliceBudget = kICCSliceBudget * sliceMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCycleCollector_collectSlice(budget);
|
||||
nsCycleCollector_collectSlice(sliceBudget);
|
||||
|
||||
gCCStats.FinishCycleCollectionSlice();
|
||||
}
|
||||
@ -1727,10 +1726,7 @@ nsJSContext::RunCycleCollectorWorkSlice(int64_t aWorkBudget)
|
||||
js::ProfileEntry::Category::CC);
|
||||
|
||||
gCCStats.PrepareForCycleCollectionSlice();
|
||||
|
||||
js::SliceBudget budget = js::SliceBudget(js::WorkBudget(aWorkBudget));
|
||||
nsCycleCollector_collectSlice(budget);
|
||||
|
||||
nsCycleCollector_collectSliceWork(aWorkBudget);
|
||||
gCCStats.FinishCycleCollectionSlice();
|
||||
}
|
||||
|
||||
|
@ -15,12 +15,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1027221
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var x = "x";
|
||||
// Trigger some incremental gc
|
||||
SpecialPowers.Cu.getJSTestingFunctions().gcslice(1);
|
||||
SpecialPowers.Cu.getJSTestingFunctions().gcslice(0);
|
||||
|
||||
// Kick off a worker that uses this same atom
|
||||
var w = new Worker("data:text/plain,Promise.resolve('x').then(function() { postMessage(1); });");
|
||||
// Maybe trigger some more incremental gc
|
||||
SpecialPowers.Cu.getJSTestingFunctions().gcslice(1);
|
||||
SpecialPowers.Cu.getJSTestingFunctions().gcslice(0);
|
||||
|
||||
w.onmessage = function() {
|
||||
ok(true, "Got here");
|
||||
|
@ -11,25 +11,11 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
struct JS_PUBLIC_API(TimeBudget)
|
||||
{
|
||||
int64_t budget;
|
||||
|
||||
explicit TimeBudget(int64_t milliseconds) { budget = milliseconds; }
|
||||
};
|
||||
|
||||
struct JS_PUBLIC_API(WorkBudget)
|
||||
{
|
||||
int64_t budget;
|
||||
|
||||
explicit WorkBudget(int64_t work) { budget = work; }
|
||||
};
|
||||
|
||||
/*
|
||||
* This class records how much work has been done in a given collection slice,
|
||||
* so that we can return before pausing for too long. Some slices are allowed
|
||||
* to run for unlimited time, and others are bounded. To reduce the number of
|
||||
* gettimeofday calls, we only check the time every 1000 operations.
|
||||
* This class records how much work has been done in a given collection slice, so that
|
||||
* we can return before pausing for too long. Some slices are allowed to run for
|
||||
* unlimited time, and others are bounded. To reduce the number of gettimeofday
|
||||
* calls, we only check the time every 1000 operations.
|
||||
*/
|
||||
struct JS_PUBLIC_API(SliceBudget)
|
||||
{
|
||||
@ -38,18 +24,17 @@ struct JS_PUBLIC_API(SliceBudget)
|
||||
|
||||
static const intptr_t CounterReset = 1000;
|
||||
|
||||
static const int64_t Unlimited = -1;
|
||||
static const int64_t Unlimited = 0;
|
||||
static int64_t TimeBudget(int64_t millis);
|
||||
static int64_t WorkBudget(int64_t work);
|
||||
|
||||
/* Use to create an unlimited budget. */
|
||||
/* Equivalent to SliceBudget(UnlimitedBudget). */
|
||||
SliceBudget();
|
||||
|
||||
/* Instantiate as SliceBudget(TimeBudget(n)). */
|
||||
explicit SliceBudget(TimeBudget time);
|
||||
/* Instantiate as SliceBudget(Time/WorkBudget(n)). */
|
||||
explicit SliceBudget(int64_t budget);
|
||||
|
||||
/* Instantiate as SliceBudget(WorkBudget(n)). */
|
||||
explicit SliceBudget(WorkBudget work);
|
||||
|
||||
void makeUnlimited() {
|
||||
void reset() {
|
||||
deadline = unlimitedDeadline;
|
||||
counter = unlimitedStartCounter;
|
||||
}
|
||||
@ -58,8 +43,10 @@ struct JS_PUBLIC_API(SliceBudget)
|
||||
counter -= amt;
|
||||
}
|
||||
|
||||
bool checkOverBudget();
|
||||
|
||||
bool isOverBudget() {
|
||||
if (counter > 0)
|
||||
if (counter >= 0)
|
||||
return false;
|
||||
return checkOverBudget();
|
||||
}
|
||||
@ -68,11 +55,10 @@ struct JS_PUBLIC_API(SliceBudget)
|
||||
return deadline == unlimitedDeadline;
|
||||
}
|
||||
|
||||
private:
|
||||
bool checkOverBudget();
|
||||
|
||||
private:
|
||||
static const int64_t unlimitedDeadline = INT64_MAX;
|
||||
static const intptr_t unlimitedStartCounter = INTPTR_MAX;
|
||||
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
@ -628,15 +628,16 @@ GCSlice(JSContext *cx, unsigned argc, Value *vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
SliceBudget budget;
|
||||
bool limit = true;
|
||||
uint32_t budget = 0;
|
||||
if (args.length() == 1) {
|
||||
uint32_t work = 0;
|
||||
if (!ToUint32(cx, args[0], &work))
|
||||
if (!ToUint32(cx, args[0], &budget))
|
||||
return false;
|
||||
budget = SliceBudget(WorkBudget(work));
|
||||
} else {
|
||||
limit = false;
|
||||
}
|
||||
|
||||
cx->runtime()->gc.gcDebugSlice(budget);
|
||||
cx->runtime()->gc.gcDebugSlice(limit, budget);
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ class GCRuntime
|
||||
void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason);
|
||||
void gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0);
|
||||
void gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason);
|
||||
void gcDebugSlice(SliceBudget &budget);
|
||||
void gcDebugSlice(bool limit, int64_t objCount);
|
||||
|
||||
void runDebugGC();
|
||||
inline void poke();
|
||||
@ -509,14 +509,14 @@ class GCRuntime
|
||||
|
||||
bool initZeal();
|
||||
void requestMajorGC(JS::gcreason::Reason reason);
|
||||
void collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind,
|
||||
void collect(bool incremental, int64_t budget, JSGCInvocationKind gckind,
|
||||
JS::gcreason::Reason reason);
|
||||
bool gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind,
|
||||
bool gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind,
|
||||
JS::gcreason::Reason reason);
|
||||
gcstats::ZoneGCStats scanZonesBeforeGC();
|
||||
void budgetIncrementalGC(SliceBudget &budget);
|
||||
void budgetIncrementalGC(int64_t *budget);
|
||||
void resetIncrementalGC(const char *reason);
|
||||
void incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason reason);
|
||||
void incrementalCollectSlice(int64_t budget, JS::gcreason::Reason reason);
|
||||
void pushZealSelectedObjects();
|
||||
void purgeRuntime();
|
||||
bool beginMarkPhase(JS::gcreason::Reason reason);
|
||||
|
@ -28,7 +28,7 @@ gcPreserveCode();
|
||||
try {
|
||||
mjitChunkLimit(1);
|
||||
} catch(exc1) {}
|
||||
gcslice(1);
|
||||
gcslice(0);
|
||||
m(1);
|
||||
gc();
|
||||
m(2);
|
||||
|
@ -3,4 +3,4 @@
|
||||
//
|
||||
|
||||
gc();
|
||||
evaluate("gcslice(1);");
|
||||
evaluate("gcslice(0);");
|
||||
|
@ -20,7 +20,7 @@ function h(code) {
|
||||
h("\
|
||||
p=m();\
|
||||
gcPreserveCode();\
|
||||
gcslice(8);\
|
||||
gcslice(7);\
|
||||
")
|
||||
h("\"\"")
|
||||
h("")
|
||||
|
@ -3,7 +3,7 @@
|
||||
//
|
||||
gc()
|
||||
schedulegc(this)
|
||||
gcslice(3)
|
||||
gcslice(2)
|
||||
function f() {
|
||||
this["x"] = this["x"] = {}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
function printBugNumber (num) {
|
||||
BUGNUMBER = num;
|
||||
}
|
||||
gcslice(1)
|
||||
gcslice(0)
|
||||
schedulegc(this);
|
||||
gcslice(2);
|
||||
gcslice(1);
|
||||
var BUGNUMBER = ("one");
|
||||
printBugNumber();
|
||||
|
@ -1,6 +1,6 @@
|
||||
var g1 = newGlobal();
|
||||
schedulegc(g1);
|
||||
gcslice(1);
|
||||
gcslice(0);
|
||||
function testEq(b) {
|
||||
var a = deserialize(serialize(b));
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ function gen()
|
||||
yield 1;
|
||||
local = null;
|
||||
gc();
|
||||
gcslice(0); // Start IGC, but don't mark anything.
|
||||
gcslice(0);
|
||||
yield 2;
|
||||
}
|
||||
|
||||
|
@ -12,5 +12,5 @@ function recur(n)
|
||||
}
|
||||
|
||||
validategc(false);
|
||||
gcslice(1);
|
||||
gcslice(0);
|
||||
recur(10);
|
||||
|
@ -11,8 +11,8 @@ expect = "generator function foo returns a value";
|
||||
actual = (function (j) {}).message;
|
||||
reportCompare(expect, actual, summary + ": 1");
|
||||
reportCompare(expect, actual, summary + ": 2");
|
||||
gcslice(0);
|
||||
gcslice(1);
|
||||
gcslice(2);
|
||||
gc();
|
||||
var strings = [ (0), ];
|
||||
for (var i = 0; i < strings.length; i++)
|
||||
|
@ -4,7 +4,7 @@ evalcx("\
|
||||
gcslice = function() { };\
|
||||
array = new Uint8Array;\
|
||||
t0 = array.subarray();\
|
||||
gcslice(12); \
|
||||
gcslice(11); \
|
||||
array.subarray();\
|
||||
gc();\
|
||||
gc();\
|
||||
|
@ -3,7 +3,7 @@
|
||||
if (typeof evalInWorker == "undefined")
|
||||
quit();
|
||||
|
||||
gcslice(11);
|
||||
gcslice(10);
|
||||
evalInWorker("print('helo world');");
|
||||
for (i = 0; i < 100000; i++) {}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
if (this.hasOwnProperty('Intl')) {
|
||||
gc();
|
||||
gcslice(1);
|
||||
gcslice(0);
|
||||
var thisValues = [ "x" ];
|
||||
thisValues.forEach(function (value) {
|
||||
var format = Intl.DateTimeFormat.call(value);
|
||||
|
@ -1,5 +1,5 @@
|
||||
gc();
|
||||
gcslice(1);
|
||||
gcslice(0);
|
||||
function isClone(a, b) {
|
||||
var rmemory = new WeakMap();
|
||||
rmemory.set(a,b);
|
||||
|
@ -9,5 +9,5 @@ var recursiveFunctions = [{
|
||||
eval(a.text.replace(/@/g, ""))
|
||||
}
|
||||
})();
|
||||
gcslice(2869);
|
||||
gcslice(2868);
|
||||
Function("v={c:[{x:[[]],N:{x:[{}[d]]}}]}=minorgc(true)")()
|
||||
|
@ -10,5 +10,5 @@ var recursiveFunctions = [{
|
||||
eval(a.text.replace(/@/g, ""))
|
||||
}
|
||||
})();
|
||||
gcslice(2869);
|
||||
gcslice(2868);
|
||||
Function("v={c:[{x:[[]],N:{x:[{}[d]]}}]}=minorgc(true)")()
|
||||
|
@ -10,5 +10,5 @@ var recursiveFunctions = [{
|
||||
eval(a.text.replace(/@/g, ""))
|
||||
}
|
||||
})();
|
||||
gcslice(2869);
|
||||
gcslice(2868);
|
||||
Function("v={c:[{x:[[]],N:{x:[{}[d]]}}]}=minorgc(true)")()
|
||||
|
@ -4,6 +4,6 @@ var juneDate = new Date(2000, 5, 20, 0, 0, 0, 0);
|
||||
for (var i = 0; i < function(x) myObj(Date.prototype.toString.apply(x)); void i) {
|
||||
eval(a.text.replace(/@/g, ""))
|
||||
}
|
||||
gcslice(2601);
|
||||
gcslice(2600);
|
||||
function testcase() {}
|
||||
new Uint16Array(testcase);
|
||||
|
@ -23,7 +23,7 @@ function init()
|
||||
*/
|
||||
eval("init()");
|
||||
|
||||
gcslice(0); // Start IGC, but don't mark anything.
|
||||
gcslice(0);
|
||||
selectforgc(objs.root2);
|
||||
gcslice(1);
|
||||
objs.root2.ptr = objs.root1.ptr;
|
||||
|
@ -22,7 +22,7 @@ function init()
|
||||
*/
|
||||
eval("init()");
|
||||
|
||||
gcslice(0); // Start IGC, but don't mark anything.
|
||||
gcslice(0);
|
||||
selectforgc(objs.root);
|
||||
gcslice(1);
|
||||
delete objs.root.b;
|
||||
|
@ -4,7 +4,7 @@ var g1 = newGlobal();
|
||||
var g2 = newGlobal();
|
||||
|
||||
schedulegc(g1);
|
||||
gcslice(0); // Start IGC, but don't mark anything.
|
||||
gcslice(0);
|
||||
schedulegc(g2);
|
||||
gcslice(1);
|
||||
gcslice();
|
||||
|
@ -5,7 +5,7 @@ var g2 = newGlobal();
|
||||
|
||||
schedulegc(g1);
|
||||
schedulegc(g2);
|
||||
gcslice(0); // Start IGC, but don't mark anything.
|
||||
gcslice(0);
|
||||
schedulegc(g1);
|
||||
gcslice(1);
|
||||
gcslice();
|
||||
|
@ -87,14 +87,12 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
FinalizeCalls = 0;
|
||||
JS_SetGCZeal(cx, 9, 1000000);
|
||||
JS::PrepareForFullGC(rt);
|
||||
js::SliceBudget budget(js::WorkBudget(1));
|
||||
rt->gc.gcDebugSlice(budget);
|
||||
rt->gc.gcDebugSlice(true, 1);
|
||||
CHECK(rt->gc.state() == js::gc::MARK);
|
||||
CHECK(rt->gc.isFullGc());
|
||||
|
||||
JS::RootedObject global4(cx, createTestGlobal());
|
||||
budget = js::SliceBudget(js::WorkBudget(1));
|
||||
rt->gc.gcDebugSlice(budget);
|
||||
rt->gc.gcDebugSlice(true, 1);
|
||||
CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL);
|
||||
CHECK(!rt->gc.isFullGc());
|
||||
CHECK(checkMultipleGroups());
|
||||
|
@ -89,8 +89,7 @@ BEGIN_TEST(testWeakMap_keyDelegates)
|
||||
* zone to finish marking before the delegate zone.
|
||||
*/
|
||||
CHECK(newCCW(map, delegate));
|
||||
js::SliceBudget budget(js::WorkBudget(1000000));
|
||||
rt->gc.gcDebugSlice(budget);
|
||||
rt->gc.gcDebugSlice(true, 1000000);
|
||||
#ifdef DEBUG
|
||||
CHECK(map->zone()->lastZoneGroupIndex() < delegate->zone()->lastZoneGroupIndex());
|
||||
#endif
|
||||
@ -103,8 +102,7 @@ BEGIN_TEST(testWeakMap_keyDelegates)
|
||||
/* Check the delegate keeps the entry alive even if the key is not reachable. */
|
||||
key = nullptr;
|
||||
CHECK(newCCW(map, delegate));
|
||||
budget = js::SliceBudget(js::WorkBudget(100000));
|
||||
rt->gc.gcDebugSlice(budget);
|
||||
rt->gc.gcDebugSlice(true, 100000);
|
||||
CHECK(checkSize(map, 1));
|
||||
|
||||
/*
|
||||
|
117
js/src/jsgc.cpp
117
js/src/jsgc.cpp
@ -1457,7 +1457,7 @@ GCRuntime::setParameter(JSGCParamKey key, uint32_t value)
|
||||
setMaxMallocBytes(value);
|
||||
break;
|
||||
case JSGC_SLICE_TIME_BUDGET:
|
||||
sliceBudget = value ? value : SliceBudget::Unlimited;
|
||||
sliceBudget = SliceBudget::TimeBudget(value);
|
||||
break;
|
||||
case JSGC_MARK_STACK_LIMIT:
|
||||
setMarkStackLimit(value);
|
||||
@ -1554,7 +1554,7 @@ GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC &lock)
|
||||
case JSGC_TOTAL_CHUNKS:
|
||||
return uint32_t(chunkSet.count() + emptyChunks(lock).count());
|
||||
case JSGC_SLICE_TIME_BUDGET:
|
||||
return uint32_t(sliceBudget > 0 ? sliceBudget : 0);
|
||||
return uint32_t(sliceBudget > 0 ? sliceBudget / PRMJ_USEC_PER_MSEC : 0);
|
||||
case JSGC_MARK_STACK_LIMIT:
|
||||
return marker.maxCapacity();
|
||||
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
|
||||
@ -2930,36 +2930,41 @@ GCRuntime::refillFreeListInGC(Zone *zone, AllocKind thingKind)
|
||||
return allocator.arenas.allocateFromArena(zone, thingKind);
|
||||
}
|
||||
|
||||
/* static */ int64_t
|
||||
SliceBudget::TimeBudget(int64_t millis)
|
||||
{
|
||||
return millis * PRMJ_USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
/* static */ int64_t
|
||||
SliceBudget::WorkBudget(int64_t work)
|
||||
{
|
||||
/* For work = 0 not to mean Unlimited, we subtract 1. */
|
||||
return -work - 1;
|
||||
}
|
||||
|
||||
SliceBudget::SliceBudget()
|
||||
{
|
||||
makeUnlimited();
|
||||
reset();
|
||||
}
|
||||
|
||||
SliceBudget::SliceBudget(TimeBudget time)
|
||||
SliceBudget::SliceBudget(int64_t budget)
|
||||
{
|
||||
if (time.budget < 0) {
|
||||
makeUnlimited();
|
||||
} else {
|
||||
// Note: TimeBudget(0) is equivalent to WorkBudget(CounterReset).
|
||||
deadline = PRMJ_Now() + time.budget * PRMJ_USEC_PER_MSEC;
|
||||
if (budget == Unlimited) {
|
||||
reset();
|
||||
} else if (budget > 0) {
|
||||
deadline = PRMJ_Now() + budget;
|
||||
counter = CounterReset;
|
||||
}
|
||||
}
|
||||
|
||||
SliceBudget::SliceBudget(WorkBudget work)
|
||||
{
|
||||
if (work.budget < 0) {
|
||||
makeUnlimited();
|
||||
} else {
|
||||
deadline = 0;
|
||||
counter = work.budget;
|
||||
counter = -budget - 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SliceBudget::checkOverBudget()
|
||||
{
|
||||
bool over = PRMJ_Now() >= deadline;
|
||||
bool over = PRMJ_Now() > deadline;
|
||||
if (!over)
|
||||
counter = CounterReset;
|
||||
return over;
|
||||
@ -5528,7 +5533,7 @@ GCRuntime::resetIncrementalGC(const char *reason)
|
||||
break;
|
||||
}
|
||||
|
||||
case SWEEP: {
|
||||
case SWEEP:
|
||||
marker.reset();
|
||||
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
|
||||
@ -5536,15 +5541,13 @@ GCRuntime::resetIncrementalGC(const char *reason)
|
||||
|
||||
/* Finish sweeping the current zone group, then abort. */
|
||||
abortSweepAfterCurrentGroup = true;
|
||||
SliceBudget budget;
|
||||
incrementalCollectSlice(budget, JS::gcreason::RESET);
|
||||
incrementalCollectSlice(SliceBudget::Unlimited, JS::gcreason::RESET);
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
|
||||
rt->gc.waitBackgroundSweepOrAllocEnd();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid incremental GC state");
|
||||
@ -5632,7 +5635,8 @@ GCRuntime::pushZealSelectedObjects()
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason reason)
|
||||
GCRuntime::incrementalCollectSlice(int64_t budget,
|
||||
JS::gcreason::Reason reason)
|
||||
{
|
||||
MOZ_ASSERT(rt->currentThreadHasExclusiveAccess());
|
||||
|
||||
@ -5645,7 +5649,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason rea
|
||||
|
||||
int zeal = 0;
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (reason == JS::gcreason::DEBUG_GC && !budget.isUnlimited()) {
|
||||
if (reason == JS::gcreason::DEBUG_GC && budget != SliceBudget::Unlimited) {
|
||||
/*
|
||||
* Do the incremental collection type specified by zeal mode if the
|
||||
* collection was triggered by runDebugGC() and incremental GC has not
|
||||
@ -5656,16 +5660,18 @@ GCRuntime::incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason rea
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT_IF(incrementalState != NO_INCREMENTAL, isIncremental);
|
||||
isIncremental = !budget.isUnlimited();
|
||||
isIncremental = budget != SliceBudget::Unlimited;
|
||||
|
||||
if (zeal == ZealIncrementalRootsThenFinish || zeal == ZealIncrementalMarkAllThenFinish) {
|
||||
/*
|
||||
* Yields between slices occurs at predetermined points in these modes;
|
||||
* the budget is not used.
|
||||
*/
|
||||
budget.makeUnlimited();
|
||||
budget = SliceBudget::Unlimited;
|
||||
}
|
||||
|
||||
SliceBudget sliceBudget(budget);
|
||||
|
||||
if (incrementalState == NO_INCREMENTAL) {
|
||||
incrementalState = MARK_ROOTS;
|
||||
lastMarkSlice = false;
|
||||
@ -5695,11 +5701,11 @@ GCRuntime::incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason rea
|
||||
case MARK: {
|
||||
/* If we needed delayed marking for gray roots, then collect until done. */
|
||||
if (!marker.hasBufferedGrayRoots()) {
|
||||
budget.makeUnlimited();
|
||||
sliceBudget.reset();
|
||||
isIncremental = false;
|
||||
}
|
||||
|
||||
bool finished = drainMarkStack(budget, gcstats::PHASE_MARK);
|
||||
bool finished = drainMarkStack(sliceBudget, gcstats::PHASE_MARK);
|
||||
if (!finished)
|
||||
break;
|
||||
|
||||
@ -5725,7 +5731,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason rea
|
||||
* now exhasted.
|
||||
*/
|
||||
beginSweepPhase(lastGC);
|
||||
if (budget.isOverBudget())
|
||||
if (sliceBudget.isOverBudget())
|
||||
break;
|
||||
|
||||
/*
|
||||
@ -5739,7 +5745,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason rea
|
||||
}
|
||||
|
||||
case SWEEP: {
|
||||
bool finished = sweepPhase(budget);
|
||||
bool finished = sweepPhase(sliceBudget);
|
||||
if (!finished)
|
||||
break;
|
||||
|
||||
@ -5780,32 +5786,32 @@ gc::IsIncrementalGCSafe(JSRuntime *rt)
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::budgetIncrementalGC(SliceBudget &budget)
|
||||
GCRuntime::budgetIncrementalGC(int64_t *budget)
|
||||
{
|
||||
IncrementalSafety safe = IsIncrementalGCSafe(rt);
|
||||
if (!safe) {
|
||||
resetIncrementalGC(safe.reason());
|
||||
budget.makeUnlimited();
|
||||
*budget = SliceBudget::Unlimited;
|
||||
stats.nonincremental(safe.reason());
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode != JSGC_MODE_INCREMENTAL) {
|
||||
resetIncrementalGC("GC mode change");
|
||||
budget.makeUnlimited();
|
||||
*budget = SliceBudget::Unlimited;
|
||||
stats.nonincremental("GC mode");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTooMuchMalloc()) {
|
||||
budget.makeUnlimited();
|
||||
*budget = SliceBudget::Unlimited;
|
||||
stats.nonincremental("malloc bytes trigger");
|
||||
}
|
||||
|
||||
bool reset = false;
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
if (zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) {
|
||||
budget.makeUnlimited();
|
||||
*budget = SliceBudget::Unlimited;
|
||||
stats.nonincremental("allocation trigger");
|
||||
}
|
||||
|
||||
@ -5816,7 +5822,7 @@ GCRuntime::budgetIncrementalGC(SliceBudget &budget)
|
||||
}
|
||||
|
||||
if (zone->isTooMuchMalloc()) {
|
||||
budget.makeUnlimited();
|
||||
*budget = SliceBudget::Unlimited;
|
||||
stats.nonincremental("malloc bytes trigger");
|
||||
}
|
||||
}
|
||||
@ -5862,7 +5868,7 @@ struct AutoDisableStoreBuffer
|
||||
* to run another cycle.
|
||||
*/
|
||||
MOZ_NEVER_INLINE bool
|
||||
GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind,
|
||||
GCRuntime::gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind,
|
||||
JS::gcreason::Reason reason)
|
||||
{
|
||||
minorGC(reason);
|
||||
@ -5916,9 +5922,9 @@ GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gck
|
||||
resetIncrementalGC("requested");
|
||||
|
||||
stats.nonincremental("requested");
|
||||
budget.makeUnlimited();
|
||||
budget = SliceBudget::Unlimited;
|
||||
} else {
|
||||
budgetIncrementalGC(budget);
|
||||
budgetIncrementalGC(&budget);
|
||||
}
|
||||
|
||||
/* The GC was reset, so we need a do-over. */
|
||||
@ -6011,7 +6017,7 @@ GCRuntime::scanZonesBeforeGC()
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind,
|
||||
GCRuntime::collect(bool incremental, int64_t budget, JSGCInvocationKind gckind,
|
||||
JS::gcreason::Reason reason)
|
||||
{
|
||||
/* GC shouldn't be running in parallel execution mode */
|
||||
@ -6036,7 +6042,7 @@ GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gck
|
||||
return;
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT_IF(!incremental || !budget.isUnlimited(), JSGC_INCREMENTAL);
|
||||
MOZ_ASSERT_IF(!incremental || budget != SliceBudget::Unlimited, JSGC_INCREMENTAL);
|
||||
|
||||
AutoStopVerifyingBarriers av(rt, reason == JS::gcreason::SHUTDOWN_CC ||
|
||||
reason == JS::gcreason::DESTROY_RUNTIME);
|
||||
@ -6103,22 +6109,21 @@ GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gck
|
||||
void
|
||||
GCRuntime::gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason)
|
||||
{
|
||||
SliceBudget budget;
|
||||
collect(false, budget, gckind, reason);
|
||||
collect(false, SliceBudget::Unlimited, gckind, reason);
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis)
|
||||
{
|
||||
SliceBudget budget;
|
||||
int64_t budget;
|
||||
if (millis)
|
||||
budget = SliceBudget(TimeBudget(millis));
|
||||
budget = SliceBudget::TimeBudget(millis);
|
||||
else if (reason == JS::gcreason::ALLOC_TRIGGER)
|
||||
budget = SliceBudget(TimeBudget(sliceBudget));
|
||||
budget = sliceBudget;
|
||||
else if (schedulingState.inHighFrequencyGCMode() && tunables.isDynamicMarkSliceEnabled())
|
||||
budget = SliceBudget(TimeBudget(sliceBudget * IGC_MARK_SLICE_MULTIPLIER));
|
||||
budget = sliceBudget * IGC_MARK_SLICE_MULTIPLIER;
|
||||
else
|
||||
budget = SliceBudget(TimeBudget(sliceBudget));
|
||||
budget = sliceBudget;
|
||||
|
||||
collect(true, budget, gckind, reason);
|
||||
}
|
||||
@ -6126,8 +6131,7 @@ GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64
|
||||
void
|
||||
GCRuntime::gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason)
|
||||
{
|
||||
SliceBudget budget;
|
||||
collect(true, budget, gckind, reason);
|
||||
collect(true, SliceBudget::Unlimited, gckind, reason);
|
||||
}
|
||||
|
||||
void
|
||||
@ -6170,8 +6174,9 @@ ZonesSelected(JSRuntime *rt)
|
||||
}
|
||||
|
||||
void
|
||||
GCRuntime::gcDebugSlice(SliceBudget &budget)
|
||||
GCRuntime::gcDebugSlice(bool limit, int64_t objCount)
|
||||
{
|
||||
int64_t budget = limit ? SliceBudget::WorkBudget(objCount) : SliceBudget::Unlimited;
|
||||
if (!ZonesSelected(rt)) {
|
||||
if (JS::IsIncrementalGCInProgress(rt))
|
||||
JS::PrepareForIncrementalGC(rt);
|
||||
@ -6422,12 +6427,12 @@ GCRuntime::runDebugGC()
|
||||
|
||||
PrepareForDebugGC(rt);
|
||||
|
||||
SliceBudget budget;
|
||||
if (type == ZealIncrementalRootsThenFinish ||
|
||||
type == ZealIncrementalMarkAllThenFinish ||
|
||||
type == ZealIncrementalMultipleSlices)
|
||||
{
|
||||
js::gc::State initialState = incrementalState;
|
||||
int64_t budget;
|
||||
if (type == ZealIncrementalMultipleSlices) {
|
||||
/*
|
||||
* Start with a small slice limit and double it every slice. This
|
||||
@ -6438,10 +6443,10 @@ GCRuntime::runDebugGC()
|
||||
incrementalLimit = zealFrequency / 2;
|
||||
else
|
||||
incrementalLimit *= 2;
|
||||
budget = SliceBudget(WorkBudget(incrementalLimit));
|
||||
budget = SliceBudget::WorkBudget(incrementalLimit);
|
||||
} else {
|
||||
// This triggers incremental GC but is actually ignored by IncrementalMarkSlice.
|
||||
budget = SliceBudget(WorkBudget(1));
|
||||
budget = SliceBudget::WorkBudget(1);
|
||||
}
|
||||
|
||||
collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC);
|
||||
@ -6456,9 +6461,9 @@ GCRuntime::runDebugGC()
|
||||
incrementalLimit = zealFrequency / 2;
|
||||
}
|
||||
} else if (type == ZealCompactValue) {
|
||||
collect(false, budget, GC_SHRINK, JS::gcreason::DEBUG_GC);
|
||||
collect(false, SliceBudget::Unlimited, GC_SHRINK, JS::gcreason::DEBUG_GC);
|
||||
} else {
|
||||
collect(false, budget, GC_NORMAL, JS::gcreason::DEBUG_GC);
|
||||
collect(false, SliceBudget::Unlimited, GC_NORMAL, JS::gcreason::DEBUG_GC);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -203,7 +203,7 @@ function test()
|
||||
gc();
|
||||
buffer = null;
|
||||
views = null;
|
||||
gcslice(3); gcslice(3); gcslice(3); gcslice(3); gcslice(3); gcslice(3); gc();
|
||||
gcslice(2); gcslice(2); gcslice(2); gcslice(2); gcslice(2); gcslice(2); gc();
|
||||
}
|
||||
|
||||
var buf, buf2;
|
||||
|
@ -3622,9 +3622,7 @@ nsCycleCollector::Collect(ccType aCCType,
|
||||
break;
|
||||
}
|
||||
if (continueSlice) {
|
||||
// Force SliceBudget::isOverBudget to check the time.
|
||||
aBudget.step(SliceBudget::CounterReset);
|
||||
continueSlice = !aBudget.isOverBudget();
|
||||
continueSlice = !aBudget.checkOverBudget();
|
||||
}
|
||||
} while (continueSlice);
|
||||
|
||||
@ -4188,7 +4186,7 @@ nsCycleCollector_collect(nsICycleCollectorListener* aManualListener)
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_collectSlice(SliceBudget& budget)
|
||||
nsCycleCollector_collectSlice(int64_t aSliceTime)
|
||||
{
|
||||
CollectorData* data = sCollectorData.get();
|
||||
|
||||
@ -4199,6 +4197,29 @@ nsCycleCollector_collectSlice(SliceBudget& budget)
|
||||
PROFILER_LABEL("nsCycleCollector", "collectSlice",
|
||||
js::ProfileEntry::Category::CC);
|
||||
|
||||
SliceBudget budget;
|
||||
if (aSliceTime >= 0) {
|
||||
budget = SliceBudget(SliceBudget::TimeBudget(aSliceTime));
|
||||
}
|
||||
data->mCollector->Collect(SliceCC, budget, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
nsCycleCollector_collectSliceWork(int64_t aSliceWork)
|
||||
{
|
||||
CollectorData* data = sCollectorData.get();
|
||||
|
||||
// We should have started the cycle collector by now.
|
||||
MOZ_ASSERT(data);
|
||||
MOZ_ASSERT(data->mCollector);
|
||||
|
||||
PROFILER_LABEL("nsCycleCollector", "collectSliceWork",
|
||||
js::ProfileEntry::Category::CC);
|
||||
|
||||
SliceBudget budget;
|
||||
if (aSliceWork >= 0) {
|
||||
budget = SliceBudget(SliceBudget::WorkBudget(aSliceWork));
|
||||
}
|
||||
data->mCollector->Collect(SliceCC, budget, nullptr);
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,6 @@ template<class T> struct already_AddRefed;
|
||||
#include "nsError.h"
|
||||
#include "nsID.h"
|
||||
|
||||
namespace js { struct SliceBudget; };
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CycleCollectedJSRuntime;
|
||||
@ -58,7 +56,13 @@ already_AddRefed<nsICycleCollectorLogSink> nsCycleCollector_createLogSink();
|
||||
|
||||
void nsCycleCollector_collect(nsICycleCollectorListener* aManualListener);
|
||||
|
||||
void nsCycleCollector_collectSlice(js::SliceBudget& budget);
|
||||
// If aSliceTime is negative, the CC will run to completion. Otherwise,
|
||||
// aSliceTime will be used as the time budget for the slice, in ms.
|
||||
void nsCycleCollector_collectSlice(int64_t aSliceTime);
|
||||
|
||||
// If aSliceTime is negative, the CC will run to completion. Otherwise,
|
||||
// aSliceTime will be used as the work budget for the slice.
|
||||
void nsCycleCollector_collectSliceWork(int64_t aSliceWork);
|
||||
|
||||
uint32_t nsCycleCollector_suspectedCount();
|
||||
void nsCycleCollector_shutdown();
|
||||
|
Loading…
Reference in New Issue
Block a user