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