Bug 1644258 - Simplify nursery size rounding r=sfink

Previously there was a quirk of nursery size rounding where requesting a nursery size of just less than a chunk resulted in a smaller size than a chunk being used even if one chunk was the nearest valid size.

This was to avoid having a sub-chunk size greater than the amount of usable space in a chunk, but that is not possible anyway as long as the sub-chunk step is greater than the chunk trailer size.

The patch simplifies the rounding code and updates the test code to add a size that will give different results depending on chunk size.  I had to add a gcparam to get the chunk size to make this work.

Differential Revision: https://phabricator.services.mozilla.com/D79148
This commit is contained in:
Jon Coppeard 2020-06-10 15:44:07 +00:00
Родитель 0fcab2f5a1
Коммит 00f99e1d69
5 изменённых файлов: 27 добавлений и 16 удалений

Просмотреть файл

@ -323,7 +323,7 @@ typedef enum JSGCParamKey {
/* /*
* The current size of the nursery. * The current size of the nursery.
* *
* read-only. * This parameter is read-only.
*/ */
JSGC_NURSERY_BYTES = 34, JSGC_NURSERY_BYTES = 34,
@ -348,6 +348,13 @@ typedef enum JSGCParamKey {
* Default: IncrementalWeakMarkEnabled * Default: IncrementalWeakMarkEnabled
*/ */
JSGC_INCREMENTAL_WEAKMAP_ENABLED = 37, JSGC_INCREMENTAL_WEAKMAP_ENABLED = 37,
/**
* The chunk size in bytes for this system.
*
* This parameter is read-only.
*/
JSGC_CHUNK_BYTES = 38,
} JSGCParamKey; } JSGCParamKey;
/* /*

Просмотреть файл

@ -585,7 +585,8 @@ static bool MinorGC(JSContext* cx, unsigned argc, Value* vp) {
_("pretenureGroupThreshold", JSGC_PRETENURE_GROUP_THRESHOLD, true) \ _("pretenureGroupThreshold", JSGC_PRETENURE_GROUP_THRESHOLD, true) \
_("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \ _("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \
_("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \ _("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \
_("mallocGrowthFactor", JSGC_MALLOC_GROWTH_FACTOR, true) _("mallocGrowthFactor", JSGC_MALLOC_GROWTH_FACTOR, true) \
_("chunkBytes", JSGC_CHUNK_BYTES, false)
static const struct ParamInfo { static const struct ParamInfo {
const char* name; const char* name;

Просмотреть файл

@ -1502,6 +1502,8 @@ uint32_t GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock) {
return tunables.mallocThresholdBase() / 1024 / 1024; return tunables.mallocThresholdBase() / 1024 / 1024;
case JSGC_MALLOC_GROWTH_FACTOR: case JSGC_MALLOC_GROWTH_FACTOR:
return uint32_t(tunables.mallocGrowthFactor() * 100); return uint32_t(tunables.mallocGrowthFactor() * 100);
case JSGC_CHUNK_BYTES:
return ChunkSize;
default: default:
MOZ_CRASH("Unknown parameter key"); MOZ_CRASH("Unknown parameter key");
} }

Просмотреть файл

@ -1543,13 +1543,15 @@ size_t js::Nursery::targetSize(JS::GCReason reason) {
/* static */ /* static */
size_t js::Nursery::roundSize(size_t size) { size_t js::Nursery::roundSize(size_t size) {
if (size >= ChunkSize) { static_assert(SubChunkStep > gc::ChunkTrailerSize,
size = Round(size, ChunkSize); "Don't allow the nursery to overwrite the trailer when using "
} else { "less than a chunk");
size = std::min(Round(size, SubChunkStep),
RoundDown(NurseryChunkUsableSize, SubChunkStep)); size_t step = size >= ChunkSize ? ChunkSize : SubChunkStep;
} size = Round(size, step);
MOZ_ASSERT(size >= ArenaSize); MOZ_ASSERT(size >= ArenaSize);
return size; return size;
} }

Просмотреть файл

@ -6,7 +6,9 @@
load(libdir + "asserts.js"); load(libdir + "asserts.js");
var testSizesKB = [128, 129, 255, 256, 1023, 1024, 3*1024, 4*1024+1, 16*1024]; const chunkSizeKB = gcparam('chunkBytes') / 1024;
var testSizesKB = [128, 129, 255, 256, 516, 1023, 1024, 3*1024, 4*1024+1, 16*1024];
// Valid maximum sizes must be >= 1MB. // Valid maximum sizes must be >= 1MB.
var testMaxSizesKB = testSizesKB.filter(x => x >= 1024); var testMaxSizesKB = testSizesKB.filter(x => x >= 1024);
@ -33,8 +35,8 @@ function setMinMax(min, max) {
// Set the maximum first so that we don't hit a case where max < min. // Set the maximum first so that we don't hit a case where max < min.
gcparam('maxNurseryBytes', max * 1024); gcparam('maxNurseryBytes', max * 1024);
gcparam('minNurseryBytes', min * 1024); gcparam('minNurseryBytes', min * 1024);
assertEq(nearestLegalSize(max) * 1024, gcparam('maxNurseryBytes')); assertEq(gcparam('maxNurseryBytes'), nearestLegalSize(max) * 1024);
assertEq(nearestLegalSize(min) * 1024, gcparam('minNurseryBytes')); assertEq(gcparam('minNurseryBytes'), nearestLegalSize(min) * 1024);
allocateSomeThings(); allocateSomeThings();
gc(); gc();
} }
@ -46,11 +48,8 @@ function allocateSomeThings() {
} }
function nearestLegalSize(sizeKB) { function nearestLegalSize(sizeKB) {
if (sizeKB >= 1024) { let step = sizeKB >= chunkSizeKB ? chunkSizeKB : 4;
return round(sizeKB, 1024); return round(sizeKB, step);
}
return Math.min(round(sizeKB, 4), 1020);
} }
function round(x, y) { function round(x, y) {