Changeset 251226 in webkit
- Timestamp:
- Oct 16, 2019 10:45:58 PM (5 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 deleted
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/glib/JSCOptions.cpp
r250278 r251226 169 169 #define SET_OPTION_VALUE(type_, name_, defaultValue_, availability_, description_) \ 170 170 if (!g_strcmp0(#name_, option)) { \ 171 Option Entry::type_ valueToSet; \171 OptionTypes::type_ valueToSet; \ 172 172 if (!valueFromGValue(value, valueToSet)) \ 173 173 return FALSE; \ … … 187 187 #define GET_OPTION_VALUE(type_, name_, defaultValue_, availability_, description_) \ 188 188 if (!g_strcmp0(#name_, option)) { \ 189 Option Entry::type_ valueToGet = Options::name_(); \189 OptionTypes::type_ valueToGet = Options::name_(); \ 190 190 valueToGValue(valueToGet, value); \ 191 191 return TRUE; \ … … 617 617 #define VISIT_OPTION(type_, name_, defaultValue_, availability_, description_) \ 618 618 if (Options::Availability::availability_ == Options::Availability::Normal \ 619 || Options::isAvailable(Option s::name_##ID, Options::Availability::availability_)) { \620 Option Entry::type_ defaultValue { }; \619 || Options::isAvailable(OptionID::name_, Options::Availability::availability_)) { \ 620 OptionTypes::type_ defaultValue { }; \ 621 621 auto optionType = jscOptionsType(defaultValue); \ 622 622 if (function (#name_, optionType, description_, userData)) \ … … 667 667 #define REGISTER_OPTION(type_, name_, defaultValue_, availability_, description_) \ 668 668 if (Options::Availability::availability_ == Options::Availability::Normal \ 669 || Options::isAvailable(Option s::name_##ID, Options::Availability::availability_)) { \669 || Options::isAvailable(OptionID::name_, Options::Availability::availability_)) { \ 670 670 GUniquePtr<char> name(g_strdup_printf("jsc-%s", #name_)); \ 671 671 entries = g_array_set_size(entries, entries->len + 1); \ -
trunk/Source/JavaScriptCore/CMakeLists.txt
r250289 r251226 921 921 runtime/ObjectPrototype.h 922 922 runtime/Operations.h 923 runtime/OptionEntry.h924 923 runtime/Options.h 925 924 runtime/OptionsList.h -
trunk/Source/JavaScriptCore/ChangeLog
r251209 r251226 1 2019-10-16 Mark Lam <mark.lam@apple.com> 2 3 Reduce the amount of memory needed to store Options. 4 https://bugs.webkit.org/show_bug.cgi?id=202105 5 6 Reviewed by Yusuke Suzuki. 7 8 The size of the JSC::Config needed to store the Options is now reduced to 4K 9 instead of 16K, enabled by constexpr template magic. 10 11 1. Instead of all options in a large array of OptionEntry (which is a union of 12 all the option types), we now have separate arrays for each of the types of 13 options. For example, 14 15 Removed g_jscConfig.options[]. 16 Added g_jscConfig.typeBoolOptions[]. 17 Added g_jscConfig.typeInt32Options[]. 18 Added g_jscConfig.typeDoubleOptions[]. 19 ... 20 21 We used to find the storage for the option using g_jscConfig.options[Options::ID]. 22 We now find the storage for each type of option using 23 g_jscConfig.options[optionTypeSpecificIndex<OptionTypeID, OptionID>()]. For 24 example, Options::useJIT() used to be implemented as: 25 26 inline bool& Options::useJIT() 27 { 28 return g_jscConfig.options[Options::useJITID]; 29 } 30 31 ... which is now replaced with: 32 33 inline bool& Options::useJIT() 34 { 35 return g_jscConfig.typeBoolOptions[optionTypeSpecificIndex<OptionTypeID::Bool, OptionID::useJIT>()]; 36 } 37 38 MSVC has a bug where it cannot handle very large source files: see 39 https://developercommunity.visualstudio.com/content/problem/653301/fatal-error-c1002-compiler-is-out-of-heap-space-in.html. 40 This bug prevents this patch from building on MSVC. To workaround this bug, 41 we don't inline the Options accessors when COMPILER(MSVC). This prevents MSVC 42 from having to parse the large body of template code code to used to implement 43 the inline accessors in every file that #include "Options.h". 44 45 Also add the @no-unify attribute to Options.cpp (where we put the accessors) 46 so that it doesn't trigger the MSVC bug also. 47 48 2. Introduce the optionTypeSpecificIndex() constexpr template function for 49 computing the index of each option in their respective type specific options 50 array. 51 52 3. Introduce OptionTypes, OptionTypeID, and OptionID. 53 54 The OptionTypes namespace replaces OptionEntry as the container of option types. 55 The OptionID enum class replaces Options::ID. 56 The OptionTypeID enum class is new and is used together with OptionID in 57 constexpr templates to compute the typeSpecificIndex of options. 58 59 4. Removed the OptionEntry struct and OptionEntry.h. After (1), this struct is 60 only used in the Option class. We just moved the union of option types (that 61 OptionEntry embeds) into the Option class. 62 63 Moved class OptionRange into OptionsList.h. 64 65 5. Removed the large OptionEntry arrays from JSC::Config. 66 Added type specific options arrays. 67 Also ordered these arrays to maximize compactness and minimize internal fragmentation. 68 69 6. Changed scaleJITPolicy() to go directly to g_jscConfig.typeInt32Options[] 70 instead of going through the Option wrapper object. This allows us to simplify 71 things and make the Option class a read only interface of options. 72 73 7. Changed Options::initialize() to only compute the option default value once. 74 The default value specified in the OptionsList may not always be a constant. 75 Sometimes, it is a function call. 76 77 8. The Option class now only gives read only access to the options. 78 79 The Option class' role is to provide an interface for reading an option at any 80 given OptionID without first knowing about the type of the specific option. 81 It is useful for iterating options, and is currently only used by 82 Options::dumpOption(). 83 84 Technically, we could merge all the Option class code into its single client. 85 We opted not to do this because the amount of code is non-trivial, and the 86 Option class does a good job of encapsulating this functionality. 87 88 * API/glib/JSCOptions.cpp: 89 (jscOptionsSetValue): 90 (jscOptionsGetValue): 91 (jsc_options_foreach): 92 (jsc_options_get_option_group): 93 * CMakeLists.txt: 94 * JavaScriptCore.xcodeproj/project.pbxproj: 95 * Sources.txt: 96 * runtime/JSCConfig.h: 97 * runtime/OptionEntry.h: Removed. 98 * runtime/Options.cpp: 99 (JSC::Options::isAvailable): 100 (JSC::overrideOptionWithHeuristic): 101 (JSC::optionTypeSpecificIndex): 102 (JSC::scaleJITPolicy): 103 (JSC::recomputeDependentOptions): 104 (JSC::Options::initialize): 105 (JSC::Options::setOptionWithoutAlias): 106 (JSC::Options::dumpAllOptions): 107 (JSC::Options::dumpOption): 108 (JSC::Option::Option): 109 (JSC::Option::defaultOption const): 110 (JSC::Option::dump const): 111 (JSC::Option::operator== const): 112 * runtime/Options.h: 113 (JSC::Option::id const): 114 (JSC::Option::name const): 115 (JSC::Option::description const): 116 (JSC::Option::type const): 117 (JSC::Option::availability const): 118 (JSC::Option::isOverridden const): 119 (JSC::Option::Option): 120 (JSC::Option::idIndex const): 121 (JSC::optionTypeSpecificIndex): 122 (JSC::Option::defaultOption const): Deleted. 123 (JSC::Option::boolVal): Deleted. 124 (JSC::Option::unsignedVal): Deleted. 125 (JSC::Option::doubleVal): Deleted. 126 (JSC::Option::int32Val): Deleted. 127 (JSC::Option::optionRangeVal): Deleted. 128 (JSC::Option::optionStringVal): Deleted. 129 (JSC::Option::gcLogLevelVal): Deleted. 130 * runtime/OptionsList.h: 131 (JSC::OptionRange::operator= ): 132 (JSC::OptionRange::rangeString const): 133 (JSC::countNumberOfJSCOptionsOfType): 134 1 135 2019-10-16 Keith Miller <keith_miller@apple.com> 2 136 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r251036 r251226 1865 1865 FE1BD0251E72053800134BC9 /* HeapVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1BD0231E72052F00134BC9 /* HeapVerifier.h */; }; 1866 1866 FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1C0FFC1B193E9800B53FCA /* Exception.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1867 FE1D6D4523580E1F007A5C26 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; }; 1867 1868 FE1E2C3F2240DD5800F6B729 /* MacroAssemblerARM64E.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1E2C3E2240D30B00F6B729 /* MacroAssemblerARM64E.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1868 1869 FE1E2C402240DD6200F6B729 /* ARM64EAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1E2C3D2240D2F600F6B729 /* ARM64EAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1873 1874 FE318FE01CAC982F00DFCC54 /* ECMAScriptSpecInternalFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = FE318FDE1CAC8C5300DFCC54 /* ECMAScriptSpecInternalFunctions.h */; }; 1874 1875 FE3422121D6B81C30032BE88 /* ThrowScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3422111D6B818C0032BE88 /* ThrowScope.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1875 FE3842322324D51B009DD445 /* OptionEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3842302324D51A009DD445 /* OptionEntry.h */; settings = {ATTRIBUTES = (Private, ); }; };1876 1876 FE3842332324D51B009DD445 /* OptionsList.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3842312324D51B009DD445 /* OptionsList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1877 1877 FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 5074 5074 FE35C2FB21B1E6C7000F4CA8 /* OpcodeGroup.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = OpcodeGroup.rb; sourceTree = "<group>"; }; 5075 5075 FE35C2FC21B1E6C7000F4CA8 /* Metadata.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = Metadata.rb; sourceTree = "<group>"; }; 5076 FE3842302324D51A009DD445 /* OptionEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionEntry.h; sourceTree = "<group>"; };5077 5076 FE3842312324D51B009DD445 /* OptionsList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionsList.h; sourceTree = "<group>"; }; 5078 5077 FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVM.cpp; sourceTree = "<group>"; }; … … 7383 7382 F692A8770255597D01FF60F7 /* Operations.cpp */, 7384 7383 F692A8780255597D01FF60F7 /* Operations.h */, 7385 FE3842302324D51A009DD445 /* OptionEntry.h */,7386 7384 0FE228EA1436AB2300196C48 /* Options.cpp */, 7387 7385 0FE228EB1436AB2300196C48 /* Options.h */, … … 9906 9904 A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */, 9907 9905 BC18C4480E16F5CD00B34460 /* Operations.h in Headers */, 9908 FE3842322324D51B009DD445 /* OptionEntry.h in Headers */,9909 9906 0FE228ED1436AB2700196C48 /* Options.h in Headers */, 9910 9907 FE3842332324D51B009DD445 /* OptionsList.h in Headers */, … … 11135 11132 536B315C1F71C5990037FC33 /* UnifiedSource88.cpp in Sources */, 11136 11133 536B31621F71C5990037FC33 /* UnifiedSource89.cpp in Sources */, 11134 FE1D6D4523580E1F007A5C26 /* Options.cpp in Sources */, 11137 11135 536B31421F71C5990037FC33 /* UnifiedSource90.cpp in Sources */, 11138 11136 536B31491F71C5990037FC33 /* UnifiedSource91.cpp in Sources */, -
trunk/Source/JavaScriptCore/Sources.txt
r251036 r251226 905 905 runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp 906 906 runtime/Operations.cpp 907 runtime/Options.cpp 907 runtime/Options.cpp @no-unify 908 908 runtime/ProgramExecutable.cpp 909 909 runtime/PromiseDeferredTimer.cpp -
trunk/Source/JavaScriptCore/runtime/JSCConfig.h
r250559 r251226 26 26 #pragma once 27 27 28 #include "OptionEntry.h"29 28 #include "OptionsList.h" 30 29 #include <wtf/StdLibExtras.h> … … 37 36 #if CPU(ARM64) || PLATFORM(WATCHOS) 38 37 constexpr size_t PageSize = 16 * KB; 38 constexpr size_t ConfigSizeToProtect = 1 * PageSize; 39 39 #else 40 40 constexpr size_t PageSize = 4 * KB; 41 constexpr size_t ConfigSizeToProtect = 1 * PageSize; 41 42 #endif 42 43 constexpr size_t ConfigSizeToProtect = 32 * KB;44 43 45 44 #if ENABLE(SEPARATED_WX_HEAP) … … 83 82 #endif 84 83 85 OptionEntry options[NumberOfOptions]; 86 OptionEntry defaultOptions[NumberOfOptions]; 84 bool typeBoolOptions[NumberOfBoolOptions]; 85 bool typeBoolDefaultOptions[NumberOfBoolOptions]; 86 87 GCLogging::Level typeGCLogLevelOptions[NumberOfGCLogLevelOptions]; 88 GCLogging::Level typeGCLogLevelDefaultOptions[NumberOfGCLogLevelOptions]; 89 90 int32_t typeInt32Options[NumberOfInt32Options]; 91 int32_t typeInt32DefaultOptions[NumberOfInt32Options]; 92 93 unsigned typeUnsignedOptions[NumberOfUnsignedOptions]; 94 unsigned typeUnsignedDefaultOptions[NumberOfUnsignedOptions]; 95 96 double typeDoubleOptions[NumberOfDoubleOptions]; 97 double typeDoubleDefaultOptions[NumberOfDoubleOptions]; 98 99 size_t typeSizeOptions[NumberOfSizeOptions]; 100 size_t typeSizeDefaultOptions[NumberOfSizeOptions]; 101 102 const char* typeOptionStringOptions[NumberOfOptionStringOptions]; 103 const char* typeOptionStringDefaultOptions[NumberOfOptionStringOptions]; 104 105 OptionRange typeOptionRangeOptions[NumberOfOptionRangeOptions]; 106 OptionRange typeOptionRangeDefaultOptions[NumberOfOptionRangeOptions]; 87 107 }; 88 108 char ensureSize[ConfigSizeToProtect]; -
trunk/Source/JavaScriptCore/runtime/Options.cpp
r250285 r251226 133 133 } 134 134 135 bool Options::isAvailable(Option s::ID id, Options::Availability availability)135 bool Options::isAvailable(OptionID id, Options::Availability availability) 136 136 { 137 137 if (availability == Availability::Restricted) … … 141 141 UNUSED_PARAM(id); 142 142 #if !defined(NDEBUG) 143 if (id == maxSingleAllocationSizeID)143 if (id == OptionID::maxSingleAllocationSize) 144 144 return true; 145 145 #endif 146 146 #if OS(DARWIN) 147 if (id == useSigillCrashAnalyzerID)147 if (id == OptionID::useSigillCrashAnalyzer) 148 148 return true; 149 149 #endif 150 150 #if ENABLE(ASSEMBLER) && OS(LINUX) 151 if (id == logJITCodeForPerfID)152 return true; 153 #endif 154 if (id == traceLLIntExecutionID)151 if (id == OptionID::logJITCodeForPerf) 152 return true; 153 #endif 154 if (id == OptionID::traceLLIntExecution) 155 155 return !!LLINT_TRACING; 156 if (id == traceLLIntSlowPathID)156 if (id == OptionID::traceLLIntSlowPath) 157 157 return !!LLINT_TRACING; 158 158 return false; … … 160 160 161 161 template<typename T> 162 bool overrideOptionWithHeuristic(T& variable, Option s::ID id, const char* name, Options::Availability availability)162 bool overrideOptionWithHeuristic(T& variable, OptionID id, const char* name, Options::Availability availability) 163 163 { 164 164 bool available = (availability == Options::Availability::Normal) … … 283 283 } 284 284 285 // FIXME: This is a workaround for MSVC's inability to handle large sources. 286 // Once the MSVC bug has been fixed, we can remove this snippet of code and 287 // make its counterpart in Options.h unconditional. 288 // See https://developercommunity.visualstudio.com/content/problem/653301/fatal-error-c1002-compiler-is-out-of-heap-space-in.html 289 #if COMPILER(MSVC) 290 291 template<OptionTypeID type, OptionID id> 292 constexpr size_t optionTypeSpecificIndex() 293 { 294 size_t index = 0; 295 #define COUNT_INDEX_AND_FIND_MATCH(type_, name_, defaultValue_, availability_, description_) \ 296 if (id == OptionID::name_) \ 297 return index; \ 298 if (type == OptionTypeID::type_) \ 299 index++; 300 301 FOR_EACH_JSC_OPTION(COUNT_INDEX_AND_FIND_MATCH); 302 #undef COUNT_INDEX_AND_FIND_MATCH 303 return InvalidOptionIndex; 304 } 305 306 #define DEFINE_OPTION_ACCESSORS(type_, name_, defaultValue_, availability_, description_) \ 307 JS_EXPORT_PRIVATE OptionTypes::type_& Options::name_() \ 308 { \ 309 return g_jscConfig.type##type_##Options[optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>()]; \ 310 } \ 311 JS_EXPORT_PRIVATE OptionTypes::type_& Options::name_##Default() \ 312 { \ 313 return g_jscConfig.type##type_##DefaultOptions[optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>()]; \ 314 } 315 FOR_EACH_JSC_OPTION(DEFINE_OPTION_ACCESSORS) 316 #undef DEFINE_OPTION_ACCESSORS 317 318 #endif // COMPILER(MSVC) 319 285 320 // Realize the names for each of the options: 286 const Options::EntryInfo Options::s_optionsInfo[ Options::numberOfOptions] = {321 const Options::EntryInfo Options::s_optionsInfo[NumberOfOptions] = { 287 322 #define FILL_OPTION_INFO(type_, name_, defaultValue_, availability_, description_) \ 288 { #name_, description_, Option s::Type::type_, Availability::availability_},323 { #name_, description_, OptionTypeID::type_, Availability::availability_, optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>() }, 289 324 FOR_EACH_JSC_OPTION(FILL_OPTION_INFO) 290 325 #undef FILL_OPTION_INFO … … 300 335 301 336 struct OptionToScale { 302 Options::ID id;337 size_t index; 303 338 int32_t minVal; 304 339 }; 305 340 306 341 static const OptionToScale optionsToScale[] = { 307 { Options::thresholdForJITAfterWarmUpID, 0 },308 { Options::thresholdForJITSoonID, 0 },309 { Options::thresholdForOptimizeAfterWarmUpID, 1 },310 { Options::thresholdForOptimizeAfterLongWarmUpID, 1 },311 { Options::thresholdForOptimizeSoonID, 1 },312 { Options::thresholdForFTLOptimizeSoonID, 2 },313 { Options::thresholdForFTLOptimizeAfterWarmUpID, 2 }342 { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForJITAfterWarmUp>(), 0 }, 343 { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForJITSoon>(), 0 }, 344 { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForOptimizeAfterWarmUp>(), 1 }, 345 { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForOptimizeAfterLongWarmUp>(), 1 }, 346 { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForOptimizeSoon>(), 1 }, 347 { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForFTLOptimizeSoon>(), 2 }, 348 { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForFTLOptimizeAfterWarmUp>(), 2 }, 314 349 }; 315 350 316 const int numberOfOptionsToScale = sizeof(optionsToScale) / sizeof(OptionToScale);351 constexpr int numberOfOptionsToScale = sizeof(optionsToScale) / sizeof(OptionToScale); 317 352 for (int i = 0; i < numberOfOptionsToScale; i++) { 318 Option option(optionsToScale[i].id); 319 ASSERT(option.type() == Options::Type::Int32); 320 option.int32Val() *= scaleFactor; 321 option.int32Val() = std::max(option.int32Val(), optionsToScale[i].minVal); 353 int32_t& optionValue = g_jscConfig.typeInt32Options[optionsToScale[i].index]; 354 optionValue *= scaleFactor; 355 optionValue = std::max(optionValue, optionsToScale[i].minVal); 322 356 } 323 357 } … … 442 476 Options::collectContinuously() = false; 443 477 444 if (Option(Option s::jitPolicyScaleID).isOverridden())478 if (Option(OptionID::jitPolicyScale).isOverridden()) 445 479 scaleJITPolicy(); 446 480 … … 523 557 #endif 524 558 // Initialize each of the options with their default values: 525 #define INIT_OPTION(type_, name_, defaultValue_, availability_, description_) \ 526 name_() = defaultValue_; \ 527 name_##Default() = defaultValue_; 559 #define INIT_OPTION(type_, name_, defaultValue_, availability_, description_) { \ 560 auto value = defaultValue_; \ 561 name_() = value; \ 562 name_##Default() = value; \ 563 } 528 564 FOR_EACH_JSC_OPTION(INIT_OPTION) 529 565 #undef INIT_OPTION … … 549 585 #else // PLATFORM(COCOA) 550 586 #define OVERRIDE_OPTION_WITH_HEURISTICS(type_, name_, defaultValue_, availability_, description_) \ 551 overrideOptionWithHeuristic(name_(), name_##ID, "JSC_" #name_, Availability::availability_);587 overrideOptionWithHeuristic(name_(), OptionID::name_, "JSC_" #name_, Availability::availability_); 552 588 FOR_EACH_JSC_OPTION(OVERRIDE_OPTION_WITH_HEURISTICS) 553 589 #undef OVERRIDE_OPTION_WITH_HEURISTICS … … 728 764 const char* valueStr = equalStr + 1; 729 765 730 // For each option, check if the specif yarg is a match. If so, set the arg766 // For each option, check if the specified arg is a match. If so, set the arg 731 767 // if the value makes sense. Otherwise, move on to checking the next option. 732 768 #define SET_OPTION_IF_MATCH(type_, name_, defaultValue_, availability_, description_) \ 733 769 if (strlen(#name_) == static_cast<size_t>(equalStr - arg) \ 734 770 && !strncmp(arg, #name_, equalStr - arg)) { \ 735 if (Availability::availability_ != Availability::Normal 736 && !isAvailable( name_##ID, Availability::availability_)) \771 if (Availability::availability_ != Availability::Normal \ 772 && !isAvailable(OptionID::name_, Availability::availability_)) \ 737 773 return false; \ 738 OptionEntry::type_ value; \ 739 value = (defaultValue_); \ 774 OptionTypes::type_ value; \ 740 775 bool success = parse(valueStr, value); \ 741 776 if (success) { \ … … 817 852 } 818 853 819 for ( int id = 0; id < numberOfOptions; id++) {854 for (size_t id = 0; id < NumberOfOptions; id++) { 820 855 if (separator && id) 821 856 builder.append(separator); 822 dumpOption(builder, level, static_cast< ID>(id), optionHeader, optionFooter, dumpDefaultsOption);857 dumpOption(builder, level, static_cast<OptionID>(id), optionHeader, optionFooter, dumpDefaultsOption); 823 858 } 824 859 } … … 836 871 } 837 872 838 void Options::dumpOption(StringBuilder& builder, DumpLevel level, Option s::ID id,873 void Options::dumpOption(StringBuilder& builder, DumpLevel level, OptionID id, 839 874 const char* header, const char* footer, DumpDefaultsOption dumpDefaultsOption) 840 875 { 841 if ( id >= numberOfOptions)876 if (static_cast<size_t>(id) >= NumberOfOptions) 842 877 return; // Illegal option. 843 878 … … 881 916 } 882 917 918 Option::Option(OptionID id) 919 : m_id(id) 920 { 921 unsigned index = static_cast<unsigned>(m_id); 922 unsigned typeSpecificIndex = Options::s_optionsInfo[index].typeSpecificIndex; 923 OptionTypeID type = Options::s_optionsInfo[index].type; 924 925 switch (type) { 926 927 #define HANDLE_CASE(OptionType_, type_) \ 928 case OptionTypeID::OptionType_: \ 929 ASSERT(typeSpecificIndex < NumberOf##OptionType_##Options); \ 930 m_val##OptionType_ = g_jscConfig.type##OptionType_##Options[typeSpecificIndex]; \ 931 break; 932 933 FOR_EACH_JSC_OPTION_TYPE(HANDLE_CASE) 934 #undef HANDLE_CASE 935 } 936 } 937 938 const Option Option::defaultOption() const 939 { 940 Option result; 941 unsigned index = static_cast<unsigned>(m_id); 942 unsigned typeSpecificIndex = Options::s_optionsInfo[index].typeSpecificIndex; 943 OptionTypeID type = Options::s_optionsInfo[index].type; 944 945 result.m_id = m_id; 946 switch (type) { 947 948 #define HANDLE_CASE(OptionType_, type_) \ 949 case OptionTypeID::OptionType_: \ 950 ASSERT(typeSpecificIndex < NumberOf##OptionType_##Options); \ 951 result.m_val##OptionType_ = g_jscConfig.type##OptionType_##DefaultOptions[typeSpecificIndex]; \ 952 break; 953 954 FOR_EACH_JSC_OPTION_TYPE(HANDLE_CASE) 955 #undef HANDLE_CASE 956 } 957 return result; 958 } 959 883 960 void Option::dump(StringBuilder& builder) const 884 961 { 885 962 switch (type()) { 886 case Option s::Type::Bool:887 builder.append(m_ entry.valBool ? "true" : "false");963 case OptionTypeID::Bool: 964 builder.append(m_valBool ? "true" : "false"); 888 965 break; 889 case Option s::Type::Unsigned:890 builder.appendNumber(m_ entry.valUnsigned);966 case OptionTypeID::Unsigned: 967 builder.appendNumber(m_valUnsigned); 891 968 break; 892 case Option s::Type::Size:893 builder.appendNumber(m_ entry.valSize);969 case OptionTypeID::Size: 970 builder.appendNumber(m_valSize); 894 971 break; 895 case Option s::Type::Double:896 builder.appendFixedPrecisionNumber(m_ entry.valDouble);972 case OptionTypeID::Double: 973 builder.appendFixedPrecisionNumber(m_valDouble); 897 974 break; 898 case Option s::Type::Int32:899 builder.appendNumber(m_ entry.valInt32);975 case OptionTypeID::Int32: 976 builder.appendNumber(m_valInt32); 900 977 break; 901 case Option s::Type::OptionRange:902 builder.append(m_ entry.valOptionRange.rangeString());978 case OptionTypeID::OptionRange: 979 builder.append(m_valOptionRange.rangeString()); 903 980 break; 904 case Option s::Type::OptionString: {905 const char* option = m_ entry.valOptionString;981 case OptionTypeID::OptionString: { 982 const char* option = m_valOptionString; 906 983 if (!option) 907 984 option = ""; … … 911 988 break; 912 989 } 913 case Option s::Type::GCLogLevel: {914 builder.append(GCLogging::levelAsString(m_ entry.valGCLogLevel));990 case OptionTypeID::GCLogLevel: { 991 builder.append(GCLogging::levelAsString(m_valGCLogLevel)); 915 992 break; 916 993 } … … 921 998 { 922 999 switch (type()) { 923 case Option s::Type::Bool:924 return m_ entry.valBool == other.m_entry.valBool;925 case Option s::Type::Unsigned:926 return m_ entry.valUnsigned == other.m_entry.valUnsigned;927 case Option s::Type::Size:928 return m_ entry.valSize == other.m_entry.valSize;929 case Option s::Type::Double:930 return (m_ entry.valDouble == other.m_entry.valDouble) || (std::isnan(m_entry.valDouble) && std::isnan(other.m_entry.valDouble));931 case Option s::Type::Int32:932 return m_ entry.valInt32 == other.m_entry.valInt32;933 case Option s::Type::OptionRange:934 return m_ entry.valOptionRange.rangeString() == other.m_entry.valOptionRange.rangeString();935 case Option s::Type::OptionString:936 return (m_ entry.valOptionString == other.m_entry.valOptionString)937 || (m_ entry.valOptionString && other.m_entry.valOptionString && !strcmp(m_entry.valOptionString, other.m_entry.valOptionString));938 case Option s::Type::GCLogLevel:939 return m_ entry.valGCLogLevel == other.m_entry.valGCLogLevel;1000 case OptionTypeID::Bool: 1001 return m_valBool == other.m_valBool; 1002 case OptionTypeID::Unsigned: 1003 return m_valUnsigned == other.m_valUnsigned; 1004 case OptionTypeID::Size: 1005 return m_valSize == other.m_valSize; 1006 case OptionTypeID::Double: 1007 return (m_valDouble == other.m_valDouble) || (std::isnan(m_valDouble) && std::isnan(other.m_valDouble)); 1008 case OptionTypeID::Int32: 1009 return m_valInt32 == other.m_valInt32; 1010 case OptionTypeID::OptionRange: 1011 return m_valOptionRange.rangeString() == other.m_valOptionRange.rangeString(); 1012 case OptionTypeID::OptionString: 1013 return (m_valOptionString == other.m_valOptionString) 1014 || (m_valOptionString && other.m_valOptionString && !strcmp(m_valOptionString, other.m_valOptionString)); 1015 case OptionTypeID::GCLogLevel: 1016 return m_valGCLogLevel == other.m_valGCLogLevel; 940 1017 } 941 1018 return false; -
trunk/Source/JavaScriptCore/runtime/Options.h
r250278 r251226 30 30 #include <stdint.h> 31 31 #include <stdio.h> 32 #include <wtf/PrintStream.h>33 32 #include <wtf/StdLibExtras.h> 34 33 … … 54 53 class Options { 55 54 public: 56 enum class DumpLevel {55 enum class DumpLevel : uint8_t { 57 56 None = 0, 58 57 Overridden, … … 61 60 }; 62 61 63 enum class Availability {62 enum class Availability : uint8_t { 64 63 Normal = 0, 65 64 Restricted, … … 67 66 }; 68 67 69 #define DECLARE_OPTION_ID(type_, name_, defaultValue_, availability_, description_) \70 name_##ID,71 72 enum ID {73 FOR_EACH_JSC_OPTION(DECLARE_OPTION_ID)74 numberOfOptions75 };76 #undef DECLARE_OPTION_ID77 78 enum class Type {79 Bool,80 Unsigned,81 Double,82 Int32,83 Size,84 OptionRange,85 OptionString,86 GCLogLevel,87 };88 89 68 JS_EXPORT_PRIVATE static void initialize(); 90 69 … … 102 81 JS_EXPORT_PRIVATE static void ensureOptionsAreCoherent(); 103 82 83 // FIXME: This is a workaround for MSVC's inability to handle large sources. 84 // See https://developercommunity.visualstudio.com/content/problem/653301/fatal-error-c1002-compiler-is-out-of-heap-space-in.html 85 #if COMPILER(MSVC) 86 #define OPTION_ACCESSOR_LINKAGE JS_EXPORT_PRIVATE 87 #else 88 #define OPTION_ACCESSOR_LINKAGE ALWAYS_INLINE 89 #endif 90 104 91 #define DECLARE_OPTION_ACCESSORS(type_, name_, defaultValue_, availability_, description_) \ 105 ALWAYS_INLINE static OptionEntry::type_& name_() { return g_jscConfig.options[name_##ID].val##type_; } \ 106 ALWAYS_INLINE static OptionEntry::type_& name_##Default() { return g_jscConfig.defaultOptions[name_##ID].val##type_; } 107 92 OPTION_ACCESSOR_LINKAGE static OptionTypes::type_& name_(); \ 93 OPTION_ACCESSOR_LINKAGE static OptionTypes::type_& name_##Default(); 108 94 FOR_EACH_JSC_OPTION(DECLARE_OPTION_ACCESSORS) 109 95 #undef DECLARE_OPTION_ACCESSORS 110 96 111 static bool isAvailable( ID, Availability);97 static bool isAvailable(OptionID, Availability); 112 98 113 99 private: … … 117 103 const char* name; 118 104 const char* description; 119 Typetype;105 OptionTypeID type; 120 106 Availability availability; 107 unsigned typeSpecificIndex; 121 108 }; 122 109 … … 130 117 static void dumpAllOptions(StringBuilder&, DumpLevel, const char* title, 131 118 const char* separator, const char* optionHeader, const char* optionFooter, DumpDefaultsOption); 132 static void dumpOption(StringBuilder&, DumpLevel, ID,119 static void dumpOption(StringBuilder&, DumpLevel, OptionID, 133 120 const char* optionHeader, const char* optionFooter, DumpDefaultsOption); 134 121 … … 137 124 static bool overrideAliasedOptionWithHeuristic(const char* name); 138 125 139 static const EntryInfo s_optionsInfo[ numberOfOptions];126 static const EntryInfo s_optionsInfo[NumberOfOptions]; 140 127 141 128 friend class Option; … … 144 131 class Option { 145 132 public: 146 Option(Options::ID id) 147 : m_id(id) 148 , m_entry(g_jscConfig.options[m_id]) 149 { 150 } 151 133 Option(OptionID); 134 152 135 void dump(StringBuilder&) const; 153 136 … … 155 138 bool operator!=(const Option& other) const { return !(*this == other); } 156 139 157 Option s::ID id() const { return m_id; }158 const char* name() const ;159 const char* description() const ;160 Option s::Type type() const;161 Options::Availability availability() const ;162 bool isOverridden() const ;140 OptionID id() const { return m_id; } 141 const char* name() const { return Options::s_optionsInfo[idIndex()].name; } 142 const char* description() const { return Options::s_optionsInfo[idIndex()].description; } 143 OptionTypeID type() const { return Options::s_optionsInfo[idIndex()].type; } 144 Options::Availability availability() const { return Options::s_optionsInfo[idIndex()].availability; } 145 bool isOverridden() const { return *this != defaultOption(); } 163 146 const Option defaultOption() const; 164 165 bool& boolVal(); 166 unsigned& unsignedVal(); 167 double& doubleVal(); 168 int32_t& int32Val(); 169 OptionRange optionRangeVal(); 170 const char* optionStringVal(); 171 GCLogging::Level& gcLogLevelVal(); 172 147 148 #define DECLARE_ACCESSOR(OptionType_, type_) \ 149 type_ val##OptionType_() const { return m_val##OptionType_; } 150 FOR_EACH_JSC_OPTION_TYPE(DECLARE_ACCESSOR) 151 #undef DECLARE_ACCESSOR 152 173 153 private: 174 // Only used for constructing default Options. 175 Option(Options::ID id, OptionEntry& entry) 176 : m_id(id) 177 , m_entry(entry) 178 { 154 Option() { } 155 156 size_t idIndex() const { return static_cast<size_t>(m_id); } 157 158 OptionID m_id; 159 union { 160 161 #define DECLARE_MEMBER(OptionType_, type_) \ 162 type_ m_val##OptionType_; 163 FOR_EACH_JSC_OPTION_TYPE(DECLARE_MEMBER) 164 #undef DECLARE_MEMBER 165 166 }; 167 }; 168 169 // FIXME: This is a workaround for MSVC's inability to handle large sources. 170 // Once the MSVC bug has been fixed, we can make the following unconditional and 171 // remove its counterpart MSVC version in Options.cpp. 172 // See https://developercommunity.visualstudio.com/content/problem/653301/fatal-error-c1002-compiler-is-out-of-heap-space-in.html 173 #if !COMPILER(MSVC) 174 175 template<OptionTypeID type, OptionID id> 176 constexpr size_t optionTypeSpecificIndex() 177 { 178 size_t index = 0; 179 #define COUNT_INDEX_AND_FIND_MATCH(type_, name_, defaultValue_, availability_, description_) \ 180 if (id == OptionID::name_) \ 181 return index; \ 182 if (type == OptionTypeID::type_) \ 183 index++; 184 185 FOR_EACH_JSC_OPTION(COUNT_INDEX_AND_FIND_MATCH); 186 #undef COUNT_INDEX_AND_FIND_MATCH 187 return InvalidOptionIndex; 188 } 189 190 #define DEFINE_OPTION_ACCESSORS(type_, name_, defaultValue_, availability_, description_) \ 191 ALWAYS_INLINE OptionTypes::type_& Options::name_() \ 192 { \ 193 return g_jscConfig.type##type_##Options[optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>()]; \ 194 } \ 195 ALWAYS_INLINE OptionTypes::type_& Options::name_##Default() \ 196 { \ 197 return g_jscConfig.type##type_##DefaultOptions[optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>()]; \ 179 198 } 180 181 Options::ID m_id; 182 OptionEntry& m_entry; 183 }; 184 185 inline const char* Option::name() const 186 { 187 return Options::s_optionsInfo[m_id].name; 188 } 189 190 inline const char* Option::description() const 191 { 192 return Options::s_optionsInfo[m_id].description; 193 } 194 195 inline Options::Type Option::type() const 196 { 197 return Options::s_optionsInfo[m_id].type; 198 } 199 200 inline Options::Availability Option::availability() const 201 { 202 return Options::s_optionsInfo[m_id].availability; 203 } 204 205 inline bool Option::isOverridden() const 206 { 207 return *this != defaultOption(); 208 } 209 210 inline const Option Option::defaultOption() const 211 { 212 return Option(m_id, g_jscConfig.defaultOptions[m_id]); 213 } 214 215 inline bool& Option::boolVal() 216 { 217 return m_entry.valBool; 218 } 219 220 inline unsigned& Option::unsignedVal() 221 { 222 return m_entry.valUnsigned; 223 } 224 225 inline double& Option::doubleVal() 226 { 227 return m_entry.valDouble; 228 } 229 230 inline int32_t& Option::int32Val() 231 { 232 return m_entry.valInt32; 233 } 234 235 inline OptionRange Option::optionRangeVal() 236 { 237 return m_entry.valOptionRange; 238 } 239 240 inline const char* Option::optionStringVal() 241 { 242 return m_entry.valOptionString; 243 } 244 245 inline GCLogging::Level& Option::gcLogLevelVal() 246 { 247 return m_entry.valGCLogLevel; 248 } 199 FOR_EACH_JSC_OPTION(DEFINE_OPTION_ACCESSORS) 200 #undef DEFINE_OPTION_ACCESSORS 201 202 #endif // !COMPILER(MSVC) 249 203 250 204 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/OptionsList.h
r250806 r251226 26 26 #pragma once 27 27 28 #include "GCLogging.h" 29 #include <wtf/PrintStream.h> 30 28 31 namespace JSC { 29 32 … … 32 35 // The FOR_EACH_JSC_OPTION() macro below defines a list of all JSC options in use, 33 36 // along with their types and default values. The options values are actually 34 // realized as a n array of OptionEntry elements in JSC::Config.37 // realized as arrays of each of the OptionTypes in JSC::Config. 35 38 // 36 // Options::initialize() will initialize the array of options values with39 // Options::initialize() will initialize the arrays of options values with 37 40 // the defaults specified in FOR_EACH_JSC_OPTION() below. After that, the values can 38 41 // be programmatically read and written to using an accessor method with the … … 55 58 // values after the sanity checks (for your own testing), then you're liable to 56 59 // ensure that the new values set are sane and reasonable for your own run. 60 // 61 // Any modifications to options must be done before the first VM is instantiate. 62 // On instantiation of the first VM instance, the Options will be write protected 63 // and cannot be modified thereafter. 64 65 class OptionRange { 66 private: 67 enum RangeState { Uninitialized, InitError, Normal, Inverted }; 68 public: 69 OptionRange& operator= (const int& rhs) 70 { // Only needed for initialization 71 if (!rhs) { 72 m_state = Uninitialized; 73 m_rangeString = 0; 74 m_lowLimit = 0; 75 m_highLimit = 0; 76 } 77 return *this; 78 } 79 80 bool init(const char*); 81 bool isInRange(unsigned); 82 const char* rangeString() const { return (m_state > InitError) ? m_rangeString : s_nullRangeStr; } 83 84 void dump(PrintStream& out) const; 85 86 private: 87 static const char* const s_nullRangeStr; 88 89 RangeState m_state; 90 const char* m_rangeString; 91 unsigned m_lowLimit; 92 unsigned m_highLimit; 93 }; 94 95 #define FOR_EACH_JSC_OPTION_TYPE(v) \ 96 v(Bool, bool) \ 97 v(Unsigned, unsigned) \ 98 v(Double, double) \ 99 v(Int32, int32_t) \ 100 v(Size, size_t) \ 101 v(OptionRange, OptionRange) \ 102 v(OptionString, const char*) \ 103 v(GCLogLevel, GCLogging::Level) \ 104 105 namespace OptionTypes { 106 107 #define DECLARE_TYPES(OptionType_, type_) \ 108 using OptionType_ = type_; 109 FOR_EACH_JSC_OPTION_TYPE(DECLARE_TYPES) 110 #undef DECLARE_TYPES 111 112 } // namespace OptionTypes 113 114 enum class OptionTypeID : uint8_t { 115 116 #define DECLARE_TYPEID(OptionType_, type_) \ 117 OptionType_, 118 FOR_EACH_JSC_OPTION_TYPE(DECLARE_TYPEID) 119 #undef DECLARE_TYPEID 120 121 }; 57 122 58 123 #define FOR_EACH_JSC_OPTION(v) \ … … 511 576 v(maximumInliningCallerSize, maximumInliningCallerBytecodeCost, SameOption) \ 512 577 578 #define DECLARE_OPTION_ID(type_, name_, defaultValue_, availability_, description_) \ 579 name_, 580 enum class OptionID : uint16_t { 581 FOR_EACH_JSC_OPTION(DECLARE_OPTION_ID) 582 }; 583 #undef DECLARE_OPTION_ID 584 585 static constexpr size_t InvalidOptionIndex = std::numeric_limits<size_t>::max(); 513 586 514 587 constexpr size_t countNumberOfJSCOptions() … … 523 596 constexpr size_t NumberOfOptions = countNumberOfJSCOptions(); 524 597 598 constexpr size_t countNumberOfJSCOptionsOfType(OptionTypeID type) 599 { 600 size_t count = 0; 601 #define COUNT_OPTION(type_, name_, defaultValue_, availability_, description_) \ 602 if (type == OptionTypeID::type_) \ 603 count++; 604 FOR_EACH_JSC_OPTION(COUNT_OPTION); 605 #undef COUNT_OPTION 606 return count; 607 } 608 609 constexpr size_t NumberOfBoolOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Bool); 610 constexpr size_t NumberOfUnsignedOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Unsigned); 611 constexpr size_t NumberOfDoubleOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Double); 612 constexpr size_t NumberOfInt32Options = countNumberOfJSCOptionsOfType(OptionTypeID::Int32); 613 constexpr size_t NumberOfSizeOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Size); 614 constexpr size_t NumberOfOptionRangeOptions = countNumberOfJSCOptionsOfType(OptionTypeID::OptionRange); 615 constexpr size_t NumberOfOptionStringOptions = countNumberOfJSCOptionsOfType(OptionTypeID::OptionString); 616 constexpr size_t NumberOfGCLogLevelOptions = countNumberOfJSCOptionsOfType(OptionTypeID::GCLogLevel); 617 525 618 } // namespace JSC 526
Note: See TracChangeset
for help on using the changeset viewer.