diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/Options.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/Options.cpp | 249 |
1 files changed, 112 insertions, 137 deletions
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp index 894ca8cc0..b5ce39c0d 100644 --- a/Source/JavaScriptCore/runtime/Options.cpp +++ b/Source/JavaScriptCore/runtime/Options.cpp @@ -26,9 +26,15 @@ #include "config.h" #include "Options.h" +#include <algorithm> #include <limits> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <wtf/NumberOfCores.h> #include <wtf/PageBlock.h> +#include <wtf/StdLibExtras.h> +#include <wtf/StringExtras.h> #if OS(DARWIN) && ENABLE(PARALLEL_GC) #include <sys/sysctl.h> @@ -37,71 +43,9 @@ // Set to 1 to control the heuristics using environment variables. #define ENABLE_RUN_TIME_HEURISTICS 0 -#if ENABLE(RUN_TIME_HEURISTICS) -#include <stdio.h> -#include <stdlib.h> -#include <wtf/StdLibExtras.h> -#endif - -namespace JSC { namespace Options { - -bool useJIT; - -bool showDisassembly; -bool showDFGDisassembly; - -unsigned maximumOptimizationCandidateInstructionCount; - -unsigned maximumFunctionForCallInlineCandidateInstructionCount; -unsigned maximumFunctionForConstructInlineCandidateInstructionCount; - -unsigned maximumInliningDepth; - -int32_t thresholdForJITAfterWarmUp; -int32_t thresholdForJITSoon; - -int32_t thresholdForOptimizeAfterWarmUp; -int32_t thresholdForOptimizeAfterLongWarmUp; -int32_t thresholdForOptimizeSoon; -int32_t executionCounterIncrementForLoop; -int32_t executionCounterIncrementForReturn; +namespace JSC { -bool randomizeExecutionCountsBetweenCheckpoints; -int32_t maximumExecutionCountsBetweenCheckpoints; - -unsigned desiredSpeculativeSuccessFailRatio; - -double likelyToTakeSlowCaseThreshold; -double couldTakeSlowCaseThreshold; -unsigned likelyToTakeSlowCaseMinimumCount; -unsigned couldTakeSlowCaseMinimumCount; - -double osrExitProminenceForFrequentExitSite; - -unsigned largeFailCountThresholdBase; -unsigned largeFailCountThresholdBaseForLoop; -unsigned forcedOSRExitCountForReoptimization; - -unsigned reoptimizationRetryCounterMax; -unsigned reoptimizationRetryCounterStep; - -unsigned minimumOptimizationDelay; -unsigned maximumOptimizationDelay; -double desiredProfileLivenessRate; -double desiredProfileFullnessRate; - -double doubleVoteRatioForDoubleFormat; - -unsigned minimumNumberOfScansBetweenRebalance; -unsigned gcMarkStackSegmentSize; -unsigned numberOfGCMarkers; -unsigned opaqueRootMergeThreshold; - -bool forceWeakRandomSeed; -unsigned forcedWeakRandomSeed; - -#if ENABLE(RUN_TIME_HEURISTICS) static bool parse(const char* string, bool& value) { if (!strcasecmp(string, "true") || !strcasecmp(string, "yes") || !strcmp(string, "1")) { @@ -130,27 +74,22 @@ static bool parse(const char* string, double& value) return sscanf(string, "%lf", &value) == 1; } -template<typename T, typename U> -void setHeuristic(T& variable, const char* name, U value) +#if ENABLE(RUN_TIME_HEURISTICS) +template<typename T> +void overrideOptionWithHeuristic(T& variable, const char* name) { const char* stringValue = getenv(name); - if (!stringValue) { - variable = safeCast<T>(value); + if (!stringValue) return; - } if (parse(stringValue, variable)) return; fprintf(stderr, "WARNING: failed to parse %s=%s\n", name, stringValue); - variable = safeCast<T>(value); } - -#define SET(variable, value) setHeuristic(variable, "JSC_" #variable, value) -#else -#define SET(variable, value) variable = value #endif + static unsigned computeNumberOfGCMarkers(int maxNumberOfGCMarkers) { int cpusToUse = 1; @@ -167,80 +106,116 @@ static unsigned computeNumberOfGCMarkers(int maxNumberOfGCMarkers) return cpusToUse; } -void initializeOptions() -{ - SET(useJIT, true); - - SET(showDisassembly, false); - SET(showDFGDisassembly, false); - - SET(maximumOptimizationCandidateInstructionCount, 10000); - - SET(maximumFunctionForCallInlineCandidateInstructionCount, 180); - SET(maximumFunctionForConstructInlineCandidateInstructionCount, 100); - - SET(maximumInliningDepth, 5); +Options::Entry Options::s_options[Options::numberOfOptions]; - SET(thresholdForJITAfterWarmUp, 100); - SET(thresholdForJITSoon, 100); +// Realize the names for each of the options: +const Options::EntryInfo Options::s_optionsInfo[Options::numberOfOptions] = { +#define FOR_EACH_OPTION(type_, name_, defaultValue_) \ + { #name_, Options::type_##Type }, + JSC_OPTIONS(FOR_EACH_OPTION) +#undef FOR_EACH_OPTION +}; - SET(thresholdForOptimizeAfterWarmUp, 1000); - SET(thresholdForOptimizeAfterLongWarmUp, 5000); - SET(thresholdForOptimizeSoon, 1000); - - SET(executionCounterIncrementForLoop, 1); - SET(executionCounterIncrementForReturn, 15); - - SET(randomizeExecutionCountsBetweenCheckpoints, false); - SET(maximumExecutionCountsBetweenCheckpoints, 1000); - - SET(desiredSpeculativeSuccessFailRatio, 6); - - SET(likelyToTakeSlowCaseThreshold, 0.15); - SET(couldTakeSlowCaseThreshold, 0.05); // Shouldn't be zero because some ops will spuriously take slow case, for example for linking or caching. - SET(likelyToTakeSlowCaseMinimumCount, 100); - SET(couldTakeSlowCaseMinimumCount, 10); +void Options::initialize() +{ + // Initialize each of the options with their default values: +#define FOR_EACH_OPTION(type_, name_, defaultValue_) \ + name_() = defaultValue_; + JSC_OPTIONS(FOR_EACH_OPTION) +#undef FOR_EACH_OPTION + + // Allow environment vars to override options if applicable. + // The evn var should be the name of the option prefixed with + // "JSC_". +#if ENABLE(RUN_TIME_HEURISTICS) +#define FOR_EACH_OPTION(type_, name_, defaultValue_) \ + overrideOptionWithHeuristic(name_(), "JSC_" #name_); + JSC_OPTIONS(FOR_EACH_OPTION) +#undef FOR_EACH_OPTION +#endif // RUN_TIME_HEURISTICS + +#if 0 + ; // Deconfuse editors that do auto indentation +#endif - SET(osrExitProminenceForFrequentExitSite, 0.3); - - SET(largeFailCountThresholdBase, 20); - SET(largeFailCountThresholdBaseForLoop, 1); - SET(forcedOSRExitCountForReoptimization, 250); + // Do range checks where needed and make corrections to the options: + ASSERT(thresholdForOptimizeAfterLongWarmUp() >= thresholdForOptimizeAfterWarmUp()); + ASSERT(thresholdForOptimizeAfterWarmUp() >= thresholdForOptimizeSoon()); + ASSERT(thresholdForOptimizeAfterWarmUp() >= 0); - SET(reoptimizationRetryCounterStep, 1); - - SET(minimumOptimizationDelay, 1); - SET(maximumOptimizationDelay, 5); - SET(desiredProfileLivenessRate, 0.75); - SET(desiredProfileFullnessRate, 0.35); - - SET(doubleVoteRatioForDoubleFormat, 2); - - SET(minimumNumberOfScansBetweenRebalance, 100); - SET(gcMarkStackSegmentSize, pageSize()); - SET(opaqueRootMergeThreshold, 1000); - SET(numberOfGCMarkers, computeNumberOfGCMarkers(7)); // We don't scale so well beyond 7. - - ASSERT(thresholdForOptimizeAfterLongWarmUp >= thresholdForOptimizeAfterWarmUp); - ASSERT(thresholdForOptimizeAfterWarmUp >= thresholdForOptimizeSoon); - ASSERT(thresholdForOptimizeAfterWarmUp >= 0); - // Compute the maximum value of the reoptimization retry counter. This is simply // the largest value at which we don't overflow the execute counter, when using it // to left-shift the execution counter by this amount. Currently the value ends // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles // total on a 32-bit processor. - reoptimizationRetryCounterMax = 0; - while ((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << (reoptimizationRetryCounterMax + 1)) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max())) - reoptimizationRetryCounterMax++; - - ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) > 0); - ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max())); - - SET(forceWeakRandomSeed, false); - SET(forcedWeakRandomSeed, 0); + reoptimizationRetryCounterMax() = 0; + while ((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << (reoptimizationRetryCounterMax() + 1)) <= static_cast<int64_t>(std::numeric_limits<int32>::max())) + reoptimizationRetryCounterMax()++; + + ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << reoptimizationRetryCounterMax()) > 0); + ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << reoptimizationRetryCounterMax()) <= static_cast<int64_t>(std::numeric_limits<int32>::max())); } -} } // namespace JSC::Options +// Parses a single command line option in the format "<optionName>=<value>" +// (no spaces allowed) and set the specified option if appropriate. +bool Options::setOption(const char* arg) +{ + // arg should look like this: + // <jscOptionName>=<appropriate value> + const char* equalStr = strchr(arg, '='); + if (!equalStr) + return false; + + const char* valueStr = equalStr + 1; + + // For each option, check if the specify arg is a match. If so, set the arg + // if the value makes sense. Otherwise, move on to checking the next option. +#define FOR_EACH_OPTION(type_, name_, defaultValue_) \ + if (!strncmp(arg, #name_, equalStr - arg)) { \ + type_ value; \ + bool success = parse(valueStr, value); \ + if (success) { \ + name_() = value; \ + return true; \ + } \ + return false; \ + } + + JSC_OPTIONS(FOR_EACH_OPTION) +#undef FOR_EACH_OPTION + + return false; // No option matched. +} + +void Options::dumpAllOptions(FILE* stream) +{ + fprintf(stream, "JSC runtime options:\n"); + for (int id = 0; id < numberOfOptions; id++) + dumpOption(static_cast<OptionID>(id), stream, " ", "\n"); +} + +void Options::dumpOption(OptionID id, FILE* stream, const char* header, const char* footer) +{ + if (id >= numberOfOptions) + return; // Illegal option. + + fprintf(stream, "%s%s: ", header, s_optionsInfo[id].name); + switch (s_optionsInfo[id].type) { + case boolType: + fprintf(stream, "%s", s_options[id].u.boolVal?"true":"false"); + break; + case unsignedType: + fprintf(stream, "%u", s_options[id].u.unsignedVal); + break; + case doubleType: + fprintf(stream, "%lf", s_options[id].u.doubleVal); + break; + case int32Type: + fprintf(stream, "%d", s_options[id].u.int32Val); + break; + } + fprintf(stream, "%s", footer); +} +} // namespace JSC |