Options.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  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.
  12. *
  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.
  24. */
  25. #include "config.h"
  26. #include "Options.h"
  27. #include "HeapStatistics.h"
  28. #include <algorithm>
  29. #include <limits>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <wtf/NumberOfCores.h>
  34. #include <wtf/PageBlock.h>
  35. #include <wtf/StdLibExtras.h>
  36. #include <wtf/StringExtras.h>
  37. #if OS(DARWIN) && ENABLE(PARALLEL_GC)
  38. #include <sys/sysctl.h>
  39. #endif
  40. #if OS(PSP2)
  41. #include <unistd.h>
  42. #endif
  43. namespace JSC {
  44. static bool parse(const char* string, bool& value)
  45. {
  46. if (!strcasecmp(string, "true") || !strcasecmp(string, "yes") || !strcmp(string, "1")) {
  47. value = true;
  48. return true;
  49. }
  50. if (!strcasecmp(string, "false") || !strcasecmp(string, "no") || !strcmp(string, "0")) {
  51. value = false;
  52. return true;
  53. }
  54. return false;
  55. }
  56. static bool parse(const char* string, int32_t& value)
  57. {
  58. return sscanf(string, "%d", &value) == 1;
  59. }
  60. static bool parse(const char* string, unsigned& value)
  61. {
  62. return sscanf(string, "%u", &value) == 1;
  63. }
  64. static bool parse(const char* string, double& value)
  65. {
  66. return sscanf(string, "%lf", &value) == 1;
  67. }
  68. static bool parse(const char* string, OptionRange& value)
  69. {
  70. return value.init(string);
  71. }
  72. template<typename T>
  73. void overrideOptionWithHeuristic(T& variable, const char* name)
  74. {
  75. #if !OS(WINCE) && !OS(ORBIS)
  76. const char* stringValue = getenv(name);
  77. if (!stringValue)
  78. return;
  79. if (parse(stringValue, variable))
  80. return;
  81. fprintf(stderr, "WARNING: failed to parse %s=%s\n", name, stringValue);
  82. #endif
  83. }
  84. static unsigned computeNumberOfGCMarkers(int maxNumberOfGCMarkers)
  85. {
  86. int cpusToUse = 1;
  87. #if ENABLE(PARALLEL_GC)
  88. cpusToUse = std::min(WTF::numberOfProcessorCores(), maxNumberOfGCMarkers);
  89. // Be paranoid, it is the OS we're dealing with, after all.
  90. ASSERT(cpusToUse >= 1);
  91. if (cpusToUse < 1)
  92. cpusToUse = 1;
  93. #else
  94. UNUSED_PARAM(maxNumberOfGCMarkers);
  95. #endif
  96. return cpusToUse;
  97. }
  98. bool OptionRange::init(const char* rangeString)
  99. {
  100. // rangeString should be in the form of [!]<low>[:<high>]
  101. // where low and high are unsigned
  102. bool invert = false;
  103. if (m_state > Uninitialized)
  104. return true;
  105. if (!rangeString) {
  106. m_state = InitError;
  107. return false;
  108. }
  109. m_rangeString = rangeString;
  110. if (*rangeString == '!') {
  111. invert = true;
  112. rangeString++;
  113. }
  114. int scanResult = sscanf(rangeString, " %u:%u", &m_lowLimit, &m_highLimit);
  115. if (!scanResult || scanResult == EOF) {
  116. m_state = InitError;
  117. return false;
  118. }
  119. if (scanResult == 1)
  120. m_highLimit = m_lowLimit;
  121. if (m_lowLimit > m_highLimit) {
  122. m_state = InitError;
  123. return false;
  124. }
  125. m_state = invert ? Inverted : Normal;
  126. return true;
  127. }
  128. bool OptionRange::isInRange(unsigned count)
  129. {
  130. if (m_state < Normal)
  131. return true;
  132. if ((m_lowLimit <= count) && (count <= m_highLimit))
  133. return m_state == Normal ? true : false;
  134. return m_state == Normal ? false : true;
  135. }
  136. Options::Entry Options::s_options[Options::numberOfOptions];
  137. // Realize the names for each of the options:
  138. const Options::EntryInfo Options::s_optionsInfo[Options::numberOfOptions] = {
  139. #define FOR_EACH_OPTION(type_, name_, defaultValue_) \
  140. { #name_, Options::type_##Type },
  141. JSC_OPTIONS(FOR_EACH_OPTION)
  142. #undef FOR_EACH_OPTION
  143. };
  144. void Options::initialize()
  145. {
  146. // Initialize each of the options with their default values:
  147. #define FOR_EACH_OPTION(type_, name_, defaultValue_) \
  148. name_() = defaultValue_;
  149. JSC_OPTIONS(FOR_EACH_OPTION)
  150. #undef FOR_EACH_OPTION
  151. #if (USE(CF) || OS(UNIX)) && !OS(ORBIS)
  152. objectsAreImmortal() = !!getenv("JSImmortalZombieEnabled");
  153. useZombieMode() = !!getenv("JSImmortalZombieEnabled") || !!getenv("JSZombieEnabled");
  154. gcMaxHeapSize() = getenv("GCMaxHeapSize") ? HeapStatistics::parseMemoryAmount(getenv("GCMaxHeapSize")) : 0;
  155. recordGCPauseTimes() = !!getenv("JSRecordGCPauseTimes");
  156. logHeapStatisticsAtExit() = gcMaxHeapSize() || recordGCPauseTimes();
  157. #endif
  158. // Allow environment vars to override options if applicable.
  159. // The evn var should be the name of the option prefixed with
  160. // "JSC_".
  161. #define FOR_EACH_OPTION(type_, name_, defaultValue_) \
  162. overrideOptionWithHeuristic(name_(), "JSC_" #name_);
  163. JSC_OPTIONS(FOR_EACH_OPTION)
  164. #undef FOR_EACH_OPTION
  165. #if 0
  166. ; // Deconfuse editors that do auto indentation
  167. #endif
  168. #if !ENABLE(JIT)
  169. useJIT() = false;
  170. useDFGJIT() = false;
  171. #endif
  172. #if !ENABLE(YARR_JIT)
  173. useRegExpJIT() = false;
  174. #endif
  175. // Do range checks where needed and make corrections to the options:
  176. ASSERT(thresholdForOptimizeAfterLongWarmUp() >= thresholdForOptimizeAfterWarmUp());
  177. ASSERT(thresholdForOptimizeAfterWarmUp() >= thresholdForOptimizeSoon());
  178. ASSERT(thresholdForOptimizeAfterWarmUp() >= 0);
  179. // Compute the maximum value of the reoptimization retry counter. This is simply
  180. // the largest value at which we don't overflow the execute counter, when using it
  181. // to left-shift the execution counter by this amount. Currently the value ends
  182. // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles
  183. // total on a 32-bit processor.
  184. reoptimizationRetryCounterMax() = 0;
  185. while ((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << (reoptimizationRetryCounterMax() + 1)) <= static_cast<int64_t>(std::numeric_limits<int32>::max()))
  186. reoptimizationRetryCounterMax()++;
  187. ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << reoptimizationRetryCounterMax()) > 0);
  188. ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp()) << reoptimizationRetryCounterMax()) <= static_cast<int64_t>(std::numeric_limits<int32>::max()));
  189. }
  190. // Parses a single command line option in the format "<optionName>=<value>"
  191. // (no spaces allowed) and set the specified option if appropriate.
  192. bool Options::setOption(const char* arg)
  193. {
  194. // arg should look like this:
  195. // <jscOptionName>=<appropriate value>
  196. const char* equalStr = strchr(arg, '=');
  197. if (!equalStr)
  198. return false;
  199. const char* valueStr = equalStr + 1;
  200. // For each option, check if the specify arg is a match. If so, set the arg
  201. // if the value makes sense. Otherwise, move on to checking the next option.
  202. #define FOR_EACH_OPTION(type_, name_, defaultValue_) \
  203. if (!strncmp(arg, #name_, equalStr - arg)) { \
  204. type_ value; \
  205. value = 0; \
  206. bool success = parse(valueStr, value); \
  207. if (success) { \
  208. name_() = value; \
  209. return true; \
  210. } \
  211. return false; \
  212. }
  213. JSC_OPTIONS(FOR_EACH_OPTION)
  214. #undef FOR_EACH_OPTION
  215. return false; // No option matched.
  216. }
  217. void Options::dumpAllOptions(FILE* stream)
  218. {
  219. fprintf(stream, "JSC runtime options:\n");
  220. for (int id = 0; id < numberOfOptions; id++)
  221. dumpOption(static_cast<OptionID>(id), stream, " ", "\n");
  222. }
  223. void Options::dumpOption(OptionID id, FILE* stream, const char* header, const char* footer)
  224. {
  225. if (id >= numberOfOptions)
  226. return; // Illegal option.
  227. fprintf(stream, "%s%s: ", header, s_optionsInfo[id].name);
  228. switch (s_optionsInfo[id].type) {
  229. case boolType:
  230. fprintf(stream, "%s", s_options[id].u.boolVal?"true":"false");
  231. break;
  232. case unsignedType:
  233. fprintf(stream, "%u", s_options[id].u.unsignedVal);
  234. break;
  235. case doubleType:
  236. fprintf(stream, "%lf", s_options[id].u.doubleVal);
  237. break;
  238. case int32Type:
  239. fprintf(stream, "%d", s_options[id].u.int32Val);
  240. break;
  241. case optionRangeType:
  242. fprintf(stream, "%s", s_options[id].u.optionRangeVal.rangeString());
  243. break;
  244. }
  245. fprintf(stream, "%s", footer);
  246. }
  247. } // namespace JSC