2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "Heuristics.h"
28 #include <wtf/PageBlock.h>
32 #if OS(DARWIN) && ENABLE(PARALLEL_GC)
33 #include <sys/sysctl.h>
36 // Set to 1 to control the heuristics using environment variables.
37 #define ENABLE_RUN_TIME_HEURISTICS 0
39 #if ENABLE(RUN_TIME_HEURISTICS)
42 #include <wtf/StdLibExtras.h>
45 namespace JSC { namespace Heuristics {
47 unsigned maximumOptimizationCandidateInstructionCount;
49 unsigned maximumFunctionForCallInlineCandidateInstructionCount;
50 unsigned maximumFunctionForConstructInlineCandidateInstructionCount;
52 unsigned maximumInliningDepth;
54 int32_t executionCounterValueForOptimizeAfterWarmUp;
55 int32_t executionCounterValueForOptimizeAfterLongWarmUp;
56 int32_t executionCounterValueForDontOptimizeAnytimeSoon;
57 int32_t executionCounterValueForOptimizeSoon;
58 int32_t executionCounterValueForOptimizeNextInvocation;
60 int32_t executionCounterIncrementForLoop;
61 int32_t executionCounterIncrementForReturn;
63 unsigned desiredSpeculativeSuccessFailRatio;
65 unsigned likelyToTakeSlowCaseThreshold;
66 unsigned couldTakeSlowCaseThreshold;
68 unsigned largeFailCountThresholdBase;
69 unsigned largeFailCountThresholdBaseForLoop;
71 unsigned reoptimizationRetryCounterMax;
72 unsigned reoptimizationRetryCounterStep;
74 unsigned minimumOptimizationDelay;
75 unsigned maximumOptimizationDelay;
76 double desiredProfileLivenessRate;
77 double desiredProfileFullnessRate;
79 unsigned minimumNumberOfScansBetweenRebalance;
80 unsigned gcMarkStackSegmentSize;
81 unsigned minimumNumberOfCellsToKeep;
82 unsigned maximumNumberOfSharedSegments;
83 unsigned sharedStackWakeupThreshold;
84 unsigned numberOfGCMarkers;
85 unsigned opaqueRootMergeThreshold;
87 #if ENABLE(RUN_TIME_HEURISTICS)
88 static bool parse(const char* string, int32_t& value)
90 return sscanf(string, "%d", &value) == 1;
93 static bool parse(const char* string, unsigned& value)
95 return sscanf(string, "%u", &value) == 1;
98 static bool parse(const char* string, double& value)
100 return sscanf(string, "%lf", &value) == 1;
103 template<typename T, typename U>
104 void setHeuristic(T& variable, const char* name, U value)
106 const char* stringValue = getenv(name);
108 variable = safeCast<T>(value);
112 if (parse(stringValue, variable))
115 fprintf(stderr, "WARNING: failed to parse %s=%s\n", name, stringValue);
116 variable = safeCast<T>(value);
119 #define SET(variable, value) setHeuristic(variable, "JSC_" #variable, value)
121 #define SET(variable, value) variable = value
124 void initializeHeuristics()
126 SET(maximumOptimizationCandidateInstructionCount, 1000);
128 SET(maximumFunctionForCallInlineCandidateInstructionCount, 150);
129 SET(maximumFunctionForConstructInlineCandidateInstructionCount, 80);
131 SET(maximumInliningDepth, 5);
133 SET(executionCounterValueForOptimizeAfterWarmUp, -1000);
134 SET(executionCounterValueForOptimizeAfterLongWarmUp, -5000);
135 SET(executionCounterValueForDontOptimizeAnytimeSoon, std::numeric_limits<int32_t>::min());
136 SET(executionCounterValueForOptimizeSoon, -1000);
137 SET(executionCounterValueForOptimizeNextInvocation, 0);
139 SET(executionCounterIncrementForLoop, 1);
140 SET(executionCounterIncrementForReturn, 15);
142 SET(desiredSpeculativeSuccessFailRatio, 6);
144 SET(likelyToTakeSlowCaseThreshold, 100);
145 SET(couldTakeSlowCaseThreshold, 10); // Shouldn't be zero because some ops will spuriously take slow case, for example for linking or caching.
147 SET(largeFailCountThresholdBase, 20);
148 SET(largeFailCountThresholdBaseForLoop, 1);
150 SET(reoptimizationRetryCounterStep, 1);
152 SET(minimumOptimizationDelay, 1);
153 SET(maximumOptimizationDelay, 5);
154 SET(desiredProfileLivenessRate, 0.75);
155 SET(desiredProfileFullnessRate, 0.35);
157 SET(minimumNumberOfScansBetweenRebalance, 10000);
158 SET(gcMarkStackSegmentSize, pageSize());
159 SET(minimumNumberOfCellsToKeep, 10);
160 SET(maximumNumberOfSharedSegments, 3);
161 SET(sharedStackWakeupThreshold, 1);
162 SET(opaqueRootMergeThreshold, 1000);
165 #if OS(DARWIN) && ENABLE(PARALLEL_GC)
167 size_t valueSize = sizeof(cpusToUse);
169 name[1] = HW_AVAILCPU;
170 sysctl(name, 2, &cpusToUse, &valueSize, 0, 0);
172 // We don't scale so well beyond 4.
175 // Be paranoid, it is the OS we're dealing with, after all.
179 SET(numberOfGCMarkers, cpusToUse);
181 ASSERT(executionCounterValueForDontOptimizeAnytimeSoon <= executionCounterValueForOptimizeAfterLongWarmUp);
182 ASSERT(executionCounterValueForOptimizeAfterLongWarmUp <= executionCounterValueForOptimizeAfterWarmUp);
183 ASSERT(executionCounterValueForOptimizeAfterWarmUp <= executionCounterValueForOptimizeSoon);
184 ASSERT(executionCounterValueForOptimizeAfterWarmUp < 0);
185 ASSERT(executionCounterValueForOptimizeSoon <= executionCounterValueForOptimizeNextInvocation);
187 // Compute the maximum value of the reoptimization retry counter. This is simply
188 // the largest value at which we don't overflow the execute counter, when using it
189 // to left-shift the execution counter by this amount. Currently the value ends
190 // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles
191 // total on a 32-bit processor.
192 reoptimizationRetryCounterMax = 0;
193 while ((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << (reoptimizationRetryCounterMax + 1)) >= static_cast<int64_t>(std::numeric_limits<int32_t>::min()))
194 reoptimizationRetryCounterMax++;
196 ASSERT((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) < 0);
197 ASSERT((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) >= static_cast<int64_t>(std::numeric_limits<int32_t>::min()));
200 } } // namespace JSC::Heuristics