Bug 1530573 - Protect maybeResizeNursery() from overflow r=sfink

Differential Revision: https://phabricator.services.mozilla.com/D21158

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Paul Bone 2019-03-01 00:09:09 +00:00
parent 0d30de1b66
commit f454488dff
2 changed files with 19 additions and 14 deletions

View File

@ -1214,26 +1214,31 @@ void js::Nursery::maybeResizeNursery(JS::GCReason reason) {
float(previousGC.tenuredBytes) / float(previousGC.nurseryCapacity);
/*
* Object lifetimes arn't going to behave linearly, but a better
* Object lifetimes aren't going to behave linearly, but a better
* relationship that works for all programs and can be predicted in
* advance doesn't exist.
*/
const float factor = promotionRate / PromotionGoal;
const unsigned newCapacity = unsigned(float(capacity()) * factor);
MOZ_ASSERT(factor >= 0.0f);
MOZ_ASSERT((float(capacity()) * factor) <= SIZE_MAX);
const size_t newCapacity = size_t(float(capacity()) * factor);
// If one of these conditions is true then we always shrink or grow the
// nursery. This way the thresholds still have an effect even if the goal
// seeking says the current size is ideal.
if (maxChunkCount() < chunkCountLimit() && promotionRate > GrowThreshold) {
unsigned lowLimit = capacity() + SubChunkStep;
unsigned highLimit =
Min(chunkCountLimit() * NurseryChunkUsableSize, capacity() * 2);
size_t lowLimit = (CheckedInt<size_t>(capacity()) + SubChunkStep).value();
size_t highLimit =
Min((CheckedInt<size_t>(chunkCountLimit()) * NurseryChunkUsableSize)
.value(),
(CheckedInt<size_t>(capacity()) * 2).value());
growAllocableSpace(mozilla::Clamp(newCapacity, lowLimit, highLimit));
} else if (capacity() >= SubChunkLimit + SubChunkStep &&
promotionRate < ShrinkThreshold) {
unsigned lowLimit = Max(SubChunkLimit, capacity() / 2);
unsigned highLimit = capacity() - SubChunkStep;
size_t lowLimit = Max(SubChunkLimit, capacity() / 2);
size_t highLimit = (CheckedInt<size_t>(capacity()) - SubChunkStep).value();
shrinkAllocableSpace(mozilla::Clamp(newCapacity, lowLimit, highLimit));
}
@ -1245,7 +1250,7 @@ void js::Nursery::maybeResizeNursery(JS::GCReason reason) {
"Nursery limit must be at least one step from the full chunk size");
}
void js::Nursery::growAllocableSpace(unsigned newCapacity) {
void js::Nursery::growAllocableSpace(size_t newCapacity) {
MOZ_ASSERT_IF(!isSubChunkMode(),
newCapacity > currentChunk_ * NurseryChunkUsableSize);
if (isSubChunkMode()) {
@ -1269,16 +1274,16 @@ void js::Nursery::freeChunksFrom(unsigned firstFreeChunk) {
chunks_.shrinkTo(firstFreeChunk);
}
void js::Nursery::shrinkAllocableSpace(unsigned newCapacity) {
void js::Nursery::shrinkAllocableSpace(size_t newCapacity) {
#ifdef JS_GC_ZEAL
if (runtime()->hasZealMode(ZealMode::GenerationalGC)) {
return;
}
#endif
unsigned stepSize = newCapacity < NurseryChunkUsableSize
? SubChunkStep
: NurseryChunkUsableSize;
size_t stepSize = newCapacity < NurseryChunkUsableSize
? SubChunkStep
: NurseryChunkUsableSize;
newCapacity -= newCapacity % stepSize;
// Don't shrink the nursery to zero (use Nursery::disable() instead)
// This can't happen due to the rounding-down performed above because of the

View File

@ -639,8 +639,8 @@ class Nursery {
/* Change the allocable space provided by the nursery. */
void maybeResizeNursery(JS::GCReason reason);
void growAllocableSpace(unsigned newCapacity);
void shrinkAllocableSpace(unsigned newCapacity);
void growAllocableSpace(size_t newCapacity);
void shrinkAllocableSpace(size_t newCapacity);
void minimizeAllocableSpace();
// Free the chunks starting at firstFreeChunk until the end of the chunks