зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1771315 - Add a command line option to the shell to set GC parameters r=sfink
This moves the parameter names and other data to a header file and adds a command line option --gc-param. Differential Revision: https://phabricator.services.mozilla.com/D147428
This commit is contained in:
Родитель
2249f5ac31
Коммит
51e87f5456
|
@ -56,6 +56,7 @@
|
|||
#include "frontend/BytecodeCompiler.h" // frontend::ParseModuleToExtensibleStencil
|
||||
#include "frontend/CompilationStencil.h" // frontend::CompilationStencil
|
||||
#include "gc/Allocator.h"
|
||||
#include "gc/GC.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/Disassemble.h"
|
||||
|
@ -698,63 +699,6 @@ static bool MinorGC(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return true;
|
||||
}
|
||||
|
||||
#define FOR_EACH_GC_PARAM(_) \
|
||||
_("maxBytes", JSGC_MAX_BYTES, true) \
|
||||
_("minNurseryBytes", JSGC_MIN_NURSERY_BYTES, true) \
|
||||
_("maxNurseryBytes", JSGC_MAX_NURSERY_BYTES, true) \
|
||||
_("gcBytes", JSGC_BYTES, false) \
|
||||
_("nurseryBytes", JSGC_NURSERY_BYTES, false) \
|
||||
_("gcNumber", JSGC_NUMBER, false) \
|
||||
_("majorGCNumber", JSGC_MAJOR_GC_NUMBER, false) \
|
||||
_("minorGCNumber", JSGC_MINOR_GC_NUMBER, false) \
|
||||
_("incrementalGCEnabled", JSGC_INCREMENTAL_GC_ENABLED, true) \
|
||||
_("perZoneGCEnabled", JSGC_PER_ZONE_GC_ENABLED, true) \
|
||||
_("unusedChunks", JSGC_UNUSED_CHUNKS, false) \
|
||||
_("totalChunks", JSGC_TOTAL_CHUNKS, false) \
|
||||
_("sliceTimeBudgetMS", JSGC_SLICE_TIME_BUDGET_MS, true) \
|
||||
_("markStackLimit", JSGC_MARK_STACK_LIMIT, true) \
|
||||
_("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true) \
|
||||
_("smallHeapSizeMax", JSGC_SMALL_HEAP_SIZE_MAX, true) \
|
||||
_("largeHeapSizeMin", JSGC_LARGE_HEAP_SIZE_MIN, true) \
|
||||
_("highFrequencySmallHeapGrowth", JSGC_HIGH_FREQUENCY_SMALL_HEAP_GROWTH, \
|
||||
true) \
|
||||
_("highFrequencyLargeHeapGrowth", JSGC_HIGH_FREQUENCY_LARGE_HEAP_GROWTH, \
|
||||
true) \
|
||||
_("lowFrequencyHeapGrowth", JSGC_LOW_FREQUENCY_HEAP_GROWTH, true) \
|
||||
_("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \
|
||||
_("smallHeapIncrementalLimit", JSGC_SMALL_HEAP_INCREMENTAL_LIMIT, true) \
|
||||
_("largeHeapIncrementalLimit", JSGC_LARGE_HEAP_INCREMENTAL_LIMIT, true) \
|
||||
_("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \
|
||||
_("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \
|
||||
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \
|
||||
_("minLastDitchGCPeriod", JSGC_MIN_LAST_DITCH_GC_PERIOD, true) \
|
||||
_("nurseryFreeThresholdForIdleCollection", \
|
||||
JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION, true) \
|
||||
_("nurseryFreeThresholdForIdleCollectionPercent", \
|
||||
JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION_PERCENT, true) \
|
||||
_("nurseryTimeoutForIdleCollectionMS", \
|
||||
JSGC_NURSERY_TIMEOUT_FOR_IDLE_COLLECTION_MS, true) \
|
||||
_("pretenureThreshold", JSGC_PRETENURE_THRESHOLD, true) \
|
||||
_("pretenureGroupThreshold", JSGC_PRETENURE_GROUP_THRESHOLD, true) \
|
||||
_("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \
|
||||
_("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \
|
||||
_("urgentThreshold", JSGC_URGENT_THRESHOLD_MB, true) \
|
||||
_("chunkBytes", JSGC_CHUNK_BYTES, false) \
|
||||
_("helperThreadRatio", JSGC_HELPER_THREAD_RATIO, true) \
|
||||
_("maxHelperThreads", JSGC_MAX_HELPER_THREADS, true) \
|
||||
_("helperThreadCount", JSGC_HELPER_THREAD_COUNT, false) \
|
||||
_("systemPageSizeKB", JSGC_SYSTEM_PAGE_SIZE_KB, false)
|
||||
|
||||
static const struct ParamInfo {
|
||||
const char* name;
|
||||
JSGCParamKey param;
|
||||
bool writable;
|
||||
} paramMap[] = {
|
||||
#define DEFINE_PARAM_INFO(name, key, writable) {name, key, writable},
|
||||
FOR_EACH_GC_PARAM(DEFINE_PARAM_INFO)
|
||||
#undef DEFINE_PARAM_INFO
|
||||
};
|
||||
|
||||
#define PARAM_NAME_LIST_ENTRY(name, key, writable) " " name
|
||||
#define GC_PARAMETER_ARGS_LIST FOR_EACH_GC_PARAM(PARAM_NAME_LIST_ENTRY)
|
||||
|
||||
|
@ -766,24 +710,19 @@ static bool GCParameter(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return false;
|
||||
}
|
||||
|
||||
JSLinearString* linearStr = JS_EnsureLinearString(cx, str);
|
||||
if (!linearStr) {
|
||||
UniqueChars name = EncodeLatin1(cx, str);
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto* ptr = std::find_if(
|
||||
std::begin(paramMap), std::end(paramMap), [&](const auto& param) {
|
||||
return JS_LinearStringEqualsAscii(linearStr, param.name);
|
||||
});
|
||||
if (ptr == std::end(paramMap)) {
|
||||
JSGCParamKey param;
|
||||
bool writable;
|
||||
if (!GetGCParameterInfo(name.get(), ¶m, &writable)) {
|
||||
JS_ReportErrorASCII(
|
||||
cx, "the first argument must be one of:" GC_PARAMETER_ARGS_LIST);
|
||||
return false;
|
||||
}
|
||||
|
||||
const ParamInfo& info = *ptr;
|
||||
JSGCParamKey param = info.param;
|
||||
|
||||
// Request mode.
|
||||
if (args.length() == 1) {
|
||||
uint32_t value = JS_GetGCParameter(cx, param);
|
||||
|
@ -791,9 +730,9 @@ static bool GCParameter(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!info.writable) {
|
||||
if (!writable) {
|
||||
JS_ReportErrorASCII(cx, "Attempt to change read-only parameter %s",
|
||||
info.name);
|
||||
name.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,58 @@ struct Cell;
|
|||
|
||||
} /* namespace gc */
|
||||
|
||||
// Define name, key and writability for the GC parameters.
|
||||
#define FOR_EACH_GC_PARAM(_) \
|
||||
_("maxBytes", JSGC_MAX_BYTES, true) \
|
||||
_("minNurseryBytes", JSGC_MIN_NURSERY_BYTES, true) \
|
||||
_("maxNurseryBytes", JSGC_MAX_NURSERY_BYTES, true) \
|
||||
_("gcBytes", JSGC_BYTES, false) \
|
||||
_("nurseryBytes", JSGC_NURSERY_BYTES, false) \
|
||||
_("gcNumber", JSGC_NUMBER, false) \
|
||||
_("majorGCNumber", JSGC_MAJOR_GC_NUMBER, false) \
|
||||
_("minorGCNumber", JSGC_MINOR_GC_NUMBER, false) \
|
||||
_("incrementalGCEnabled", JSGC_INCREMENTAL_GC_ENABLED, true) \
|
||||
_("perZoneGCEnabled", JSGC_PER_ZONE_GC_ENABLED, true) \
|
||||
_("unusedChunks", JSGC_UNUSED_CHUNKS, false) \
|
||||
_("totalChunks", JSGC_TOTAL_CHUNKS, false) \
|
||||
_("sliceTimeBudgetMS", JSGC_SLICE_TIME_BUDGET_MS, true) \
|
||||
_("markStackLimit", JSGC_MARK_STACK_LIMIT, true) \
|
||||
_("highFrequencyTimeLimit", JSGC_HIGH_FREQUENCY_TIME_LIMIT, true) \
|
||||
_("smallHeapSizeMax", JSGC_SMALL_HEAP_SIZE_MAX, true) \
|
||||
_("largeHeapSizeMin", JSGC_LARGE_HEAP_SIZE_MIN, true) \
|
||||
_("highFrequencySmallHeapGrowth", JSGC_HIGH_FREQUENCY_SMALL_HEAP_GROWTH, \
|
||||
true) \
|
||||
_("highFrequencyLargeHeapGrowth", JSGC_HIGH_FREQUENCY_LARGE_HEAP_GROWTH, \
|
||||
true) \
|
||||
_("lowFrequencyHeapGrowth", JSGC_LOW_FREQUENCY_HEAP_GROWTH, true) \
|
||||
_("allocationThreshold", JSGC_ALLOCATION_THRESHOLD, true) \
|
||||
_("smallHeapIncrementalLimit", JSGC_SMALL_HEAP_INCREMENTAL_LIMIT, true) \
|
||||
_("largeHeapIncrementalLimit", JSGC_LARGE_HEAP_INCREMENTAL_LIMIT, true) \
|
||||
_("minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT, true) \
|
||||
_("maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT, true) \
|
||||
_("compactingEnabled", JSGC_COMPACTING_ENABLED, true) \
|
||||
_("minLastDitchGCPeriod", JSGC_MIN_LAST_DITCH_GC_PERIOD, true) \
|
||||
_("nurseryFreeThresholdForIdleCollection", \
|
||||
JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION, true) \
|
||||
_("nurseryFreeThresholdForIdleCollectionPercent", \
|
||||
JSGC_NURSERY_FREE_THRESHOLD_FOR_IDLE_COLLECTION_PERCENT, true) \
|
||||
_("nurseryTimeoutForIdleCollectionMS", \
|
||||
JSGC_NURSERY_TIMEOUT_FOR_IDLE_COLLECTION_MS, true) \
|
||||
_("pretenureThreshold", JSGC_PRETENURE_THRESHOLD, true) \
|
||||
_("pretenureGroupThreshold", JSGC_PRETENURE_GROUP_THRESHOLD, true) \
|
||||
_("zoneAllocDelayKB", JSGC_ZONE_ALLOC_DELAY_KB, true) \
|
||||
_("mallocThresholdBase", JSGC_MALLOC_THRESHOLD_BASE, true) \
|
||||
_("urgentThreshold", JSGC_URGENT_THRESHOLD_MB, true) \
|
||||
_("chunkBytes", JSGC_CHUNK_BYTES, false) \
|
||||
_("helperThreadRatio", JSGC_HELPER_THREAD_RATIO, true) \
|
||||
_("maxHelperThreads", JSGC_MAX_HELPER_THREADS, true) \
|
||||
_("helperThreadCount", JSGC_HELPER_THREAD_COUNT, false) \
|
||||
_("systemPageSizeKB", JSGC_SYSTEM_PAGE_SIZE_KB, false)
|
||||
|
||||
// Get the key and writability give a GC parameter name.
|
||||
extern bool GetGCParameterInfo(const char* name, JSGCParamKey* keyOut,
|
||||
bool* writableOut);
|
||||
|
||||
extern void TraceRuntime(JSTracer* trc);
|
||||
|
||||
// Trace roots but don't evict the nursery first; used from DumpHeap.
|
||||
|
|
|
@ -474,6 +474,33 @@ uint64_t js::gc::NextCellUniqueId(JSRuntime* rt) {
|
|||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
static const struct GCParamInfo {
|
||||
const char* name;
|
||||
JSGCParamKey key;
|
||||
bool writable;
|
||||
} GCParameters[] = {
|
||||
#define DEFINE_PARAM_INFO(name, key, writable) {name, key, writable},
|
||||
FOR_EACH_GC_PARAM(DEFINE_PARAM_INFO)
|
||||
#undef DEFINE_PARAM_INFO
|
||||
};
|
||||
|
||||
bool GetGCParameterInfo(const char* name, JSGCParamKey* keyOut,
|
||||
bool* writableOut) {
|
||||
MOZ_ASSERT(keyOut);
|
||||
MOZ_ASSERT(writableOut);
|
||||
|
||||
for (const GCParamInfo& info : GCParameters) {
|
||||
if (strcmp(name, info.name) == 0) {
|
||||
*keyOut = info.key;
|
||||
*writableOut = info.writable;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace gc {
|
||||
namespace MemInfo {
|
||||
|
||||
|
|
|
@ -11847,6 +11847,59 @@ static bool WriteSelfHostedXDRFile(JSContext* cx, JS::SelfHostedCache buffer) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool SetGCParameterFromArg(JSContext* cx, char* arg) {
|
||||
char* c = strchr(arg, '=');
|
||||
if (!c) {
|
||||
fprintf(stderr,
|
||||
"Error: --gc-param argument '%s' must be of the form "
|
||||
"name=decimalValue\n",
|
||||
arg);
|
||||
return false;
|
||||
}
|
||||
|
||||
*c = '\0';
|
||||
const char* name = arg;
|
||||
const char* valueStr = c + 1;
|
||||
|
||||
JSGCParamKey key;
|
||||
bool writable;
|
||||
if (!GetGCParameterInfo(name, &key, &writable)) {
|
||||
fprintf(stderr, "Error: Unknown GC parameter name '%s'\n", name);
|
||||
fprintf(stderr, "Writable GC parameter names are:\n");
|
||||
#define PRINT_WRITABLE_PARAM_NAME(name, _, writable) \
|
||||
if (writable) { \
|
||||
fprintf(stderr, " %s\n", name); \
|
||||
}
|
||||
FOR_EACH_GC_PARAM(PRINT_WRITABLE_PARAM_NAME)
|
||||
#undef PRINT_WRITABLE_PARAM_NAME
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!writable) {
|
||||
fprintf(stderr, "Error: GC parameter '%s' is not writable\n", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
char* end = nullptr;
|
||||
unsigned long int value = strtoul(valueStr, &end, 10);
|
||||
if (end == valueStr || *end) {
|
||||
fprintf(stderr,
|
||||
"Error: Could not parse '%s' as decimal for GC parameter '%s'\n",
|
||||
valueStr, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t paramValue = uint32_t(value);
|
||||
if (value == ULONG_MAX || value != paramValue ||
|
||||
!cx->runtime()->gc.setParameter(key, paramValue)) {
|
||||
fprintf(stderr, "Error: Value %s is out of range for GC parameter '%s'\n",
|
||||
valueStr, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
PreInit();
|
||||
|
||||
|
@ -12268,6 +12321,8 @@ int main(int argc, char** argv) {
|
|||
!op.addStringOption('z', "gc-zeal", "LEVEL(;LEVEL)*[,N]",
|
||||
"option ignored in non-gc-zeal builds") ||
|
||||
#endif
|
||||
!op.addMultiStringOption('\0', "gc-param", "NAME=VALUE",
|
||||
"Set a named GC parameter") ||
|
||||
!op.addStringOption('\0', "module-load-path", "DIR",
|
||||
"Set directory to load modules from") ||
|
||||
!op.addBoolOption('\0', "no-source-pragmas",
|
||||
|
@ -12287,12 +12342,12 @@ int main(int argc, char** argv) {
|
|||
!op.addBoolOption('\0', "smoosh", "No-op") ||
|
||||
#endif
|
||||
!op.addStringOption(
|
||||
'\0', "delazification-mode", "[option]",
|
||||
"Select one of the delazification mode for scripts given on the "
|
||||
"command line, valid options are: "
|
||||
"'on-demand', 'concurrent-df', 'eager', 'concurrent-df+on-demand'. "
|
||||
"Choosing 'concurrent-df+on-demand' will run both concurrent-df and "
|
||||
"on-demand delazification mode, and compare compilation outcome. ") ||
|
||||
'\0', "delazification-mode", "[option]",
|
||||
"Select one of the delazification mode for scripts given on the "
|
||||
"command line, valid options are: "
|
||||
"'on-demand', 'concurrent-df', 'eager', 'concurrent-df+on-demand'. "
|
||||
"Choosing 'concurrent-df+on-demand' will run both concurrent-df and "
|
||||
"on-demand delazification mode, and compare compilation outcome. ") ||
|
||||
!op.addBoolOption('\0', "wasm-compile-and-serialize",
|
||||
"Compile the wasm bytecode from stdin and serialize "
|
||||
"the results to stdout") ||
|
||||
|
@ -12679,6 +12734,13 @@ int main(int argc, char** argv) {
|
|||
|
||||
JS_SetGCParameter(cx, JSGC_PER_ZONE_GC_ENABLED, true);
|
||||
|
||||
for (MultiStringRange args = op.getMultiStringOption("gc-param");
|
||||
!args.empty(); args.popFront()) {
|
||||
if (!SetGCParameterFromArg(cx, args.front())) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
JS::SetProcessLargeAllocationFailureCallback(my_LargeAllocFailCallback);
|
||||
|
||||
js::SetPreserveWrapperCallbacks(cx, DummyPreserveWrapperCallback,
|
||||
|
|
Загрузка…
Ссылка в новой задаче