blob: ddfba6e7c44d33939073858839f44132aca7ae0c [file] [log] [blame]
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "Options.h"
#include <limits>
#include <wtf/NumberOfCores.h>
#include <wtf/PageBlock.h>
#if OS(DARWIN) && ENABLE(PARALLEL_GC)
#include <sys/sysctl.h>
#endif
// 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 {
unsigned maximumOptimizationCandidateInstructionCount;
unsigned maximumFunctionForCallInlineCandidateInstructionCount;
unsigned maximumFunctionForConstructInlineCandidateInstructionCount;
unsigned maximumInliningDepth;
int32_t executionCounterValueForOptimizeAfterWarmUp;
int32_t executionCounterValueForOptimizeAfterLongWarmUp;
int32_t executionCounterValueForDontOptimizeAnytimeSoon;
int32_t executionCounterValueForOptimizeSoon;
int32_t executionCounterValueForOptimizeNextInvocation;
int32_t executionCounterIncrementForLoop;
int32_t executionCounterIncrementForReturn;
unsigned desiredSpeculativeSuccessFailRatio;
double likelyToTakeSlowCaseThreshold;
double couldTakeSlowCaseThreshold;
unsigned likelyToTakeSlowCaseMinimumCount;
unsigned couldTakeSlowCaseMinimumCount;
double osrExitProminenceForFrequentExitSite;
unsigned largeFailCountThresholdBase;
unsigned largeFailCountThresholdBaseForLoop;
unsigned reoptimizationRetryCounterMax;
unsigned reoptimizationRetryCounterStep;
unsigned minimumOptimizationDelay;
unsigned maximumOptimizationDelay;
double desiredProfileLivenessRate;
double desiredProfileFullnessRate;
double doubleVoteRatioForDoubleFormat;
unsigned minimumNumberOfScansBetweenRebalance;
unsigned gcMarkStackSegmentSize;
unsigned minimumNumberOfCellsToKeep;
unsigned maximumNumberOfSharedSegments;
unsigned sharedStackWakeupThreshold;
unsigned numberOfGCMarkers;
unsigned opaqueRootMergeThreshold;
#if ENABLE(RUN_TIME_HEURISTICS)
static bool parse(const char* string, int32_t& value)
{
return sscanf(string, "%d", &value) == 1;
}
static bool parse(const char* string, unsigned& value)
{
return sscanf(string, "%u", &value) == 1;
}
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)
{
const char* stringValue = getenv(name);
if (!stringValue) {
variable = safeCast<T>(value);
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
void initializeOptions()
{
SET(maximumOptimizationCandidateInstructionCount, 1100);
SET(maximumFunctionForCallInlineCandidateInstructionCount, 180);
SET(maximumFunctionForConstructInlineCandidateInstructionCount, 100);
SET(maximumInliningDepth, 5);
SET(executionCounterValueForOptimizeAfterWarmUp, -1000);
SET(executionCounterValueForOptimizeAfterLongWarmUp, -5000);
SET(executionCounterValueForDontOptimizeAnytimeSoon, std::numeric_limits<int32_t>::min());
SET(executionCounterValueForOptimizeSoon, -1000);
SET(executionCounterValueForOptimizeNextInvocation, 0);
SET(executionCounterIncrementForLoop, 1);
SET(executionCounterIncrementForReturn, 15);
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);
SET(osrExitProminenceForFrequentExitSite, 0.3);
SET(largeFailCountThresholdBase, 20);
SET(largeFailCountThresholdBaseForLoop, 1);
SET(reoptimizationRetryCounterStep, 1);
SET(minimumOptimizationDelay, 1);
SET(maximumOptimizationDelay, 5);
SET(desiredProfileLivenessRate, 0.75);
SET(desiredProfileFullnessRate, 0.35);
SET(doubleVoteRatioForDoubleFormat, 2);
SET(minimumNumberOfScansBetweenRebalance, 10000);
SET(gcMarkStackSegmentSize, pageSize());
SET(minimumNumberOfCellsToKeep, 10);
SET(maximumNumberOfSharedSegments, 3);
SET(sharedStackWakeupThreshold, 1);
SET(opaqueRootMergeThreshold, 1000);
int cpusToUse = 1;
#if ENABLE(PARALLEL_GC)
cpusToUse = WTF::numberOfProcessorCores();
#endif
// We don't scale so well beyond 4.
if (cpusToUse > 4)
cpusToUse = 4;
// Be paranoid, it is the OS we're dealing with, after all.
if (cpusToUse < 1)
cpusToUse = 1;
SET(numberOfGCMarkers, cpusToUse);
ASSERT(executionCounterValueForDontOptimizeAnytimeSoon <= executionCounterValueForOptimizeAfterLongWarmUp);
ASSERT(executionCounterValueForOptimizeAfterLongWarmUp <= executionCounterValueForOptimizeAfterWarmUp);
ASSERT(executionCounterValueForOptimizeAfterWarmUp <= executionCounterValueForOptimizeSoon);
ASSERT(executionCounterValueForOptimizeAfterWarmUp < 0);
ASSERT(executionCounterValueForOptimizeSoon <= executionCounterValueForOptimizeNextInvocation);
// 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>(executionCounterValueForOptimizeAfterLongWarmUp) << (reoptimizationRetryCounterMax + 1)) >= static_cast<int64_t>(std::numeric_limits<int32_t>::min()))
reoptimizationRetryCounterMax++;
ASSERT((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) < 0);
ASSERT((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) >= static_cast<int64_t>(std::numeric_limits<int32_t>::min()));
}
} } // namespace JSC::Options